Изменить CSS выделенного текста с помощью Javascript - PullRequest
11 голосов
/ 11 июля 2010

Я пытаюсь создать букмарклет javascript, который будет выполнять функцию подсветки, меняя фон выделенного текста на веб-странице на желтый при нажатии на букмарклет.

Я использую следующий код дляполучить выделенный текст, и он работает нормально, возвращая правильную строку

function getSelText() {
var SelText = '';
if (window.getSelection) {
    SelText = window.getSelection();
} else if (document.getSelection) {
    SelText = document.getSelection();
} else if (document.selection) {
    SelText = document.selection.createRange().text;
}
return SelText;

}

Однако, когда я создал подобную функцию для изменения CSS выделенного текста с помощью jQuery,не работает:

function highlightSelText() {
var SelText;
if (window.getSelection) {
    SelText = window.getSelection();
} else if (document.getSelection) {
    SelText = document.getSelection();
} else if (document.selection) {
    SelText = document.selection.createRange().text;
}
$(SelText).css({'background-color' : 'yellow', 'font-weight' : 'bolder'});

}

Есть идеи?

Ответы [ 6 ]

19 голосов
/ 12 июля 2010

Самый простой способ сделать это - использовать execCommand(), который имеет команду для изменения цвета фона во всех современных браузерах.

Следующее должно делать то, что вы хотите на любом выделении, в том числе на нескольких элементах. В браузерах, отличных от IE, он включает designMode, применяет цвет фона, а затем снова выключает designMode.

UPDATE

Исправлено в IE 9.

function makeEditableAndHighlight(colour) {
    var range, sel = window.getSelection();
    if (sel.rangeCount && sel.getRangeAt) {
        range = sel.getRangeAt(0);
    }
    document.designMode = "on";
    if (range) {
        sel.removeAllRanges();
        sel.addRange(range);
    }
    // Use HiliteColor since some browsers apply BackColor to the whole block
    if (!document.execCommand("HiliteColor", false, colour)) {
        document.execCommand("BackColor", false, colour);
    }
    document.designMode = "off";
}

function highlight(colour) {
    var range, sel;
    if (window.getSelection) {
        // IE9 and non-IE
        try {
            if (!document.execCommand("BackColor", false, colour)) {
                makeEditableAndHighlight(colour);
            }
        } catch (ex) {
            makeEditableAndHighlight(colour)
        }
    } else if (document.selection && document.selection.createRange) {
        // IE <= 8 case
        range = document.selection.createRange();
        range.execCommand("BackColor", false, colour);
    }
}
6 голосов
/ 11 июля 2010

Вот грубый пример того, как это может работать. Как отмечает Зак, вам нужно знать о случаях, когда выбор охватывает несколько элементов. Это не предназначено для использования как есть, просто что-то, чтобы помочь реализации идей. Проверено в Chrome.

var selection = window.getSelection();
var text = selection.toString();
var parent = $(selection.focusNode.parentElement);
var oldHtml = parent.html();
var newHtml = oldHtml.replace(text, "<span class='highlight'>"+text+"</span>");
parent.html( newHtml );
2 голосов
/ 11 июля 2010

Посмотрите на небольшой пример, который я сделал на http://www.jsfiddle.net/hbwEE/3/

Он не учитывает выборки, охватывающие несколько элементов .. ( IE подойдет, но немного испортит HTML.. )

2 голосов
/ 11 июля 2010

В Firefox вы можете использовать псевдо-класс ::-moz-selection.
В Webkit вы можете использовать псевдокласс ::selection.

1 голос
/ 11 июля 2010

Чтобы сделать выделение постоянным, я полагаю, вам нужно будет обернуть выделение в новый элемент DOM (должен сделать span), к которому вы затем можете прикрепить свойства стиля. Я не знаю, сможет ли jQuery сделать это для вас. Имейте в виду, что выборки могут охватывать границы элементов, поэтому в общем случае вам придется добавить целую кучу новых элементов

0 голосов
/ 24 апреля 2017

Мне нравится ответ Тима, он чистый и быстрый. Но это также закрывает двери для любых взаимодействий с основными моментами.

Вставка встроенных элементов непосредственно вокруг текста - плохой выбор, поскольку они нарушают поток текста и запутывают вещи в сложных ситуациях

Поэтому я предлагаю грязный взлом , что

  1. вычисляет абсолютное расположение каждой строки выделенного текста (независимо от того, где они находятся),
  2. затем вставьте цветные, полупрозрачные элементы встроенного блока в конец тела документа.

Это расширение chrome является примером того, как это можно сделать.

Он использует API из этой библиотеки , чтобы получить абсолютный макет каждой выбранной строки.

...