Ref:
http://www.quirksmode.org/dom/execCommand.html
http://www.quirksmode.org/dom/execCommand/
http://stackoverflow.com/questions/8429290/any-alternative-to-using-execcommand-for-highlighting-html-in-ios-ebook-reader
<script>
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);
}
}
var doHighlight = function(color){
highlight(color);
};
</script>
<p> some text here, you can select and click the highlight button to highlight selection </p>
<button onclick="javascript:doHighlight('yellow');">Yellow Highlight</button>
Replace document.execCommand("HiliteColor", false, colour) with styleRange(range, style) will make it faster:
<script>
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);
}
/* ***********REPLACE ************/
// Use HiliteColor since some browsers apply BackColor to the whole block
styleRange(range, "background-color:yellow; color:red;");
document.designMode = "off";
}
function styleRange(range, style) // the style is a string of css styles. eg."background-color:darkblue; color:blue;"{ // Get the start and end nodes and split them to give new start and end nodes with only text that falls inside the range. var startNode = range.startContainer.splitText(range.startOffset); var endNode = range.endContainer.splitText(range.endOffset).previousSibling;
// Adjust the range to contain the new start and end nodes // The offsets are not really important anymore but might as well set them correctly range.setStart(startNode,0); range.setEnd(endNode,endNode.length);
// Get an array of all text nodes within the range var nodes = getNodesInRange(range);
// Place span tags with style around each textnode for (i = 0; i < nodes.length; i++) { var span = document.createElement('span'); span.setAttribute("style", style); span.appendChild( document.createTextNode(nodes[i].nodeValue)); nodes[i].parentNode.replaceChild( span, nodes[i] ); }}
function getNodesInRange(range){ var start = range.startContainer; var end = range.endContainer; var commonAncestor = range.commonAncestorContainer; var nodes = []; var node;
// walk parent nodes from start to common ancestor for (node = start.parentNode; node; node = node.parentNode) { if (node.nodeType == 3) //modified to only add text nodes to the array nodes.push(node); if (node == commonAncestor) break; } nodes.reverse();
// walk children and siblings from start until end is found for (node = start; node; node = getNextNode(node)) { if (node.nodeType == 3) //modified to only add text nodes to the array nodes.push(node); if (node == end) break; }
return nodes;}
function getNextNode(node, end){ if (node.firstChild) return node.firstChild; while (node) { if (node.nextSibling) return node.nextSibling; node = node.parentNode; }}
沒有留言:
張貼留言