v1.0
只读模式 group, 分享 评论更多问题 博客标签总是存在一个
This commit is contained in:
153
public/tinymce/classes/NodeChange.js
Executable file
153
public/tinymce/classes/NodeChange.js
Executable file
@ -0,0 +1,153 @@
|
||||
/**
|
||||
* NodeChange.js
|
||||
*
|
||||
* Copyright, Moxiecode Systems AB
|
||||
* Released under LGPL License.
|
||||
*
|
||||
* License: http://www.tinymce.com/license
|
||||
* Contributing: http://www.tinymce.com/contributing
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class handles the nodechange event dispatching both manual and though selection change events.
|
||||
*
|
||||
* @class tinymce.NodeChange
|
||||
* @private
|
||||
*/
|
||||
define("tinymce/NodeChange", [
|
||||
"tinymce/dom/RangeUtils",
|
||||
"tinymce/Env"
|
||||
], function(RangeUtils, Env) {
|
||||
return function(editor) {
|
||||
var lastRng, lastPath = [];
|
||||
|
||||
/**
|
||||
* Returns true/false if the current element path has been changed or not.
|
||||
*
|
||||
* @private
|
||||
* @return {Boolean} True if the element path is the same false if it's not.
|
||||
*/
|
||||
function isSameElementPath(startElm) {
|
||||
var i, currentPath;
|
||||
|
||||
currentPath = editor.$(startElm).parentsUntil(editor.getBody()).add(startElm);
|
||||
if (currentPath.length === lastPath.length) {
|
||||
for (i = currentPath.length; i >= 0; i--) {
|
||||
if (currentPath[i] !== lastPath[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i === -1) {
|
||||
lastPath = currentPath;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
lastPath = currentPath;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Gecko doesn't support the "selectionchange" event
|
||||
if (!('onselectionchange' in editor.getDoc())) {
|
||||
editor.on('NodeChange Click MouseUp KeyUp Focus', function(e) {
|
||||
var nativeRng, fakeRng;
|
||||
|
||||
// Since DOM Ranges mutate on modification
|
||||
// of the DOM we need to clone it's contents
|
||||
nativeRng = editor.selection.getRng();
|
||||
fakeRng = {
|
||||
startContainer: nativeRng.startContainer,
|
||||
startOffset: nativeRng.startOffset,
|
||||
endContainer: nativeRng.endContainer,
|
||||
endOffset: nativeRng.endOffset
|
||||
};
|
||||
|
||||
// Always treat nodechange as a selectionchange since applying
|
||||
// formatting to the current range wouldn't update the range but it's parent
|
||||
if (e.type == 'nodechange' || !RangeUtils.compareRanges(fakeRng, lastRng)) {
|
||||
editor.fire('SelectionChange');
|
||||
}
|
||||
|
||||
lastRng = fakeRng;
|
||||
});
|
||||
}
|
||||
|
||||
// IE has a bug where it fires a selectionchange on right click that has a range at the start of the body
|
||||
// When the contextmenu event fires the selection is located at the right location
|
||||
editor.on('contextmenu', function() {
|
||||
editor.fire('SelectionChange');
|
||||
});
|
||||
|
||||
// Selection change is delayed ~200ms on IE when you click inside the current range
|
||||
editor.on('SelectionChange', function() {
|
||||
var startElm = editor.selection.getStart(true);
|
||||
|
||||
// IE 8 will fire a selectionchange event with an incorrect selection
|
||||
// when focusing out of table cells. Click inside cell -> toolbar = Invalid SelectionChange event
|
||||
if (!Env.range && editor.selection.isCollapsed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isSameElementPath(startElm) && editor.dom.isChildOf(startElm, editor.getBody())) {
|
||||
editor.nodeChanged({selectionChange: true});
|
||||
}
|
||||
});
|
||||
|
||||
// Fire an extra nodeChange on mouseup for compatibility reasons
|
||||
editor.on('MouseUp', function(e) {
|
||||
if (!e.isDefaultPrevented()) {
|
||||
// Delay nodeChanged call for WebKit edge case issue where the range
|
||||
// isn't updated until after you click outside a selected image
|
||||
if (editor.selection.getNode().nodeName == 'IMG') {
|
||||
setTimeout(function() {
|
||||
editor.nodeChanged();
|
||||
}, 0);
|
||||
} else {
|
||||
editor.nodeChanged();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Distpaches out a onNodeChange event to all observers. This method should be called when you
|
||||
* need to update the UI states or element path etc.
|
||||
*
|
||||
* @method nodeChanged
|
||||
* @param {Object} args Optional args to pass to NodeChange event handlers.
|
||||
*/
|
||||
this.nodeChanged = function(args) {
|
||||
var selection = editor.selection, node, parents, root;
|
||||
|
||||
// Fix for bug #1896577 it seems that this can not be fired while the editor is loading
|
||||
if (editor.initialized && selection && !editor.settings.disable_nodechange && !editor.settings.readonly) {
|
||||
// Get start node
|
||||
root = editor.getBody();
|
||||
node = selection.getStart() || root;
|
||||
node = node.ownerDocument != editor.getDoc() ? editor.getBody() : node;
|
||||
|
||||
// Edge case for <p>|<img></p>
|
||||
if (node.nodeName == 'IMG' && selection.isCollapsed()) {
|
||||
node = node.parentNode;
|
||||
}
|
||||
|
||||
// Get parents and add them to object
|
||||
parents = [];
|
||||
editor.dom.getParent(node, function(node) {
|
||||
if (node === root) {
|
||||
return true;
|
||||
}
|
||||
|
||||
parents.push(node);
|
||||
});
|
||||
|
||||
args = args || {};
|
||||
args.element = node;
|
||||
args.parents = parents;
|
||||
|
||||
editor.fire('NodeChange', args);
|
||||
}
|
||||
};
|
||||
};
|
||||
});
|
Reference in New Issue
Block a user