mirror of
https://github.com/UnickSoft/graphonline.git
synced 2025-07-03 08:15:38 +00:00
167 lines
5.2 KiB
JavaScript
Executable File
167 lines
5.2 KiB
JavaScript
Executable File
(function() {
|
|
|
|
var exports = this, Bookmark;
|
|
|
|
Bookmark = function(env, range, keepOldBookmarks) {
|
|
|
|
this.env = env;
|
|
this.element = env.element;
|
|
this.selection = this.env.selection;
|
|
|
|
// Remove all bookmarks?
|
|
if (!keepOldBookmarks) {
|
|
this.removeBookmarks(this.element);
|
|
}
|
|
|
|
var currRange = range || this.selection.getRangeAt(0);
|
|
range = currRange.cloneRange();
|
|
var startContainer = range.startContainer;
|
|
var endContainer = range.endContainer;
|
|
var startOffset = range.startOffset;
|
|
var endOffset = range.endOffset;
|
|
var tmp;
|
|
|
|
// Collapse to the end of range.
|
|
range.collapse(false);
|
|
|
|
var endBookmark = this.env.document.createElement('span');
|
|
endBookmark.style.display = 'none';
|
|
ice.dom.setHtml(endBookmark, ' ');
|
|
ice.dom.addClass(endBookmark, 'iceBookmark iceBookmark_end');
|
|
endBookmark.setAttribute('iceBookmark', 'end');
|
|
range.insertNode(endBookmark);
|
|
if(!ice.dom.isChildOf(endBookmark, this.element)) {
|
|
this.element.appendChild(endBookmark);
|
|
}
|
|
|
|
// Move the range to where it was before.
|
|
range.setStart(startContainer, startOffset);
|
|
range.collapse(true);
|
|
|
|
// Create the start bookmark.
|
|
var startBookmark = this.env.document.createElement('span');
|
|
startBookmark.style.display = 'none';
|
|
ice.dom.addClass(startBookmark, 'iceBookmark iceBookmark_start');
|
|
ice.dom.setHtml(startBookmark, ' ');
|
|
startBookmark.setAttribute('iceBookmark', 'start');
|
|
try {
|
|
range.insertNode(startBookmark);
|
|
|
|
// Make sure start and end are in correct position.
|
|
if (startBookmark.previousSibling === endBookmark) {
|
|
// Reverse..
|
|
tmp = startBookmark;
|
|
startBookmark = endBookmark;
|
|
endBookmark = tmp;
|
|
}
|
|
} catch (e) {
|
|
// NS_ERROR_UNEXPECTED: I believe this is a Firefox bug.
|
|
// It seems like if the range is collapsed and the text node is empty
|
|
// (i.e. length = 0) then Firefox tries to split the node for no reason and fails...
|
|
ice.dom.insertBefore(endBookmark, startBookmark);
|
|
}
|
|
|
|
if (ice.dom.isChildOf(startBookmark, this.element) === false) {
|
|
if (this.element.firstChild) {
|
|
ice.dom.insertBefore(this.element.firstChild, startBookmark);
|
|
} else {
|
|
// Should not happen...
|
|
this.element.appendChild(startBookmark);
|
|
}
|
|
}
|
|
|
|
if (!endBookmark.previousSibling) {
|
|
tmp = this.env.document.createTextNode('');
|
|
ice.dom.insertBefore(endBookmark, tmp);
|
|
}
|
|
|
|
// The original range object must be changed.
|
|
if (!startBookmark.nextSibling) {
|
|
tmp = this.env.document.createTextNode('');
|
|
ice.dom.insertAfter(startBookmark, tmp);
|
|
}
|
|
|
|
currRange.setStart(startBookmark.nextSibling, 0);
|
|
currRange.setEnd(endBookmark.previousSibling, (endBookmark.previousSibling.length || 0));
|
|
|
|
this.start = startBookmark;
|
|
this.end = endBookmark;
|
|
};
|
|
|
|
Bookmark.prototype = {
|
|
|
|
selectBookmark: function() {
|
|
var range = this.selection.getRangeAt(0);
|
|
var startPos = null;
|
|
var endPos = null;
|
|
var startOffset = 0;
|
|
var endOffset = null;
|
|
if (this.start.nextSibling === this.end || ice.dom.getElementsBetween(this.start, this.end).length === 0) {
|
|
// Bookmark is collapsed.
|
|
if (this.end.nextSibling) {
|
|
startPos = ice.dom.getFirstChild(this.end.nextSibling);
|
|
} else if (this.start.previousSibling) {
|
|
startPos = ice.dom.getFirstChild(this.start.previousSibling);
|
|
if (startPos.nodeType === ice.dom.TEXT_NODE) {
|
|
startOffset = startPos.length;
|
|
}
|
|
} else {
|
|
// Create a text node in parent.
|
|
this.end.parentNode.appendChild(this.env.document.createTextNode(''));
|
|
startPos = ice.dom.getFirstChild(this.end.nextSibling);
|
|
}
|
|
} else {
|
|
if (this.start.nextSibling) {
|
|
startPos = ice.dom.getFirstChild(this.start.nextSibling);
|
|
} else {
|
|
if (!this.start.previousSibling) {
|
|
var tmp = this.env.document.createTextNode('');
|
|
ice.dom.insertBefore(this.start, tmp);
|
|
}
|
|
|
|
startPos = ice.dom.getLastChild(this.start.previousSibling);
|
|
startOffset = startPos.length;
|
|
}
|
|
|
|
if (this.end.previousSibling) {
|
|
endPos = ice.dom.getLastChild(this.end.previousSibling);
|
|
} else {
|
|
endPos = ice.dom.getFirstChild(this.end.nextSibling || this.end);
|
|
endOffset = 0;
|
|
}
|
|
}
|
|
|
|
ice.dom.remove([this.start, this.end]);
|
|
|
|
if (endPos === null) {
|
|
range.setEnd(startPos, startOffset);
|
|
range.collapse(false);
|
|
} else {
|
|
range.setStart(startPos, startOffset);
|
|
if (endOffset === null) {
|
|
endOffset = (endPos.length || 0);
|
|
}
|
|
range.setEnd(endPos, endOffset);
|
|
}
|
|
|
|
try {
|
|
this.selection.addRange(range);
|
|
} catch (e) {
|
|
// IE may throw exception for hidden elements..
|
|
}
|
|
},
|
|
|
|
getBookmark: function(parent, type) {
|
|
var elem = ice.dom.getClass('iceBookmark_' + type, parent)[0];
|
|
return elem;
|
|
},
|
|
|
|
removeBookmarks: function(elem) {
|
|
ice.dom.remove(ice.dom.getClass('iceBookmark', elem, 'span'));
|
|
}
|
|
};
|
|
|
|
exports.Bookmark = Bookmark;
|
|
|
|
}).call(this.ice);
|