From 6bfd450a6d6a817abc5da1dcfa1e43be499e4476 Mon Sep 17 00:00:00 2001 From: Damyon Wiese Date: Wed, 30 Jul 2014 14:20:55 +0800 Subject: [PATCH] MDL-18014 Atto: Make the autosave frequency configurable --- lib/editor/atto/lang/en/editor_atto.php | 6 +- lib/editor/atto/lib.php | 7 +- lib/editor/atto/settings.php | 7 ++ lib/editor/atto/styles.css | 1 + .../moodle-editor_atto-editor-debug.js | 85 ++++++++++--------- .../moodle-editor_atto-editor-min.js | 6 +- .../moodle-editor_atto-editor.js | 84 +++++++++--------- lib/editor/atto/yui/src/editor/js/autosave.js | 69 +++++++++------ lib/editor/atto/yui/src/editor/js/editor.js | 12 --- lib/editor/atto/yui/src/editor/js/notify.js | 4 +- 10 files changed, 150 insertions(+), 131 deletions(-) diff --git a/lib/editor/atto/lang/en/editor_atto.php b/lib/editor/atto/lang/en/editor_atto.php index de85fa4b3eb..c0e005f8530 100644 --- a/lib/editor/atto/lang/en/editor_atto.php +++ b/lib/editor/atto/lang/en/editor_atto.php @@ -25,10 +25,7 @@ $string['autosavefailed'] = 'Could not connect to the server. If you submit this page now, your changes may be lost.'; $string['autosavefrequency'] = 'Autosave frequency (seconds).'; $string['autosavefrequency_desc'] = 'This is the number of seconds between auto save attempts. Atto will automatically save the text in the editor according to this setting, so that text can be automatically restored when the same user returns to the same form.'; -$string['autosavesucceeded'] = 'Text was automatically saved.'; -$string['cancel'] = 'Cancel'; -$string['confirm'] = 'Confirm'; -$string['confirmrecover'] = 'A previously unsaved version of the text for field "{$a->label}" was found. Do you want to recover it?'; +$string['autosavesucceeded'] = 'A draft of this text was automatically saved.'; $string['errorcannotparseline'] = 'The line \'{$a}\' is not in the correct format.'; $string['errorgroupisusedtwice'] = 'The group \'{$a}\' is defined twice; group names must be unique.'; $string['errornopluginsorgroupsfound'] = 'No plugins or groups found; please add some groups and plugins.'; @@ -38,6 +35,7 @@ $string['pluginname'] = 'Atto HTML editor'; $string['subplugintype_atto'] = 'Atto plugin'; $string['subplugintype_atto_plural'] = 'Atto plugins'; $string['settings'] = 'Atto toolbar settings'; +$string['textrecovered'] = 'A draft version of this text was automatically restored.'; $string['toolbarconfig'] = 'Toolbar config'; $string['toolbarconfig_desc'] = 'The list of plugins and the order they are displayed can be configured here. The configuration consists of groups (one per line) followed by the ordered list of plugins for that group. The group is separated from the plugins with an equals sign and the plugins are separated with commas. The group names must be unique and should indicate what the buttons have in common. Button and group names should not be repeated and may only contain alphanumeric characters.'; $string['editor_command_keycode'] = 'Cmd + {$a}'; diff --git a/lib/editor/atto/lib.php b/lib/editor/atto/lib.php index b536098cce8..e112d448569 100644 --- a/lib/editor/atto/lib.php +++ b/lib/editor/atto/lib.php @@ -125,10 +125,7 @@ class atto_texteditor extends texteditor { 'editor_command_keycode', 'editor_control_keycode', 'plugin_title_shortcut', - 'confirm', - 'recover', - 'cancel', - 'confirmrecover', + 'textrecovered', 'autosavefailed', 'autosavesucceeded' ), 'editor_atto'); @@ -157,6 +154,7 @@ class atto_texteditor extends texteditor { $strdate = get_string('strftimedaydate'); $lang = current_language(); $autosave = true; + $autosavefrequency = get_config('editor_atto', 'autosavefrequency'); if (isset($options['autosave'])) { $autosave = $options['autosave']; } @@ -167,6 +165,7 @@ class atto_texteditor extends texteditor { 'content_css' => $contentcss, 'contextid' => $options['context']->id, 'autosaveEnabled' => $autosave, + 'autosaveFrequency' => $autosavefrequency, 'language' => $lang, 'directionality' => $directionality, 'filepickeroptions' => array(), diff --git a/lib/editor/atto/settings.php b/lib/editor/atto/settings.php index f7d61dca974..b0dbc5e3f44 100644 --- a/lib/editor/atto/settings.php +++ b/lib/editor/atto/settings.php @@ -48,6 +48,13 @@ other = html'; $settings->add($setting); } + +$name = new lang_string('autosavefrequency', 'editor_atto'); +$desc = new lang_string('autosavefrequency_desc', 'editor_atto'); +$default = 60; +$setting = new admin_setting_configduration('editor_atto/autosavefrequency', $name, $desc, $default); +$settings->add($setting); + $ADMIN->add('editoratto', $settings); foreach (core_plugin_manager::instance()->get_plugins_of_type('atto') as $plugin) { diff --git a/lib/editor/atto/styles.css b/lib/editor/atto/styles.css index e7c79a017cc..425642f52e3 100644 --- a/lib/editor/atto/styles.css +++ b/lib/editor/atto/styles.css @@ -190,6 +190,7 @@ div.editor_atto_content:hover .atto_control { margin-left: 1px; margin-right: 1px; margin-bottom: 1em; + cursor: pointer; } .editor_atto_notification .atto_info { display: inline-block; diff --git a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js index ed8cd76b306..21ab03ff8c0 100644 --- a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js +++ b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-debug.js @@ -406,18 +406,6 @@ Y.extend(Editor, Y.Base, { writeOnce: true }, - /** - * Enable/Disable auto save for this instance. - * - * @attribute autosaveEnabled - * @type Boolean - * @writeOnce - */ - autosaveEnabled: { - value: true, - writeOnce: true - }, - /** * Plugins with their configuration. * @@ -557,11 +545,11 @@ EditorNotify.prototype = { var messageTypeIcon = ''; if (type === "warning") { - messageTypeIcon = '' + M.util.get_string('warning', 'moodle') + ''; } else if (type === "info") { - messageTypeIcon = '' + M.util.get_string('info', 'moodle') + ''; } else { @@ -733,12 +721,36 @@ Y.Base.mix(Y.M.editor_atto.Editor, [EditorTextArea]); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -var AUTOSAVE_FREQUENCY = 60000, - SUCCESS_MESSAGE_TIMEOUT = 5000; +var SUCCESS_MESSAGE_TIMEOUT = 5000, + RECOVER_MESSAGE_TIMEOUT = 60000; function EditorAutosave() {} EditorAutosave.ATTRS= { + /** + * Enable/Disable auto save for this instance. + * + * @attribute autosaveEnabled + * @type Boolean + * @writeOnce + */ + autosaveEnabled: { + value: true, + writeOnce: true + }, + + /** + * The time between autosaves (in seconds). + * + * @attribute autosaveFrequency + * @type Integer + * @default 60 + * @writeOnce + */ + autosaveFrequency: { + value: 60, + writeOnce: true + } }; EditorAutosave.prototype = { @@ -766,15 +778,16 @@ EditorAutosave.prototype = { * @chainable */ setupAutosave: function() { + var draftid = -1, + optiontype = null, + options = this.get('filepickeroptions'); if (!this.get('autosaveEnabled')) { // Autosave disabled for this instance. return; } - this.autosaveInstance = Y.stamp(this); - var draftid = -1, optiontype, options = this.get('filepickeroptions'); for (optiontype in options) { if (typeof options[optiontype].itemid !== "undefined") { draftid = options[optiontype].itemid; @@ -813,7 +826,9 @@ EditorAutosave.prototype = { // Now setup the timer for periodic saves. - Y.later(AUTOSAVE_FREQUENCY, this, this.saveDraft, false, true); + Y.log(this.get('autosaveFrequency')); + var delay = parseInt(this.get('autosaveFrequency'), 10) * 1000; + Y.later(delay, this, this.saveDraft, false, true); // Now setup the listener for form submission. this.textarea.ancestor('form').on('submit', this.resetAutosave, this); @@ -849,30 +864,19 @@ EditorAutosave.prototype = { /** - * Show a confirm dialogue and recover some text returned by ajax. + * Recover a previous version of this text and show a message. * * @method recoverText * @param {String} text * @chainable */ recoverText: function(text) { - var confirm = new M.core.confirm({ - title : M.util.get_string('confirm', 'editor_atto'), - question : M.util.get_string('confirmrecover', 'editor_atto', { - label : this.textareaLabel.get('text') - }), - yesLabel : M.util.get_string('recover', 'editor_atto'), - noLabel : M.util.get_string('cancel', 'editor_atto') - }); - confirm.on('complete-yes', function() { - confirm.hide(); - confirm.destroy(); - this.editor.setHTML(text); - this.saveSelection(); - this.updateOriginal(); - this.lastText = text; - }, this); - confirm.show(); + this.editor.setHTML(text); + this.saveSelection(); + this.updateOriginal(); + this.lastText = text; + + this.showMessage(M.util.get_string('textrecovered', 'editor_atto'), 'info', RECOVER_MESSAGE_TIMEOUT); return this; }, @@ -901,6 +905,7 @@ EditorAutosave.prototype = { pagedomid: Y.one('body').get('id'), pageinstance: this.autosaveInstance }; + var errorDuration = parseInt(this.get('autosaveFrequency'), 10) * 1000; Y.io(url, { method: 'POST', @@ -909,18 +914,18 @@ EditorAutosave.prototype = { error: function(code, response) { Y.log('Error while autosaving text:' + code, 'warn'); Y.log(response, 'warn'); - this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', AUTOSAVE_FREQUENCY); + this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', errorDuration); }, failure: function(code, response) { Y.log('Failure while autosaving text:' + code, 'warn'); Y.log(response, 'warn'); - this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', AUTOSAVE_FREQUENCY); + this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', errorDuration); }, success: function(code, response) { if (response.response !== "") { Y.log('Failure while autosaving text.', 'warn'); Y.log(response, 'debug'); - this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', AUTOSAVE_FREQUENCY); + this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', errorDuration); } else { // All working. this.lastText = newText; diff --git a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-min.js b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-min.js index 231fa81edac..a6115c86919 100644 --- a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-min.js +++ b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor-min.js @@ -1,3 +1,3 @@ -YUI.add("moodle-editor_atto-editor",function(e,t){function i(){i.superclass.constructor.apply(this,arguments)}function s(){}function o(){}function f(){}function l(){}function c(){}function h(){}function p(){}function d(){}function v(){}var n="moodle-editor_atto-editor",r={CONTENT:"editor_atto_content",CONTENTWRAPPER:"editor_atto_content_wrap",TOOLBAR:"editor_atto_toolbar",WRAPPER:"editor_atto",HIGHLIGHT:"highlight"};e.extend(i,e.Base,{BLOCK_TAGS:["address","article","aside","audio","blockquote","canvas","dd","div","dl","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","noscript","ol","output","p","pre","section","table","tfoot","ul","video"],PLACEHOLDER_CLASS:"atto-tmp-class",ALL_NODES_SELECTOR:"[style],font[face]",FONT_FAMILY:"fontFamily",_wrapper:null,editor:null,textarea:null,textareaLabel:null,plugins:null,_eventHandles:null,initializer:function(){var t;this.textarea=e.one(document.getElementById(this.get("elementid")));if(!this.textarea)return;this._eventHandles=[],this._wrapper=e.Node.create('
'),t=e.Handlebars.compile('
'),this.editor=e.Node.create(t({elementid:this.get("elementid"),CSS:r})),this.textareaLabel=e.one('[for="'+this.get("elementid")+'"]'),this.textareaLabel&&(this.textareaLabel.generateID(),this.editor.setAttribute("aria-labelledby",this.textareaLabel.get("id"))),this.setupToolbar();var n=e.Node.create('
');n.appendChild(this.editor),this._wrapper.appendChild(n),this.editor.setStyle("minHeight",20*this.textarea.getAttribute("rows")+8+"px"),e.UA.ie===0&&this.editor.setStyle("height",20*this.textarea.getAttribute("rows")+8+"px"),this.disableCssStyling(),document.queryCommandSupported("DefaultParagraphSeparator")&&document.execCommand("DefaultParagraphSeparator",!1,"p"),this.textarea.get("parentNode").insert(this._wrapper,this.textarea),this.textarea.hide(),this.updateFromTextArea(),this.publishEvents(),this.setupSelectionWatchers(),this.setupAutomaticPolling(),this.setupPlugins(),this.setupAutosave(),this.setupNotifications()},focus:function(){return this.editor.focus(),this},publishEvents:function(){return this.publish("change",{broadcast:!0,preventable:!0}),this.publish("pluginsloaded",{fireOnce:!0}),this.publish("atto:selectionchanged",{prefix:"atto"}),this},setupAutomaticPolling:function(){return this._registerEventHandle(this.editor.on(["keyup","paste","cut"],this.updateOriginal,this)),this},setupPlugins:function(){this.plugins={};var t=this.get("plugins"),n,r,i,s,o;for(n in t){r=t[n];if(!r.plugins)continue;for(i in r.plugins){s=r.plugins[i],o=e.mix({name:s.name,group:r.group,editor:this.editor,toolbar:this.toolbar,host:this},s);if(typeof e.M["atto_"+s.name]=="undefined")continue;this.plugins[s.name]=new e.M["atto_"+s.name].Button(o)}}return this.fire("pluginsloaded"),this},enablePlugins:function(e){this._setPluginState(!0,e)},disablePlugins:function(e){this._setPluginState(!1,e)},_setPluginState:function(t,n){var r="disableButtons";t&&(r="enableButtons"),n?this.plugins[n][r]():e.Object.each(this.plugins,function(e){e[r]()},this)},_registerEventHandle:function(e){this._eventHandles.push(e)}},{NS:"editor_atto",ATTRS:{elementid:{value:null,writeOnce:!0},contextid:{value:null,writeOnce:!0},autosaveEnabled:{value:!0,writeOnce:!0},plugins:{value:{},writeOnce:!0}}}),e.augment(i,e.EventTarget),e.namespace("M.editor_atto").Editor=i,e.namespace("M.editor_atto.Editor").init=function(t){return new e.M.editor_atto.Editor(t)},s.ATTRS={},s.prototype={messageOverlay:null,hideTimer:null,setupNotifications:function(){var e=new Image,t=new Image;return e.src=M.util.image_url("i/warning","moodle"),t.src=M.util.image_url("i/info","moodle"),this},showMessage:function(t,n,r){this.messageOverlay===null&&(this.messageOverlay=e.Node.create('
'),this.messageOverlay.hide(),this._wrapper.append(this.messageOverlay),this.messageOverlay.on("click",function(){this.messageOverlay.hide()},this)),this.hideTimer!==null&&this.hideTimer.cancel();var i="";n==="warning"?i=''+M.util.get_string(':n==="info"&&(i=''+M.util.get_string(');var s=parseInt(r,10);s<=0&&(s=6e4),n="atto_"+n;var o=e.Node.create('");return this.messageOverlay.empty(),this.messageOverlay.append(o),this.messageOverlay.show(),this.hideTimer=e.later(s,this,function(){this.hideTimer=null,this.messageOverlay.hide()}),this}},e.Base.mix(e.M.editor_atto.Editor,[s]),o.ATTRS={},o.prototype={_getEmptyContent:function(){return e.UA.ie&&e.UA.ie<10?"

":"


"},updateFromTextArea:function(){this.editor.setHTML(""),this.editor.append(this.textarea.get("value")),this.cleanEditorHTML(),this.editor.getHTML()===""&&this.editor.setHTML(this._getEmptyContent())},updateOriginal:function(){var e=this.textarea.get("value"),t=this.getCleanHTML();return t===""&&this.isActive()&&(t=this._getEmptyContent()),e!==t&&(this.textarea.set("value",t),this.textarea.simulate("change"),this.fire("change")),this}},e.Base.mix(e.M.editor_atto.Editor,[o]);var u=6e4,a=5e3;f.ATTRS={},f.prototype={lastText:null,autosaveInstance:null,setupAutosave:function(){if(!this.get("autosaveEnabled"))return;this.autosaveInstance=e.stamp(this);var t=-1,n,r=this.get("filepickeroptions");for(n in r)typeof r[n].itemid!="undefined"&&(t=r[n].itemid);return url=M.cfg.wwwroot+"/lib/editor/atto/autosave-ajax.php",params={sesskey:M.cfg.sesskey,contextid:this.get("contextid"),action:"resume",drafttext:"",draftid:t,elementid:this.get("elementid"),pageinstance:this.autosaveInstance,pagedomid:e.one("body").get("id")},e.io(url -,{method:"POST",data:params,on:{success:function(e,t){typeof t.responseText!="undefined"&&t.responseText!==""&&t.responseText!==this.textarea.get("value")&&this.recoverText(t.responseText)}},context:this}),e.later(u,this,this.saveDraft,!1,!0),this.textarea.ancestor("form").on("submit",this.resetAutosave,this),this},resetAutosave:function(){return url=M.cfg.wwwroot+"/lib/editor/atto/autosave-ajax.php",params={sesskey:M.cfg.sesskey,contextid:this.get("contextid"),action:"reset",elementid:this.get("elementid"),pageinstance:this.autosaveInstance,pagedomid:e.one("body").get("id")},e.io(url,{method:"POST",data:params,sync:!0}),this},recoverText:function(e){var t=new M.core.confirm({title:M.util.get_string("confirm","editor_atto"),question:M.util.get_string("confirmrecover","editor_atto",{label:this.textareaLabel.get("text")}),yesLabel:M.util.get_string("recover","editor_atto"),noLabel:M.util.get_string("cancel","editor_atto")});return t.on("complete-yes",function(){t.hide(),t.destroy(),this.editor.setHTML(e),this.saveSelection(),this.updateOriginal(),this.lastText=e},this),t.show(),this},saveDraft:function(){this.updateOriginal();var t=this.textarea.get("value");return t!==this.lastText&&(url=M.cfg.wwwroot+"/lib/editor/atto/autosave-ajax.php",params={sesskey:M.cfg.sesskey,contextid:this.get("contextid"),action:"save",drafttext:t,elementid:this.get("elementid"),pagedomid:e.one("body").get("id"),pageinstance:this.autosaveInstance},e.io(url,{method:"POST",data:params,on:{error:function(e,t){this.showMessage(M.util.get_string("autosavefailed","editor_atto"),"warning",u)},failure:function(e,t){this.showMessage(M.util.get_string("autosavefailed","editor_atto"),"warning",u)},success:function(e,n){n.response!==""?this.showMessage(M.util.get_string("autosavefailed","editor_atto"),"warning",u):(this.lastText=t,this.showMessage(M.util.get_string("autosavesucceeded","editor_atto"),"info",a))}},context:this})),this}},e.Base.mix(e.M.editor_atto.Editor,[f]),l.ATTRS={},l.prototype={getCleanHTML:function(){var t=this.editor.cloneNode(!0),n;return e.each(t.all('[id^="yui"]'),function(e){e.removeAttribute("id")}),t.all(".atto_control").remove(!0),n=t.get("innerHTML"),n==="

"||n==="


"?"":this._cleanHTML(n)},cleanEditorHTML:function(){var e=this.editor.get("innerHTML");return this.editor.set("innerHTML",this._cleanHTML(e)),this},_cleanHTML:function(e){var t=[{regex://gi,replace:""},{regex:/<\\?\?xml[^>]*>/gi,replace:""},{regex:/<\/?\w+:[^>]*>/gi,replace:""},{regex:/\s*MSO[-:][^;"']*;?/gi,replace:""},{regex:/]*>( |\s)*<\/span>/gi,replace:""},{regex:/class="Mso[^"]*"/gi,replace:""},{regex:/<(\/?title|\/?meta|\/?style|\/?st\d|\/?head|\/?font|\/?html|\/?body|!\[)[^>]*?>/gi,replace:""},{regex:new RegExp(String.fromCharCode(8220),"gi"),replace:'"'},{regex:new RegExp(String.fromCharCode(8216),"gi"),replace:"'"},{regex:new RegExp(String.fromCharCode(8217),"gi"),replace:"'"},{regex:new RegExp(String.fromCharCode(8211),"gi"),replace:"-"},{regex:new RegExp(String.fromCharCode(8212),"gi"),replace:"--"},{regex:new RegExp(String.fromCharCode(189),"gi"),replace:"1/2"},{regex:new RegExp(String.fromCharCode(188),"gi"),replace:"1/4"},{regex:new RegExp(String.fromCharCode(190),"gi"),replace:"3/4"},{regex:new RegExp(String.fromCharCode(169),"gi"),replace:"(c)"},{regex:new RegExp(String.fromCharCode(174),"gi"),replace:"(r)"},{regex:new RegExp(String.fromCharCode(8230),"gi"),replace:"..."}],n=0;for(n=0;n'),this.openMenus=[],this._wrapper.appendChild(this.toolbar),this.textareaLabel&&this.toolbar.setAttribute("aria-labelledby",this.textareaLabel.get("id")),this.setupToolbarNavigation(),this}},e.Base.mix(e.M.editor_atto.Editor,[c]),h.ATTRS={},h.prototype={_tabFocus:null,setupToolbarNavigation:function(){return this._wrapper.delegate("key",this.toolbarKeyboardNavigation,"down:37,39","."+r.TOOLBAR,this),this._wrapper.delegate("focus",function(e){this._setTabFocus(e.currentTarget)},"."+r.TOOLBAR+" button",this),this},toolbarKeyboardNavigation:function(e){e.preventDefault();var t=this.toolbar.all("button"),n=1,r,i=e.target.ancestor("button",!0);e.keyCode===37&&(n=-1),r=this._findFirstFocusable(t,i,n),r&&(r.focus(),this._setTabFocus(r))},_findFirstFocusable:function(e,t,n){var r=0,i,s,o,u;u=e.indexOf(t),u<-1&&(u=0);while(r=e.size()&&(u=0),s=e.item(u),r++;if(s.hasAttribute("hidden")||s.hasAttribute("disabled"))continue;i=s.ancestor(".atto_group");if(i.hasAttribute("hidden"))continue;o=s;break}return o},checkTabFocus:function(){return this._tabFocus&&(this._tabFocus.hasAttribute("disabled")||this._tabFocus.hasAttribute("hidden")||this._tabFocus.ancestor(".atto_group").hasAttribute("hidden"))&&(button=this._findFirstFocusable(this.toolbar.all("button"),this._tabFocus,-1),button&&(this._tabFocus.compareTo(document.activeElement)&&button.focus(),this._setTabFocus(button))),this},_setTabFocus:function(e){return this._tabFocus&&this._tabFocus.setAttribute("tabindex","-1"),this._tabFocus=e,this._tabFocus.setAttribute("tabindex",0),this.toolbar.setAttribute("aria-activedescendant",this._tabFocus.generateID()),this}},e.Base.mix(e.M.editor_atto.Editor,[h]),p.ATTRS={},p.prototype={_selections:null,_lastSelection:null,_focusFromClick:!1,setupSelectionWatchers:function(){return this.on("atto:selectionchanged",this.saveSelection,this),this.editor.on("focus",this.restoreSelection,this),this.editor.on("mousedown",function(){this._focusFromClick=!0},this),this.editor.on("blur",function(){this._focusFromClick=!1,this.updateOriginal()},this),e.delegate(["keyup","focus"],function(t){e.soon(e.bind(this._hasSelectionChanged,this,t))},document.body,"#"+this.editor.get("id"),this),e.delegate("gesturemoveend",function(t){e.soon -(e.bind(this._hasSelectionChanged,this,t))},document.body,"#"+this.editor.get("id"),{standAlone:!0},this),this},isActive:function(){var t=rangy.createRange(),n=rangy.getSelection();return n.rangeCount?!document.activeElement||e.one(document.activeElement)!==this.editor?!1:(t.selectNode(this.editor.getDOMNode()),t.intersectsRange(n.getRangeAt(0))):!1},getSelectionFromNode:function(e){var t=rangy.createRange();return t.selectNode(e.getDOMNode()),[t]},saveSelection:function(){this.isActive()&&(this._selections=this.getSelection())},restoreSelection:function(){this._focusFromClick||this._selections&&this.setSelection(this._selections),this._focusFromClick=!1},getSelection:function(){return rangy.getSelection().getAllRanges()},selectionContainsNode:function(e){return rangy.getSelection().containsNode(e.getDOMNode(),!0)},selectionFilterMatches:function(e,t,n){typeof n=="undefined"&&(n=!0),t||(t=this.getSelectedNodes());var r=t.size()>0,i=!1,s=this.editor,o=function(e){return e===s};return s.one(e)?(t.each(function(t){if(n){if(!r||!t.ancestor(e,!0,o))r=!1}else!i&&t.ancestor(e,!0,o)&&(i=!0)},this),n?r:i):!1},getSelectedNodes:function(){var t=new e.NodeList,n,r,i,s,o;r=rangy.getSelection(),r.rangeCount?i=r.getRangeAt(0):i=rangy.createRange(),i.collapsed&&i.commonAncestorContainer!==this.editor.getDOMNode()&&i.commonAncestorContainer!==e.config.doc&&(i=i.cloneRange(),i.selectNode(i.commonAncestorContainer)),n=i.getNodes();for(o=0;o

"),i.get("childNodes").each(function(e){u.append(e.remove())}),i.append(u),o=u),t&&t!==""&&(f=e.Node.create("<"+t+">"),f.setAttrs(o.getAttrs()),o.get("childNodes").each(function(e){e.remove(),f.append(e)}),o.replace(f),o=f),n&&o.setAttrs(n);var l=this.getSelectionFromNode(o);return this.setSelection(l),o}},e.Base.mix(e.M.editor_atto.Editor,[d]),v.ATTRS={filepickeroptions:{value:{}}},v.prototype={canShowFilepicker:function(e){return typeof this.get("filepickeroptions")[e]!="undefined"},showFilepicker:function(t,n,r){var i=this;e.use("core_filepicker",function(e){var s=e.clone(i.get("filepickeroptions")[t],!0);s.formcallback=n,r&&(s.magicscope=r),M.core_filepicker.show(e,s)})}},e.Base.mix(e.M.editor_atto.Editor,[v])},"@VERSION@",{requires:["node","io","overlay","escape","event","event-simulate","event-custom","yui-throttle","moodle-core-notification-dialogue","moodle-core-notification-confirm","moodle-editor_atto-rangy","handlebars","timers"]}); +YUI.add("moodle-editor_atto-editor",function(e,t){function i(){i.superclass.constructor.apply(this,arguments)}function s(){}function o(){}function f(){}function l(){}function c(){}function h(){}function p(){}function d(){}function v(){}var n="moodle-editor_atto-editor",r={CONTENT:"editor_atto_content",CONTENTWRAPPER:"editor_atto_content_wrap",TOOLBAR:"editor_atto_toolbar",WRAPPER:"editor_atto",HIGHLIGHT:"highlight"};e.extend(i,e.Base,{BLOCK_TAGS:["address","article","aside","audio","blockquote","canvas","dd","div","dl","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","noscript","ol","output","p","pre","section","table","tfoot","ul","video"],PLACEHOLDER_CLASS:"atto-tmp-class",ALL_NODES_SELECTOR:"[style],font[face]",FONT_FAMILY:"fontFamily",_wrapper:null,editor:null,textarea:null,textareaLabel:null,plugins:null,_eventHandles:null,initializer:function(){var t;this.textarea=e.one(document.getElementById(this.get("elementid")));if(!this.textarea)return;this._eventHandles=[],this._wrapper=e.Node.create('
'),t=e.Handlebars.compile('
'),this.editor=e.Node.create(t({elementid:this.get("elementid"),CSS:r})),this.textareaLabel=e.one('[for="'+this.get("elementid")+'"]'),this.textareaLabel&&(this.textareaLabel.generateID(),this.editor.setAttribute("aria-labelledby",this.textareaLabel.get("id"))),this.setupToolbar();var n=e.Node.create('
');n.appendChild(this.editor),this._wrapper.appendChild(n),this.editor.setStyle("minHeight",20*this.textarea.getAttribute("rows")+8+"px"),e.UA.ie===0&&this.editor.setStyle("height",20*this.textarea.getAttribute("rows")+8+"px"),this.disableCssStyling(),document.queryCommandSupported("DefaultParagraphSeparator")&&document.execCommand("DefaultParagraphSeparator",!1,"p"),this.textarea.get("parentNode").insert(this._wrapper,this.textarea),this.textarea.hide(),this.updateFromTextArea(),this.publishEvents(),this.setupSelectionWatchers(),this.setupAutomaticPolling(),this.setupPlugins(),this.setupAutosave(),this.setupNotifications()},focus:function(){return this.editor.focus(),this},publishEvents:function(){return this.publish("change",{broadcast:!0,preventable:!0}),this.publish("pluginsloaded",{fireOnce:!0}),this.publish("atto:selectionchanged",{prefix:"atto"}),this},setupAutomaticPolling:function(){return this._registerEventHandle(this.editor.on(["keyup","paste","cut"],this.updateOriginal,this)),this},setupPlugins:function(){this.plugins={};var t=this.get("plugins"),n,r,i,s,o;for(n in t){r=t[n];if(!r.plugins)continue;for(i in r.plugins){s=r.plugins[i],o=e.mix({name:s.name,group:r.group,editor:this.editor,toolbar:this.toolbar,host:this},s);if(typeof e.M["atto_"+s.name]=="undefined")continue;this.plugins[s.name]=new e.M["atto_"+s.name].Button(o)}}return this.fire("pluginsloaded"),this},enablePlugins:function(e){this._setPluginState(!0,e)},disablePlugins:function(e){this._setPluginState(!1,e)},_setPluginState:function(t,n){var r="disableButtons";t&&(r="enableButtons"),n?this.plugins[n][r]():e.Object.each(this.plugins,function(e){e[r]()},this)},_registerEventHandle:function(e){this._eventHandles.push(e)}},{NS:"editor_atto",ATTRS:{elementid:{value:null,writeOnce:!0},contextid:{value:null,writeOnce:!0},plugins:{value:{},writeOnce:!0}}}),e.augment(i,e.EventTarget),e.namespace("M.editor_atto").Editor=i,e.namespace("M.editor_atto.Editor").init=function(t){return new e.M.editor_atto.Editor(t)},s.ATTRS={},s.prototype={messageOverlay:null,hideTimer:null,setupNotifications:function(){var e=new Image,t=new Image;return e.src=M.util.image_url("i/warning","moodle"),t.src=M.util.image_url("i/info","moodle"),this},showMessage:function(t,n,r){this.messageOverlay===null&&(this.messageOverlay=e.Node.create('
'),this.messageOverlay.hide(),this._wrapper.append(this.messageOverlay),this.messageOverlay.on("click",function(){this.messageOverlay.hide()},this)),this.hideTimer!==null&&this.hideTimer.cancel();var i="";n==="warning"?i=''+M.util.get_string(':n==="info"&&(i=''+M.util.get_string(');var s=parseInt(r,10);s<=0&&(s=6e4),n="atto_"+n;var o=e.Node.create('");return this.messageOverlay.empty(),this.messageOverlay.append(o),this.messageOverlay.show(),this.hideTimer=e.later(s,this,function(){this.hideTimer=null,this.messageOverlay.hide()}),this}},e.Base.mix(e.M.editor_atto.Editor,[s]),o.ATTRS={},o.prototype={_getEmptyContent:function(){return e.UA.ie&&e.UA.ie<10?"

":"


"},updateFromTextArea:function(){this.editor.setHTML(""),this.editor.append(this.textarea.get("value")),this.cleanEditorHTML(),this.editor.getHTML()===""&&this.editor.setHTML(this._getEmptyContent())},updateOriginal:function(){var e=this.textarea.get("value"),t=this.getCleanHTML();return t===""&&this.isActive()&&(t=this._getEmptyContent()),e!==t&&(this.textarea.set("value",t),this.textarea.simulate("change"),this.fire("change")),this}},e.Base.mix(e.M.editor_atto.Editor,[o]);var u=5e3,a=6e4;f.ATTRS={autosaveEnabled:{value:!0,writeOnce:!0},autosaveFrequency:{value:60,writeOnce:!0}},f.prototype={lastText:null,autosaveInstance:null,setupAutosave:function(){var t=-1,n=null,r=this.get("filepickeroptions");if(!this.get("autosaveEnabled"))return;this.autosaveInstance=e.stamp(this);for(n in r)typeof r[n].itemid!="undefined"&&(t=r[n].itemid);url=M.cfg.wwwroot+"/lib/editor/atto/autosave-ajax.php",params={sesskey:M.cfg.sesskey,contextid:this.get("contextid"),action:"resume",drafttext:"",draftid:t,elementid:this.get("elementid"),pageinstance:this.autosaveInstance,pagedomid:e.one("body").get("id")},e.io(url,{method +:"POST",data:params,on:{success:function(e,t){typeof t.responseText!="undefined"&&t.responseText!==""&&t.responseText!==this.textarea.get("value")&&this.recoverText(t.responseText)}},context:this});var i=parseInt(this.get("autosaveFrequency"),10)*1e3;return e.later(i,this,this.saveDraft,!1,!0),this.textarea.ancestor("form").on("submit",this.resetAutosave,this),this},resetAutosave:function(){return url=M.cfg.wwwroot+"/lib/editor/atto/autosave-ajax.php",params={sesskey:M.cfg.sesskey,contextid:this.get("contextid"),action:"reset",elementid:this.get("elementid"),pageinstance:this.autosaveInstance,pagedomid:e.one("body").get("id")},e.io(url,{method:"POST",data:params,sync:!0}),this},recoverText:function(e){return this.editor.setHTML(e),this.saveSelection(),this.updateOriginal(),this.lastText=e,this.showMessage(M.util.get_string("textrecovered","editor_atto"),"info",a),this},saveDraft:function(){this.updateOriginal();var t=this.textarea.get("value");if(t!==this.lastText){url=M.cfg.wwwroot+"/lib/editor/atto/autosave-ajax.php",params={sesskey:M.cfg.sesskey,contextid:this.get("contextid"),action:"save",drafttext:t,elementid:this.get("elementid"),pagedomid:e.one("body").get("id"),pageinstance:this.autosaveInstance};var n=parseInt(this.get("autosaveFrequency"),10)*1e3;e.io(url,{method:"POST",data:params,on:{error:function(e,t){this.showMessage(M.util.get_string("autosavefailed","editor_atto"),"warning",n)},failure:function(e,t){this.showMessage(M.util.get_string("autosavefailed","editor_atto"),"warning",n)},success:function(e,r){r.response!==""?this.showMessage(M.util.get_string("autosavefailed","editor_atto"),"warning",n):(this.lastText=t,this.showMessage(M.util.get_string("autosavesucceeded","editor_atto"),"info",u))}},context:this})}return this}},e.Base.mix(e.M.editor_atto.Editor,[f]),l.ATTRS={},l.prototype={getCleanHTML:function(){var t=this.editor.cloneNode(!0),n;return e.each(t.all('[id^="yui"]'),function(e){e.removeAttribute("id")}),t.all(".atto_control").remove(!0),n=t.get("innerHTML"),n==="

"||n==="


"?"":this._cleanHTML(n)},cleanEditorHTML:function(){var e=this.editor.get("innerHTML");return this.editor.set("innerHTML",this._cleanHTML(e)),this},_cleanHTML:function(e){var t=[{regex://gi,replace:""},{regex:/<\\?\?xml[^>]*>/gi,replace:""},{regex:/<\/?\w+:[^>]*>/gi,replace:""},{regex:/\s*MSO[-:][^;"']*;?/gi,replace:""},{regex:/]*>( |\s)*<\/span>/gi,replace:""},{regex:/class="Mso[^"]*"/gi,replace:""},{regex:/<(\/?title|\/?meta|\/?style|\/?st\d|\/?head|\/?font|\/?html|\/?body|!\[)[^>]*?>/gi,replace:""},{regex:new RegExp(String.fromCharCode(8220),"gi"),replace:'"'},{regex:new RegExp(String.fromCharCode(8216),"gi"),replace:"'"},{regex:new RegExp(String.fromCharCode(8217),"gi"),replace:"'"},{regex:new RegExp(String.fromCharCode(8211),"gi"),replace:"-"},{regex:new RegExp(String.fromCharCode(8212),"gi"),replace:"--"},{regex:new RegExp(String.fromCharCode(189),"gi"),replace:"1/2"},{regex:new RegExp(String.fromCharCode(188),"gi"),replace:"1/4"},{regex:new RegExp(String.fromCharCode(190),"gi"),replace:"3/4"},{regex:new RegExp(String.fromCharCode(169),"gi"),replace:"(c)"},{regex:new RegExp(String.fromCharCode(174),"gi"),replace:"(r)"},{regex:new RegExp(String.fromCharCode(8230),"gi"),replace:"..."}],n=0;for(n=0;n'),this.openMenus=[],this._wrapper.appendChild(this.toolbar),this.textareaLabel&&this.toolbar.setAttribute("aria-labelledby",this.textareaLabel.get("id")),this.setupToolbarNavigation(),this}},e.Base.mix(e.M.editor_atto.Editor,[c]),h.ATTRS={},h.prototype={_tabFocus:null,setupToolbarNavigation:function(){return this._wrapper.delegate("key",this.toolbarKeyboardNavigation,"down:37,39","."+r.TOOLBAR,this),this._wrapper.delegate("focus",function(e){this._setTabFocus(e.currentTarget)},"."+r.TOOLBAR+" button",this),this},toolbarKeyboardNavigation:function(e){e.preventDefault();var t=this.toolbar.all("button"),n=1,r,i=e.target.ancestor("button",!0);e.keyCode===37&&(n=-1),r=this._findFirstFocusable(t,i,n),r&&(r.focus(),this._setTabFocus(r))},_findFirstFocusable:function(e,t,n){var r=0,i,s,o,u;u=e.indexOf(t),u<-1&&(u=0);while(r=e.size()&&(u=0),s=e.item(u),r++;if(s.hasAttribute("hidden")||s.hasAttribute("disabled"))continue;i=s.ancestor(".atto_group");if(i.hasAttribute("hidden"))continue;o=s;break}return o},checkTabFocus:function(){return this._tabFocus&&(this._tabFocus.hasAttribute("disabled")||this._tabFocus.hasAttribute("hidden")||this._tabFocus.ancestor(".atto_group").hasAttribute("hidden"))&&(button=this._findFirstFocusable(this.toolbar.all("button"),this._tabFocus,-1),button&&(this._tabFocus.compareTo(document.activeElement)&&button.focus(),this._setTabFocus(button))),this},_setTabFocus:function(e){return this._tabFocus&&this._tabFocus.setAttribute("tabindex","-1"),this._tabFocus=e,this._tabFocus.setAttribute("tabindex",0),this.toolbar.setAttribute("aria-activedescendant",this._tabFocus.generateID()),this}},e.Base.mix(e.M.editor_atto.Editor,[h]),p.ATTRS={},p.prototype={_selections:null,_lastSelection:null,_focusFromClick:!1,setupSelectionWatchers:function(){return this.on("atto:selectionchanged",this.saveSelection,this),this.editor.on("focus",this.restoreSelection,this),this.editor.on("mousedown",function(){this._focusFromClick=!0},this),this.editor.on("blur",function(){this._focusFromClick=!1,this.updateOriginal()},this),e.delegate(["keyup","focus"],function(t){e.soon(e.bind(this._hasSelectionChanged,this,t))},document.body,"#"+this.editor.get("id"),this),e.delegate("gesturemoveend",function(t){e.soon(e.bind(this._hasSelectionChanged,this,t))},document.body,"#"+this.editor.get("id"),{standAlone:!0},this),this},isActive:function(){var t=rangy.createRange(),n=rangy +.getSelection();return n.rangeCount?!document.activeElement||e.one(document.activeElement)!==this.editor?!1:(t.selectNode(this.editor.getDOMNode()),t.intersectsRange(n.getRangeAt(0))):!1},getSelectionFromNode:function(e){var t=rangy.createRange();return t.selectNode(e.getDOMNode()),[t]},saveSelection:function(){this.isActive()&&(this._selections=this.getSelection())},restoreSelection:function(){this._focusFromClick||this._selections&&this.setSelection(this._selections),this._focusFromClick=!1},getSelection:function(){return rangy.getSelection().getAllRanges()},selectionContainsNode:function(e){return rangy.getSelection().containsNode(e.getDOMNode(),!0)},selectionFilterMatches:function(e,t,n){typeof n=="undefined"&&(n=!0),t||(t=this.getSelectedNodes());var r=t.size()>0,i=!1,s=this.editor,o=function(e){return e===s};return s.one(e)?(t.each(function(t){if(n){if(!r||!t.ancestor(e,!0,o))r=!1}else!i&&t.ancestor(e,!0,o)&&(i=!0)},this),n?r:i):!1},getSelectedNodes:function(){var t=new e.NodeList,n,r,i,s,o;r=rangy.getSelection(),r.rangeCount?i=r.getRangeAt(0):i=rangy.createRange(),i.collapsed&&i.commonAncestorContainer!==this.editor.getDOMNode()&&i.commonAncestorContainer!==e.config.doc&&(i=i.cloneRange(),i.selectNode(i.commonAncestorContainer)),n=i.getNodes();for(o=0;o

"),i.get("childNodes").each(function(e){u.append(e.remove())}),i.append(u),o=u),t&&t!==""&&(f=e.Node.create("<"+t+">"),f.setAttrs(o.getAttrs()),o.get("childNodes").each(function(e){e.remove(),f.append(e)}),o.replace(f),o=f),n&&o.setAttrs(n);var l=this.getSelectionFromNode(o);return this.setSelection(l),o}},e.Base.mix(e.M.editor_atto.Editor,[d]),v.ATTRS={filepickeroptions:{value:{}}},v.prototype={canShowFilepicker:function(e){return typeof this.get("filepickeroptions")[e]!="undefined"},showFilepicker:function(t,n,r){var i=this;e.use("core_filepicker",function(e){var s=e.clone(i.get("filepickeroptions")[t],!0);s.formcallback=n,r&&(s.magicscope=r),M.core_filepicker.show(e,s)})}},e.Base.mix(e.M.editor_atto.Editor,[v])},"@VERSION@",{requires:["node","io","overlay","escape","event","event-simulate","event-custom","yui-throttle","moodle-core-notification-dialogue","moodle-core-notification-confirm","moodle-editor_atto-rangy","handlebars","timers"]}); diff --git a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js index 54d75e6b94a..18bdb920723 100644 --- a/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js +++ b/lib/editor/atto/yui/build/moodle-editor_atto-editor/moodle-editor_atto-editor.js @@ -403,18 +403,6 @@ Y.extend(Editor, Y.Base, { writeOnce: true }, - /** - * Enable/Disable auto save for this instance. - * - * @attribute autosaveEnabled - * @type Boolean - * @writeOnce - */ - autosaveEnabled: { - value: true, - writeOnce: true - }, - /** * Plugins with their configuration. * @@ -554,11 +542,11 @@ EditorNotify.prototype = { var messageTypeIcon = ''; if (type === "warning") { - messageTypeIcon = '' + M.util.get_string('warning', 'moodle') + ''; } else if (type === "info") { - messageTypeIcon = '' + M.util.get_string('info', 'moodle') + ''; } else { @@ -728,12 +716,36 @@ Y.Base.mix(Y.M.editor_atto.Editor, [EditorTextArea]); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -var AUTOSAVE_FREQUENCY = 60000, - SUCCESS_MESSAGE_TIMEOUT = 5000; +var SUCCESS_MESSAGE_TIMEOUT = 5000, + RECOVER_MESSAGE_TIMEOUT = 60000; function EditorAutosave() {} EditorAutosave.ATTRS= { + /** + * Enable/Disable auto save for this instance. + * + * @attribute autosaveEnabled + * @type Boolean + * @writeOnce + */ + autosaveEnabled: { + value: true, + writeOnce: true + }, + + /** + * The time between autosaves (in seconds). + * + * @attribute autosaveFrequency + * @type Integer + * @default 60 + * @writeOnce + */ + autosaveFrequency: { + value: 60, + writeOnce: true + } }; EditorAutosave.prototype = { @@ -761,15 +773,16 @@ EditorAutosave.prototype = { * @chainable */ setupAutosave: function() { + var draftid = -1, + optiontype = null, + options = this.get('filepickeroptions'); if (!this.get('autosaveEnabled')) { // Autosave disabled for this instance. return; } - this.autosaveInstance = Y.stamp(this); - var draftid = -1, optiontype, options = this.get('filepickeroptions'); for (optiontype in options) { if (typeof options[optiontype].itemid !== "undefined") { draftid = options[optiontype].itemid; @@ -807,7 +820,8 @@ EditorAutosave.prototype = { // Now setup the timer for periodic saves. - Y.later(AUTOSAVE_FREQUENCY, this, this.saveDraft, false, true); + var delay = parseInt(this.get('autosaveFrequency'), 10) * 1000; + Y.later(delay, this, this.saveDraft, false, true); // Now setup the listener for form submission. this.textarea.ancestor('form').on('submit', this.resetAutosave, this); @@ -843,30 +857,19 @@ EditorAutosave.prototype = { /** - * Show a confirm dialogue and recover some text returned by ajax. + * Recover a previous version of this text and show a message. * * @method recoverText * @param {String} text * @chainable */ recoverText: function(text) { - var confirm = new M.core.confirm({ - title : M.util.get_string('confirm', 'editor_atto'), - question : M.util.get_string('confirmrecover', 'editor_atto', { - label : this.textareaLabel.get('text') - }), - yesLabel : M.util.get_string('recover', 'editor_atto'), - noLabel : M.util.get_string('cancel', 'editor_atto') - }); - confirm.on('complete-yes', function() { - confirm.hide(); - confirm.destroy(); - this.editor.setHTML(text); - this.saveSelection(); - this.updateOriginal(); - this.lastText = text; - }, this); - confirm.show(); + this.editor.setHTML(text); + this.saveSelection(); + this.updateOriginal(); + this.lastText = text; + + this.showMessage(M.util.get_string('textrecovered', 'editor_atto'), 'info', RECOVER_MESSAGE_TIMEOUT); return this; }, @@ -894,20 +897,21 @@ EditorAutosave.prototype = { pagedomid: Y.one('body').get('id'), pageinstance: this.autosaveInstance }; + var errorDuration = parseInt(this.get('autosaveFrequency'), 10) * 1000; Y.io(url, { method: 'POST', data: params, on: { error: function(code, response) { - this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', AUTOSAVE_FREQUENCY); + this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', errorDuration); }, failure: function(code, response) { - this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', AUTOSAVE_FREQUENCY); + this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', errorDuration); }, success: function(code, response) { if (response.response !== "") { - this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', AUTOSAVE_FREQUENCY); + this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', errorDuration); } else { // All working. this.lastText = newText; diff --git a/lib/editor/atto/yui/src/editor/js/autosave.js b/lib/editor/atto/yui/src/editor/js/autosave.js index 7e4adecb84b..0f6f4454a70 100644 --- a/lib/editor/atto/yui/src/editor/js/autosave.js +++ b/lib/editor/atto/yui/src/editor/js/autosave.js @@ -23,12 +23,36 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -var AUTOSAVE_FREQUENCY = 60000, - SUCCESS_MESSAGE_TIMEOUT = 5000; +var SUCCESS_MESSAGE_TIMEOUT = 5000, + RECOVER_MESSAGE_TIMEOUT = 60000; function EditorAutosave() {} EditorAutosave.ATTRS= { + /** + * Enable/Disable auto save for this instance. + * + * @attribute autosaveEnabled + * @type Boolean + * @writeOnce + */ + autosaveEnabled: { + value: true, + writeOnce: true + }, + + /** + * The time between autosaves (in seconds). + * + * @attribute autosaveFrequency + * @type Integer + * @default 60 + * @writeOnce + */ + autosaveFrequency: { + value: 60, + writeOnce: true + } }; EditorAutosave.prototype = { @@ -56,15 +80,16 @@ EditorAutosave.prototype = { * @chainable */ setupAutosave: function() { + var draftid = -1, + optiontype = null, + options = this.get('filepickeroptions'); if (!this.get('autosaveEnabled')) { // Autosave disabled for this instance. return; } - this.autosaveInstance = Y.stamp(this); - var draftid = -1, optiontype, options = this.get('filepickeroptions'); for (optiontype in options) { if (typeof options[optiontype].itemid !== "undefined") { draftid = options[optiontype].itemid; @@ -103,7 +128,9 @@ EditorAutosave.prototype = { // Now setup the timer for periodic saves. - Y.later(AUTOSAVE_FREQUENCY, this, this.saveDraft, false, true); + Y.log(this.get('autosaveFrequency')); + var delay = parseInt(this.get('autosaveFrequency'), 10) * 1000; + Y.later(delay, this, this.saveDraft, false, true); // Now setup the listener for form submission. this.textarea.ancestor('form').on('submit', this.resetAutosave, this); @@ -139,30 +166,19 @@ EditorAutosave.prototype = { /** - * Show a confirm dialogue and recover some text returned by ajax. + * Recover a previous version of this text and show a message. * * @method recoverText * @param {String} text * @chainable */ recoverText: function(text) { - var confirm = new M.core.confirm({ - title : M.util.get_string('confirm', 'editor_atto'), - question : M.util.get_string('confirmrecover', 'editor_atto', { - label : this.textareaLabel.get('text') - }), - yesLabel : M.util.get_string('recover', 'editor_atto'), - noLabel : M.util.get_string('cancel', 'editor_atto') - }); - confirm.on('complete-yes', function() { - confirm.hide(); - confirm.destroy(); - this.editor.setHTML(text); - this.saveSelection(); - this.updateOriginal(); - this.lastText = text; - }, this); - confirm.show(); + this.editor.setHTML(text); + this.saveSelection(); + this.updateOriginal(); + this.lastText = text; + + this.showMessage(M.util.get_string('textrecovered', 'editor_atto'), 'info', RECOVER_MESSAGE_TIMEOUT); return this; }, @@ -191,6 +207,7 @@ EditorAutosave.prototype = { pagedomid: Y.one('body').get('id'), pageinstance: this.autosaveInstance }; + var errorDuration = parseInt(this.get('autosaveFrequency'), 10) * 1000; Y.io(url, { method: 'POST', @@ -199,18 +216,18 @@ EditorAutosave.prototype = { error: function(code, response) { Y.log('Error while autosaving text:' + code, 'warn'); Y.log(response, 'warn'); - this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', AUTOSAVE_FREQUENCY); + this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', errorDuration); }, failure: function(code, response) { Y.log('Failure while autosaving text:' + code, 'warn'); Y.log(response, 'warn'); - this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', AUTOSAVE_FREQUENCY); + this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', errorDuration); }, success: function(code, response) { if (response.response !== "") { Y.log('Failure while autosaving text.', 'warn'); Y.log(response, 'debug'); - this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', AUTOSAVE_FREQUENCY); + this.showMessage(M.util.get_string('autosavefailed', 'editor_atto'), 'warning', errorDuration); } else { // All working. this.lastText = newText; diff --git a/lib/editor/atto/yui/src/editor/js/editor.js b/lib/editor/atto/yui/src/editor/js/editor.js index a8bc3372acb..e03c03f6e64 100644 --- a/lib/editor/atto/yui/src/editor/js/editor.js +++ b/lib/editor/atto/yui/src/editor/js/editor.js @@ -404,18 +404,6 @@ Y.extend(Editor, Y.Base, { writeOnce: true }, - /** - * Enable/Disable auto save for this instance. - * - * @attribute autosaveEnabled - * @type Boolean - * @writeOnce - */ - autosaveEnabled: { - value: true, - writeOnce: true - }, - /** * Plugins with their configuration. * diff --git a/lib/editor/atto/yui/src/editor/js/notify.js b/lib/editor/atto/yui/src/editor/js/notify.js index f5374e51b60..1b29a3e1249 100644 --- a/lib/editor/atto/yui/src/editor/js/notify.js +++ b/lib/editor/atto/yui/src/editor/js/notify.js @@ -90,11 +90,11 @@ EditorNotify.prototype = { var messageTypeIcon = ''; if (type === "warning") { - messageTypeIcon = '' + M.util.get_string('warning', 'moodle') + ''; } else if (type === "info") { - messageTypeIcon = '' + M.util.get_string('info', 'moodle') + ''; } else {