summaryrefslogtreecommitdiff
path: root/addons/web_editor/static/lib/summernote/src/js/EventHandler.js
diff options
context:
space:
mode:
authorNicolas Lempereur <nle@odoo.com>2015-08-28 17:22:17 +0200
committerNicolas Lempereur <nle@odoo.com>2015-09-25 08:29:16 +0200
commit7747e0751f7a0409132d3171162d67d0885a70cb (patch)
tree7da063ae03180622c1e2e1b193f7d2c5c0477318 /addons/web_editor/static/lib/summernote/src/js/EventHandler.js
parent9798b57b12c5f943fc0f8ee7b82a9eb04434a635 (diff)
[IMP] web_editor: update summernote up to 2015-08-31
update summernote library up to revision: https://github.com/summernote/summernote/commit/a0f26e300 see https://github.com/summernote/summernote/ for history closes #8704
Diffstat (limited to 'addons/web_editor/static/lib/summernote/src/js/EventHandler.js')
-rw-r--r--addons/web_editor/static/lib/summernote/src/js/EventHandler.js829
1 files changed, 311 insertions, 518 deletions
diff --git a/addons/web_editor/static/lib/summernote/src/js/EventHandler.js b/addons/web_editor/static/lib/summernote/src/js/EventHandler.js
index 068ceff735f..09a7b00082a 100644
--- a/addons/web_editor/static/lib/summernote/src/js/EventHandler.js
+++ b/addons/web_editor/static/lib/summernote/src/js/EventHandler.js
@@ -1,92 +1,131 @@
define([
- 'summernote/core/agent', 'summernote/core/dom', 'summernote/core/async', 'summernote/core/key', 'summernote/core/list', 'summernote/core/range',
- 'summernote/editing/Style', 'summernote/editing/Editor', 'summernote/editing/History',
- 'summernote/module/Toolbar', 'summernote/module/Popover', 'summernote/module/Handle', 'summernote/module/Dialog'
-], function (agent, dom, async, key, list, range,
- Style, Editor, History,
- Toolbar, Popover, Handle, Dialog) {
-
- var CodeMirror;
- if (agent.hasCodeMirror) {
- if (agent.isSupportAmd) {
- require(['CodeMirror'], function (cm) {
- CodeMirror = cm;
- });
- } else {
- CodeMirror = window.CodeMirror;
- }
- }
+ 'summernote/core/agent',
+ 'summernote/core/func',
+ 'summernote/core/dom',
+ 'summernote/core/async',
+ 'summernote/core/key',
+ 'summernote/core/list',
+ 'summernote/editing/History',
+ 'summernote/module/Editor',
+ 'summernote/module/Toolbar',
+ 'summernote/module/Statusbar',
+ 'summernote/module/Popover',
+ 'summernote/module/Handle',
+ 'summernote/module/Fullscreen',
+ 'summernote/module/Codeview',
+ 'summernote/module/DragAndDrop',
+ 'summernote/module/Clipboard',
+ 'summernote/module/LinkDialog',
+ 'summernote/module/ImageDialog',
+ 'summernote/module/HelpDialog'
+], function (agent, func, dom, async, key, list, History,
+ Editor, Toolbar, Statusbar, Popover, Handle, Fullscreen, Codeview,
+ DragAndDrop, Clipboard, LinkDialog, ImageDialog, HelpDialog) {
/**
+ * @class EventHandler
+ *
* EventHandler
+ * - TODO: new instance per a editor
*/
var EventHandler = function () {
- var $window = $(window);
- var $document = $(document);
- var $scrollbar = $('html, body');
-
- var editor = new Editor();
- var toolbar = new Toolbar(), popover = new Popover();
- var handle = new Handle(), dialog = new Dialog();
+ var self = this;
- this.getEditor = function () {
- return editor;
+ /**
+ * Modules
+ */
+ var modules = this.modules = {
+ editor: new Editor(this),
+ toolbar: new Toolbar(this),
+ statusbar: new Statusbar(this),
+ popover: new Popover(this),
+ handle: new Handle(this),
+ fullscreen: new Fullscreen(this),
+ codeview: new Codeview(this),
+ dragAndDrop: new DragAndDrop(this),
+ clipboard: new Clipboard(this),
+ linkDialog: new LinkDialog(this),
+ imageDialog: new ImageDialog(this),
+ helpDialog: new HelpDialog(this)
};
/**
- * returns makeLayoutInfo from editor's descendant node.
+ * invoke module's method
*
- * @param {Node} descendant
- * @returns {Object}
+ * @param {String} moduleAndMethod - ex) 'editor.redo'
+ * @param {...*} arguments - arguments of method
+ * @return {*}
*/
- var makeLayoutInfo = function (descendant) {
- var $target = $(descendant).closest('.note-editor, .note-air-editor, .note-air-layout');
+ this.invoke = function () {
+ var moduleAndMethod = list.head(list.from(arguments));
+ var args = list.tail(list.from(arguments));
- if (!$target.length) { return null; }
+ var splits = moduleAndMethod.split('.');
+ var hasSeparator = splits.length > 1;
+ var moduleName = hasSeparator && list.head(splits);
+ var methodName = hasSeparator ? list.last(splits) : list.head(splits);
- var $editor;
- if ($target.is('.note-editor, .note-air-editor')) {
- $editor = $target;
- } else {
- $editor = $('[data-note-id="' + list.last($target.attr('id').split('-')) + '"]');
- }
+ var module = this.getModule(moduleName);
+ var method = module[methodName];
+
+ return method && method.apply(module, args);
+ };
+
+ /**
+ * returns module
+ *
+ * @param {String} moduleName - name of module
+ * @return {Module} - defaults is editor
+ */
+ this.getModule = function (moduleName) {
+ return this.modules[moduleName] || this.modules.editor;
+ };
- return dom.buildLayoutInfo($editor);
+ /**
+ * @param {jQuery} $holder
+ * @param {Object} callbacks
+ * @param {String} eventNamespace
+ * @returns {Function}
+ */
+ var bindCustomEvent = this.bindCustomEvent = function ($holder, callbacks, eventNamespace) {
+ return function () {
+ var callback = callbacks[func.namespaceToCamel(eventNamespace, 'on')];
+ if (callback) {
+ callback.apply($holder[0], arguments);
+ }
+ return $holder.trigger('summernote.' + eventNamespace, arguments);
+ };
};
/**
* insert Images from file array.
*
+ * @private
* @param {Object} layoutInfo
* @param {File[]} files
*/
- var insertImages = function (layoutInfo, files) {
+ this.insertImages = function (layoutInfo, files) {
var $editor = layoutInfo.editor(),
- $editable = layoutInfo.editable();
+ $editable = layoutInfo.editable(),
+ $holder = layoutInfo.holder();
var callbacks = $editable.data('callbacks');
var options = $editor.data('options');
// If onImageUpload options setted
if (callbacks.onImageUpload) {
- callbacks.onImageUpload(files, editor, $editable);
+ bindCustomEvent($holder, callbacks, 'image.upload')(files);
// else insert Image as dataURL
} else {
$.each(files, function (idx, file) {
var filename = file.name;
if (options.maximumImageFileSize && options.maximumImageFileSize < file.size) {
- if (callbacks.onImageUploadError) {
- callbacks.onImageUploadError(options.langInfo.image.maximumFileSizeError);
- } else {
- alert(options.langInfo.image.maximumFileSizeError);
- }
+ bindCustomEvent($holder, callbacks, 'image.upload.error')(options.langInfo.image.maximumFileSizeError);
} else {
async.readFileAsDataURL(file).then(function (sDataURL) {
- editor.insertImage($editable, sDataURL, filename);
+ modules.editor.insertImage($editable, sDataURL, filename);
}).fail(function () {
- if (callbacks.onImageUploadError) {
- callbacks.onImageUploadError();
- }
+ bindCustomEvent($holder, callbacks, 'image.upload.error')(options.langInfo.image.maximumFileSizeError);
});
}
});
@@ -98,292 +137,90 @@ define([
* @param {Object} layoutInfo
*/
showLinkDialog: function (layoutInfo) {
- var $editor = layoutInfo.editor(),
- $dialog = layoutInfo.dialog(),
- $editable = layoutInfo.editable(),
- linkInfo = editor.getLinkInfo($editable);
-
- var options = $editor.data('options');
-
- editor.saveRange($editable);
- dialog.showLinkDialog($editable, $dialog, linkInfo).then(function (linkInfo) {
- editor.restoreRange($editable);
- editor.createLink($editable, linkInfo, options);
- // hide popover after creating link
- popover.hide(layoutInfo.popover());
- }).fail(function () {
- editor.restoreRange($editable);
- });
+ modules.linkDialog.show(layoutInfo);
},
/**
* @param {Object} layoutInfo
*/
showImageDialog: function (layoutInfo) {
- var $dialog = layoutInfo.dialog(),
- $editable = layoutInfo.editable();
-
- editor.saveRange($editable);
- dialog.showImageDialog($editable, $dialog).then(function (data) {
- editor.restoreRange($editable);
-
- if (typeof data === 'string') {
- // image url
- editor.insertImage($editable, data);
- } else {
- // array of files
- insertImages(layoutInfo, data);
- }
- }).fail(function () {
- editor.restoreRange($editable);
- });
+ modules.imageDialog.show(layoutInfo);
},
/**
* @param {Object} layoutInfo
*/
showHelpDialog: function (layoutInfo) {
- var $dialog = layoutInfo.dialog(),
- $editable = layoutInfo.editable();
-
- editor.saveRange($editable, true);
- dialog.showHelpDialog($editable, $dialog).then(function () {
- editor.restoreRange($editable);
- });
+ modules.helpDialog.show(layoutInfo);
},
+ /**
+ * @param {Object} layoutInfo
+ */
fullscreen: function (layoutInfo) {
- var $editor = layoutInfo.editor(),
- $toolbar = layoutInfo.toolbar(),
- $editable = layoutInfo.editable(),
- $codable = layoutInfo.codable();
-
- var resize = function (size) {
- $editable.css('height', size.h);
- $codable.css('height', size.h);
- if ($codable.data('cmeditor')) {
- $codable.data('cmeditor').setsize(null, size.h);
- }
- };
-
- $editor.toggleClass('fullscreen');
- var isFullscreen = $editor.hasClass('fullscreen');
- if (isFullscreen) {
- $editable.data('orgheight', $editable.css('height'));
-
- $window.on('resize', function () {
- resize({
- h: $window.height() - $toolbar.outerHeight()
- });
- }).trigger('resize');
-
- $scrollbar.css('overflow', 'hidden');
- } else {
- $window.off('resize');
- resize({
- h: $editable.data('orgheight')
- });
- $scrollbar.css('overflow', 'visible');
- }
-
- toolbar.updateFullscreen($toolbar, isFullscreen);
+ modules.fullscreen.toggle(layoutInfo);
},
+ /**
+ * @param {Object} layoutInfo
+ */
codeview: function (layoutInfo) {
- var $editor = layoutInfo.editor(),
- $toolbar = layoutInfo.toolbar(),
- $editable = layoutInfo.editable(),
- $codable = layoutInfo.codable(),
- $popover = layoutInfo.popover(),
- $handle = layoutInfo.handle();
-
- var options = $editor.data('options');
-
- var cmEditor, server;
-
- $editor.toggleClass('codeview');
-
- var isCodeview = $editor.hasClass('codeview');
- if (isCodeview) {
- $codable.val(dom.html($editable, true));
- $codable.height($editable.height());
- toolbar.deactivate($toolbar);
- popover.hide($popover);
- handle.hide($handle);
- $codable.focus();
-
- // activate CodeMirror as codable
- if (agent.hasCodeMirror) {
- cmEditor = CodeMirror.fromTextArea($codable[0], options.codemirror);
-
- // CodeMirror TernServer
- if (options.codemirror.tern) {
- server = new CodeMirror.TernServer(options.codemirror.tern);
- cmEditor.ternServer = server;
- cmEditor.on('cursorActivity', function (cm) {
- server.updateArgHints(cm);
- });
- }
-
- // CodeMirror hasn't Padding.
- cmEditor.setSize(null, $editable.outerHeight());
- $codable.data('cmEditor', cmEditor);
- }
- } else {
- // deactivate CodeMirror as codable
- if (agent.hasCodeMirror) {
- cmEditor = $codable.data('cmEditor');
- $codable.val(cmEditor.getValue());
- cmEditor.toTextArea();
- }
-
- $editable.html(dom.value($codable) || dom.emptyPara);
- $editable.height(options.height ? $codable.height() : 'auto');
-
- toolbar.activate($toolbar);
- $editable.focus();
- }
-
- toolbar.updateCodeview(layoutInfo.toolbar(), isCodeview);
+ modules.codeview.toggle(layoutInfo);
}
};
- this.commands = commands; // odoo change for overwrite
- this.editor = editor; // odoo change for overwrite
- this.toolbar = toolbar; // odoo change for overwrite
- this.popover = popover; // odoo change for overwrite
- this.handle = handle; // odoo change for overwrite
- this.dialog = dialog; // odoo change for overwrite
-
var hMousedown = function (event) {
//preventDefault Selection for FF, IE8+
if (dom.isImg(event.target)) {
event.preventDefault();
- range.createFromNode(event.target).select();
}
};
- var hToolbarAndPopoverUpdate = function (event) {
- // delay for range after mouseup
- setTimeout(function () {
- var layoutInfo = makeLayoutInfo(event.target);
- var $editable = layoutInfo.editable();
- editor.saveRange($editable);
- var styleInfo = editor.currentStyle();
- if (!styleInfo) { return; }
-
- var isAirMode = layoutInfo.editor().data('options').airMode;
- if (!isAirMode) {
- toolbar.update(layoutInfo.toolbar(), styleInfo);
- }
-
- popover.update(layoutInfo.popover(), styleInfo, isAirMode);
- handle.update(layoutInfo.handle(), styleInfo, isAirMode);
- }, 0);
- };
-
- var hScroll = function (event) {
- var layoutInfo = makeLayoutInfo(event.currentTarget || event.target);
- //hide popover and handle when scrolled
- popover.hide(layoutInfo.popover());
- handle.hide(layoutInfo.handle());
+ var hKeyupAndMouseup = function (event) {
+ var layoutInfo = dom.makeLayoutInfo(event.currentTarget || event.target);
+ modules.editor.removeBogus(layoutInfo.editable());
+ hToolbarAndPopoverUpdate(event);
};
/**
- * paste clipboard image
- *
- * @param {Event} event
+ * update sytle info
+ * @param {Object} styleInfo
+ * @param {Object} layoutInfo
*/
- var hPasteClipboardImage = function (event) {
- var clipboardData = event.originalEvent.clipboardData;
- var layoutInfo = makeLayoutInfo(event.currentTarget || event.target);
- var $editable = layoutInfo.editable();
-
- if (!clipboardData || !clipboardData.items || !clipboardData.items.length) {
- var callbacks = $editable.data('callbacks');
- // only can run if it has onImageUpload method
- if (!callbacks.onImageUpload) {
- return;
- }
-
- // save cursor
- editor.saveNode($editable);
- editor.saveRange($editable);
-
- $editable.html('');
-
- setTimeout(function () {
- var $img = $editable.find('img');
- var datauri = $img[0].src;
-
- var data = atob(datauri.split(',')[1]);
- var array = new Uint8Array(data.length);
- for (var i = 0; i < data.length; i++) {
- array[i] = data.charCodeAt(i);
- }
-
- var blob = new Blob([array], { type : 'image/png'});
- blob.name = 'clipboard.png';
-
- editor.restoreNode($editable);
- editor.restoreRange($editable);
- insertImages(layoutInfo, [blob]);
-
- editor.afterCommand($editable);
- }, 0);
-
+ this.updateStyleInfo = function (styleInfo, layoutInfo) {
+ if (!styleInfo) {
return;
}
-
- var item = list.head(clipboardData.items);
- var isClipboardImage = item.kind === 'file' && item.type.indexOf('image/') !== -1;
-
- if (isClipboardImage) {
- insertImages(layoutInfo, [item.getAsFile()]);
+ var isAirMode = layoutInfo.editor().data('options').airMode;
+ if (!isAirMode) {
+ modules.toolbar.update(layoutInfo.toolbar(), styleInfo);
}
- editor.afterCommand($editable);
+ modules.popover.update(layoutInfo.popover(), styleInfo, isAirMode);
+ modules.handle.update(layoutInfo.handle(), styleInfo, isAirMode);
};
- /**
- * `mousedown` event handler on $handle
- * - controlSizing: resize image
- *
- * @param {MouseEvent} event
- */
- var hHandleMousedown = function (event) {
- if (dom.isControlSizing(event.target)) {
- event.preventDefault();
- event.stopPropagation();
-
- var layoutInfo = makeLayoutInfo(event.target),
- $handle = layoutInfo.handle(), $popover = layoutInfo.popover(),
- $editable = layoutInfo.editable(),
- $editor = layoutInfo.editor();
-
- var target = $handle.find('.note-control-selection').data('target'),
- $target = $(target), posStart = $target.offset(),
- scrollTop = $document.scrollTop();
-
- var isAirMode = $editor.data('options').airMode;
-
- $document.on('mousemove', function (event) {
- editor.resizeTo({
- x: event.clientX - posStart.left,
- y: event.clientY - (posStart.top - scrollTop)
- }, $target, !event.shiftKey);
-
- handle.update($handle, {image: target}, isAirMode);
- popover.update($popover, {image: target}, isAirMode);
- }).one('mouseup', function () {
- $document.off('mousemove');
- editor.afterCommand($editable);
- });
-
- if (!$target.data('ratio')) { // original ratio.
- $target.data('ratio', $target.height() / $target.width());
+ var hToolbarAndPopoverUpdate = function (event) {
+ var target = event.target;
+ // delay for range after mouseup
+ setTimeout(function () {
+ var layoutInfo = dom.makeLayoutInfo(target);
+ /* ODOO: (start_modification */
+ var $editable = layoutInfo.editable();
+ if (!event.isDefaultPrevented()) {
+ modules.editor.saveRange($editable);
}
- }
+ /* ODOO: end_modification) */
+ var styleInfo = modules.editor.currentStyle(target);
+ self.updateStyleInfo(styleInfo, layoutInfo);
+ }, 0);
+ };
+
+ var hScroll = function (event) {
+ var layoutInfo = dom.makeLayoutInfo(event.currentTarget || event.target);
+ //hide popover and handle when scrolled
+ modules.popover.hide(layoutInfo.popover());
+ modules.handle.hide(layoutInfo.handle());
};
var hToolbarAndPopoverMousedown = function (event) {
@@ -397,76 +234,49 @@ define([
var hToolbarAndPopoverClick = function (event) {
var $btn = $(event.target).closest('[data-event]');
- if ($btn.length && !$btn.is(':disabled')) {
- var eventName = $btn.attr('data-event'),
- value = $btn.attr('data-value'),
- hide = $btn.attr('data-hide');
-
- var layoutInfo = makeLayoutInfo(event.target);
-
- var $editable = layoutInfo.editable();
- editor.restoreRange($editable);
-
- // before command: detect control selection element($target)
- var $target;
- if ($.inArray(eventName, ['resize', 'floatMe', 'removeMedia', 'imageShape']) !== -1) {
- var $selection = layoutInfo.handle().find('.note-control-selection');
- $target = $($selection.data('target'));
- }
-
- // If requested, hide the popover when the button is clicked.
- // Useful for things like showHelpDialog.
- if (hide) {
- $btn.parents('.popover').hide();
- }
+ if (!$btn.length) {
+ return;
+ }
- if ($.isFunction($.summernote.pluginEvents[eventName])) {
- $.summernote.pluginEvents[eventName](event, editor, layoutInfo, value);
- } else if (editor[eventName]) { // on command
- $editable.trigger('focus');
- editor[eventName]($editable, value, $target);
- event.preventDefault();
- } else if (commands[eventName]) {
- commands[eventName].call(this, layoutInfo);
- event.preventDefault();
- }
+ var eventName = $btn.attr('data-event'),
+ value = $btn.attr('data-value'),
+ hide = $btn.attr('data-hide');
- // after command
- if ($.inArray(eventName, ['backColor', 'foreColor']) !== -1) {
- var options = layoutInfo.editor().data('options', options);
- var module = options.airMode ? popover : toolbar;
- module.updateRecentColor(list.head($btn), eventName, value);
- }
+ var layoutInfo = dom.makeLayoutInfo(event.target);
- hToolbarAndPopoverUpdate(event);
+ // before command: detect control selection element($target)
+ var $target;
+ if ($.inArray(eventName, ['resize', 'floatMe', 'removeMedia', 'imageShape']) !== -1) {
+ var $selection = layoutInfo.handle().find('.note-control-selection');
+ $target = $($selection.data('target'));
}
- };
- var EDITABLE_PADDING = 24;
- /**
- * `mousedown` event handler on statusbar
- *
- * @param {MouseEvent} event
- */
- var hStatusbarMousedown = function (event) {
- event.preventDefault();
- event.stopPropagation();
-
- var layoutInfo = makeLayoutInfo(event.target);
- var $editable = layoutInfo.editable();
- var nEditableTop = $editable.offset().top - $document.scrollTop();
- var options = layoutInfo.editor().data('options');
+ // If requested, hide the popover when the button is clicked.
+ // Useful for things like showHelpDialog.
+ if (hide) {
+ $btn.parents('.popover').hide();
+ }
- $document.on('mousemove', function (event) {
- var nHeight = event.clientY - (nEditableTop + EDITABLE_PADDING);
+ if ($.isFunction($.summernote.pluginEvents[eventName])) {
+ $.summernote.pluginEvents[eventName](event, modules.editor, layoutInfo, value);
+ } else if (modules.editor[eventName]) { // on command
+ var $editable = layoutInfo.editable();
+ $editable.focus();
+ modules.editor[eventName]($editable, value, $target);
+ event.preventDefault();
+ } else if (commands[eventName]) {
+ commands[eventName].call(this, layoutInfo);
+ event.preventDefault();
+ }
- nHeight = (options.minHeight > 0) ? Math.max(nHeight, options.minHeight) : nHeight;
- nHeight = (options.maxHeight > 0) ? Math.min(nHeight, options.maxHeight) : nHeight;
+ // after command
+ if ($.inArray(eventName, ['backColor', 'foreColor']) !== -1) {
+ var options = layoutInfo.editor().data('options', options);
+ var module = options.airMode ? modules.popover : modules.toolbar;
+ module.updateRecentColor(list.head($btn), eventName, value);
+ }
- $editable.height(nHeight);
- }).one('mouseup', function () {
- $document.off('mousemove');
- });
+ hToolbarAndPopoverUpdate(event);
};
var PX_PER_EM = 18;
@@ -510,81 +320,7 @@ define([
$dimensionDisplay.html(dim.c + ' x ' + dim.r);
};
-
- /**
- * Drag and Drop Events
- *
- * @param {Object} layoutInfo - layout Informations
- * @param {Object} options
- */
- var handleDragAndDropEvent = function (layoutInfo, options) {
- if (options.disableDragAndDrop) {
- // prevent default drop event
- $document.on('drop', function (e) {
- e.preventDefault();
- });
- } else {
- attachDragAndDropEvent(layoutInfo, options);
- }
- };
-
- /**
- * attach Drag and Drop Events
- *
- * @param {Object} layoutInfo - layout Informations
- * @param {Object} options
- */
- var attachDragAndDropEvent = function (layoutInfo, options) {
- var collection = $(),
- $dropzone = layoutInfo.dropzone,
- $dropzoneMessage = layoutInfo.dropzone.find('.note-dropzone-message');
-
- // show dropzone on dragenter when dragging a object to document.
- $document.on('dragenter', function (e) {
- var isCodeview = layoutInfo.editor.hasClass('codeview');
- if (!isCodeview && !collection.length) {
- layoutInfo.editor.addClass('dragover');
- $dropzone.width(layoutInfo.editor.width());
- $dropzone.height(layoutInfo.editor.height());
- $dropzoneMessage.text(options.langInfo.image.dragImageHere);
- }
- collection = collection.add(e.target);
- }).on('dragleave', function (e) {
- collection = collection.not(e.target);
- if (!collection.length) {
- layoutInfo.editor.removeClass('dragover');
- }
- }).on('drop', function () {
- collection = $();
- layoutInfo.editor.removeClass('dragover');
- });
-
- // change dropzone's message on hover.
- $dropzone.on('dragenter', function () {
- $dropzone.addClass('hover');
- $dropzoneMessage.text(options.langInfo.image.dropImage);
- }).on('dragleave', function () {
- $dropzone.removeClass('hover');
- $dropzoneMessage.text(options.langInfo.image.dragImageHere);
- });
-
- // attach dropImage
- $dropzone.on('drop', function (event) {
- event.preventDefault();
-
- var dataTransfer = event.originalEvent.dataTransfer;
- var text = dataTransfer.getData('text/plain');
- var layoutInfo = makeLayoutInfo(event.currentTarget || event.target);
- layoutInfo.editable().focus();
- if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
- insertImages(layoutInfo, dataTransfer.files);
- } else if (text) {
- editor.insertText(layoutInfo.editable(), text);
- }
- }).on('dragover', false); // prevent default dragover event
- };
-
-
+
/**
* bind KeyMap on keydown
*
@@ -592,25 +328,28 @@ define([
* @param {Object} keyMap
*/
this.bindKeyMap = function (layoutInfo, keyMap) {
- var $editor = layoutInfo.editor;
- var $editable = layoutInfo.editable;
-
- layoutInfo = makeLayoutInfo($editable);
+ var $editor = layoutInfo.editor();
+ var $editable = layoutInfo.editable();
$editable.on('keydown', function (event) {
- var aKey = [];
+ var keys = [];
// modifier
- if (event.metaKey) { aKey.push('CMD'); }
- if (event.ctrlKey && !event.altKey) { aKey.push('CTRL'); }
- if (event.shiftKey) { aKey.push('SHIFT'); }
+ if (event.metaKey) { keys.push('CMD'); }
+ if (event.ctrlKey && !event.altKey) { keys.push('CTRL'); }
+ if (event.shiftKey) { keys.push('SHIFT'); }
// keycode
var keyName = key.nameFromCode[event.keyCode];
- if (keyName) { aKey.push(keyName); }
+ if (keyName) {
+ keys.push(keyName);
+ }
- var eventName = keyMap[aKey.join('+')];
+ var pluginEvent;
+ var keyString = keys.join('+');
+ var eventName = keyMap[keyString];
+ // ODOO: (start_modification
// odoo change: add visible event to overwrite the browser comportment
var keycode = event.keyCode;
if (!eventName &&
@@ -623,27 +362,33 @@ define([
(keycode > 218 && keycode < 223))) { // [\]' (in order))
eventName = 'visible';
} else if (!keycode) {
- editor.restoreRange($editable);
+ self.invoke('restoreRange', $editable);
}
+ // ODOO: end_modification)
if (eventName) {
- if ($.summernote.pluginEvents[eventName]) {
- var plugin = $.summernote.pluginEvents[eventName];
- if ($.isFunction(plugin)) {
- plugin(event, editor, layoutInfo);
+ // FIXME Summernote doesn't support event pipeline yet.
+ // - Plugin -> Base Code
+ pluginEvent = $.summernote.pluginEvents[keyString];
+ if ($.isFunction(pluginEvent)) {
+ if (pluginEvent(event, modules.editor, layoutInfo)) {
+ return false;
}
- } else if (editor[eventName]) {
- editor[eventName]($editable, $editor.data('options'));
+ }
+
+ pluginEvent = $.summernote.pluginEvents[eventName];
+
+ if ($.isFunction(pluginEvent)) {
+ pluginEvent(event, modules.editor, layoutInfo);
+ } else if (modules.editor[eventName]) {
+ modules.editor[eventName]($editable, $editor.data('options'));
event.preventDefault();
} else if (commands[eventName]) {
commands[eventName].call(this, layoutInfo);
event.preventDefault();
}
- if (keycode) {
- editor.saveRange($editable);
- }
} else if (key.isEdit(event.keyCode)) {
- editor.afterCommand($editable);
+ modules.editor.afterCommand($editable);
}
});
};
@@ -653,41 +398,40 @@ define([
*
* @param {Object} layoutInfo - layout Informations
* @param {Object} options - user options include custom event handlers
- * @param {Function} options.enter - enter key handler
*/
this.attach = function (layoutInfo, options) {
// handlers for editable
if (options.shortcuts) {
this.bindKeyMap(layoutInfo, options.keyMap[agent.isMac ? 'mac' : 'pc']);
}
- layoutInfo.editable.on('mousedown', hMousedown);
- layoutInfo.editable.on('keyup mouseup', hToolbarAndPopoverUpdate);
- layoutInfo.editable.on('scroll', hScroll);
- layoutInfo.editable.on('paste', hPasteClipboardImage);
+ layoutInfo.editable().on('mousedown', hMousedown);
+ layoutInfo.editable().on('keyup mouseup', hKeyupAndMouseup);
+ layoutInfo.editable().on('scroll', hScroll);
+
+ // handler for clipboard
+ modules.clipboard.attach(layoutInfo, options);
// handler for handle and popover
- layoutInfo.handle.on('mousedown', hHandleMousedown);
- layoutInfo.popover.on('click', hToolbarAndPopoverClick);
- layoutInfo.popover.on('mousedown', hToolbarAndPopoverMousedown);
+ modules.handle.attach(layoutInfo, options);
+ layoutInfo.popover().on('click', hToolbarAndPopoverClick);
+ layoutInfo.popover().on('mousedown', hToolbarAndPopoverMousedown);
+
+ // handler for drag and drop
+ modules.dragAndDrop.attach(layoutInfo, options);
// handlers for frame mode (toolbar, statusbar)
if (!options.airMode) {
- // handler for drag and drop
- handleDragAndDropEvent(layoutInfo, options);
-
// handler for toolbar
- layoutInfo.toolbar.on('click', hToolbarAndPopoverClick);
- layoutInfo.toolbar.on('mousedown', hToolbarAndPopoverMousedown);
+ layoutInfo.toolbar().on('click', hToolbarAndPopoverClick);
+ layoutInfo.toolbar().on('mousedown', hToolbarAndPopoverMousedown);
// handler for statusbar
- if (!options.disableResizeEditor) {
- layoutInfo.statusbar.on('mousedown', hStatusbarMousedown);
- }
+ modules.statusbar.attach(layoutInfo, options);
}
// handler for table dimension
- var $catcherContainer = options.airMode ? layoutInfo.popover :
- layoutInfo.toolbar;
+ var $catcherContainer = options.airMode ? layoutInfo.popover() :
+ layoutInfo.toolbar();
var $catcher = $catcherContainer.find('.note-dimension-picker-mousecatcher');
$catcher.css({
width: options.insertTableMaxSize.col + 'em',
@@ -697,72 +441,121 @@ define([
});
// save options on editor
- layoutInfo.editor.data('options', options);
+ layoutInfo.editor().data('options', options);
// ret styleWithCSS for backColor / foreColor clearing with 'inherit'.
if (!agent.isMSIE) {
- // protect FF Error: NS_ERROR_FAILURE: Failure
+ // [workaround] for Firefox
+ // - protect FF Error: NS_ERROR_FAILURE: Failure
setTimeout(function () {
document.execCommand('styleWithCSS', 0, options.styleWithSpan);
}, 0);
}
// History
- var history = new History(layoutInfo.editable);
- layoutInfo.editable.data('NoteHistory', history);
-
- // basic event callbacks (lowercase)
- // enter, focus, blur, keyup, keydown
- if (options.onenter) {
- layoutInfo.editable.keypress(function (event) {
- if (event.keyCode === key.ENTER) { options.onenter(event); }
- });
- }
-
- if (options.onfocus) { layoutInfo.editable.focus(options.onfocus); }
- if (options.onblur) { layoutInfo.editable.blur(options.onblur); }
- if (options.onkeyup) { layoutInfo.editable.keyup(options.onkeyup); }
- if (options.onkeydown) { layoutInfo.editable.keydown(options.onkeydown); }
- if (options.onpaste) { layoutInfo.editable.on('paste', options.onpaste); }
-
- // callbacks for advanced features (camel)
- if (options.onToolbarClick) { layoutInfo.toolbar.click(options.onToolbarClick); }
- if (options.onChange) {
- var hChange = function () {
- editor.triggerOnChange(layoutInfo.editable);
- };
-
- if (agent.isMSIE) {
- var sDomEvents = 'DOMCharacterDataModified DOMSubtreeModified DOMNodeInserted';
- layoutInfo.editable.on(sDomEvents, hChange);
- } else {
- layoutInfo.editable.on('input', hChange);
- }
- }
+ var history = new History(layoutInfo.editable());
+ layoutInfo.editable().data('NoteHistory', history);
// All editor status will be saved on editable with jquery's data
// for support multiple editor with singleton object.
- layoutInfo.editable.data('callbacks', {
+ layoutInfo.editable().data('callbacks', {
+ onInit: options.onInit,
+ onFocus: options.onFocus,
+ onBlur: options.onBlur,
+ onKeydown: options.onKeydown,
+ onKeyup: options.onKeyup,
+ onMousedown: options.onMousedown,
+ onEnter: options.onEnter,
+ onPaste: options.onPaste,
+ onBeforeCommand: options.onBeforeCommand,
onChange: options.onChange,
- onAutoSave: options.onAutoSave,
onImageUpload: options.onImageUpload,
onImageUploadError: options.onImageUploadError,
- onFileUpload: options.onFileUpload,
- onFileUploadError: options.onFileUpload
+ onMediaDelete: options.onMediaDelete,
+ onToolbarClick: options.onToolbarClick
});
+
+ var styleInfo = modules.editor.styleFromNode(layoutInfo.editable());
+ this.updateStyleInfo(styleInfo, layoutInfo);
};
+ /**
+ * attach jquery custom event
+ *
+ * @param {Object} layoutInfo - layout Informations
+ */
+ this.attachCustomEvent = function (layoutInfo, options) {
+ var $holder = layoutInfo.holder();
+ var $editable = layoutInfo.editable();
+ var callbacks = $editable.data('callbacks');
+
+ $editable.focus(bindCustomEvent($holder, callbacks, 'focus'));
+ $editable.blur(bindCustomEvent($holder, callbacks, 'blur'));
+
+ $editable.keydown(function (event) {
+ if (event.keyCode === key.code.ENTER) {
+ bindCustomEvent($holder, callbacks, 'enter').call(this, event);
+ }
+ bindCustomEvent($holder, callbacks, 'keydown').call(this, event);
+ });
+ $editable.keyup(bindCustomEvent($holder, callbacks, 'keyup'));
+
+ $editable.on('mousedown', bindCustomEvent($holder, callbacks, 'mousedown'));
+ $editable.on('mouseup', bindCustomEvent($holder, callbacks, 'mouseup'));
+ $editable.on('scroll', bindCustomEvent($holder, callbacks, 'scroll'));
+
+ $editable.on('paste', bindCustomEvent($holder, callbacks, 'paste'));
+
+ // [workaround] IE doesn't have input events for contentEditable
+ // - see: https://goo.gl/4bfIvA
+ var changeEventName = agent.isMSIE ? 'DOMCharacterDataModified DOMSubtreeModified DOMNodeInserted' : 'input';
+ $editable.on(changeEventName, function () {
+ bindCustomEvent($holder, callbacks, 'change')($editable.html(), $editable);
+ });
+
+ if (!options.airMode) {
+ layoutInfo.toolbar().click(bindCustomEvent($holder, callbacks, 'toolbar.click'));
+ layoutInfo.popover().click(bindCustomEvent($holder, callbacks, 'popover.click'));
+ }
+
+ // Textarea: auto filling the code before form submit.
+ if (dom.isTextarea(list.head($holder))) {
+ $holder.closest('form').submit(function (e) {
+ layoutInfo.holder().val(layoutInfo.holder().code());
+ bindCustomEvent($holder, callbacks, 'submit').call(this, e, $holder.code());
+ });
+ }
+
+ // textarea auto sync
+ if (dom.isTextarea(list.head($holder)) && options.textareaAutoSync) {
+ $holder.on('summernote.change', function () {
+ layoutInfo.holder().val(layoutInfo.holder().code());
+ });
+ }
+
+ // fire init event
+ bindCustomEvent($holder, callbacks, 'init')(layoutInfo);
+
+ // fire plugin init event
+ for (var i = 0, len = $.summernote.plugins.length; i < len; i++) {
+ if ($.isFunction($.summernote.plugins[i].init)) {
+ $.summernote.plugins[i].init(layoutInfo);
+ }
+ }
+ };
+
this.detach = function (layoutInfo, options) {
- layoutInfo.editable.off();
+ layoutInfo.holder().off();
+ layoutInfo.editable().off();
- layoutInfo.popover.off();
- layoutInfo.handle.off();
- layoutInfo.dialog.off();
+ layoutInfo.popover().off();
+ layoutInfo.handle().off();
+ layoutInfo.dialog().off();
if (!options.airMode) {
- layoutInfo.dropzone.off();
- layoutInfo.toolbar.off();
- layoutInfo.statusbar.off();
+ layoutInfo.dropzone().off();
+ layoutInfo.toolbar().off();
+ layoutInfo.statusbar().off();
}
};
};