From a3234fdc4c5e085d9752b41953cd24df7aa15990 Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Thu, 27 Mar 2014 15:58:22 +0100 Subject: [PATCH] Added autosave feature --- com.woltlab.wcf/templates/wysiwyg.tpl | 12 +- .../js/3rdParty/redactor/plugins/wbbcode.js | 11 ++ .../js/3rdParty/redactor/plugins/wutil.js | 127 +++++++++++++++++- wcfsetup/install/files/js/WCF.Message.js | 4 + 4 files changed, 148 insertions(+), 6 deletions(-) diff --git a/com.woltlab.wcf/templates/wysiwyg.tpl b/com.woltlab.wcf/templates/wysiwyg.tpl index 365d41e819..4a1283fce4 100644 --- a/com.woltlab.wcf/templates/wysiwyg.tpl +++ b/com.woltlab.wcf/templates/wysiwyg.tpl @@ -11,6 +11,8 @@ $(function() { var $callbackIdentifier = 'Redactor_' + $editorName; WCF.System.Dependency.Manager.setup($callbackIdentifier, function() { + var $textarea = $('#' + $editorName); + // // TODO: toolbar configuration / 'wysiwygToolbar.tpl' // @@ -21,9 +23,17 @@ $(function() { plugins: [ 'wbbcode', 'wbutton', 'wfontcolor', 'wmonkeypatch', 'wutil' ] }; + // autosave config + if ($textarea.data('autosave')) { + $config.wautosave = { + active: true, + key: $textarea.data('autosave') + } + } + {event name='javascriptInit'} - $('#' + $editorName).redactor($config); + $textarea.redactor($config); }); head.load([ diff --git a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js index 7fbf48892f..7fc2e3808d 100644 --- a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js +++ b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js @@ -89,6 +89,17 @@ RedactorPlugins.wbbcode = { return true; }, + /** + * Overwrites $.Redactor.buildContent() to handle BBCode -> HTML on init + */ + buildContent: function() { + if (this.opts.textareamode) this.content = $.trim(this.$source.val()); + else { + this._convertToHtml(); + this.content = $.trim(this.$source.html()); + } + }, + /** * Overwrites $.Redactor.toggle() to transform the source mode into a BBCode view. * diff --git a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wutil.js b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wutil.js index e85bb0bb6a..2d5b59c097 100644 --- a/wcfsetup/install/files/js/3rdParty/redactor/plugins/wutil.js +++ b/wcfsetup/install/files/js/3rdParty/redactor/plugins/wutil.js @@ -8,12 +8,32 @@ if (!RedactorPlugins) var RedactorPlugins = {}; * @license GNU Lesser General Public License */ RedactorPlugins.wutil = { + /** + * autosave worker process + * @var WCF.PeriodicalExecuter + */ + _autosaveWorker: null, + /** * Initializes the RedactorPlugins.wutil plugin. */ init: function() { // convert HTML to BBCode upon submit this.$source.parents('form').submit($.proxy(this.submit, this)); + + if (this.getOption('wautosave').active) { + this.autosaveEnable(); + + if (this.getOption('wautosave').saveOnInit || this.$source.data('saveOnInit')) { + this._saveTextToStorage(); + } + else { + this.autosaveRestore(); + } + } + + // prevent Redactor's own autosave + this.setOption('autosave', false); }, /** @@ -49,26 +69,42 @@ RedactorPlugins.wutil = { * @param string plainValue */ insertDynamic: function(html, plainValue) { - if (plainValue === undefined || plainValue === null) { - // shortcut if both 'html' and 'html' are the same - plainValue = html; - } - if (this.inWysiwygMode()) { this.insertHtml(html); } else { + if (plainValue === undefined || plainValue === null) { + plainValue = html; + } + this.insertAtCaret(plainValue); } }, /** * Sets an option value after initialization. + * + * @param string key + * @param mixed value */ setOption: function(key, value) { this.opts[key] = value; }, + /** + * Reads an option value, returns null if key is unknown. + * + * @param string key + * @return mixed + */ + getOption: function(key) { + if (this.opts[key]) { + return this.opts[key]; + } + + return null; + }, + /** * Returns true if editor is in source mode. * @@ -121,6 +157,8 @@ RedactorPlugins.wutil = { this._convertFromHtml(); } + + this.autosavePurge(); }, /** @@ -134,5 +172,84 @@ RedactorPlugins.wutil = { else { this.$source.val(''); } + }, + + /** + * Enables automatic saving every minute. + * + * @param string key + */ + autosaveEnable: function(key) { + if (!this.getOption('wautosave').active) { + this.setOption('wautosave', { + active: true, + key: key + }); + } + + if (this._autosaveWorker === null) { + var self = this; + this._autosaveWorker = new WCF.PeriodicalExecuter($.proxy(this._saveTextToStorage, this), 60 * 1000); + } + + return true; + }, + + /** + * Saves current editor text to local browser storage. + */ + _saveTextToStorage: function() { + localStorage.setItem(this.getOption('wautosave').key, this.getText()); + }, + + /** + * Disables automatic saving. + */ + autosaveDisable: function() { + if (!this.getOption('wautosave').active) { + return false; + } + + this._autosaveWorker.stop(); + this._autosaveWorker = null; + + this.setOption('wautosave', { + active: false, + key: '' + }); + + return true; + }, + + /** + * Attempts to purge saved text. + * + * @param string key + */ + autosavePurge: function() { + localStorage.removeItem(this.getOption('wautosave').key); + }, + + /** + * Attempts to restore a saved text. + */ + autosaveRestore: function() { + var $options = this.getOption('wautosave'); + var $text = localStorage.getItem($options.key); + if ($text !== null) { + if (this.inWysiwygMode()) { + this.toggle(false); + this.$source.val($text); + this.toggle(false); + this.focusEnd(); + } + else { + this.$source.val($text); + } + + return true; + } + + return false; } }; diff --git a/wcfsetup/install/files/js/WCF.Message.js b/wcfsetup/install/files/js/WCF.Message.js index e39176b070..f36592e370 100644 --- a/wcfsetup/install/files/js/WCF.Message.js +++ b/wcfsetup/install/files/js/WCF.Message.js @@ -862,6 +862,10 @@ WCF.Message.QuickReply = Class.extend({ * @param jQuery jqXHR */ _success: function(data, textStatus, jqXHR) { + if ($.browser.redactor) { + this._messageField.redactor('autosavePurge'); + } + // redirect to new page if (data.returnValues.url) { window.location = data.returnValues.url; -- 2.20.1