diff --git a/wagtail/wagtailadmin/static/wagtailadmin/js/vendor/hallo.js b/wagtail/wagtailadmin/static/wagtailadmin/js/vendor/hallo.js index 7ba3ff2c03..af5950fdbd 100644 --- a/wagtail/wagtailadmin/static/wagtailadmin/js/vendor/hallo.js +++ b/wagtail/wagtailadmin/static/wagtailadmin/js/vendor/hallo.js @@ -1,671 +1,607 @@ -// Generated by CoffeeScript 1.3.3 -(function() { - - $.widget("ncri.hallohtml", { - options: { - editable: null, +/* Hallo 1.0.4 - rich text editor for jQuery UI +* by Henri Bergius and contributors. Available under the MIT license. +* See http://hallojs.org for more information +*/(function() { + (function(jQuery) { + return jQuery.widget('IKS.hallo', { toolbar: null, - uuid: "", - lang: 'en', - dialogOpts: { - autoOpen: false, - width: 600, - height: 'auto', - modal: false, - resizable: true, - draggable: true, - dialogClass: 'htmledit-dialog' + bound: false, + originalContent: '', + previousContent: '', + uuid: '', + selection: null, + _keepActivated: false, + originalHref: null, + options: { + editable: true, + plugins: {}, + toolbar: 'halloToolbarContextual', + parentElement: 'body', + buttonCssClass: null, + toolbarCssClass: null, + toolbarPositionAbove: false, + toolbarOptions: {}, + placeholder: '', + forceStructured: true, + checkTouch: true, + touchScreen: null }, - dialog: null, - buttonCssClass: null - }, - translations: { - en: { - title: 'Edit HTML', - update: 'Update' + _create: function() { + var options, plugin, _ref, + _this = this; + this.id = this._generateUUID(); + if (this.options.checkTouch && this.options.touchScreen === null) { + this.checkTouch(); + } + _ref = this.options.plugins; + for (plugin in _ref) { + options = _ref[plugin]; + if (!jQuery.isPlainObject(options)) { + options = {}; + } + jQuery.extend(options, { + editable: this, + uuid: this.id, + buttonCssClass: this.options.buttonCssClass + }); + jQuery(this.element)[plugin](options); + } + this.element.one('halloactivated', function() { + return _this._prepareToolbar(); + }); + return this.originalContent = this.getContents(); }, - de: { - title: 'HTML bearbeiten', - update: 'Aktualisieren' - } - }, - texts: null, - populateToolbar: function($toolbar) { - var $buttonHolder, $buttonset, id, widget; - widget = this; - this.texts = this.translations[this.options.lang]; - this.options.toolbar = $toolbar; - this.options.dialog = $("
").attr('id', "" + this.options.uuid + "-htmledit-dialog"); - $buttonset = $("").addClass(widget.widgetName); - id = "" + this.options.uuid + "-htmledit"; - $buttonHolder = $(''); - $buttonHolder.hallobutton({ - label: this.texts.title, - icon: 'icon-list-alt', - editable: this.options.editable, - command: null, - queryState: false, - uuid: this.options.uuid, - cssClass: this.options.buttonCssClass - }); - $buttonset.append($buttonHolder); - this.button = $buttonHolder; - this.button.click(function() { - if (widget.options.dialog.dialog("isOpen")) { - widget._closeDialog(); + _init: function() { + if (this.options.editable) { + return this.enable(); } else { - widget._openDialog(); + return this.disable(); + } + }, + destroy: function() { + var options, plugin, _ref; + this.disable(); + if (this.toolbar) { + this.toolbar.remove(); + this.element[this.options.toolbar]('destroy'); + } + _ref = this.options.plugins; + for (plugin in _ref) { + options = _ref[plugin]; + jQuery(this.element)[plugin]('destroy'); + } + return jQuery.Widget.prototype.destroy.call(this); + }, + disable: function() { + var _this = this; + this.element.attr("contentEditable", false); + this.element.off("focus", this._activated); + this.element.off("blur", this._deactivated); + this.element.off("keyup paste change", this._checkModified); + this.element.off("keyup", this._keys); + this.element.off("keyup mouseup", this._checkSelection); + this.bound = false; + jQuery(this.element).removeClass('isModified'); + jQuery(this.element).removeClass('inEditMode'); + this.element.parents('a').addBack().each(function(idx, elem) { + var element; + element = jQuery(elem); + if (!element.is('a')) { + return; + } + if (!_this.originalHref) { + return; + } + return element.attr('href', _this.originalHref); + }); + return this._trigger("disabled", null); + }, + enable: function() { + var _this = this; + this.element.parents('a[href]').addBack().each(function(idx, elem) { + var element; + element = jQuery(elem); + if (!element.is('a[href]')) { + return; + } + _this.originalHref = element.attr('href'); + return element.removeAttr('href'); + }); + this.element.attr("contentEditable", true); + if (!jQuery.parseHTML(this.element.html())) { + this.element.html(this.options.placeholder); + jQuery(this.element).addClass('inPlaceholderMode'); + this.element.css({ + 'min-width': this.element.innerWidth(), + 'min-height': this.element.innerHeight() + }); + } + if (!this.bound) { + this.element.on("focus", this, this._activated); + this.element.on("blur", this, this._deactivated); + this.element.on("keyup paste change", this, this._checkModified); + this.element.on("keyup", this, this._keys); + this.element.on("keyup mouseup", this, this._checkSelection); + this.bound = true; + } + if (this.options.forceStructured) { + this._forceStructured(); + } + return this._trigger("enabled", null); + }, + activate: function() { + return this.element.focus(); + }, + containsSelection: function() { + var range; + range = this.getSelection(); + return this.element.has(range.startContainer).length > 0; + }, + getSelection: function() { + var range, sel; + sel = rangy.getSelection(); + range = null; + if (sel.rangeCount > 0) { + range = sel.getRangeAt(0); + } else { + range = rangy.createRange(); + } + return range; + }, + restoreSelection: function(range) { + var sel; + sel = rangy.getSelection(); + return sel.setSingleRange(range); + }, + replaceSelection: function(cb) { + var newTextNode, r, range, sel, t; + if (navigator.appName === 'Microsoft Internet Explorer') { + t = document.selection.createRange().text; + r = document.selection.createRange(); + return r.pasteHTML(cb(t)); + } else { + sel = window.getSelection(); + range = sel.getRangeAt(0); + newTextNode = document.createTextNode(cb(range.extractContents())); + range.insertNode(newTextNode); + range.setStartAfter(newTextNode); + sel.removeAllRanges(); + return sel.addRange(range); + } + }, + removeAllSelections: function() { + if (navigator.appName === 'Microsoft Internet Explorer') { + return range.empty(); + } else { + return window.getSelection().removeAllRanges(); + } + }, + getPluginInstance: function(plugin) { + var instance; + instance = jQuery(this.element).data("IKS-" + plugin); + if (instance) { + return instance; + } + instance = jQuery(this.element).data(plugin); + if (instance) { + return instance; + } + throw new Error("Plugin " + plugin + " not found"); + }, + getContents: function() { + var cleanup, instance, plugin; + for (plugin in this.options.plugins) { + instance = this.getPluginInstance(plugin); + if (!instance) { + continue; + } + cleanup = instance.cleanupContentClone; + if (!jQuery.isFunction(cleanup)) { + continue; + } + jQuery(this.element)[plugin]('cleanupContentClone', this.element); + } + return this.element.html(); + }, + setContents: function(contents) { + return this.element.html(contents); + }, + isModified: function() { + if (!this.previousContent) { + this.previousContent = this.originalContent; + } + return this.previousContent !== this.getContents(); + }, + setUnmodified: function() { + jQuery(this.element).removeClass('isModified'); + return this.previousContent = this.getContents(); + }, + setModified: function() { + jQuery(this.element).addClass('isModified'); + return this._trigger('modified', null, { + editable: this, + content: this.getContents() + }); + }, + restoreOriginalContent: function() { + return this.element.html(this.originalContent); + }, + execute: function(command, value) { + if (document.execCommand(command, false, value)) { + return this.element.trigger("change"); + } + }, + protectFocusFrom: function(el) { + var _this = this; + return el.on("mousedown", function(event) { + event.preventDefault(); + _this._protectToolbarFocus = true; + return setTimeout(function() { + return _this._protectToolbarFocus = false; + }, 300); + }); + }, + keepActivated: function(_keepActivated) { + this._keepActivated = _keepActivated; + }, + _generateUUID: function() { + var S4; + S4 = function() { + return ((1 + Math.random()) * 0x10000 | 0).toString(16).substring(1); + }; + return "" + (S4()) + (S4()) + "-" + (S4()) + "-" + (S4()) + "-" + (S4()) + "-" + (S4()) + (S4()) + (S4()); + }, + _prepareToolbar: function() { + var defaults, instance, plugin, populate, toolbarOptions; + this.toolbar = jQuery('
').hide(); + if (this.options.toolbarCssClass) { + this.toolbar.addClass(this.options.toolbarCssClass); + } + defaults = { + editable: this, + parentElement: this.options.parentElement, + toolbar: this.toolbar, + positionAbove: this.options.toolbarPositionAbove + }; + toolbarOptions = jQuery.extend({}, defaults, this.options.toolbarOptions); + this.element[this.options.toolbar](toolbarOptions); + for (plugin in this.options.plugins) { + instance = this.getPluginInstance(plugin); + if (!instance) { + continue; + } + populate = instance.populateToolbar; + if (!jQuery.isFunction(populate)) { + continue; + } + this.element[plugin]('populateToolbar', this.toolbar); + } + this.element[this.options.toolbar]('setPosition'); + return this.protectFocusFrom(this.toolbar); + }, + changeToolbar: function(element, toolbar, hide) { + var originalToolbar; + if (hide == null) { + hide = false; + } + originalToolbar = this.options.toolbar; + this.options.parentElement = element; + if (toolbar) { + this.options.toolbar = toolbar; + } + if (!this.toolbar) { + return; + } + this.element[originalToolbar]('destroy'); + this.toolbar.remove(); + this._prepareToolbar(); + if (hide) { + return this.toolbar.hide(); + } + }, + _checkModified: function(event) { + var widget; + widget = event.data; + if (widget.isModified()) { + return widget.setModified(); + } + }, + _keys: function(event) { + var old, widget; + widget = event.data; + if (event.keyCode === 27) { + old = widget.getContents(); + widget.restoreOriginalContent(event); + widget._trigger("restored", null, { + editable: widget, + content: widget.getContents(), + thrown: old + }); + return widget.turnOff(); + } + }, + _rangesEqual: function(r1, r2) { + if (r1.startContainer !== r2.startContainer) { + return false; + } + if (r1.startOffset !== r2.startOffset) { + return false; + } + if (r1.endContainer !== r2.endContainer) { + return false; + } + if (r1.endOffset !== r2.endOffset) { + return false; + } + return true; + }, + _checkSelection: function(event) { + var widget; + if (event.keyCode === 27) { + return; + } + widget = event.data; + return setTimeout(function() { + var sel; + sel = widget.getSelection(); + if (widget._isEmptySelection(sel) || widget._isEmptyRange(sel)) { + if (widget.selection) { + widget.selection = null; + widget._trigger("unselected", null, { + editable: widget, + originalEvent: event + }); + } + return; + } + if (!widget.selection || !widget._rangesEqual(sel, widget.selection)) { + widget.selection = sel.cloneRange(); + return widget._trigger("selected", null, { + editable: widget, + selection: widget.selection, + ranges: [widget.selection], + originalEvent: event + }); + } + }, 0); + }, + _isEmptySelection: function(selection) { + if (selection.type === "Caret") { + return true; } return false; - }); - this.options.editable.element.on("hallodeactivated", function() { - return widget._closeDialog(); - }); - $toolbar.append($buttonset); - this.options.dialog.dialog(this.options.dialogOpts); - return this.options.dialog.dialog("option", "title", this.texts.title); - }, - _openDialog: function() { - var $editableEl, html, widget, xposition, yposition, - _this = this; - widget = this; - $editableEl = $(this.options.editable.element); - xposition = $editableEl.offset().left + $editableEl.outerWidth() + 10; - yposition = this.options.toolbar.offset().top - $(document).scrollTop(); - this.options.dialog.dialog("option", "position", [xposition, yposition]); - this.options.editable.keepActivated(true); - this.options.dialog.dialog("open"); - this.options.dialog.on('dialogclose', function() { - $('label', _this.button).removeClass('ui-state-active'); - _this.options.editable.element.focus(); - return _this.options.editable.keepActivated(false); - }); - this.options.dialog.html($("