tinymce-editor/copy_this/modules/hdi/hdi-tinymce/tinymce/classes/FocusManager.js

154 lines
4.6 KiB
JavaScript

/**
* FocusManager.js
*
* Copyright, Moxiecode Systems AB
* Released under LGPL License.
*
* License: http://www.tinymce.com/license
* Contributing: http://www.tinymce.com/contributing
*/
/**
* This class manages the focus/blur state of the editor. This class is needed since some
* browsers fire false focus/blur states when the selection is moved to a UI dialog or similar.
*
* This class will fire two events focus and blur on the editor instances that got affected.
* It will also handle the restore of selection when the focus is lost and returned.
*
* @class tinymce.FocusManager
*/
define("tinymce/FocusManager", [
"tinymce/dom/DOMUtils",
"tinymce/Env"
], function(DOMUtils, Env) {
/**
* Constructs a new focus manager instance.
*
* @constructor FocusManager
* @param {tinymce.EditorManager} editorManager Editor manager instance to handle focus for.
*/
function FocusManager(editorManager) {
function getActiveElement() {
try {
return document.activeElement;
} catch (ex) {
// IE sometimes fails to get the activeElement when resizing table
// TODO: Investigate this
return document.body;
}
}
function registerEvents(e) {
var editor = e.editor, lastRng, selectionChangeHandler;
function isUIElement(elm) {
return !!DOMUtils.DOM.getParent(elm, FocusManager.isEditorUIElement);
}
editor.on('init', function() {
// On IE take selection snapshot onbeforedeactivate
if ("onbeforedeactivate" in document) {
editor.dom.bind(editor.getBody(), 'beforedeactivate', function() {
var ieSelection = editor.getDoc().selection;
lastRng = ieSelection && ieSelection.createRange ? ieSelection.createRange() : editor.selection.getRng();
});
} else if (editor.inline) {
// On other browsers take snapshot on nodechange in inline mode since they have Ghost selections for iframes
editor.on('nodechange', function() {
var isInBody, node = document.activeElement;
// Check if selection is within editor body
while (node) {
if (node == editor.getBody()) {
isInBody = true;
break;
}
node = node.parentNode;
}
if (isInBody) {
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) {
selectionChangeHandler = function() {
var rng = editor.selection.getRng();
// Store when it's non collapsed
if (!rng.collapsed) {
lastRng = rng;
}
};
// Bind selection handler
DOMUtils.DOM.bind(document, 'selectionchange', selectionChangeHandler);
editor.on('remove', function() {
DOMUtils.DOM.unbind(document, 'selectionchange', selectionChangeHandler);
});
}
}
});
editor.on('focusin', function() {
var focusedEditor = editorManager.focusedEditor;
if (editor.selection.restoreRng) {
editor.selection.setRng(editor.selection.restoreRng);
editor.selection.restoreRng = null;
}
if (focusedEditor != editor) {
if (focusedEditor) {
focusedEditor.fire('blur', {focusedEditor: editor});
}
editor.fire('focus', {blurredEditor: focusedEditor});
editor.focus(false);
editorManager.focusedEditor = editor;
}
});
editor.on('focusout', function() {
editor.selection.restoreRng = lastRng;
window.setTimeout(function() {
var focusedEditor = editorManager.focusedEditor;
// Focus from editorA into editorB then don't restore selection
if (focusedEditor != editor) {
editor.selection.restoreRng = null;
}
// Still the same editor the the blur was outside any editor
if (!isUIElement(getActiveElement()) && focusedEditor == editor) {
editor.fire('blur', {focusedEditor: null});
editorManager.focusedEditor = null;
editor.selection.restoreRng = null;
}
}, 0);
});
}
editorManager.on('AddEditor', registerEvents);
}
/**
* Returns true if the specified element is part of the UI for example an button or text input.
*
* @method isEditorUIElement
* @param {Element} elm Element to check if it's part of the UI or not.
* @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;
};
return FocusManager;
});