%PDF- %PDF-
| Direktori : /var/www/crm/include/javascript/tiny_mce/classes/dom/ |
| Current File : /var/www/crm/include/javascript/tiny_mce/classes/dom/RangeUtils.js |
/**
* Range.js
*
* Copyright 2009, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://tinymce.moxiecode.com/license
* Contributing: http://tinymce.moxiecode.com/contributing
*/
(function(tinymce) {
tinymce.dom.RangeUtils = function(dom) {
var INVISIBLE_CHAR = '\uFEFF';
/**
* Walks the specified range like object and executes the callback for each sibling collection it finds.
*
* @param {Object} rng Range like object.
* @param {function} callback Callback function to execute for each sibling collection.
*/
this.walk = function(rng, callback) {
var startContainer = rng.startContainer,
startOffset = rng.startOffset,
endContainer = rng.endContainer,
endOffset = rng.endOffset,
ancestor, startPoint,
endPoint, node, parent, siblings, nodes;
// Handle table cell selection the table plugin enables
// you to fake select table cells and perform formatting actions on them
nodes = dom.select('td.mceSelected,th.mceSelected');
if (nodes.length > 0) {
tinymce.each(nodes, function(node) {
callback([node]);
});
return;
}
/**
* Collects siblings
*
* @private
* @param {Node} node Node to collect siblings from.
* @param {String} name Name of the sibling to check for.
* @return {Array} Array of collected siblings.
*/
function collectSiblings(node, name, end_node) {
var siblings = [];
for (; node && node != end_node; node = node[name])
siblings.push(node);
return siblings;
};
/**
* Find an end point this is the node just before the common ancestor root.
*
* @private
* @param {Node} node Node to start at.
* @param {Node} root Root/ancestor element to stop just before.
* @return {Node} Node just before the root element.
*/
function findEndPoint(node, root) {
do {
if (node.parentNode == root)
return node;
node = node.parentNode;
} while(node);
};
function walkBoundary(start_node, end_node, next) {
var siblingName = next ? 'nextSibling' : 'previousSibling';
for (node = start_node, parent = node.parentNode; node && node != end_node; node = parent) {
parent = node.parentNode;
siblings = collectSiblings(node == start_node ? node : node[siblingName], siblingName);
if (siblings.length) {
if (!next)
siblings.reverse();
callback(siblings);
}
}
};
// If index based start position then resolve it
if (startContainer.nodeType == 1 && startContainer.hasChildNodes())
startContainer = startContainer.childNodes[startOffset];
// If index based end position then resolve it
if (endContainer.nodeType == 1 && endContainer.hasChildNodes())
endContainer = endContainer.childNodes[Math.min(endOffset - 1, endContainer.childNodes.length - 1)];
// Find common ancestor and end points
ancestor = dom.findCommonAncestor(startContainer, endContainer);
// Same container
if (startContainer == endContainer)
return callback([startContainer]);
// Process left side
for (node = startContainer; node; node = node.parentNode) {
if (node == endContainer)
return walkBoundary(startContainer, ancestor, true);
if (node == ancestor)
break;
}
// Process right side
for (node = endContainer; node; node = node.parentNode) {
if (node == startContainer)
return walkBoundary(endContainer, ancestor);
if (node == ancestor)
break;
}
// Find start/end point
startPoint = findEndPoint(startContainer, ancestor) || startContainer;
endPoint = findEndPoint(endContainer, ancestor) || endContainer;
// Walk left leaf
walkBoundary(startContainer, startPoint, true);
// Walk the middle from start to end point
siblings = collectSiblings(
startPoint == startContainer ? startPoint : startPoint.nextSibling,
'nextSibling',
endPoint == endContainer ? endPoint.nextSibling : endPoint
);
if (siblings.length)
callback(siblings);
// Walk right leaf
walkBoundary(endContainer, endPoint);
};
/**
* Splits the specified range at it's start/end points.
*
* @param {Range/RangeObject} rng Range to split.
* @return {Object} Range position object.
*/
/* this.split = function(rng) {
var startContainer = rng.startContainer,
startOffset = rng.startOffset,
endContainer = rng.endContainer,
endOffset = rng.endOffset;
function splitText(node, offset) {
if (offset == node.nodeValue.length)
node.appendData(INVISIBLE_CHAR);
node = node.splitText(offset);
if (node.nodeValue === INVISIBLE_CHAR)
node.nodeValue = '';
return node;
};
// Handle single text node
if (startContainer == endContainer) {
if (startContainer.nodeType == 3) {
if (startOffset != 0)
startContainer = endContainer = splitText(startContainer, startOffset);
if (endOffset - startOffset != startContainer.nodeValue.length)
splitText(startContainer, endOffset - startOffset);
}
} else {
// Split startContainer text node if needed
if (startContainer.nodeType == 3 && startOffset != 0) {
startContainer = splitText(startContainer, startOffset);
startOffset = 0;
}
// Split endContainer text node if needed
if (endContainer.nodeType == 3 && endOffset != endContainer.nodeValue.length) {
endContainer = splitText(endContainer, endOffset).previousSibling;
endOffset = endContainer.nodeValue.length;
}
}
return {
startContainer : startContainer,
startOffset : startOffset,
endContainer : endContainer,
endOffset : endOffset
};
};
*/
};
/**
* Compares two ranges and checks if they are equal.
*
* @static
* @param {DOMRange} rng1 First range to compare.
* @param {DOMRange} rng2 First range to compare.
* @return {Boolean} true/false if the ranges are equal.
*/
tinymce.dom.RangeUtils.compareRanges = function(rng1, rng2) {
if (rng1 && rng2) {
// Compare native IE ranges
if (rng1.item || rng1.duplicate) {
// Both are control ranges and the selected element matches
if (rng1.item && rng2.item && rng1.item(0) === rng2.item(0))
return true;
// Both are text ranges and the range matches
if (rng1.isEqual && rng2.isEqual && rng2.isEqual(rng1))
return true;
} else {
// Compare w3c ranges
return rng1.startContainer == rng2.startContainer && rng1.startOffset == rng2.startOffset;
}
}
return false;
};
})(tinymce);