X-Git-Url: https://git.mdrn.pl/redakcja.git/blobdiff_plain/8132fc186eb0c5fd02c86828c3a4735754296d02..5913c54d19b8f6775633176032161d49f9b2f1aa:/redakcja/static/js/lib/codemirror-0.8/select.js diff --git a/redakcja/static/js/lib/codemirror-0.8/select.js b/redakcja/static/js/lib/codemirror-0.8/select.js deleted file mode 100644 index 01fe9960..00000000 --- a/redakcja/static/js/lib/codemirror-0.8/select.js +++ /dev/null @@ -1,672 +0,0 @@ -/* Functionality for finding, storing, and restoring selections - * - * This does not provide a generic API, just the minimal functionality - * required by the CodeMirror system. - */ - -// Namespace object. -var select = {}; - -(function() { - select.ie_selection = document.selection && document.selection.createRangeCollection; - - // Find the 'top-level' (defined as 'a direct child of the node - // passed as the top argument') node that the given node is - // contained in. Return null if the given node is not inside the top - // node. - function topLevelNodeAt(node, top) { - while (node && node.parentNode != top) - node = node.parentNode; - return node; - } - - // Find the top-level node that contains the node before this one. - function topLevelNodeBefore(node, top) { - while (!node.previousSibling && node.parentNode != top) - node = node.parentNode; - return topLevelNodeAt(node.previousSibling, top); - } - - var fourSpaces = "\u00a0\u00a0\u00a0\u00a0"; - - select.scrollToNode = function(node, cursor) { - if (!node) return; - var element = node, - doc = element.ownerDocument, body = doc.body, - win = (doc.defaultView || doc.parentWindow), - html = doc.documentElement, - atEnd = !element.nextSibling || !element.nextSibling.nextSibling - || !element.nextSibling.nextSibling.nextSibling; - // In Opera (and recent Webkit versions), BR elements *always* - // have a offsetTop property of zero. - var compensateHack = 0; - while (element && !element.offsetTop) { - compensateHack++; - element = element.previousSibling; - } - // atEnd is another kludge for these browsers -- if the cursor is - // at the end of the document, and the node doesn't have an - // offset, just scroll to the end. - if (compensateHack == 0) atEnd = false; - - // WebKit has a bad habit of (sometimes) happily returning bogus - // offsets when the document has just been changed. This seems to - // always be 5/5, so we don't use those. - if (webkit && element && element.offsetTop == 5 && element.offsetLeft == 5) - return; - - var y = compensateHack * (element ? element.offsetHeight : 0), x = 0, - width = (node ? node.offsetWidth : 0), pos = element; - while (pos && pos.offsetParent) { - y += pos.offsetTop; - // Don't count X offset for
nodes - if (!isBR(pos)) - x += pos.offsetLeft; - pos = pos.offsetParent; - } - - var scroll_x = body.scrollLeft || html.scrollLeft || 0, - scroll_y = body.scrollTop || html.scrollTop || 0, - scroll = false, screen_width = win.innerWidth || html.clientWidth || 0; - - if (cursor || width < screen_width) { - if (cursor) { - var off = select.offsetInNode(win, node), size = nodeText(node).length; - if (size) x += width * (off / size); - } - var screen_x = x - scroll_x; - if (screen_x < 0 || screen_x > screen_width) { - scroll_x = x; - scroll = true; - } - } - var screen_y = y - scroll_y; - if (screen_y < 0 || atEnd || screen_y > (win.innerHeight || html.clientHeight || 0) - 50) { - scroll_y = atEnd ? 1e6 : y; - scroll = true; - } - if (scroll) win.scrollTo(scroll_x, scroll_y); - }; - - select.scrollToCursor = function(container) { - select.scrollToNode(select.selectionTopNode(container, true) || container.firstChild, true); - }; - - // Used to prevent restoring a selection when we do not need to. - var currentSelection = null; - - select.snapshotChanged = function() { - if (currentSelection) currentSelection.changed = true; - }; - - // This is called by the code in editor.js whenever it is replacing - // a text node. The function sees whether the given oldNode is part - // of the current selection, and updates this selection if it is. - // Because nodes are often only partially replaced, the length of - // the part that gets replaced has to be taken into account -- the - // selection might stay in the oldNode if the newNode is smaller - // than the selection's offset. The offset argument is needed in - // case the selection does move to the new object, and the given - // length is not the whole length of the new node (part of it might - // have been used to replace another node). - select.snapshotReplaceNode = function(from, to, length, offset) { - if (!currentSelection) return; - - function replace(point) { - if (from == point.node) { - currentSelection.changed = true; - if (length && point.offset > length) { - point.offset -= length; - } - else { - point.node = to; - point.offset += (offset || 0); - } - } - } - replace(currentSelection.start); - replace(currentSelection.end); - }; - - select.snapshotMove = function(from, to, distance, relative, ifAtStart) { - if (!currentSelection) return; - - function move(point) { - if (from == point.node && (!ifAtStart || point.offset == 0)) { - currentSelection.changed = true; - point.node = to; - if (relative) point.offset = Math.max(0, point.offset + distance); - else point.offset = distance; - } - } - move(currentSelection.start); - move(currentSelection.end); - }; - - // Most functions are defined in two ways, one for the IE selection - // model, one for the W3C one. - if (select.ie_selection) { - function selectionNode(win, start) { - var range = win.document.selection.createRange(); - range.collapse(start); - - function nodeAfter(node) { - var found = null; - while (!found && node) { - found = node.nextSibling; - node = node.parentNode; - } - return nodeAtStartOf(found); - } - - function nodeAtStartOf(node) { - while (node && node.firstChild) node = node.firstChild; - return {node: node, offset: 0}; - } - - var containing = range.parentElement(); - if (!isAncestor(win.document.body, containing)) return null; - if (!containing.firstChild) return nodeAtStartOf(containing); - - var working = range.duplicate(); - working.moveToElementText(containing); - working.collapse(true); - for (var cur = containing.firstChild; cur; cur = cur.nextSibling) { - if (cur.nodeType == 3) { - var size = cur.nodeValue.length; - working.move("character", size); - } - else { - working.moveToElementText(cur); - working.collapse(false); - } - - var dir = range.compareEndPoints("StartToStart", working); - if (dir == 0) return nodeAfter(cur); - if (dir == 1) continue; - if (cur.nodeType != 3) return nodeAtStartOf(cur); - - working.setEndPoint("StartToEnd", range); - return {node: cur, offset: size - working.text.length}; - } - return nodeAfter(containing); - } - - select.markSelection = function(win) { - currentSelection = null; - var sel = win.document.selection; - if (!sel) return; - var start = selectionNode(win, true), - end = selectionNode(win, false); - if (!start || !end) return; - currentSelection = {start: start, end: end, window: win, changed: false}; - }; - - select.selectMarked = function() { - if (!currentSelection || !currentSelection.changed) return; - var win = currentSelection.window, doc = win.document; - - function makeRange(point) { - var range = doc.body.createTextRange(), - node = point.node; - if (!node) { - range.moveToElementText(currentSelection.window.document.body); - range.collapse(false); - } - else if (node.nodeType == 3) { - range.moveToElementText(node.parentNode); - var offset = point.offset; - while (node.previousSibling) { - node = node.previousSibling; - offset += (node.innerText || "").length; - } - range.move("character", offset); - } - else { - range.moveToElementText(node); - range.collapse(true); - } - return range; - } - - var start = makeRange(currentSelection.start), end = makeRange(currentSelection.end); - start.setEndPoint("StartToEnd", end); - start.select(); - }; - - select.offsetInNode = function(win, node) { - var sel = win.document.selection; - if (!sel) return 0; - var range = sel.createRange(), range2 = range.duplicate(); - try {range2.moveToElementText(node);} catch(e){return 0;} - range.setEndPoint("StartToStart", range2); - return range.text.length; - }; - - // Get the top-level node that one end of the cursor is inside or - // after. Note that this returns false for 'no cursor', and null - // for 'start of document'. - select.selectionTopNode = function(container, start) { - var selection = container.ownerDocument.selection; - if (!selection) return false; - - var range = selection.createRange(), range2 = range.duplicate(); - range.collapse(start); - var around = range.parentElement(); - if (around && isAncestor(container, around)) { - // Only use this node if the selection is not at its start. - range2.moveToElementText(around); - if (range.compareEndPoints("StartToStart", range2) == 1) - return topLevelNodeAt(around, container); - } - - // Move the start of a range to the start of a node, - // compensating for the fact that you can't call - // moveToElementText with text nodes. - function moveToNodeStart(range, node) { - if (node.nodeType == 3) { - var count = 0, cur = node.previousSibling; - while (cur && cur.nodeType == 3) { - count += cur.nodeValue.length; - cur = cur.previousSibling; - } - if (cur) { - try{range.moveToElementText(cur);} - catch(e){return false;} - range.collapse(false); - } - else range.moveToElementText(node.parentNode); - if (count) range.move("character", count); - } - else { - try{range.moveToElementText(node);} - catch(e){return false;} - } - return true; - } - - // Do a binary search through the container object, comparing - // the start of each node to the selection - var start = 0, end = container.childNodes.length - 1; - while (start < end) { - var middle = Math.ceil((end + start) / 2), node = container.childNodes[middle]; - if (!node) return false; // Don't ask. IE6 manages this sometimes. - if (!moveToNodeStart(range2, node)) return false; - if (range.compareEndPoints("StartToStart", range2) == 1) - start = middle; - else - end = middle - 1; - } - return container.childNodes[start] || null; - }; - - // Place the cursor after this.start. This is only useful when - // manually moving the cursor instead of restoring it to its old - // position. - select.focusAfterNode = function(node, container) { - var range = container.ownerDocument.body.createTextRange(); - range.moveToElementText(node || container); - range.collapse(!node); - range.select(); - }; - - select.somethingSelected = function(win) { - var sel = win.document.selection; - return sel && (sel.createRange().text != ""); - }; - - function insertAtCursor(window, html) { - var selection = window.document.selection; - if (selection) { - var range = selection.createRange(); - range.pasteHTML(html); - range.collapse(false); - range.select(); - } - } - - // Used to normalize the effect of the enter key, since browsers - // do widely different things when pressing enter in designMode. - select.insertNewlineAtCursor = function(window) { - insertAtCursor(window, "
"); - }; - - select.insertTabAtCursor = function(window) { - insertAtCursor(window, fourSpaces); - }; - - // Get the BR node at the start of the line on which the cursor - // currently is, and the offset into the line. Returns null as - // node if cursor is on first line. - select.cursorPos = function(container, start) { - var selection = container.ownerDocument.selection; - if (!selection) return null; - - var topNode = select.selectionTopNode(container, start); - while (topNode && !isBR(topNode)) - topNode = topNode.previousSibling; - - var range = selection.createRange(), range2 = range.duplicate(); - range.collapse(start); - if (topNode) { - range2.moveToElementText(topNode); - range2.collapse(false); - } - else { - // When nothing is selected, we can get all kinds of funky errors here. - try { range2.moveToElementText(container); } - catch (e) { return null; } - range2.collapse(true); - } - range.setEndPoint("StartToStart", range2); - - return {node: topNode, offset: range.text.length}; - }; - - select.setCursorPos = function(container, from, to) { - function rangeAt(pos) { - var range = container.ownerDocument.body.createTextRange(); - if (!pos.node) { - range.moveToElementText(container); - range.collapse(true); - } - else { - range.moveToElementText(pos.node); - range.collapse(false); - } - range.move("character", pos.offset); - return range; - } - - var range = rangeAt(from); - if (to && to != from) - range.setEndPoint("EndToEnd", rangeAt(to)); - range.select(); - } - - // Some hacks for storing and re-storing the selection when the editor loses and regains focus. - select.getBookmark = function (container) { - var from = select.cursorPos(container, true), to = select.cursorPos(container, false); - if (from && to) return {from: from, to: to}; - }; - - // Restore a stored selection. - select.setBookmark = function(container, mark) { - if (!mark) return; - select.setCursorPos(container, mark.from, mark.to); - }; - } - // W3C model - else { - // Find the node right at the cursor, not one of its - // ancestors with a suitable offset. This goes down the DOM tree - // until a 'leaf' is reached (or is it *up* the DOM tree?). - function innerNode(node, offset) { - while (node.nodeType != 3 && !isBR(node)) { - var newNode = node.childNodes[offset] || node.nextSibling; - offset = 0; - while (!newNode && node.parentNode) { - node = node.parentNode; - newNode = node.nextSibling; - } - node = newNode; - if (!newNode) break; - } - return {node: node, offset: offset}; - } - - // Store start and end nodes, and offsets within these, and refer - // back to the selection object from those nodes, so that this - // object can be updated when the nodes are replaced before the - // selection is restored. - select.markSelection = function (win) { - var selection = win.getSelection(); - if (!selection || selection.rangeCount == 0) - return (currentSelection = null); - var range = selection.getRangeAt(0); - - currentSelection = { - start: innerNode(range.startContainer, range.startOffset), - end: innerNode(range.endContainer, range.endOffset), - window: win, - changed: false - }; - }; - - select.selectMarked = function () { - var cs = currentSelection; - // on webkit-based browsers, it is apparently possible that the - // selection gets reset even when a node that is not one of the - // endpoints get messed with. the most common situation where - // this occurs is when a selection is deleted or overwitten. we - // check for that here. - function focusIssue() { - if (cs.start.node == cs.end.node && cs.start.offset == cs.end.offset) { - var selection = cs.window.getSelection(); - if (!selection || selection.rangeCount == 0) return true; - var range = selection.getRangeAt(0), point = innerNode(range.startContainer, range.startOffset); - return cs.start.node != point.node || cs.start.offset != point.offset; - } - } - if (!cs || !(cs.changed || (webkit && focusIssue()))) return; - var win = cs.window, range = win.document.createRange(); - - function setPoint(point, which) { - if (point.node) { - // Some magic to generalize the setting of the start and end - // of a range. - if (point.offset == 0) - range["set" + which + "Before"](point.node); - else - range["set" + which](point.node, point.offset); - } - else { - range.setStartAfter(win.document.body.lastChild || win.document.body); - } - } - - setPoint(cs.end, "End"); - setPoint(cs.start, "Start"); - selectRange(range, win); - }; - - // Helper for selecting a range object. - function selectRange(range, window) { - var selection = window.getSelection(); - if (!selection) return; - selection.removeAllRanges(); - selection.addRange(range); - } - function selectionRange(window) { - var selection = window.getSelection(); - if (!selection || selection.rangeCount == 0) - return false; - else - return selection.getRangeAt(0); - } - - // Finding the top-level node at the cursor in the W3C is, as you - // can see, quite an involved process. - select.selectionTopNode = function(container, start) { - var range = selectionRange(container.ownerDocument.defaultView); - if (!range) return false; - - var node = start ? range.startContainer : range.endContainer; - var offset = start ? range.startOffset : range.endOffset; - // Work around (yet another) bug in Opera's selection model. - if (window.opera && !start && range.endContainer == container && range.endOffset == range.startOffset + 1 && - container.childNodes[range.startOffset] && isBR(container.childNodes[range.startOffset])) - offset--; - - // For text nodes, we look at the node itself if the cursor is - // inside, or at the node before it if the cursor is at the - // start. - if (node.nodeType == 3){ - if (offset > 0) - return topLevelNodeAt(node, container); - else - return topLevelNodeBefore(node, container); - } - // Occasionally, browsers will return the HTML node as - // selection. If the offset is 0, we take the start of the frame - // ('after null'), otherwise, we take the last node. - else if (node.nodeName.toUpperCase() == "HTML") { - return (offset == 1 ? null : container.lastChild); - } - // If the given node is our 'container', we just look up the - // correct node by using the offset. - else if (node == container) { - return (offset == 0) ? null : node.childNodes[offset - 1]; - } - // In any other case, we have a regular node. If the cursor is - // at the end of the node, we use the node itself, if it is at - // the start, we use the node before it, and in any other - // case, we look up the child before the cursor and use that. - else { - if (offset == node.childNodes.length) - return topLevelNodeAt(node, container); - else if (offset == 0) - return topLevelNodeBefore(node, container); - else - return topLevelNodeAt(node.childNodes[offset - 1], container); - } - }; - - select.focusAfterNode = function(node, container) { - var win = container.ownerDocument.defaultView, - range = win.document.createRange(); - range.setStartBefore(container.firstChild || container); - // In Opera, setting the end of a range at the end of a line - // (before a BR) will cause the cursor to appear on the next - // line, so we set the end inside of the start node when - // possible. - if (node && !node.firstChild) - range.setEndAfter(node); - else if (node) - range.setEnd(node, node.childNodes.length); - else - range.setEndBefore(container.firstChild || container); - range.collapse(false); - selectRange(range, win); - }; - - select.somethingSelected = function(win) { - var range = selectionRange(win); - return range && !range.collapsed; - }; - - select.offsetInNode = function(win, node) { - var range = selectionRange(win); - if (!range) return 0; - range = range.cloneRange(); - range.setStartBefore(node); - return range.toString().length; - }; - - function insertNodeAtCursor(window, node) { - var range = selectionRange(window); - if (!range) return; - - range.deleteContents(); - range.insertNode(node); - - // work around weirdness where Opera will magically insert a new - // BR node when a BR node inside a span is moved around. makes - // sure the BR ends up outside of spans. - if (window.opera && isBR(node) && isSpan(node.parentNode)) { - var next = node.nextSibling, p = node.parentNode, outer = p.parentNode; - outer.insertBefore(node, p.nextSibling); - var textAfter = ""; - for (; next && next.nodeType == 3; next = next.nextSibling) { - textAfter += next.nodeValue; - removeElement(next); - } - outer.insertBefore(makePartSpan(textAfter, window.document), node.nextSibling); - } - range = window.document.createRange(); - range.selectNode(node); - range.collapse(false); - selectRange(range, window); - } - - select.insertNewlineAtCursor = function(window) { - if (webkit) - document.execCommand('insertLineBreak'); - else - insertNodeAtCursor(window, window.document.createElement("BR")); - }; - - select.insertTabAtCursor = function(window) { - insertNodeAtCursor(window, window.document.createTextNode(fourSpaces)); - }; - - select.cursorPos = function(container, start) { - var range = selectionRange(window); - if (!range) return; - - var topNode = select.selectionTopNode(container, start); - while (topNode && !isBR(topNode)) - topNode = topNode.previousSibling; - - range = range.cloneRange(); - range.collapse(start); - if (topNode) - range.setStartAfter(topNode); - else - range.setStartBefore(container); - - return {node: topNode, offset: range.toString().length}; - }; - - select.setCursorPos = function(container, from, to) { - var win = container.ownerDocument.defaultView, - range = win.document.createRange(); - - function setPoint(node, offset, side) { - if (offset == 0 && node && !node.nextSibling) { - range["set" + side + "After"](node); - return true; - } - - if (!node) - node = container.firstChild; - else - node = node.nextSibling; - - if (!node) return; - - if (offset == 0) { - range["set" + side + "Before"](node); - return true; - } - - var backlog = [] - function decompose(node) { - if (node.nodeType == 3) - backlog.push(node); - else - forEach(node.childNodes, decompose); - } - while (true) { - while (node && !backlog.length) { - decompose(node); - node = node.nextSibling; - } - var cur = backlog.shift(); - if (!cur) return false; - - var length = cur.nodeValue.length; - if (length >= offset) { - range["set" + side](cur, offset); - return true; - } - offset -= length; - } - } - - to = to || from; - if (setPoint(to.node, to.offset, "End") && setPoint(from.node, from.offset, "Start")) - selectRange(range, win); - }; - } -})();