From 8fe92b94ce5e1e2857d088752d94e19db7e3d8a8 Mon Sep 17 00:00:00 2001 From: Valerio Virgillito Date: Sun, 17 Jun 2012 22:31:44 -0700 Subject: montage v11 merge into ninja Signed-off-by: Valerio Virgillito --- .../rich-text-linkpopup.html | 34 ++-- .../rich-text-resizer.reel/rich-text-resizer.html | 32 ++-- .../rich-text-resizer.reel/rich-text-resizer.js | 2 +- .../rich-text-editor.reel/rich-text-editor-base.js | 201 ++++++++++++--------- .../rich-text-editor.reel/rich-text-editor.css | 6 + .../rich-text-editor.reel/rich-text-editor.html | 38 ++-- .../rich-text-editor.reel/rich-text-editor.js | 78 +++++--- 7 files changed, 226 insertions(+), 165 deletions(-) (limited to 'node_modules/montage/ui/rich-text-editor') diff --git a/node_modules/montage/ui/rich-text-editor/overlays/rich-text-linkpopup.reel/rich-text-linkpopup.html b/node_modules/montage/ui/rich-text-editor/overlays/rich-text-linkpopup.reel/rich-text-linkpopup.html index 9595d7ab..9bb4b0df 100644 --- a/node_modules/montage/ui/rich-text-editor/overlays/rich-text-linkpopup.reel/rich-text-linkpopup.html +++ b/node_modules/montage/ui/rich-text-editor/overlays/rich-text-linkpopup.reel/rich-text-linkpopup.html @@ -6,25 +6,25 @@ --> - - + + @@ -32,4 +32,4 @@ - + \ No newline at end of file diff --git a/node_modules/montage/ui/rich-text-editor/overlays/rich-text-resizer.reel/rich-text-resizer.html b/node_modules/montage/ui/rich-text-editor/overlays/rich-text-resizer.reel/rich-text-resizer.html index 526d6563..d7dbe11c 100644 --- a/node_modules/montage/ui/rich-text-editor/overlays/rich-text-resizer.reel/rich-text-resizer.html +++ b/node_modules/montage/ui/rich-text-editor/overlays/rich-text-resizer.reel/rich-text-resizer.html @@ -6,25 +6,25 @@ --> - - + + diff --git a/node_modules/montage/ui/rich-text-editor/overlays/rich-text-resizer.reel/rich-text-resizer.js b/node_modules/montage/ui/rich-text-editor/overlays/rich-text-resizer.reel/rich-text-resizer.js index c9f94565..2b0fa5c0 100644 --- a/node_modules/montage/ui/rich-text-editor/overlays/rich-text-resizer.reel/rich-text-resizer.js +++ b/node_modules/montage/ui/rich-text-editor/overlays/rich-text-resizer.reel/rich-text-resizer.js @@ -231,7 +231,7 @@ exports.RichTextResizer = Montage.create(Component,/** @lends module:"montage/ui var zero = Point.create().init(0, 0), framePosition = dom.convertPointFromNodeToPage(element, zero), cursor = this._cursorPosition, - direction = this._draggedElement.id.substring("montage-resizer-handle-".length), + direction = this._draggedElement.getAttribute("data-montage-id").substring("montage-resizer-handle-".length), info = this._resizerFrameInfo, ratio = info.ratio, height = parseFloat(element.style.height, 10), diff --git a/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor-base.js b/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor-base.js index 0bdf67e7..9791908f 100644 --- a/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor-base.js +++ b/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor-base.js @@ -9,13 +9,31 @@ */ var Montage = require("montage").Montage, Component = require("ui/component").Component, - MutableEvent = require("core/event/mutable-event").MutableEvent, Sanitizer = require("./rich-text-sanitizer").Sanitizer, RichTextLinkPopup = require("../overlays/rich-text-linkpopup.reel").RichTextLinkPopup, RichTextResizer = require("../overlays/rich-text-resizer.reel").RichTextResizer, - defaultEventManager = require("core/event/event-manager").defaultEventManager, + ChangeNotification = require("core/change-notification").ChangeNotification, defaultUndoManager = require("core/undo-manager").defaultUndoManager; + +/** static variables, constants + */ +var COMMANDS = [ + {property: "bold"}, + {property: "underline"}, + {property: "italic"}, + {property: "strikeThrough"}, + {property: "baselineShift", method: this._baselineShiftGetState}, + {property: "justify", method: this._justifyGetState}, + {property: "listStyle", method: this._listStyleGetState}, + {property: "fontName", method: this._fontNameGetState}, + {property: "fontSize"}, + {property: "backColor"}, + {property: "foreColor"} + ], + NBR_COMMANDS = COMMANDS.length; + + /** @class module:"montage/ui/rich-text-editor.reel".RichTextEditorBase @extends module:montage/ui/component.Component @@ -254,9 +272,17 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage // Commands Helpers _getState: { value: function(property, command) { - var state; + var state, + savedActiveElement = document.activeElement, + editorElement = this._innerElement; + + if (editorElement && !this["_" + property + "_locked"]) { + + // Make sure we are the active element before calling execCommand + if (editorElement && editorElement != savedActiveElement) { + editorElement.focus(); + } - if (this._innerElement == document.activeElement) { state = document.queryCommandValue(command); // Convert string to boolean if (state == "true") { @@ -264,9 +290,15 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage } if (state == "false") { state = false; } + + // Reset the focus + if (editorElement && editorElement != savedActiveElement) { + savedActiveElement.focus(); + } + return state; } else { - return this["_" + property]; + return this["_" + property]; } } }, @@ -320,7 +352,15 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage _baselineShiftGetState: { enumerable: false, value: function() { - if (this._innerElement == document.activeElement) { + var savedActiveElement = document.activeElement, + editorElement = this._innerElement; + + if (editorElement && !this._baselineShift_locked) { + // Make sure we are the active element before calling execCommand + if (editorElement != savedActiveElement) { + editorElement.focus(); + } + if (this._getState("baselineShift", "subscript")) { return "subscript" } else if (this._getState("baselineShift", "superscript")) { @@ -328,6 +368,11 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage } else { return "baseline"; // default } + + // Reset the focus + if (editorElement != savedActiveElement) { + savedActiveElement.focus(); + } } else { return this._baselineShift; } @@ -347,7 +392,15 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage _listStyleGetState: { enumerable: false, value: function() { - if (this._innerElement == document.activeElement) { + var savedActiveElement = document.activeElement, + editorElement = this._innerElement; + + if (editorElement && !this._listStyle_locked) { + // Make sure we are the active element before calling execCommand + if (editorElement != savedActiveElement) { + editorElement.focus(); + } + if (this._getState("listStyle", "insertorderedlist")) { return "ordered" } else if (this._getState("listStyle", "insertunorderedlist")) { @@ -355,6 +408,11 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage } else { return "none"; // default } + + // Reset the focus + if (editorElement != savedActiveElement) { + savedActiveElement.focus(); + } } else { return this._listStyle; } @@ -373,7 +431,15 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage _justifyGetState: { enumerable: false, value: function() { - if (this._innerElement == document.activeElement) { + var savedActiveElement = document.activeElement, + editorElement = this._innerElement; + + if (editorElement && !this._justify_locked) { + // Make sure we are the active element before calling execCommand + if (editorElement != savedActiveElement) { + editorElement.focus(); + } + if (this._getState("justify", "justifyleft")) { return "left" } else if (this._getState("justify", "justifycenter")) { @@ -385,6 +451,11 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage } else { return "left"; // default } + + // Reset the focus + if (editorElement != savedActiveElement) { + savedActiveElement.focus(); + } } else { return this._justify; } @@ -404,12 +475,12 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage _fontNameGetState: { enumerable: false, value: function() { - this._fontName = this._getState("fontName", "fontname"); - if (this._fontName) { - this._fontName = this._fontName.replace(/\"|\'/g, ""); + var fontName = this._getState("fontName", "fontname"); + if (fontName) { + fontName = fontName.replace(/\"|\'/g, ""); } - return this._fontName; + return fontName; } }, /** @@ -436,7 +507,6 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage */ _foreColor: { value: "" }, - /** Description TODO @type {Function} @@ -444,49 +514,39 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage _updateStates: { enumerable: true, value: function() { - var commands = [{property: "bold"}, - {property: "underline"}, - {property: "italic"}, - {property: "strikeThrough"}, - {property: "baselineShift", method: this._baselineShiftGetState}, - {property: "justify", method: this._justifyGetState}, - {property: "listStyle", method: this._listStyleGetState}, - {property: "fontName", method: this._fontNameGetState}, - {property: "fontSize"}, - {property: "backColor"}, - {property: "foreColor"} - ], - nbrCommands = commands.length, + var thisRef = this, command, commandName, propertyName, state, prevState, method, + descriptor, i; - if (this._innerElement == document.activeElement) { - for (i = 0; i < nbrCommands; i ++) { - command = commands[i]; + for (i = 0; i < NBR_COMMANDS; i ++) { + command = COMMANDS[i]; - if (typeof command == "object") { - propertyName = command.property; - commandName = command.name || propertyName.toLowerCase(); - method = command.method || this._getState; - } else { - continue; - } + if (typeof command == "object") { + propertyName = command.property; + commandName = command.name || propertyName.toLowerCase(); + method = command.method || this._getState; + } else { + continue; + } - if (defaultEventManager.registeredEventListenersForEventType_onTarget_("change@" + propertyName, this)) { - prevState = this["_" + propertyName]; - state = method.call(this, propertyName, commandName); - if (state !== prevState) { - this["_" + propertyName] = state; - this.dispatchEvent(MutableEvent.changeEventForKeyAndValue(propertyName , prevState).withPlusValue(state)); - } + descriptor = ChangeNotification.getPropertyChangeDescriptor(this, propertyName); + if (descriptor) { + prevState = this["_" + propertyName]; + state = method.call(this, propertyName, commandName); + if (state !== prevState) { + this["_" + propertyName + "_locked"] = true; + this.dispatchPropertyChange(propertyName, function() { + thisRef["_" + propertyName] = state; + }); + thisRef["_" + propertyName + "_locked"] = false; } } - } } }, @@ -543,6 +603,7 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage content, contentChanged, prevValue, + descriptor, i; if (this._needsAssingValue || this._needsAssignOriginalContent) { @@ -565,26 +626,12 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage // Set the contentEditable value if (this._value && !this._dirtyValue) { editorInnerElement.innerHTML = this._value; - // Since this property affects the textValue, we need to fire a change event for it as well - if (defaultEventManager.registeredEventListenersForEventType_onTarget_("change@textValue", this)) { - prevValue = this._textValue; - if (this.textValue !== prevValue) { - this.dispatchEvent(MutableEvent.changeEventForKeyAndValue("textValue" , prevValue).withPlusValue(this.textValue)); - } - } } else if (this._textValue && !this._dirtyTextValue) { if (editorInnerElement.innerText) { editorInnerElement.innerText = this._textValue; } else { editorInnerElement.textContent = this._textValue; } - // Since this property affects the value, we need to fire a change event for it as well - if (defaultEventManager.registeredEventListenersForEventType_onTarget_("change@value", this)) { - prevValue = this._value; - if (this.value !== prevValue) { - this.dispatchEvent(MutableEvent.changeEventForKeyAndValue("value" , prevValue).withPlusValue(this.value)); - } - } } } else if (this._needsAssignOriginalContent) { contents = this.originalContent; @@ -599,19 +646,6 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage } } if (contentChanged) { - if (defaultEventManager.registeredEventListenersForEventType_onTarget_("change@value", this)) { - prevValue = this._value; - if (this.value !== prevValue) { - this.dispatchEvent(MutableEvent.changeEventForKeyAndValue("value" , prevValue).withPlusValue(this.value)); - } - } - if (defaultEventManager.registeredEventListenersForEventType_onTarget_("change@textValue", this)) { - prevValue = this._textValue; - if (this.textValue !== prevValue) { - this.dispatchEvent(MutableEvent.changeEventForKeyAndValue("textValue" , prevValue).withPlusValue(this.textValue)); - } - } - // Clear the cached value in order to force an editorChange event this._dirtyValue = true; this._dirtyTextValue = true; @@ -759,12 +793,14 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage savedRange, timer; - this._hasFocus = true; - this.dispatchEvent(MutableEvent.changeEventForKeyAndValue("hasFocus" , false).withPlusValue(true)); + this.dispatchPropertyChange("hasFocus", function() { + thisRef._hasFocus = true; + }); isActive = (content && content === document.activeElement); if (isActive != this._isActiveElement) { - this._isActiveElement = isActive; - this.dispatchEvent(MutableEvent.changeEventForKeyAndValue("isActiveElement" , false).withPlusValue(true)); + this.dispatchPropertyChange("isActiveElement", function() { + thisRef._isActiveElement = isActive; + }); } if (this._setCaretAtEndOfContent) { @@ -840,16 +876,19 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage handleBlur: { enumerable: false, value: function() { - var el = this.element, + var thisRef = this, + el = this.element, content = this._innerElement, isActive; - this._hasFocus = false; - this.dispatchEvent(MutableEvent.changeEventForKeyAndValue("hasFocus" , true).withPlusValue(false)); + this.dispatchPropertyChange("hasFocus", function() { + thisRef._hasFocus = false; + }); isActive = (content && content === document.activeElement); if (isActive != this._isActiveElement) { - this._isActiveElement = isActive; - this.dispatchEvent(MutableEvent.changeEventForKeyAndValue("isActiveElement" , !isActive).withPlusValue(isActive)); + this.dispatchPropertyChange("isActiveElement", function() { + thisRef._isActiveElement = isActive; + }); } // Force a selectionchange when we lose the focus @@ -1324,13 +1363,13 @@ exports.RichTextEditorBase = Montage.create(Component,/** @lends module:"montage file = item.getAsFile(); response = true; + delegateMethod = thisRef._delegateMethod("shouldPasteFile"); if (window.FileReader) { reader = new FileReader(); reader.onload = function() { data = reader.result; - thisRef._delegateMethod("shouldPasteFile"); if (delegateMethod) { response = delegateMethod.call(thisRef.delegate, thisRef, file, data); } diff --git a/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor.css b/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor.css index f5b00e84..58b7e02d 100644 --- a/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor.css +++ b/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor.css @@ -13,8 +13,14 @@ .montage-editor { position: relative; + height: inherit; outline: none; overflow: auto; + + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; } /* diff --git a/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor.html b/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor.html index 9cebd32e..2e773e5f 100644 --- a/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor.html +++ b/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor.html @@ -6,28 +6,27 @@ --> - - + + -
@@ -35,5 +34,4 @@
- - + \ No newline at end of file diff --git a/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor.js b/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor.js index 3665ca1b..dc78816d 100644 --- a/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor.js +++ b/node_modules/montage/ui/rich-text-editor/rich-text-editor.reel/rich-text-editor.js @@ -13,8 +13,7 @@ var Montage = require("montage").Montage, RichTextEditorBase = require("./rich-text-editor-base").RichTextEditorBase, Sanitizer = require("./rich-text-sanitizer").Sanitizer, - MutableEvent = require("core/event/mutable-event").MutableEvent, - defaultEventManager = require("core/event/event-manager").defaultEventManager; + ChangeNotification = require("core/change-notification").ChangeNotification; /** @classdesc The RichTextEditor component is a lightweight Montage component that provides basic HTML editing capability. It wraps the HTML5 contentEditable property and largely relies on the browser's support of execCommand. @@ -130,9 +129,11 @@ exports.RichTextEditor = Montage.create(RichTextEditorBase,/** @lends module:"mo overlayParent, overlayNextSibling; - if (this._dirtyValue) { + if (this._dirtyValue && !this._value_locked) { + this._value_locked = true; + if (contentNode) { - // Temporary orphran the overlay slot while retrieving the content + // Temporary orphan the overlay slot while retrieving the content overlayElement = contentNode.querySelector(".montage-editor-overlay"); if (overlayElement) { overlayParent = overlayElement.parentNode; @@ -158,8 +159,14 @@ exports.RichTextEditor = Montage.create(RichTextEditorBase,/** @lends module:"mo overlayParent.insertBefore(overlayElement, overlayNextSibling); } - this._value = content; + if (this._value != content) { + this.dispatchPropertyChange("value", function(){ + this._value = content; + }); + } + this._dirtyValue = false; + this._value_locked = false; } return this._value; }, @@ -192,13 +199,16 @@ exports.RichTextEditor = Montage.create(RichTextEditorBase,/** @lends module:"mo enumerable: true, get: function() { var contentNode = this._innerElement, + content = "", overlayElement = null, overlayParent, overlayNextSibling; - if (this._dirtyTextValue) { + if (this._dirtyTextValue && !this._textValue_locked) { + this._textValue_locked = true; + if (contentNode) { - // Temporary orphran the overlay slot in order to retrieve the content + // Temporary orphan the overlay slot in order to retrieve the content overlayElement = contentNode.querySelector(".montage-editor-overlay"); if (overlayElement) { overlayParent = overlayElement.parentNode; @@ -206,17 +216,22 @@ exports.RichTextEditor = Montage.create(RichTextEditorBase,/** @lends module:"mo overlayParent.removeChild(overlayElement); } - this._textValue = this._innerText(contentNode); + content = this._innerText(contentNode); // restore the overlay if (overlayElement) { overlayParent.insertBefore(overlayElement, overlayNextSibling); } - } else { - this._textValue = ""; + } + + if (this._textValue != content) { + this.dispatchPropertyChange("textValue", function(){ + this._textValue = content; + }); } this._dirtyTextValue = false; + this._textValue_locked = false; } return this._textValue; }, @@ -641,28 +656,31 @@ exports.RichTextEditor = Montage.create(RichTextEditorBase,/** @lends module:"mo markDirty: { enumerable: false, value: function() { - var thisRef = this, - prevValue; - var updateValues = function() { - clearTimeout(thisRef._forceUpdateValuesTimeout); - delete thisRef._forceUpdateValuesTimeout; - clearTimeout(thisRef._updateValuesTimeout); - delete thisRef._updateValuesTimeout; - - if (defaultEventManager.registeredEventListenersForEventType_onTarget_("change@value", thisRef)) { - prevValue = thisRef._value; - if (thisRef.value !== prevValue) { - thisRef.dispatchEvent(MutableEvent.changeEventForKeyAndValue("value" , prevValue).withPlusValue(thisRef.value)); - } + var thisRef = this; + + var updateValues = function() { + var value, + descriptor; + + clearTimeout(thisRef._forceUpdateValuesTimeout); + delete thisRef._forceUpdateValuesTimeout; + clearTimeout(thisRef._updateValuesTimeout); + delete thisRef._updateValuesTimeout; + + if (thisRef._dirtyValue) { + descriptor = ChangeNotification.getPropertyChangeDescriptor(thisRef, "value"); + if (descriptor) { + value = thisRef.value; // Will force to update the value and send a property change notification } - if (defaultEventManager.registeredEventListenersForEventType_onTarget_("change@textValue", thisRef)) { - prevValue = thisRef._textValue; - if (thisRef.textValue !== prevValue) { - thisRef.dispatchEvent(MutableEvent.changeEventForKeyAndValue("textValue" , prevValue).withPlusValue(thisRef.textValue)); - } + } + if (thisRef._dirtyTextValue) { + descriptor = ChangeNotification.getPropertyChangeDescriptor(thisRef, "textValue"); + if (descriptor) { + value = thisRef.textValue; // Will force to update the value and send a property change notification } - thisRef._dispatchEditorEvent("editorChange"); - }; + } + thisRef._dispatchEditorEvent("editorChange"); + }; if (!this._needsAssingValue) { // Clear the cached value -- cgit v1.2.3