static/tinymce/plugins/noneditable/editor_plugin_src.js
function moveSelection() {
			var nonEditableStart, nonEditableEnd, isCollapsed, rng, element;

			// Checks if there is any contents to the left/right side of caret returns the noneditable element or any editable element if it finds one inside
			function hasSideContent(element, left) {
				var container, offset, walker, node, len;

				container = rng.startContainer;
				offset = rng.startOffset;

				// If endpoint is in middle of text node then expand to beginning/end of element
				if (container.nodeType == 3) {
					len = container.nodeValue.length;
					if ((offset > 0 && offset < len) || (left ? offset == len : offset == 0)) {
						return;
					}
				} else {
					// Can we resolve the node by index
					if (offset < container.childNodes.length) {
						// Browser represents caret position as the offset at the start of an element. When moving right
						// this is the element we are moving into so we consider our container to be child node at offset-1
						var pos = !left && offset > 0 ? offset-1 : offset;
						container = container.childNodes[pos];
						if (container.hasChildNodes()) {
							container = container.firstChild;
						}
					} else {
						// If not then the caret is at the last position in it's container and the caret container should be inserted after the noneditable element
						return !left ? element : null;
					}
				}

				// Walk left/right to look for contents
				walker = new TreeWalker(container, element);
				while (node = walker[left ? 'prev' : 'next']()) {
					if (node.nodeType === 3 && node.nodeValue.length > 0) {
						return;
					} else if (getContentEditable(node) === "true") {
						// Found contentEditable=true element return this one to we can move the caret inside it
						return node;
					}
				}

				return element;
			};

			// Remove any existing caret containers
			removeCaretContainer();

			// Get noneditable start/end elements
			isCollapsed = selection.isCollapsed();
			nonEditableStart = getNonEditableParent(selection.getStart());
			nonEditableEnd = getNonEditableParent(selection.getEnd());

			// Is any fo the range endpoints noneditable
			if (nonEditableStart || nonEditableEnd) {
				rng = selection.getRng(true);

				// If it's a caret selection then look left/right to see if we need to move the caret out side or expand
				if (isCollapsed) {
					nonEditableStart = nonEditableStart || nonEditableEnd;
					var start = selection.getStart();
					if (element = hasSideContent(nonEditableStart, true)) {
						// We have no contents to the left of the caret then insert a caret container before the noneditable element
						insertCaretContainerOrExpandToBlock(element, true);
					} else if (element = hasSideContent(nonEditableStart, false)) {
						// We have no contents to the right of the caret then insert a caret container after the noneditable element
						insertCaretContainerOrExpandToBlock(element, false);
					} else {
						// We are in the middle of a noneditable so expand to select it
						selection.select(nonEditableStart);
					}
				} else {
					rng = selection.getRng(true);

					// Expand selection to include start non editable element
					if (nonEditableStart) {
						rng.setStartBefore(nonEditableStart);
					}

					// Expand selection to include end non editable element
					if (nonEditableEnd) {
						rng.setEndAfter(nonEditableEnd);
					}

					selection.setRng(rng);
				}
			}
		}
function moveSelection() {
			var nonEditableStart, nonEditableEnd, isCollapsed, rng, element;

			// Checks if there is any contents to the left/right side of caret returns the noneditable element or any editable element if it finds one inside
			function hasSideContent(element, left) {
				var container, offset, walker, node, len;

				container = rng.startContainer;
				offset = rng.startOffset;

				// If endpoint is in middle of text node then expand to beginning/end of element
				if (container.nodeType == 3) {
					len = container.nodeValue.length;
					if ((offset > 0 && offset < len) || (left ? offset == len : offset == 0)) {
						return;
					}
				} else {
					// Can we resolve the node by index
					if (offset < container.childNodes.length) {
						// Browser represents caret position as the offset at the start of an element. When moving right
						// this is the element we are moving into so we consider our container to be child node at offset-1
						var pos = !left && offset > 0 ? offset-1 : offset;
						container = container.childNodes[pos];
						if (container.hasChildNodes()) {
							container = container.firstChild;
						}
					} else {
						// If not then the caret is at the last position in it's container and the caret container should be inserted after the noneditable element
						return !left ? element : null;
					}
				}

				// Walk left/right to look for contents
				walker = new TreeWalker(container, element);
				while (node = walker[left ? 'prev' : 'next']()) {
					if (node.nodeType === 3 && node.nodeValue.length > 0) {
						return;
					} else if (getContentEditable(node) === "true") {
						// Found contentEditable=true element return this one to we can move the caret inside it
						return node;
					}
				}

				return element;
			};

			// Remove any existing caret containers
			removeCaretContainer();

			// Get noneditable start/end elements
			isCollapsed = selection.isCollapsed();
			nonEditableStart = getNonEditableParent(selection.getStart());
			nonEditableEnd = getNonEditableParent(selection.getEnd());

			// Is any fo the range endpoints noneditable
			if (nonEditableStart || nonEditableEnd) {
				rng = selection.getRng(true);

				// If it's a caret selection then look left/right to see if we need to move the caret out side or expand
				if (isCollapsed) {
					nonEditableStart = nonEditableStart || nonEditableEnd;
					var start = selection.getStart();
					if (element = hasSideContent(nonEditableStart, true)) {
						// We have no contents to the left of the caret then insert a caret container before the noneditable element
						insertCaretContainerOrExpandToBlock(element, true);
					} else if (element = hasSideContent(nonEditableStart, false)) {
						// We have no contents to the right of the caret then insert a caret container after the noneditable element
						insertCaretContainerOrExpandToBlock(element, false);
					} else {
						// We are in the middle of a noneditable so expand to select it
						selection.select(nonEditableStart);
					}
				} else {
					rng = selection.getRng(true);

					// Expand selection to include start non editable element
					if (nonEditableStart) {
						rng.setStartBefore(nonEditableStart);
					}

					// Expand selection to include end non editable element
					if (nonEditableEnd) {
						rng.setEndAfter(nonEditableEnd);
					}

					selection.setRng(rng);
				}
			}
		}
Modifies the selection to include contentEditable false elements or insert caret containers