Skip to content

Instantly share code, notes, and snippets.

@albertein
Created July 5, 2012 00:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save albertein/3050333 to your computer and use it in GitHub Desktop.
Save albertein/3050333 to your computer and use it in GitHub Desktop.
Selection highlighting
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