Added autosave feature
authorAlexander Ebert <ebert@woltlab.com>
Thu, 27 Mar 2014 14:58:22 +0000 (15:58 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Thu, 27 Mar 2014 14:58:22 +0000 (15:58 +0100)
com.woltlab.wcf/templates/wysiwyg.tpl
wcfsetup/install/files/js/3rdParty/redactor/plugins/wbbcode.js
wcfsetup/install/files/js/3rdParty/redactor/plugins/wutil.js
wcfsetup/install/files/js/WCF.Message.js

index 365d41e8191104591b46f276cd398d704e0e84d7..4a1283fce42ff85556e13dca52fee979057de696 100644 (file)
@@ -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([
index 7fbf48892f937ab072247eeebb74ea7093d219b0..7fc2e3808d7ea6ec39117a554f68cfe56e5917c7 100644 (file)
@@ -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.
         * 
index e85bb0bb6a84239b80e7ccd46b695cc573044d7d..2d5b59c097132860b70173a8727deea65fe386a4 100644 (file)
@@ -8,12 +8,32 @@ if (!RedactorPlugins) var RedactorPlugins = {};
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  */
 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;
        }
 };
index e39176b070e468889c910ed93da0b2e67d2cdd78..f36592e3705165a7638055cfefe237a1c2f15cb7 100644 (file)
@@ -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;