From 23aec4144f9d4352ba6d10367288f51d57ba990f Mon Sep 17 00:00:00 2001 From: Armen Kesablyan Date: Sat, 23 Jun 2012 13:44:49 -0700 Subject: Text Tool Fix - Can Not Switch Document when Text Tool Initialized Signed-off-by: Armen Kesablyan --- .../labs/rich-text-editor.reel/rich-text-editor.js | 1716 -------------------- 1 file changed, 1716 deletions(-) delete mode 100644 node_modules/labs/rich-text-editor.reel/rich-text-editor.js (limited to 'node_modules/labs/rich-text-editor.reel/rich-text-editor.js') diff --git a/node_modules/labs/rich-text-editor.reel/rich-text-editor.js b/node_modules/labs/rich-text-editor.reel/rich-text-editor.js deleted file mode 100644 index b88d5868..00000000 --- a/node_modules/labs/rich-text-editor.reel/rich-text-editor.js +++ /dev/null @@ -1,1716 +0,0 @@ -/* - This file contains proprietary software owned by Motorola Mobility, Inc.
- No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
- (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. -
*/ -/** - @module "montage/ui/rich-text-editor.reel" - @requires montage/core/core -*/ -var Montage = require("montage/core/core").Montage, - Component = require("montage/ui/component").Component, - MutableEvent = require("montage/core/event/mutable-event").MutableEvent, - Resizer = require("node_modules/labs/rich-text-editor.reel/rich-text-resizer").Resizer, - Sanitizer = require("node_modules/labs/rich-text-editor.reel/rich-text-sanitizer").Sanitizer; - Point = require("montage/core/geometry/point").Point; - - -/** - @class module:"montage/ui/rich-text-editor.reel".RichTextEditor - @extends module:montage/ui/component.Component -*/ -exports.RichTextEditor = Montage.create(Component,/** @lends module:"montage/ui/rich-text-editor.reel".RichTextEditor# */ { - - /** - Description TODO - @private - */ - _hasSelectionChangeEvent: { - enumerable: false, - value: null // Need to be preset to null, will be set to true or false later on - }, - - /** - Description TODO - @private - */ - _uniqueId: { - enumerable: false, - value: Math.floor(Math.random() * 1000) + "-" + Math.floor(Math.random() * 1000) - }, - - /** - Description TODO - @private - */ - _needsSelectionReset: { - enumerable: false, - value: false - }, - - /** - Description TODO - @private - */ - _selectionChangeTimer: { - enumerable: false, - value: null - }, - - /** - Description TODO - @private - */ - _activeLink: { - enumerable: false, - value: null - }, - - /** - Description TODO - @private - */ - _needsActiveLinkOn: { - enumerable: false, - value: false - }, - - /** - Description TODO - @private - */ - _hasFocus: { - enumerable: false, - value: false - }, - - /** - Description TODO - @type {Function} - */ - hasFocus: { - enumerable: true, - get: function() { - return this._hasFocus; - } - }, - - /** - Description TODO - @private - */ - _dirty: { - enumerable: false, - value: false - }, - - /** - Description TODO - @private - */ - _value: { - enumerable: false, - value: "" - }, - - /** - Description TODO - @type {Function} - */ - value: { - enumerable: true, - serializable: true, - get: function() { - var contentNode = this.element.firstChild, - content; - - if (this._dirtyValue) { - if (this._resizer) { - contentNode = this._resizer.cleanup(contentNode); - } - - contentNode = this._cleanupActiveLink(contentNode); - - content = contentNode ? contentNode.innerHTML : ""; - if (content == "
") { - // when the contentEditable div is emptied, Chrome add a
, let's filter it out - content = ""; - } - if (this._sanitizer) { - content = this._sanitizer.didGetValue(content, this._uniqueId); - } - - this._value = content; - this._dirtyValue = false; - } - return this._value; - }, - set: function(value) { - if (this._value !== value || this._dirtyValue) { - if (this._resizer) { - this._needsHideResizer = true; - } - if (this._sanitizer) { - value = this._sanitizer.willSetValue(value, this._uniqueId); - } - this._value = value; - this._dirtyValue = false; - this._dirtyTextValue = true; - this._needsSelectionReset = true; - this._needsResetContent = true; - this.needsDraw = true; - } - } - }, - - /** - Description TODO - @private - */ - _textValue: { - enumerable: false, - value: "" - }, - - /** - Description TODO - @type {Function} - */ - textValue: { - enumerable: true, - get: function() { - var contentNode = this.element.firstChild, - childNodes; - - if (this._dirtyTextValue) { - if (contentNode) { - if (this._resizer) { - contentNode = this._resizer.cleanup(contentNode); - } - contentNode = this._cleanupActiveLink(contentNode); - } - - this._textValue = contentNode ? this._innerText(contentNode) : ""; - this._dirtyTextValue = false; - } - return this._textValue; - }, - set: function (value) { - if (this._textValue !== value || this._dirtyTextValue) { - if (this._resizer) { - this._needsHideResizer = true; - } - - this._textValue = value; - this._dirtyTextValue = false; - this._dirtyValue = true; - this._needsSelectionReset = true; - this._needsResetContent = true; - this.needsDraw = true; - } - } - }, - - /** - Description TODO - @type {} - */ - delegate: { - enumerable: true, - value: null - }, - - /** - Description TODO - @private - */ - _sanitizer: { - enumerable: false, - value: Sanitizer.create() - }, - - /** - Description TODO - @type {Function} - */ - sanitizer: { - enumerable: false, - get: function() { - return this._sanitizer; - }, - set: function(value) { - this._sanitizer = value; - } - }, - - /** - Description TODO - @private - */ - _resizer: { - enumerable: false, - value: Resizer.create() - }, - - /** - Description TODO - @type {Function} - */ - resizer: { - enumerable: false, - get: function() { - return this._resizer; - }, - set: function(value) { - // force hide the current resizer - if (this._resizer){ - this._resizer.hide(true); - delete this._needsHideResizer; - } - this._resizer = value; - this._resizer.initialize(this); - } - }, - - /** - Description TODO - @private - */ - _statesDirty: { - enumerable: false, - value: false - }, - - /** - Description TODO - @private - */ - _states: { - enumerable: false, - value: null - }, - - /** - Description TODO - @type {Function} - */ - states: { - enumerable: true, - get: function() { - if (this._statesDirty || !this._states) { - this.updateStates(); - } - return this._states; - } - }, - - /** - Description TODO - @type {Function} - */ - updateStates: { - enumerable: true, - value: function() { - var actions = this._actions, - key, - action, - states, - state, - hasFocus = this._hasFocus; - - if (this._states == null || this._statesDirty) { - this._states = this._states || {}; - - if (hasFocus) { - this._statesDirty = false; - states = this._states; - for (key in actions) { - action = actions[key]; - state = "false"; - if (action.enabled && action.status) { - state = document.queryCommandValue(key); - if (typeof state == "boolean") { - state = state ? "true" : "false"; - } - - // Clean up font name - if (key == "fontname") { - state = state.replace(/'/g, ""); - } - } - - if (states[key] !== state) { - states[key] = state; - } - } - } - } - - return this._states; - } - }, - - /** - Description TODO - @private - */ - _allowDrop: { - enumerable: false, - value: true - }, - - /** - Description TODO - @type {Function} - */ - allowDrop: { - enumerable: true, - serializable: true, - get: function() { - return this._allowDrop; - }, - set: function(value) { - this._allowDrop = value; - } - }, - - /** - Description TODO - @private - */ - _actions: { - enumerable: false, - value: { - bold: {enabled: true, needsValue:false, status: true}, - justifyleft: {enabled: true, needsValue:false, status: true}, - justifycenter: {enabled: true, needsValue:false, status: true}, - justifyright: {enabled: true, needsValue:false, status: true}, - justifyfull: {enabled: true, needsValue:false, status: true}, - italic: {enabled: true, needsValue:false, status: true}, - underline: {enabled: true, needsValue:false, status: true}, - strikethrough: {enabled: true, needsValue:false, status: true}, - indent: {enabled: true, needsValue:false, status: false}, - outdent: {enabled: true, needsValue:false, status: false}, - insertorderedlist: {enabled: true, needsValue:false, status: true}, - insertunorderedlist: {enabled: true, needsValue:false, status: true}, - fontname: {enabled: true, needsValue:true, status: true}, - fontsize: {enabled: true, needsValue:true, status: true}, - hilitecolor: {enabled: true, needsValue:true, status: true}, - forecolor: {enabled: true, needsValue:true, status: true} - } - }, - - /** - Description TODO - @type {Function} - */ - actions: { - enumerable: false, - get: function() { - var actions = this._actions, - action, - actionsArray = []; - - for (action in actions) { - actionsArray.push(action); - } - - return actionsArray; - } - }, - - /** - Description TODO - @type {Function} - */ - enabledActions: { - enumerable: true, - serializable: true, - get: function() { - var actions = this._actions, - action, - actionsArray = []; - - for (action in actions) { - if (actions[action].enabled) { - actionsArray.push(action); - } - } - - return actionsArray; - }, - set: function(enabledActions) { - var actions = this._actions, - nbrEnabledActions = enabledActions.length, - action, - i; - - for (action in actions) { - actions[action].enabled = false; - } - - for (i = 0; i < nbrEnabledActions; i ++) { - action = enabledActions[i]; - if (actions[action] !== undefined) { - actions[action].enabled = true; - } - } - } - }, - - /** - Description TODO - @private - */ - _needsFocus: { - value: false - }, - - /** - Description TODO - @type {Function} - */ - focus: { - value: function() { - this._needsFocus = true; - this.needsDraw = true; - } - }, - - // Component Callbacks - /** - Description TODO - @function - */ - prepareForDraw: { - enumerable: false, - value: function() { - var el = this.element, - div; - - if (this._resizer) { - this._resizer.initialize(this); - } - el.classList.add('montage-editor-frame'); - - el.addEventListener("focus", this); - el.addEventListener("dragstart", this, false); - el.addEventListener("dragend", this, false); - el.addEventListener("dragover", this, false); - el.addEventListener("drop", this, false); - - this._needsResetContent = true; - } - }, - - /** - Description TODO - @function - */ - draw: { - enumerable: false, - value: function() { - var thisRef = this, - editorElement = this.element, - element, - range, - offset; - - if (this._needsResetContent === true) { - // Reset the editor content in order to reset the browser undo stack - editorElement.innerHTML = '
'; - - // Set the contentEditable value - if (this._value && !this._dirtyValue) { - editorElement.firstChild.innerHTML = this._value; - // Since this property affects the textValue, we need to fire a change event for it as well - this.dispatchEvent(MutableEvent.changeEventForKeyAndValue("textValue" , this.textValue)); - } else if (this._textValue && !this._dirtyTextValue) { - editorElement.firstChild.innerText = this._textValue; - // Since this property affects the value, we need to fire a change event for it as well - this.dispatchEvent(MutableEvent.changeEventForKeyAndValue("value" , this.value)); - } else { - editorElement.firstChild.innerHTML = ""; - } - - this._adjustPadding(); - this._markDirty(); - delete this._needsResetContent; - } - - if (this._resizer) { - // Need to hide the resizer? - if (this._needsHideResizer) { - this._resizer.hide(); - delete this._needsHideResizer; - } - - // Need to show the resizer? - if (this._needsShowResizerOn) { - element = this._needsShowResizerOn; - this._resizer.show(element); - - // Select the element and its resizer - this._selectingResizer = true; - offset = this._nodeOffset(element); - range = document.createRange(); - range.setStart(element.parentNode, offset); - range.setEnd(element.parentNode, offset + 1); - this._selectedRange = range; - - // Note: Chrome (and maybe other browsers) will fire 2 selectionchange event asynchronously, to work around it let's use a timer - setTimeout(function() {delete thisRef._selectingResizer;}, 0); - - delete this._needsShowResizerOn; - } - - // Let's give a change to the resizer to do any custom drawing if needed - this._resizer.draw(); - } - - if (this._needsActiveLinkOn !== false && this._needsActiveLinkOn != this._activeLink) { - this._showActiveLink(this._needsActiveLinkOn); - this._needsActiveLinkOn = false; - } - - } - }, - - /** - Description TODO - @function - */ - didDraw: { - value: function() { - if (this._needsFocus) { - this.element.firstChild.focus(); - if(document.activeElement == this.element.firstChild) { - this._needsFocus = false; - } else { - // Make sure the element is visible before trying again to set the focus - var style = window.getComputedStyle(this.element); - if (style.getPropertyValue("visibility") == "hidden" || style.getPropertyValue("display") == "none") { - this._needsFocus = false; - } else { - this.needsDraw = true; - } - } - } - } - }, - - /** - Description TODO - @function - */ - _adjustPadding: { - enumerable: false, - value: function() { - var el = this.element.firstChild, - minLeft = 0, - minTop = 0; - - var walkTree = function(node, parentLeft, parentTop) { - var nodes = node ? node.childNodes : [], - nbrNodes = nodes.length, - i, - offsetLeft = node.offsetLeft, - offsetTop = node.offsetTop; - - if (node.offsetParent) { - offsetLeft += parentLeft; - offsetTop += parentTop; - } - if (minLeft > offsetLeft) { - minLeft = offsetLeft; - } - if (minTop > offsetTop) { - minTop = offsetTop; - } - - for (i = 0; i < nbrNodes; i ++) { - walkTree(nodes[i], offsetLeft, offsetTop) - } - }; - walkTree(el, el.offsetLeft, el.offsetTop); - - var computedStyle = document.defaultView.getComputedStyle(el), - paddingLeft = computedStyle.paddingLeft, - paddingTop = computedStyle.paddingTop; - - if (paddingLeft.match(/%$/)) { - paddingLeft = parseInt(paddingLeft, 10) * el.clientWidth; - } else { - paddingLeft = parseInt(paddingLeft, 10); - } - if (paddingTop.match(/%$/)) { - paddingTop = parseInt(paddingTop, 10) * el.clientHeight; - } else { - paddingTop = parseInt(paddingTop, 10); - } - - if (minLeft < 0) { - el.style.paddingLeft = (-minLeft - paddingLeft) + "px"; - } - if (minTop < 0) { - el.style.paddingTop = (-minTop - paddingTop) + "px"; - } - } - }, - - // Event handlers - // Event handlers - /** - Description TODO - @function - */ - handleFocus: { - enumerable: false, - value: function() { - var thisRef = this, - el = this.element, - content = el.firstChild, - savedRange, - timer; - - this._hasFocus = true; - if (this._needsSelectionReset) { - var node = this._lastInnerNode(), - range, - length, - leafNodes = ["#text", "BR", "IMG"]; - - // Select the last inner node - if (node) { - if (leafNodes.indexOf(node.nodeName) !== -1) { - node = node.parentNode; - } - range = document.createRange(); - length = node.childNodes ? node.childNodes.length : 0; - range.setStart(node, length); - range.setEnd(node, length); - this._selectedRange = range; - } - - // Scroll the content to make sure the caret is visible, but only only if the focus wasn't the result of a user click/touch - savedRange = this._selectedRange; - timer = setInterval(function() { - if (thisRef._equalRange(thisRef._selectedRange, savedRange) && - content.scrollTop + content.offsetHeight != content.scrollHeight) { - content.scrollTop = content.scrollHeight - content.offsetHeight; - } - }, 10); - - setTimeout(function(){clearInterval(timer)}, 1000); - - this._needsSelectionReset = false; - } - - el.addEventListener("blur", this); - el.addEventListener("input", this); - el.addEventListener("keypress", this); - el.addEventListener("paste", this, false); - el.addEventListener(window.Touch ? "touchstart" : "mousedown", this); - document.addEventListener(window.Touch ? "touchend" : "mouseup", this); - - document.addEventListener("selectionchange", this, false); - // Check if the browser does not supports the DOM event selectionchange - if (this._hasSelectionChangeEvent === null) { - var thisRef = this; - setTimeout(function(){ - if (thisRef._hasSelectionChangeEvent === null) { - thisRef._hasSelectionChangeEvent = false; - } - }, 0); - } - if (this._hasSelectionChangeEvent === false) { - // We need to listen to more event in order to simulate a selectionchange event - el.addEventListener("keydup", this); - } - - // Turn off image resize (if supported) - document.execCommand("enableObjectResizing", false, false); - // Force use css for styling (if supported) - document.execCommand("styleWithCSS", false, true); - - // Update the states if they are dirty - if (this._statesDirty) { - this.updateStates(); - } - } - }, - - /** - Description TODO - @function - */ - handleBlur: { - enumerable: false, - value: function() { - var el = this.element; - - // Force a selectionchange when we lose the focus - this.handleSelectionchange(); - - el.removeEventListener("blur", this); - el.removeEventListener("input", this); - el.removeEventListener("keypress", this); - el.removeEventListener("paste", this, false); - el.removeEventListener(window.Touch ? "touchstart" : "mousedown", this); - document.removeEventListener(window.Touch ? "touchend" : "mouseup", this); - - document.removeEventListener("selectionchange", this); - - if (this._hasSelectionChangeEvent === false) { - el.removeEventListener("keydup", this); - } - - this._hasFocus = false; - } - }, - - /** - Description TODO - @function - */ - handleKeypress: { - enumerable: false, - value: function() { - if (this._hasSelectionChangeEvent === false) { - this.handleSelectionchange(); - } - - if (this._activeLink) { - this._hideActiveLink(); - } - - this._markDirty(); - } - }, - - /** - Description TODO - @function - */ - handleInput: { - enumerable: false, - value: function(event) { - if (this._hasSelectionChangeEvent === false) { - this.handleSelectionchange(); - } - - if (this._activeLink) { - this._hideActiveLink(); - } - - this.handleDragend(event); - this._markDirty(); - } - }, - - /** - Description TODO - @function - */ - handleShortcut: { - enumerable: false, - value: function(event, action) { - if (this._actions[action] && this._actions[action].enabled) { - this.doAction(action); - return true; - } - - return false; - } - }, - - /** - Description TODO - @function - */ - handleMousedown: { - enumerable: false, - value: function(event) { - if (this._resizer) { - if (this.resizer.startUserAction(event)) { - event.preventDefault(); - event.stopPropagation(); - - return; - } - } - } - }, - - /** - Description TODO - @function - */ - handleMouseup: { - enumerable: false, - value: function(event) { - var thisRef = this, - element = event.target, - range, - offset; - - if (this._resizer) { - if (this.resizer.endUserAction(event)) { - event.preventDefault(); - event.stopPropagation(); - - return; - } - } - - if (element.tagName === "IMG") { - if (this._currentResizerElement !== element) { - this._needsShowResizerOn = element; - this.needsDraw = true; - } - } else { - if (this._resizer && this._resizer.element) { - this._needsHideResizer = true; - this.needsDraw = true; - } - - if (this._hasSelectionChangeEvent === false) { - this.handleSelectionchange(); - } - this.handleDragend(event); - } - } - }, - - /** - Description TODO - @function - */ - handleTouchstart: { - enumerable: false, - value: function() { - this.handleMousedown(event); - } - }, - - /** - Description TODO - @function - */ - handleTouchend: { - enumerable: false, - value: function() { - this.handleMouseup(event); - } - }, - - /** - Description TODO - @function - */ - handleSelectionchange: { - enumerable: false, - value: function() { - var thisRef = this, - range, - element, - hideLinkPopup = true; - - if (this._ignoreSelectionchange) { - return; - } - - if (this._hasSelectionChangeEvent == null) { - this._hasSelectionChangeEvent = true; - } - - if (this._resizer) { - if (this._selectingResizer !== true && this._resizer.element) { - this._needsHideResizer = true; - this.needsDraw = true; - } - } - - //Check if we are inside an anchor - range = this._selectedRange; - if (range && range.collapsed) { - element = range.commonAncestorContainer; - while (element && element != this._element) { - if (element.nodeName == "A") { - hideLinkPopup = false; - if (element != this._activeLink) { - this._needsActiveLinkOn = element; - this.needsDraw = true; - } - break; - } - element = element.parentElement; - } - } - if (hideLinkPopup) { - this._needsActiveLinkOn = null; - this.needsDraw = true; - } - - this._statesDirty = true; - if (this._selectionChangeTimer) { - clearTimeout(this._selectionChangeTimer); - } - this._selectionChangeTimer = setTimeout(function() { - thisRef._dispatchEditorEvent("editorSelect"); - }, 50); - } - }, - - /** - Description TODO - @function - */ - handleDragstart: { - enumerable: false, - value: function(event) { - // let's remember which element we are dragging - this._dragSourceElement = event.srcElement; - } - }, - - /** - Description TODO - @function - */ - handleDragend: { - enumerable: false, - value: function(event) { - delete this._dragSourceElement; - delete this._dragOverX; - delete this._dragOverY; - - this.handleSelectionchange(); - } - }, - - /** - Description TODO - @function - */ - handleDragover: { - enumerable: false, - value: function(event) { - var thisRef = this, - range; - - // If we are moving an element from within the ourselves, let the browser deal with it... - if (this._dragSourceElement) { - return; - } - - // JFD TODO: check if drop type is acceptable... - event.dataTransfer.dropEffect = this._allowDrop ? "copy" : "none"; - - event.preventDefault(); - event.stopPropagation(); - - // Remove the link popup - if (this._needsActiveLinkOn === false && this._activeLink) { - this._needsActiveLinkOn = null; - this.needsDraw = true; - } - - // Update the caret - if (event.x !== this._dragOverX || event.y !== this._dragOverY) { - this._dragOverX = event.x; - this._dragOverY = event.y; - - this._ignoreSelectionchange = true; - if (document.caretRangeFromPoint) { - range = document.caretRangeFromPoint(event.x, event.y); - } else if (event.rangeParent && event.rangeOffset) { - range = document.createRange(); - range.setStart(event.rangeParent, event.rangeOffset); - range.setEnd(event.rangeParent, event.rangeOffset); - } - - if (range) { - this._selectedRange = range; - } - if (this._ignoreSelectionchangeTimer) { - clearTimeout(this._ignoreSelectionchangeTimer) - } - this._ignoreSelectionchangeTimer = setTimeout(function(){ - delete thisRef._ignoreSelectionchange; - thisRef._ignoreSelectionchangeTimer = null; - }, 0); - } - } - }, - - /** - Description TODO - @function - */ - handleDrop: { - enumerable: false, - value: function(event) { - var thisRef = this, - files = event.dataTransfer.files, - fileLength = files.length, - file, - data, - reader, - i, - delegateMethod, - response; - - if (this._dragSourceElement) { - // Let the browser do the job for us, just make sure we cleanup after us - this.handleDragend(event); - this.handleSelectionchange(); - return; - } - - event.preventDefault(); - event.stopPropagation(); - - if (fileLength) { - for (i = 0; i < fileLength; i ++) { - file = files[i]; - delegateMethod = this._delegateMethod("fileDrop"); - response = true; - - if (window.FileReader) { - reader = new FileReader(); - reader.onload = function() { - data = reader.result; - - if (delegateMethod) { - response = delegateMethod.call(this.delegate, this, file, data); - } - if (response === true) { - if (file.type.match(/^image\//i)) { - document.execCommand("insertimage", false, data); - thisRef._markDirty(); - } - } - } - reader.onprogress = function(e) { - } - reader.onerror = function(e) { - } - reader.readAsDataURL(file); - } else { - // Note: This browser does not support the File API, we cannot do a preview... - if (delegateMethod) { - response = delegateMethod.call(this.delegate, this, file); - } - if (response === true) { - // TODO: for now, we do nothing, up to the consumer to deal with that case - } - } - } - } else { - data = event.dataTransfer.getData("text/html"); - if (data) { - // Sanitize Fragment (CSS & JS) - if (this._sanitizer) { - data = this._sanitizer.willInsertHTMLData(data, this._uniqueId); - } - } else { - data = event.dataTransfer.getData("text/plain") || event.dataTransfer.getData("text"); - if (data) { - var div = document.createElement('div'); - div.innerText = data; - data = div.innerHTML; - } - } - if (data) { - var delegateMethod = this._delegateMethod("drop"), - response; - - if (delegateMethod) { - response = delegateMethod.call(this.delegate, this, data, "text/html"); - if (response === true) { - data = data.replace(/\]+>/gi, ""); // Remove the meta tag. - } else { - data = response === false ? null : response ; - } - } else { - data = data.replace(/\]+>/gi, ""); // Remove the meta tag. - } - if (data && data.length) { - document.execCommand("inserthtml", false, data); - this._markDirty(); - } - } - } - this.handleDragend(event); - } - }, - - /** - Description TODO - @function - */ - handlePaste: { - enumerable: false, - value: function(event) { - var thisRef = this, - clipboardData = event.clipboardData, - data = clipboardData.getData("text/html"), - delegateMethod, - response, - div, - isHTML, - item, - file, - reader; - - /* NOTE: Chrome, and maybe the other browser too, returns html or plain text data when calling getData("text/html), - To determine if the data is actually html, check the data starts with either an html or a meta tag - */ - isHTML = data && data.match(/^(]*>|)/i); - if (data && isHTML) { - // Sanitize Fragment (CSS & JS) - if (this._sanitizer) { - data = this._sanitizer.willInsertHTMLData(data, this._uniqueId); - } - } else { - data = clipboardData.getData("text/plain") || clipboardData.getData("text"); - if (data) { - // Convert plain text to html - div = document.createElement('div'); - div.innerText = data; - data = div.innerHTML; - } - } - - if (data) { - delegateMethod = this._delegateMethod("paste"); - if (delegateMethod) { - response = delegateMethod.call(this.delegate, this, data, "text/html"); - if (response === true) { - data = data.replace(/\]+>/gi, ""); // Remove the meta tag. - } else { - data = response === false ? null : response ; - } - } else { - data = data.replace(/\]+>/gi, ""); // Remove the meta tag. - } - if (data && data.length) { - document.execCommand("inserthtml", false, data); - this._markDirty(); - } - } else { - // Maybe we have trying to paste an image as Blob... - if (clipboardData.items.length) { - item = clipboardData.items[0]; - if (item.kind == "file" && item.type.match(/^image\/.*$/)) { - file = item.getAsFile(); - - response = true; - - if (window.FileReader) { - reader = new FileReader(); - reader.onload = function() { - data = reader.result; - - this._delegateMethod("filePaste"); - if (delegateMethod) { - response = delegateMethod.call(this.delegate, this, file, data); - } - if (response === true) { - if (file.type.match(/^image\//i)) { - document.execCommand("insertimage", false, data); - thisRef._markDirty(); - } - } - } - reader.onprogress = function(e) { - } - reader.onerror = function(e) { - } - reader.readAsDataURL(file); - } else { - // Note: This browser does not support the File API, we cannot handle it directly... - if (delegateMethod) { - response = delegateMethod.call(this.delegate, this, file); - } - if (response === true) { - // TODO: for now, we do nothing, up to the consumer to deal with that case - } - } - } - } - } - - event.preventDefault(); - event.stopPropagation(); - } - }, - - /** - Description TODO - @function - @param {String} pointer TODO - @param {Component} demandingComponent TODO - @returns {Boolean} false - */ - surrenderPointer: { - value: function(pointer, demandingComponent) { - return false; - } - }, - - /** - Description TODO - @private - */ - _observePointer: { - value: function(pointer) { - this.eventManager.claimPointer(pointer, this); - this._observedPointer = pointer; - } - }, - - /** - Description TODO - @private - */ - _releaseInterest: { - value: function() { - this.eventManager.forfeitPointer(this._observedPointer, this); - this._observedPointer = null; - } - }, - - // Actions - /** - Description TODO - @function - */ - handleAction: { - enumerable: false, - value: function(event) { - var target = event.currentTarget, - action = target.action || target.identifier, - value = false; - if (action) { - if (this._actions[action].needsValue) { - value = target.actionValue; - if (value !== undefined) { - value = target[value]; - if (value === undefined) { - value = target.actionValue; - } - } else { - value = target.value; - } - - if (value === undefined) { - value = false; - } - } - this.doAction(action, value); - } - } - }, - - /** - Description TODO - @function - */ - doAction: { - enumerable: true, - value: function(action, value) { - // Check if the action is valid and enabled - if (this._actions[action] && this._actions[action].enabled === true) { - if (value === undefined) { - value = false; - } - document.execCommand(action, false, value); - - this.handleSelectionchange(); - this._markDirty(); - } - } - }, - - - // Private methods - /** - Description TODO - @private - @function - */ - _dispatchEditorEvent: { - enumerable: false, - value: function(type, value) { - var editorEvent = document.createEvent("CustomEvent"); - editorEvent.initCustomEvent(type, true, false, value === undefined ? null : value); - editorEvent.type = type; - this.dispatchEvent(editorEvent); - } - }, - - /** - Description TODO - @private - @function - */ - _markDirty: { - enumerable: false, - value: function() { - var thisRef = this, - updateValues = function() { - clearTimeout(thisRef._forceUpdateValuesTimeout); - delete thisRef._forceUpdateValuesTimeout; - clearTimeout(thisRef._updateValuesTimeout); - delete thisRef._updateValuesTimeout; - thisRef.dispatchEvent(MutableEvent.changeEventForKeyAndValue("value" , thisRef.value)); - thisRef.dispatchEvent(MutableEvent.changeEventForKeyAndValue("textValue" , thisRef.textValue)); - thisRef._dispatchEditorEvent("editorChange"); - }; - - if (!this._needsResetContent) { - // Clear the cached value - this._dirtyValue = true; - this._dirtyTextValue = true; - } - - if (!this._forceUpdateValuesTimeout) { - this._forceUpdateValuesTimeout = setTimeout(updateValues, 1000); - } - if (this._updateValuesTimeout) { - clearTimeout(this._updateValuesTimeout); - } - this._updateValuesTimeout = setTimeout(updateValues, 200); - } - }, - - /** - Description TODO - @private - @function - */ - _delegateMethod: { - enumerable: false, - value: function(name) { - var delegate, delegateFunctionName, delegateFunction; - if (typeof this.identifier === "string") { - delegateFunctionName = this.identifier + name.toCapitalized(); - } else { - delegateFunctionName = name; - } - if ((delegate = this.delegate) && typeof (delegateFunction = delegate[delegateFunctionName]) === "function") { - return delegateFunction; - } - - return null; - } - }, - - /** - Description TODO - @private - @function - */ - _nodeOffset: { - enumerable: false, - value: function(node) { - var parentNode = node.parentNode, - childNodes = parentNode.childNodes, - i; - - for (i in childNodes) { - if (childNodes[i] === node) { - return parseInt(i, 10); // i is a string, we need an integer - } - } - return 0; - } - }, - - /** - Description TODO - @private - @function - */ - _lastInnerNode: { - enumerable: false, - value: function() { - var nodes = this.element.firstChild.childNodes, - nbrNodes = nodes.length, - node = null; - - while (nodes) { - nbrNodes = nodes.length; - if (nbrNodes) { - node = nodes[nbrNodes - 1]; - nodes = node.childNodes; - } else { - break; - } - } - - return node; - } - }, - - /** - Description TODO - @private - @function - */ - _selectedRange: { - enumerable: false, - set: function(range) { - if (window.getSelection) { - var selection = window.getSelection(); - selection.removeAllRanges(); - selection.addRange(range); - } else { - range.select(); - } - }, - - get: function() { - var userSelection, - range; - - if (window.getSelection) { - userSelection = window.getSelection(); - } else if (document.selection) { // Opera! - userSelection = document.selection.createRange(); - } - - if (userSelection.getRangeAt) { - if (userSelection.rangeCount) { - return userSelection.getRangeAt(0); - } else { - // return an empty selection - return document.createRange(); - } - } - else { // Safari! - var range = document.createRange(); - range.setStart(userSelection.anchorNode, userSelection.anchorOffset); - range.setEnd(userSelection.focusNode, userSelection.focusOffset); - return range; - } - } - }, - - /** - Description TODO - @private - @function - */ - _equalRange: { - enumerable: false, - value: function(rangeA, rangeB) { - return (rangeA.startContainer == rangeB.startContainer && - rangeA.startOffset == rangeB.startOffset && - rangeA.endContainer == rangeB.endContainer && - rangeA.endOffset == rangeB.endOffset); - } - }, - - /** - Description TODO - @private - @function - */ - _showActiveLink: { - enumerable: false, - value: function(element) { - var editorElement = this._element.firstChild, - popup, - parentNode, - nextSibling, - w, h, l, t, - left, right, leftWidth, rightWidth, - style, - popupExtraWidth = 53; // This is depending of the popup css - - var offsetLeft, - offsetTop, - _findOffset = function(node) { - offsetLeft = node.offsetLeft; - offsetTop = node.offsetTop; - - while ((node = node.offsetParent) && node != editorElement) { - offsetLeft += node.offsetLeft; - offsetTop += node.offsetTop; - } - }; - - - if (this._activeLink != element) { - this._hideActiveLink(); - if (element) { - - _findOffset(element); - - parentNode = element.parentNode; - nextSibling = element.nextSibling; - - oh = editorElement.offsetHeight; - ow = editorElement.offsetWidth; - st = editorElement.scrollTop; - sl = editorElement.scrollLeft; - - w = element.offsetWidth -1, - h = element.offsetHeight -1, - l = offsetLeft, - t = offsetTop, - - style = ""; - - // Should we display the popup on top or below the element? - if (t > 60 && t - st + h + 50 > oh) { - style = "bottom: " + (oh - t + 5) + "px;"; - } else { - style = "top: " + (t + h + 5 ) + "px;"; - } - - // Should we display the popup aligned on the left or right of the element? - left = sl; - right = sl + ow; - leftWidth = right - l; - rightWidth = l + w - left; - - if (leftWidth > rightWidth) { - //Let's align the popup to the left of the element or to the far left - if (leftWidth < 150) { - style += " left: " + (left + 5) + "px;"; - style += " max-width: " + (ow - 10 - popupExtraWidth) + "px;"; - } else { - style += " left: " + (left + l) + "px;"; - style += " max-width: " + (leftWidth - 5 - popupExtraWidth) + "px;"; - } - } else { - if (rightWidth < 150) { - style += " right: " + (left + 6) + "px;"; - style += " max-width: " + (ow - 10 - popupExtraWidth) + "px;"; - } else { - style += " right: " + (right - (left + l + w + 10)) + "px;"; - style += " max-width: " + (rightWidth - popupExtraWidth) + "px;"; - } - } - - popup = document.createElement("DIV"); - popup.className = "montage-link-popup"; - popup.setAttribute("contentEditable", "false"); - popup.setAttribute("style", style); - popup.innerHTML = '' + element.href + ''; - editorElement.insertBefore(popup, null); - - this._activeLink = element; - } - } - } - }, - - /** - Description TODO - @private - @function - */ - _hideActiveLink: { - enumerable: false, - value: function() { - var popups, - nbrPopups, - popup, - i; - - if (this._activeLink) { - popups = this._element.firstChild.getElementsByClassName("montage-link-popup"); - nbrPopups = popups.length; - - // Note: We should not have more than one popup, this is just in case... - for (i = 0; i < nbrPopups; i ++) { - popup = popups[0]; - popup.parentNode.removeChild(popup); - } - - this._activeLink = null; - } - } - }, - - /** - Description TODO - @private - @function - */ - _cleanupActiveLink: { - enumerable: false, - value: function(contentNode) { - var cleanContentNode = contentNode, - popups = contentNode.getElementsByClassName("montage-link-popup"), - nbrPopups, - popup, - i; - - if (popups) { - // We don't want to hide the popup, just return a copy of the content without any popup - cleanContentNode = contentNode.cloneNode(true); - popups = cleanContentNode.getElementsByClassName("montage-link-popup"); - nbrPopups = popups.length; - - // Note: We should not have more than one popup, this is just in case... - for (i = 0; i < nbrPopups; i ++) { - popup = popups[0]; - popup.parentNode.removeChild(popup); - } - } - - return cleanContentNode; - } - }, - - _innerText: { - enumerable: false, - value: function(contentNode) { - var result = "", - textNodeContents = [], - newLines = "", - gotText = false, - _walkNode = function(node) { - var nodeName = node.nodeName, - child - - if (nodeName.match(/^(TITLE|STYLE|SCRIPT)$/)) { - return; - } - - if (gotText && nodeName.match(/^(P|DIV|BR|TR|LI)$/)) { - newLines += "\n"; - } - - for (child = node.firstChild; child; child = child.nextSibling) { - if (child.nodeType == 3) { // text node - textNodeContents.push(newLines + child.nodeValue); - newLines = ""; - gotText = true; - } else { - if (child.nodeName != "BR" || child.nextSibling) { - _walkNode(child); - } - } - } - - if (gotText && nodeName.match(/^(TABLE|UL|OL)$/)) { - newLines += "\n"; - } - }; - - if (contentNode) { - _walkNode(contentNode); - result = textNodeContents.join(""); - } - - return result; - } - } -}); -- cgit v1.2.3