只读模式
group, 分享
评论更多问题
博客标签总是存在一个
This commit is contained in:
lealife
2015-06-15 18:01:48 +08:00
parent 7e458bb433
commit 6987a38820
1453 changed files with 114561 additions and 91536 deletions

193
public/tinymce/classes/FocusManager.js Normal file → Executable file
View File

@ -21,6 +21,8 @@ define("tinymce/FocusManager", [
"tinymce/dom/DOMUtils",
"tinymce/Env"
], function(DOMUtils, Env) {
var selectionChangeHandler, documentFocusInHandler, documentMouseUpHandler, DOM = DOMUtils.DOM;
/**
* Constructs a new focus manager instance.
*
@ -40,8 +42,13 @@ define("tinymce/FocusManager", [
// We can't store a real range on IE 11 since it gets mutated so we need to use a bookmark object
// TODO: Move this to a separate range utils class since it's it's logic is present in Selection as well.
function createBookmark(rng) {
function createBookmark(dom, rng) {
if (rng && rng.startContainer) {
// Verify that the range is within the root of the editor
if (!dom.isChildOf(rng.startContainer, dom.getRoot()) || !dom.isChildOf(rng.endContainer, dom.getRoot())) {
return;
}
return {
startContainer: rng.startContainer,
startOffset: rng.startOffset,
@ -67,76 +74,73 @@ define("tinymce/FocusManager", [
return rng;
}
function registerEvents(e) {
var editor = e.editor, lastRng, selectionChangeHandler;
function isUIElement(elm) {
return !!DOM.getParent(elm, FocusManager.isEditorUIElement);
}
function isUIElement(elm) {
return !!DOMUtils.DOM.getParent(elm, FocusManager.isEditorUIElement);
}
function registerEvents(e) {
var editor = e.editor;
editor.on('init', function() {
// On IE take selection snapshot onbeforedeactivate
if ("onbeforedeactivate" in document && Env.ie < 11) {
editor.dom.bind(editor.getBody(), 'beforedeactivate', function() {
var ieSelection = editor.getDoc().selection;
try {
lastRng = ieSelection && ieSelection.createRange ? ieSelection.createRange() : editor.selection.getRng();
} catch (ex) {
// IE throws "Unexcpected call to method or property access" some times so lets ignore it
}
});
} else if (editor.inline || Env.ie > 10) {
// On other browsers take snapshot on nodechange in inline mode since they have Ghost selections for iframes
editor.on('nodechange keyup', function() {
var isInBody, node = document.activeElement;
// IE 11 reports active element as iframe not body of iframe
if (node && node.id == editor.id + '_ifr') {
node = editor.getBody();
}
// Check if selection is within editor body
while (node) {
if (node == editor.getBody()) {
isInBody = true;
break;
// Gecko/WebKit has ghost selections in iframes and IE only has one selection per browser tab
if (editor.inline || Env.ie) {
// Use the onbeforedeactivate event when available since it works better see #7023
if ("onbeforedeactivate" in document && Env.ie < 9) {
editor.dom.bind(editor.getBody(), 'beforedeactivate', function(e) {
if (e.target != editor.getBody()) {
return;
}
node = node.parentNode;
}
try {
editor.lastRng = editor.selection.getRng();
} catch (ex) {
// IE throws "Unexcpected call to method or property access" some times so lets ignore it
}
});
} else {
// On other browsers take snapshot on nodechange in inline mode since they have Ghost selections for iframes
editor.on('nodechange mouseup keyup', function(e) {
var node = getActiveElement();
if (isInBody) {
lastRng = editor.selection.getRng();
}
});
// Only act on manual nodechanges
if (e.type == 'nodechange' && e.selectionChange) {
return;
}
// IE 11 reports active element as iframe not body of iframe
if (node && node.id == editor.id + '_ifr') {
node = editor.getBody();
}
if (editor.dom.isChildOf(node, editor.getBody())) {
editor.lastRng = editor.selection.getRng();
}
});
}
// Handles the issue with WebKit not retaining selection within inline document
// If the user releases the mouse out side the body while selecting a nodeChange won't
// fire and there for the selection snapshot won't be stored
// TODO: Optimize this since we only need to bind these on the active editor
if (Env.webkit) {
// If the user releases the mouse out side the body since a mouse up event wont occur on the body
if (Env.webkit && !selectionChangeHandler) {
selectionChangeHandler = function() {
var rng = editor.selection.getRng();
var activeEditor = editorManager.activeEditor;
// Store when it's non collapsed
if (!rng.collapsed) {
lastRng = rng;
if (activeEditor && activeEditor.selection) {
var rng = activeEditor.selection.getRng();
// Store when it's non collapsed
if (rng && !rng.collapsed) {
editor.lastRng = rng;
}
}
};
// Bind selection handler
DOMUtils.DOM.bind(document, 'selectionchange', selectionChangeHandler);
editor.on('remove', function() {
DOMUtils.DOM.unbind(document, 'selectionchange', selectionChangeHandler);
});
DOM.bind(document, 'selectionchange', selectionChangeHandler);
}
}
});
editor.on('setcontent', function() {
lastRng = null;
editor.lastRng = null;
});
// Remove last selection bookmark on mousedown see #6305
@ -157,37 +161,91 @@ define("tinymce/FocusManager", [
focusedEditor.fire('blur', {focusedEditor: editor});
}
editorManager.activeEditor = editor;
editor.fire('focus', {blurredEditor: focusedEditor});
editor.focus(false);
editorManager.setActive(editor);
editorManager.focusedEditor = editor;
editor.fire('focus', {blurredEditor: focusedEditor});
editor.focus(true);
}
lastRng = null;
editor.lastRng = null;
});
editor.on('focusout', function() {
editor.selection.lastFocusBookmark = createBookmark(lastRng);
window.setTimeout(function() {
var focusedEditor = editorManager.focusedEditor;
// Focus from editorA into editorB then don't restore selection
if (focusedEditor != editor) {
editor.selection.lastFocusBookmark = null;
}
// Still the same editor the the blur was outside any editor UI
if (!isUIElement(getActiveElement()) && focusedEditor == editor) {
editor.fire('blur', {focusedEditor: null});
editorManager.focusedEditor = null;
editor.selection.lastFocusBookmark = null;
// Make sure selection is valid could be invalid if the editor is blured and removed before the timeout occurs
if (editor.selection) {
editor.selection.lastFocusBookmark = null;
}
}
}, 0);
});
// Check if focus is moved to an element outside the active editor by checking if the target node
// isn't within the body of the activeEditor nor a UI element such as a dialog child control
if (!documentFocusInHandler) {
documentFocusInHandler = function(e) {
var activeEditor = editorManager.activeEditor;
if (activeEditor && e.target.ownerDocument == document) {
// Check to make sure we have a valid selection don't update the bookmark if it's
// a focusin to the body of the editor see #7025
if (activeEditor.selection && e.target != activeEditor.getBody()) {
activeEditor.selection.lastFocusBookmark = createBookmark(activeEditor.dom, activeEditor.lastRng);
}
// Fire a blur event if the element isn't a UI element
if (e.target != document.body && !isUIElement(e.target) && editorManager.focusedEditor == activeEditor) {
activeEditor.fire('blur', {focusedEditor: null});
editorManager.focusedEditor = null;
}
}
};
DOM.bind(document, 'focusin', documentFocusInHandler);
}
// Handle edge case when user starts the selection inside the editor and releases
// the mouse outside the editor producing a new selection. This weird workaround is needed since
// Gecko doesn't have the "selectionchange" event we need to do this. Fixes: #6843
if (editor.inline && !documentMouseUpHandler) {
documentMouseUpHandler = function(e) {
var activeEditor = editorManager.activeEditor;
if (activeEditor.inline && !activeEditor.dom.isChildOf(e.target, activeEditor.getBody())) {
var rng = activeEditor.selection.getRng();
if (!rng.collapsed) {
activeEditor.lastRng = rng;
}
}
};
DOM.bind(document, 'mouseup', documentMouseUpHandler);
}
}
function unregisterDocumentEvents(e) {
if (editorManager.focusedEditor == e.editor) {
editorManager.focusedEditor = null;
}
if (!editorManager.activeEditor) {
DOM.unbind(document, 'selectionchange', selectionChangeHandler);
DOM.unbind(document, 'focusin', documentFocusInHandler);
DOM.unbind(document, 'mouseup', documentMouseUpHandler);
selectionChangeHandler = documentFocusInHandler = documentMouseUpHandler = null;
}
}
editorManager.on('AddEditor', registerEvents);
editorManager.on('RemoveEditor', unregisterDocumentEvents);
}
/**
@ -198,8 +256,9 @@ define("tinymce/FocusManager", [
* @return {Boolean} True/false state if the element is part of the UI or not.
*/
FocusManager.isEditorUIElement = function(elm) {
return elm.className.indexOf('mce-') !== -1;
// Needs to be converted to string since svg can have focus: #6776
return elm.className.toString().indexOf('mce-') !== -1;
};
return FocusManager;
});
});