diff --git a/sandbox/aloha-bootstrap-ui/index.html b/sandbox/aloha-bootstrap-ui/index.html index 9c5961cadf..8f2e9e9e1a 100644 --- a/sandbox/aloha-bootstrap-ui/index.html +++ b/sandbox/aloha-bootstrap-ui/index.html @@ -13,7 +13,7 @@ - testing +

Aloha Editot Bootstrap UI

diff --git a/src/aloha.js b/src/aloha.js index 16e8215e48..be0de0f787 100644 --- a/src/aloha.js +++ b/src/aloha.js @@ -7,6 +7,7 @@ define([ 'dragdrop', 'editables', 'autoformat', + 'boundaries', 'events', 'functions', 'keys', @@ -23,6 +24,7 @@ define([ DragDrop, Editables, AutoFormat, + Boundaries, Events, Fn, Keys, @@ -37,14 +39,92 @@ define([ var doc = document; var win = Dom.documentWindow(doc); + function getBoundaries(type, nativeEvent, target) { + var doc = target.document || target.ownerDocument; + if (('mousedown' === type || 'click' === type) && nativeEvent && doc) { + return Boundaries.fromPosition( + nativeEvent.clientX, + nativeEvent.clientY, + doc + ); + } + if ('aloha' === type || 'mahalo' === type) { + return [Boundaries.create(target, 0), Boundaries.create(target, 0)]; + } + return doc && Boundaries.get(doc); + } + + /** + * Creates an event object that will contain the following properties: + * type + * target + * editor + * boundaries + * + * In addition to these mandatory properties, it may contain the following: + * editable + * nativeEvent + * + * @param {!Editor} editor + * @param {!Event} nativeEvent + * @param {!Object} custom + * @return {?Event} + */ + function createEvent(editor, nativeEvent, custom) { + var type, target, editable, boundaries; + if (custom) { + type = custom.type; + target = custom.target; + editable = custom.editable; + boundaries = custom.boundaries; + } + if (!type && nativeEvent) { + type = nativeEvent.type; + if (!type) { + console.warn('no type'); + return null; + } + } + if ('mousemove' === type) { + console.warn('ignore mousemove'); + return null; + } + if (!target && nativeEvent) { + target = nativeEvent.target; + if (!target) { + console.warn('no target'); + return null; + } + } + if (!boundaries) { + boundaries = getBoundaries(type, nativeEvent, target); + if (!boundaries) { + console.warn('no boundaries'); + return null; + } + } + if (!editable) { + var cac = Boundaries.commonContainer(boundaries[0], boundaries[1]); + if (Dom.isEditableNode(cac)) { + editable = Editables.fromBoundary(editor, boundaries[0]); + } + } + return { + type : type, + target : target, + editor : editor, + editable : editable, + boundaries : boundaries, + nativeEvent : nativeEvent + }; + } + function editor(nativeEvent, custom) { - var event = custom || {nativeEvent : nativeEvent}; - event.editor = editor; - event.lastEditableBoundaries = editor.lastEditableBoundaries; - event.type = event.type || (nativeEvent && nativeEvent.type) || 'unknown'; - event = Fn.comp.apply(editor.stack, editor.stack)(event); - editor.lastEditableBoundaries = event.boundaries; - Selections.update(event); + var event = createEvent(editor, nativeEvent, custom); + if (event) { + event = Fn.comp.apply(editor.stack, editor.stack)(event); + Selections.update(event); + } } editor.BLOCK_CLASS = 'aloha-block'; @@ -73,24 +153,26 @@ define([ * * Also serves as short aloha.aloha. * - * @param {Element} element - * @parma {Object} options + * @param {!Element} element + * @parma {Object=} options */ function aloha(element, options) { editor(null, { type : 'aloha', - element : element, + target : element, options : options }); } + /** + * Destroys an editable. + * + * @param {!Element} element + */ function mahalo(element) { - var editable = Editables.fromElem(editor, element); - Editables.close(editable); - Editables.dissocFromEditor(editor, editable); editor(null, { - type : 'mahalo', - editable : editable + type : 'mahalo', + target : element }); } diff --git a/src/autoformat.js b/src/autoformat.js index 06e8f1afff..88ff4f1070 100644 --- a/src/autoformat.js +++ b/src/autoformat.js @@ -131,7 +131,7 @@ define([ } function handleAutoFormat(event) { - if ('keydown' !== event.type || !event.editable || !event.boundaries) { + if (!event.editable || 'keydown' !== event.type) { return event; } if ( diff --git a/src/blocks.js b/src/blocks.js index 001ff55721..9f38cf83ff 100644 --- a/src/blocks.js +++ b/src/blocks.js @@ -80,7 +80,7 @@ define([ } function handleAloha(event) { - var blocks = event.editable['elem'].querySelectorAll('.aloha-block,img'); + var blocks = event.editable.elem.querySelectorAll('.aloha-block,img'); [].forEach.call(blocks, function (block) { block.setAttribute('contentEditable', 'false'); Dom.setStyle(block, 'cursor', Browsers.VENDOR_PREFIX + 'grab'); @@ -128,18 +128,16 @@ define([ }; /** - * Requires: - * editor - * Updates: - * editable + * Updates editable * * @param {AlohaEvent} event * @return {Event} */ function handleBlocks(event) { - if (handlers[event.type]) { - handlers[event.type](event); + if (!event.editable || !handlers[event.type]) { + return event; } + handlers[event.type](event); return event; } diff --git a/src/dragdrop.js b/src/dragdrop.js index 6b6188c0b7..e81173c204 100644 --- a/src/dragdrop.js +++ b/src/dragdrop.js @@ -174,9 +174,7 @@ define([ alohaEvent.editor.dnd.element ); } - if (event.stopPropagation) { - event.stopPropagation(); - } + Events.stopPropagation(event); // Because some browsers will otherwise redirect Events.preventDefault(event); } @@ -190,20 +188,16 @@ define([ /** * Processes drag and drop events. * - * Requires: - * editor - * target - * Updates: - * editor.dnd - * nativeEvent + * Updates editor.dnd and nativeEvent * * @param {AlohaEvent} event * @return {AlohaEvent} */ function handleDragDrop(event) { - if (event.editor.dnd && handlers[event.type]) { - handlers[event.type](event); + if (!event.editable || !event.editor.dnd || !handlers[event.type]) { + return event; } + handlers[event.type](event); return event; } diff --git a/src/editables.js b/src/editables.js index 57e47bc67c..a04a77083b 100644 --- a/src/editables.js +++ b/src/editables.js @@ -106,25 +106,26 @@ define([ return editable; } + function destroy(editor, element) { + var editable = fromElem(editor, element); + close(editable); + dissocFromEditor(editor, editable); + return editable; + } + /** * Associates an editable to the given AlohaEvent. * - * Require: - * type - * editor - * Provides: - * editable + * Provides editable * * @param {AlohaEvent} event * @return {AlohaEvent} */ function handleEditables(event) { if ('aloha' === event.type) { - event.editable = create(event.editor, event.element, event.options); - } else if (event.boundaries) { - if (Dom.isEditableNode(Boundaries.container(event.boundaries[0]))) { - event.editable = fromBoundary(event.editor, event.boundaries[0]); - } + event.editable = create(event.editor, event.target, event.options); + } else if ('mahalo' === event.type) { + event.editable = destroy(event.editor, event.target); } return event; } diff --git a/src/keys.js b/src/keys.js index d742f7df6c..8732b8f9d4 100644 --- a/src/keys.js +++ b/src/keys.js @@ -88,22 +88,16 @@ define(['strings', 'boundaries'], function (Strings, Boundaries) { }; /** - * Requires: - * type - * target - * Provides: - * meta - * keycode + * Provides meta, keycode */ function handleKeys(event) { - if (event.nativeEvent) { - event.meta = metaKeys(event.nativeEvent); - if (EVENTS[event.type]) { - event.keycode = event.nativeEvent.which; - if (!event.boundaries) { - event.boundaries = Boundaries.get(event.target.ownerDocument); - } - } + if (!event.editable || !event.nativeEvent) { + return event; + } + event.meta = metaKeys(event.nativeEvent); + if (EVENTS[event.type]) { + event.keycode = event.nativeEvent.which; + event.boundaries = Boundaries.get(event.target.ownerDocument); } return event; } diff --git a/src/links.js b/src/links.js index cfee7c8b5e..d07c32578f 100644 --- a/src/links.js +++ b/src/links.js @@ -228,7 +228,7 @@ define([ } function handleLinks(event) { - if (!event.boundaries || 'click' !== event.type) { + if (!event.editable || 'click' !== event.type) { return event; } var cac = Boundaries.commonContainer(event.boundaries[0], event.boundaries[1]); diff --git a/src/mouse.js b/src/mouse.js index aa5683e3a0..fb2019c1e5 100644 --- a/src/mouse.js +++ b/src/mouse.js @@ -25,40 +25,17 @@ define(['boundaries'], function (Boundaries) { }; /** - * Requires: - * type - * editor - * Provides: - * target - * boundaries - * Updates: - * editor.selection + * Updates event.editor.selection * * @param {AlohaEvent} event * @return {AlohaEVent} */ function handleMouse(event) { - var nativeEvent = event.nativeEvent; - if (!nativeEvent) { + if (!event.editable || !event.nativeEvent || 'mousedown' !== event.type) { return event; } - event.target = nativeEvent.target; - if ('mousedown' === event.type) { - event.editor.selection.formatting = []; - event.editor.selection.overrides = []; - } - if (event.boundaries || !event.target.ownerDocument) { - return event; - } - if ('mousedown' === event.type || 'click' === event.type) { - event.boundaries = Boundaries.fromPosition( - nativeEvent.clientX, - nativeEvent.clientY, - event.target.ownerDocument - ); - } else if ('mousemove' !== event.type) { - event.boundaries = Boundaries.get(event.target.ownerDocument); - } + event.editor.selection.formatting = []; + event.editor.selection.overrides = []; return event; } diff --git a/src/paste.js b/src/paste.js index 99c557047b..f890efd782 100644 --- a/src/paste.js +++ b/src/paste.js @@ -58,7 +58,7 @@ define([ */ function isPasteEvent(event) { return 'paste' === event.type - || (event.nativeEvent && event.nativeEvent.clipboardData !== undefined); + || (event.nativeEvent && 'undefined' !== typeof event.nativeEvent.clipboardData); } /** @@ -209,7 +209,7 @@ define([ * @return {AlohaEvent} */ function handlePaste(event) { - if (!event.editable || !event.boundaries || !isPasteEvent(event)) { + if (!event.editable || !isPasteEvent(event)) { return event; } Events.suppress(event.nativeEvent); @@ -221,7 +221,7 @@ define([ if (!content) { return event; } - Undo.capture(event.editable['undoContext'], { + Undo.capture(event.editable.undoContext, { meta: {type: 'paste'} }, function () { event.boundaries = insert(event.boundaries[0], event.boundaries[1], content); diff --git a/src/selections.js b/src/selections.js index e5417dff61..5835b7529e 100644 --- a/src/selections.js +++ b/src/selections.js @@ -800,7 +800,7 @@ define([ * @return {AlohaEvent} */ function handleSelections(event) { - if (!handlers[event.type]) { + if (!event.editable || !handlers[event.type]) { return event; } diff --git a/src/typing.js b/src/typing.js index d7e74e2d46..a8ed87f485 100644 --- a/src/typing.js +++ b/src/typing.js @@ -366,11 +366,12 @@ define([ * nativeEvent */ function handleTyping(event) { - if (!event.boundaries) { + if (!event.editable) { return event; } var start = event.boundaries[0]; var end = event.boundaries[1]; + /* if (!event.editable) { if ('keydown' === event.type) { if (Dom.isEditableNode(Boundaries.container(start)) @@ -380,6 +381,7 @@ define([ } return event; } + */ var handling = handler(event); if (!handling) { return event;