| Server IP : 213.186.33.4 / Your IP : 216.73.216.193 Web Server : Apache System : Linux webm006.cluster103.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64 User : awebpaca ( 35430) PHP Version : 8.5.0 Disable Function : _dyuweyrj4,_dyuweyrj4r,dl MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/a/w/e/awebpaca/boutiques/js/tiny_mce/classes/dom/ |
Upload File : |
/**
* TridentSelection.js
*
* Copyright 2009, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://tinymce.moxiecode.com/license
* Contributing: http://tinymce.moxiecode.com/contributing
*/
(function() {
function Selection(selection) {
var t = this, invisibleChar = '\uFEFF', range, lastIERng, dom = selection.dom, TRUE = true, FALSE = false;
// Compares two IE specific ranges to see if they are different
// this method is useful when invalidating the cached selection range
function compareRanges(rng1, rng2) {
if (rng1 && rng2) {
// 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)) {
// IE will say that the range is equal then produce an invalid argument exception
// if you perform specific operations in a keyup event. For example Ctrl+Del.
// This hack will invalidate the range cache if the exception occurs
try {
// Try accessing nextSibling will producer an invalid argument some times
range.startContainer.nextSibling;
return TRUE;
} catch (ex) {
// Ignore
}
}
}
return FALSE;
};
// Returns a W3C DOM compatible range object by using the IE Range API
function getRange() {
var ieRange = selection.getRng(), domRange = dom.createRng(), ieRange2, element, collapsed, isMerged;
// If selection is outside the current document just return an empty range
element = ieRange.item ? ieRange.item(0) : ieRange.parentElement();
if (element.ownerDocument != dom.doc)
return domRange;
// Handle control selection or text selection of a image
if (ieRange.item || !element.hasChildNodes()) {
domRange.setStart(element.parentNode, dom.nodeIndex(element));
domRange.setEnd(domRange.startContainer, domRange.startOffset + 1);
return domRange;
}
// Duplicare IE selection range and check if the range is collapsed
ieRange2 = ieRange.duplicate();
collapsed = selection.isCollapsed();
// Insert invisible start marker
ieRange.collapse();
ieRange.pasteHTML('<span id="_mce_start" style="display:none;line-height:0">' + invisibleChar + '</span>');
// Insert invisible end marker
if (!collapsed) {
ieRange2.collapse(FALSE);
ieRange2.pasteHTML('<span id="_mce_end" style="display:none;line-height:0">' + invisibleChar + '</span>');
}
// Sets the end point of the range by looking for the marker
// This method also merges the text nodes it splits so that
// the DOM doesn't get fragmented.
function setEndPoint(start) {
var container, offset, marker, sibling;
// Look for endpoint marker
marker = dom.get('_mce_' + (start ? 'start' : 'end'));
sibling = marker.previousSibling;
// Is marker after a text node
if (sibling && sibling.nodeType == 3) {
// Get container node and calc offset
container = sibling;
offset = container.nodeValue.length;
dom.remove(marker);
// Merge text nodes to reduce DOM fragmentation
sibling = container.nextSibling;
if (sibling && sibling.nodeType == 3) {
isMerged = TRUE;
container.appendData(sibling.nodeValue);
dom.remove(sibling);
}
} else {
sibling = marker.nextSibling;
// Is marker before a text node
if (sibling && sibling.nodeType == 3) {
container = sibling;
offset = 0;
} else {
// Is marker before an element
if (sibling)
offset = dom.nodeIndex(sibling) - 1;
else
offset = dom.nodeIndex(marker);
container = marker.parentNode;
}
dom.remove(marker);
}
// Set start of range
if (start)
domRange.setStart(container, offset);
// Set end of range or automatically if it's collapsed to increase performance
if (!start || collapsed)
domRange.setEnd(container, offset);
};
// Set start of range
setEndPoint(TRUE);
// Set end of range if needed
if (!collapsed)
setEndPoint(FALSE);
// Restore selection if the range contents was merged
// since the selection was then moved since the text nodes got changed
if (isMerged)
t.addRange(domRange);
return domRange;
};
this.addRange = function(rng) {
var ieRng, ieRng2, doc = selection.dom.doc, body = doc.body, startPos, endPos, sc, so, ec, eo, marker, lastIndex, skipStart, skipEnd;
this.destroy();
// Setup some shorter versions
sc = rng.startContainer;
so = rng.startOffset;
ec = rng.endContainer;
eo = rng.endOffset;
ieRng = body.createTextRange();
// If document selection move caret to first node in document
if (sc == doc || ec == doc) {
ieRng = body.createTextRange();
ieRng.collapse();
ieRng.select();
return;
}
// If child index resolve it
if (sc.nodeType == 1 && sc.hasChildNodes()) {
lastIndex = sc.childNodes.length - 1;
// Index is higher that the child count then we need to jump over the start container
if (so > lastIndex) {
skipStart = 1;
sc = sc.childNodes[lastIndex];
} else
sc = sc.childNodes[so];
// Child was text node then move offset to start of it
if (sc.nodeType == 3)
so = 0;
}
// If child index resolve it
if (ec.nodeType == 1 && ec.hasChildNodes()) {
lastIndex = ec.childNodes.length - 1;
if (eo == 0) {
skipEnd = 1;
ec = ec.childNodes[0];
} else {
ec = ec.childNodes[Math.min(lastIndex, eo - 1)];
// Child was text node then move offset to end of text node
if (ec.nodeType == 3)
eo = ec.nodeValue.length;
}
}
// Single element selection
if (sc == ec && sc.nodeType == 1) {
// Make control selection for some elements
if (/^(IMG|TABLE)$/.test(sc.nodeName) && so != eo) {
ieRng = body.createControlRange();
ieRng.addElement(sc);
} else {
ieRng = body.createTextRange();
// Padd empty elements with invisible character
if (!sc.hasChildNodes() && sc.canHaveHTML)
sc.innerHTML = invisibleChar;
// Select element contents
ieRng.moveToElementText(sc);
// If it's only containing a padding remove it so the caret remains
if (sc.innerHTML == invisibleChar) {
ieRng.collapse(TRUE);
sc.removeChild(sc.firstChild);
}
}
if (so == eo)
ieRng.collapse(eo <= rng.endContainer.childNodes.length - 1);
ieRng.select();
ieRng.scrollIntoView();
return;
}
// Create range and marker
ieRng = body.createTextRange();
marker = doc.createElement('span');
marker.innerHTML = ' ';
// Set start of range to startContainer/startOffset
if (sc.nodeType == 3) {
// Insert marker after/before startContainer
if (skipStart)
dom.insertAfter(marker, sc);
else
sc.parentNode.insertBefore(marker, sc);
// Select marker the caret to offset position
ieRng.moveToElementText(marker);
marker.parentNode.removeChild(marker);
ieRng.move('character', so);
} else {
ieRng.moveToElementText(sc);
if (skipStart)
ieRng.collapse(FALSE);
}
// If same text container then we can do a more simple move
if (sc == ec && sc.nodeType == 3) {
ieRng.moveEnd('character', eo - so);
ieRng.select();
ieRng.scrollIntoView();
return;
}
// Set end of range to endContainer/endOffset
ieRng2 = body.createTextRange();
if (ec.nodeType == 3) {
// Insert marker after/before startContainer
ec.parentNode.insertBefore(marker, ec);
// Move selection to end marker and move caret to end offset
ieRng2.moveToElementText(marker);
marker.parentNode.removeChild(marker);
ieRng2.move('character', eo);
ieRng.setEndPoint('EndToStart', ieRng2);
} else {
ieRng2.moveToElementText(ec);
ieRng2.collapse(!!skipEnd);
ieRng.setEndPoint('EndToEnd', ieRng2);
}
ieRng.select();
ieRng.scrollIntoView();
};
this.getRangeAt = function() {
// Setup new range if the cache is empty
if (!range || !compareRanges(lastIERng, selection.getRng())) {
range = getRange();
// Store away text range for next call
lastIERng = selection.getRng();
}
// Return cached range
return range;
};
this.destroy = function() {
// Destroy cached range and last IE range to avoid memory leaks
lastIERng = range = null;
};
// IE has an issue where you can't select/move the caret by clicking outside the body if the document is in standards mode
if (selection.dom.boxModel) {
(function() {
var doc = dom.doc, body = doc.body, started, startRng;
// Make HTML element unselectable since we are going to handle selection by hand
doc.documentElement.unselectable = TRUE;
// Return range from point or null if it failed
function rngFromPoint(x, y) {
var rng = body.createTextRange();
try {
rng.moveToPoint(x, y);
} catch (ex) {
// IE sometimes throws and exception, so lets just ignore it
rng = null;
}
return rng;
};
// Fires while the selection is changing
function selectionChange(e) {
var pointRng;
// Check if the button is down or not
if (e.button) {
// Create range from mouse position
pointRng = rngFromPoint(e.x, e.y);
if (pointRng) {
// Check if pointRange is before/after selection then change the endPoint
if (pointRng.compareEndPoints('StartToStart', startRng) > 0)
pointRng.setEndPoint('StartToStart', startRng);
else
pointRng.setEndPoint('EndToEnd', startRng);
pointRng.select();
}
} else
endSelection();
}
// Removes listeners
function endSelection() {
dom.unbind(doc, 'mouseup', endSelection);
dom.unbind(doc, 'mousemove', selectionChange);
started = 0;
};
// Detect when user selects outside BODY
dom.bind(doc, 'mousedown', function(e) {
if (e.target.nodeName === 'HTML') {
if (started)
endSelection();
started = 1;
// Setup start position
startRng = rngFromPoint(e.x, e.y);
if (startRng) {
// Listen for selection change events
dom.bind(doc, 'mouseup', endSelection);
dom.bind(doc, 'mousemove', selectionChange);
startRng.select();
}
}
});
})();
}
};
// Expose the selection object
tinymce.dom.TridentSelection = Selection;
})();