src/myams/resources/js/ext/tinymce/dev/classes/NodeChange.js
changeset 0 f05d7aea098a
equal deleted inserted replaced
-1:000000000000 0:f05d7aea098a
       
     1 /**
       
     2  * NodeChange.js
       
     3  *
       
     4  * Copyright, Moxiecode Systems AB
       
     5  * Released under LGPL License.
       
     6  *
       
     7  * License: http://www.tinymce.com/license
       
     8  * Contributing: http://www.tinymce.com/contributing
       
     9  */
       
    10 
       
    11 /**
       
    12  * This class handles the nodechange event dispatching both manual and though selection change events.
       
    13  *
       
    14  * @class tinymce.NodeChange
       
    15  * @private
       
    16  */
       
    17 define("tinymce/NodeChange", [
       
    18 	"tinymce/dom/RangeUtils",
       
    19 	"tinymce/Env"
       
    20 ], function(RangeUtils, Env) {
       
    21 	return function(editor) {
       
    22 		var lastRng, lastPath = [];
       
    23 
       
    24 		/**
       
    25 		 * Returns true/false if the current element path has been changed or not.
       
    26 		 *
       
    27 		 * @private
       
    28 		 * @return {Boolean} True if the element path is the same false if it's not.
       
    29 		 */
       
    30 		function isSameElementPath(startElm) {
       
    31 			var i, currentPath;
       
    32 
       
    33 			currentPath = editor.$(startElm).parentsUntil(editor.getBody()).add(startElm);
       
    34 			if (currentPath.length === lastPath.length) {
       
    35 				for (i = currentPath.length; i >= 0; i--) {
       
    36 					if (currentPath[i] !== lastPath[i]) {
       
    37 						break;
       
    38 					}
       
    39 				}
       
    40 
       
    41 				if (i === -1) {
       
    42 					lastPath = currentPath;
       
    43 					return true;
       
    44 				}
       
    45 			}
       
    46 
       
    47 			lastPath = currentPath;
       
    48 
       
    49 			return false;
       
    50 		}
       
    51 
       
    52 		// Gecko doesn't support the "selectionchange" event
       
    53 		if (!('onselectionchange' in editor.getDoc())) {
       
    54 			editor.on('NodeChange Click MouseUp KeyUp Focus', function(e) {
       
    55 				var nativeRng, fakeRng;
       
    56 
       
    57 				// Since DOM Ranges mutate on modification
       
    58 				// of the DOM we need to clone it's contents
       
    59 				nativeRng = editor.selection.getRng();
       
    60 				fakeRng = {
       
    61 					startContainer: nativeRng.startContainer,
       
    62 					startOffset: nativeRng.startOffset,
       
    63 					endContainer: nativeRng.endContainer,
       
    64 					endOffset: nativeRng.endOffset
       
    65 				};
       
    66 
       
    67 				// Always treat nodechange as a selectionchange since applying
       
    68 				// formatting to the current range wouldn't update the range but it's parent
       
    69 				if (e.type == 'nodechange' || !RangeUtils.compareRanges(fakeRng, lastRng)) {
       
    70 					editor.fire('SelectionChange');
       
    71 				}
       
    72 
       
    73 				lastRng = fakeRng;
       
    74 			});
       
    75 		}
       
    76 
       
    77 		// IE has a bug where it fires a selectionchange on right click that has a range at the start of the body
       
    78 		// When the contextmenu event fires the selection is located at the right location
       
    79 		editor.on('contextmenu', function() {
       
    80 			editor.fire('SelectionChange');
       
    81 		});
       
    82 
       
    83 		// Selection change is delayed ~200ms on IE when you click inside the current range
       
    84 		editor.on('SelectionChange', function() {
       
    85 			var startElm = editor.selection.getStart(true);
       
    86 
       
    87 			// IE 8 will fire a selectionchange event with an incorrect selection
       
    88 			// when focusing out of table cells. Click inside cell -> toolbar = Invalid SelectionChange event
       
    89 			if (!Env.range && editor.selection.isCollapsed()) {
       
    90 				return;
       
    91 			}
       
    92 
       
    93 			if (!isSameElementPath(startElm) && editor.dom.isChildOf(startElm, editor.getBody())) {
       
    94 				editor.nodeChanged({selectionChange: true});
       
    95 			}
       
    96 		});
       
    97 
       
    98 		// Fire an extra nodeChange on mouseup for compatibility reasons
       
    99 		editor.on('MouseUp', function(e) {
       
   100 			if (!e.isDefaultPrevented()) {
       
   101 				// Delay nodeChanged call for WebKit edge case issue where the range
       
   102 				// isn't updated until after you click outside a selected image
       
   103 				if (editor.selection.getNode().nodeName == 'IMG') {
       
   104 					setTimeout(function() {
       
   105 						editor.nodeChanged();
       
   106 					}, 0);
       
   107 				} else {
       
   108 					editor.nodeChanged();
       
   109 				}
       
   110 			}
       
   111 		});
       
   112 
       
   113 		/**
       
   114 		 * Distpaches out a onNodeChange event to all observers. This method should be called when you
       
   115 		 * need to update the UI states or element path etc.
       
   116 		 *
       
   117 		 * @method nodeChanged
       
   118 		 * @param {Object} args Optional args to pass to NodeChange event handlers.
       
   119 		 */
       
   120 		this.nodeChanged = function(args) {
       
   121 			var selection = editor.selection, node, parents, root;
       
   122 
       
   123 			// Fix for bug #1896577 it seems that this can not be fired while the editor is loading
       
   124 			if (editor.initialized && selection && !editor.settings.disable_nodechange && !editor.settings.readonly) {
       
   125 				// Get start node
       
   126 				root = editor.getBody();
       
   127 				node = selection.getStart() || root;
       
   128 				node = node.ownerDocument != editor.getDoc() ? editor.getBody() : node;
       
   129 
       
   130 				// Edge case for <p>|<img></p>
       
   131 				if (node.nodeName == 'IMG' && selection.isCollapsed()) {
       
   132 					node = node.parentNode;
       
   133 				}
       
   134 
       
   135 				// Get parents and add them to object
       
   136 				parents = [];
       
   137 				editor.dom.getParent(node, function(node) {
       
   138 					if (node === root) {
       
   139 						return true;
       
   140 					}
       
   141 
       
   142 					parents.push(node);
       
   143 				});
       
   144 
       
   145 				args = args || {};
       
   146 				args.element = node;
       
   147 				args.parents = parents;
       
   148 
       
   149 				editor.fire('NodeChange', args);
       
   150 			}
       
   151 		};
       
   152 	};
       
   153 });