Created
July 5, 2012 00:48
-
-
Save albertein/3050333 to your computer and use it in GitHub Desktop.
Selection highlighting
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function getSelectedText(){ | |
if(window.getSelection){ | |
return window.getSelection().toString(); | |
} | |
else if(document.getSelection){ | |
return document.getSelection(); | |
} | |
else if(document.selection){ | |
return document.selection.createRange().text; | |
} | |
} | |
var $ = jQuery; | |
var startingP = null; | |
$(document).ready (function () { | |
$("div.entry p").mousedown(function () { | |
startingP = $(this); | |
}).mouseup(function () { | |
if (startingP === null) | |
return; | |
var start = startingP; | |
startingP = null; | |
var end = $(this); | |
var text = getSelectedText (); | |
if (text === "") | |
return; | |
var fullText = start.text(); | |
if (start.get(0) === end.get(0)) { | |
var index = start.text().indexOf(text); | |
var TEXT_NODE = 3; | |
var ELEMENT_NODE = 1; | |
var root = start.get(0); | |
var textIndex = 0; | |
var ended = false; | |
var nodes = []; | |
var pushNode = function (node, startIndex, endIndex) { | |
if (!startIndex) | |
startIndex = 0; | |
if (!endIndex) | |
endIndex = node.textContent.length; | |
nodes.push ({node: node, startIndex: startIndex, endIndex: endIndex}); | |
}; | |
var analize = function(node) { | |
if (node.nodeType == TEXT_NODE) { | |
var startIndex = 0; | |
var endIndex = 0; | |
if (textIndex + node.textContent.length <= index) { //If we are not on the start of the tag continue | |
textIndex += node.textContent.length; | |
return; | |
} else if (textIndex > index) { //Text is in the middle of the selection | |
if (textIndex + node.textContent.length < index + text.length) { //If the selection continues after the element | |
pushNode (node); | |
textIndex += node.textContent.length; | |
} else { //If the selection ends inside this element | |
pushNode(node, 0, index + text.length - textIndex); | |
ended = true; | |
return; | |
} | |
} else if (textIndex + node.textContent.length > index) { //If the selection starts inside this element | |
if (textIndex + node.textContent.length < index + text.length) { //If the sleection continues after the element | |
pushNode(node, index - textIndex); | |
textIndex += node.textContent.length; | |
} else { | |
pushNode(node, index - textIndex, index + text.length - textIndex); | |
ended = true; | |
return; | |
} | |
} | |
} | |
var childs = node.childNodes; | |
for (var i = 0; i < childs.length; i++) { | |
if (ended) | |
return; | |
analize(childs[i]); | |
} | |
}; | |
var childs = root.childNodes; | |
for (var i = 0; i < childs.length; i++) { | |
if (ended) | |
break; | |
analize(childs[i]); | |
} | |
var serializeNode = function (node, data) { | |
var nthChild = 0; | |
var pivot = node; | |
while ((pivot = pivot.previousSibling) != null) nthChild++; | |
data = nthChild + data; | |
node = node.parentNode; | |
if (node.nodeName != "P") { | |
data = "-" + data; | |
return serializeNode(node, data); | |
} else { | |
pivot = node; | |
nthChild = 0; | |
while ((pivot = pivot.previousSibling) != null) nthChild++; | |
return nthChild + "-" + data; | |
} | |
}; | |
var data = ""; | |
for (var i = 0; i < nodes.length; i++) { | |
var node = nodes[i]; | |
data += serializeNode(node.node, "") + "|" + node.startIndex + "," + node.endIndex + ";"; | |
} | |
data = "highlight:" + data.substring(0, data.length - 1); | |
window.location.hash = data; | |
} | |
}); | |
var hash = window.location.hash; | |
var nodes = []; | |
var firstHighlight = null; | |
if (hash.substring(0, "#highlight:".length) == "#highlight:") { | |
hash = hash.replace("#highlight:", ""); | |
var nodesData = hash.split(";"); | |
for (var i = 0; i < nodesData.length; i++) { | |
var nodeInfo = nodesData[i].split ("|"); | |
var nodeLocation = nodeInfo [0]; | |
var selectionData = nodeInfo [1].split (","); | |
var startIndex = selectionData [0]; | |
var endIndex = selectionData [1]; | |
var baseNode = $("div.entry").get(0); | |
var subNodes = nodeLocation.split ("-"); | |
for (var j = 0; j < subNodes.length; j++) | |
baseNode = baseNode.childNodes [subNodes [j]]; | |
nodes.push ( {node: baseNode, start: startIndex, end: endIndex } ); | |
} | |
for (var i = 0; i < nodes.length; i++) { | |
var node = nodes [i]; | |
var text = node.node.data; | |
var preText = text.substring (0, node.start); | |
var spanText = text.substring (node.start, node.end); | |
var postText = text.substring (node.end); | |
var parentNode = node.node.parentNode; | |
if (preText != "") | |
parentNode.insertBefore (document.createTextNode (preText), node.node); | |
var span = $("<span class='highlight'></span>").text (spanText); | |
span.insertBefore (node.node); | |
if (firstHighlight == null) | |
firstHighlight = span.get (0); | |
if (postText != "") | |
parentNode.insertBefore (document.createTextNode (postText), node.node); | |
$(node.node).remove (); | |
} | |
var x = 0; | |
var y = 0; | |
while (firstHighlight != null) { | |
x += firstHighlight.offsetLeft; | |
y += firstHighlight.offsetTop; | |
firstHighlight = firstHighlight.offsetParent; | |
} | |
window.scrollTo (x, y); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment