简体   繁体   English

使用Java脚本更改所选文本的CSS

[英]Change CSS of selected text using Javascript

I'm trying to make a javascript bookmarklet that will act as a highlighter, changing the background of selected text on a webpage to yellow when the bookmarklet is pressed. 我正在尝试制作一个将用作荧光笔的javascript小书签,当按小书签时,将网页上所选文本的背景更改为黄色。

I'm using the following code to get the selected text, and it works fine, returning the correct string 我正在使用以下代码来获取选定的文本,并且工作正常,返回正确的字符串

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;

} }

However, when I created a similar function to change the CSS of the selected text using jQuery, it isn't working: 但是,当我创建了一个类似的函数来使用jQuery更改所选文本的CSS时,它不起作用:

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'});

} }

Any ideas? 有任何想法吗?

The easiest way to do this is to use execCommand() , which has a command to change the background colour in all modern browsers. 最简单的方法是使用execCommand() ,该命令具有在所有现代浏览器中更改背景颜色的命令。

The following should do what you want on any selection, including ones spanning multiple elements. 以下应该在任何选择上做您想要的,包括跨越多个元素的选择。 In non-IE browsers it turns on designMode , applies a background colour and then switches designMode off again. 在非IE浏览器中,它将打开designMode ,应用背景色,然后再次关闭designMode

UPDATE 更新

Fixed in IE 9. 在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);
    }
}

Here is a crude example of how it could work. 这是它如何工作的粗略示例。 As Zack points out you'll need to be aware of cases where the selection spans multiple elements. 正如Zack指出的那样,您需要注意选择跨越多个元素的情况。 This isn't intended to be used as-is, just something to help get ideas flowing. 这并不是按原样使用的,只是可以帮助使想法流传的东西。 Tested in Chrome. 在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 );

In Firefox, you can use the ::-moz-selection psuedo-class. 在Firefox中,您可以使用::-moz-selection psuedo-class。
In Webkit, you can use the ::selection pseudo-class. 在Webkit中,可以使用::selection伪类。

Have a look at a little example i made at http://www.jsfiddle.net/hbwEE/3/ 看看我在http://www.jsfiddle.net/hbwEE/3/上做的一个小例子

It does not take into account selections that span multiple elements.. ( IE will do but will mess the html a bit .. ) 它没有考虑跨多个元素的选择。( IE会这样做,但会使HTML有点混乱..

To make the highlight stick permanently, I believe you are going to have to wrap the selection in a new DOM element ( span should do), to which you can then attach style properties. 为了使高光棒永久保持不变,我相信您将不得不将选择内容包装在新的DOM元素中( span应该这样做),然后可以将样式属性附加到该元素。 I don't know if jQuery can do that for you. 我不知道jQuery是否可以为您做到这一点。 Keep in mind that selections can span element boundaries, so in the general case you're going to have to inject a whole bunch of new elements 请记住,选择可能会跨越元素边界,因此在一般情况下,您将不得不注入一堆新元素

I like Tim's answer, it's clean and fast. 我喜欢蒂姆的答案,它干净快捷。 But it also shuts down the doors to doing any interactions with the highlights. 但这也关闭了与高光进行任何交互的大门。

Inserting inline elements directly around the texts is a bad choice, as they broke the text flow and mess things up in complex situations, 直接在文本周围插入内联元素是一个不好的选择,因为它们会破坏文本流并使混乱的情况变得混乱,

So I suggest a dirty hack that 因此,我建议一个肮脏的黑客

  1. calculates the absolute layout of each line of selected text (no matter where they are), 计算所选文本每行的绝对布局(无论它们在哪里),
  2. then insert colored, semi-transparent inline-block elements in the end of the document body. 然后在文档主体的末尾插入彩色的,半透明的内联块元素。

This chrome extension is an example of how this can be done. chrome扩展程序是如何完成此操作的示例。

It uses API from this library to get the absolute layout of each selected line. 它使用此库中的 API来获取每个选定行的绝对布局。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM