[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 // This file is part of Moodle - http://moodle.org/ 2 // 3 // Moodle is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // (at your option) any later version. 7 // 8 // Moodle is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 15 16 /** 17 * AJAX helper for the inline editing a value. 18 * 19 * This script is automatically included from template core/inplace_editable 20 * It registers a click-listener on [data-inplaceeditablelink] link (the "inplace edit" icon), 21 * then replaces the displayed value with an input field. On "Enter" it sends a request 22 * to web service core_update_inplace_editable, which invokes the specified callback. 23 * Any exception thrown by the web service (or callback) is displayed as an error popup. 24 * 25 * @module core/inplace_editable 26 * @package core 27 * @copyright 2016 Marina Glancy 28 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 29 * @since 3.1 30 */ 31 define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str', 'core/config', 'core/url'], 32 function($, ajax, templates, notification, str, cfg, url) { 33 34 $('body').on('click keypress', '[data-inplaceeditable] [data-inplaceeditablelink]', function(e) { 35 if (e.type === 'keypress' && e.keyCode !== 13) { 36 return; 37 } 38 e.stopImmediatePropagation(); 39 e.preventDefault(); 40 var target = $(this), 41 mainelement = target.closest('[data-inplaceeditable]'); 42 43 var addSpinner = function(element) { 44 element.addClass('updating'); 45 var spinner = element.find('img.spinner'); 46 if (spinner.length) { 47 spinner.show(); 48 } else { 49 spinner = $('<img/>') 50 .attr('src', url.imageUrl('i/loading_small')) 51 .addClass('spinner').addClass('smallicon') 52 ; 53 element.append(spinner); 54 } 55 }; 56 57 var removeSpinner = function(element) { 58 element.removeClass('updating'); 59 element.find('img.spinner').hide(); 60 }; 61 62 var updateValue = function(mainelement, value) { 63 addSpinner(mainelement); 64 ajax 65 .call([{ 66 methodname: 'core_update_inplace_editable', 67 args: { 68 itemid: mainelement.attr('data-itemid'), 69 component: mainelement.attr('data-component'), 70 itemtype: mainelement.attr('data-itemtype'), 71 value: value 72 }, 73 done: function(data) { 74 var oldvalue = mainelement.attr('data-value'); 75 templates.render('core/inplace_editable', data).done(function(html, js) { 76 var newelement = $(html); 77 templates.replaceNode(mainelement, newelement, js); 78 newelement.find('[data-inplaceeditablelink]').focus(); 79 newelement.trigger({type: 'updated', ajaxreturn: data, oldvalue: oldvalue}); 80 }); 81 }, 82 fail: function(ex) { 83 var e = $.Event('updatefailed', { 84 exception: ex, 85 newvalue: value 86 }); 87 removeSpinner(mainelement); 88 mainelement.trigger(e); 89 if (!e.isDefaultPrevented()) { 90 notification.exception(ex); 91 } 92 } 93 }], true); 94 }; 95 96 var turnEditingOff = function(el) { 97 el.find('input').off(); 98 el.find('select').off(); 99 el.html(el.attr('data-oldcontent')); 100 el.removeAttr('data-oldcontent'); 101 el.removeClass('inplaceeditingon'); 102 el.find('[data-inplaceeditablelink]').focus(); 103 }; 104 105 var turnEditingOffEverywhere = function() { 106 $('span.inplaceeditable.inplaceeditingon').each(function() { 107 turnEditingOff($(this)); 108 }); 109 }; 110 111 var uniqueId = function(prefix, idlength) { 112 var uniqid = prefix, 113 i; 114 for (i = 0; i < idlength; i++) { 115 uniqid += String(Math.floor(Math.random() * 10)); 116 } 117 // Make sure this ID is not already taken by an existing element. 118 if ($("#" + uniqid).length === 0) { 119 return uniqid; 120 } 121 return uniqueId(prefix, idlength); 122 }; 123 124 var turnEditingOnText = function(el) { 125 str.get_string('edittitleinstructions').done(function(s) { 126 var instr = $('<span class="editinstructions">' + s + '</span>'). 127 attr('id', uniqueId('id_editinstructions_', 20)), 128 inputelement = $('<input type="text"/>'). 129 attr('id', uniqueId('id_inplacevalue_', 20)). 130 attr('value', el.attr('data-value')). 131 attr('aria-describedby', instr.attr('id')), 132 lbl = $('<label class="accesshide">' + mainelement.attr('data-editlabel') + '</label>'). 133 attr('for', inputelement.attr('id')); 134 el.html('').append(instr).append(lbl).append(inputelement); 135 136 inputelement.focus(); 137 inputelement.select(); 138 inputelement.on('keyup keypress focusout', function(e) { 139 if (cfg.behatsiterunning && e.type === 'focusout') { 140 // Behat triggers focusout too often. 141 return; 142 } 143 if (e.type === 'keypress' && e.keyCode === 13) { 144 // We need 'keypress' event for Enter because keyup/keydown would catch Enter that was 145 // pressed in other fields. 146 var val = inputelement.val(); 147 turnEditingOff(el); 148 updateValue(el, val); 149 } 150 if ((e.type === 'keyup' && e.keyCode === 27) || e.type === 'focusout') { 151 // We need 'keyup' event for Escape because keypress does not work with Escape. 152 turnEditingOff(el); 153 } 154 }); 155 }); 156 }; 157 158 var turnEditingOnToggle = function(el, newvalue) { 159 turnEditingOff(el); 160 updateValue(el, newvalue); 161 }; 162 163 var turnEditingOnSelect = function(el, options) { 164 var i, 165 inputelement = $('<select></select>') 166 .attr('id', uniqueId('id_inplacevalue_', 20)), 167 lbl = $('<label class="accesshide">' + mainelement.attr('data-editlabel') + '</label>') 168 .attr('for', inputelement.attr('id')); 169 for (i in options) { 170 inputelement 171 .append($('<option>') 172 .attr('value', options[i].key) 173 .html(options[i].value)); 174 } 175 inputelement.val(el.attr('data-value')); 176 el.html('') 177 .append(lbl) 178 .append(inputelement); 179 180 inputelement.focus(); 181 inputelement.select(); 182 inputelement.on('keyup change focusout', function(e) { 183 if (cfg.behatsiterunning && e.type === 'focusout') { 184 // Behat triggers focusout too often. 185 return; 186 } 187 if (e.type === 'change') { 188 var val = inputelement.val(); 189 turnEditingOff(el); 190 updateValue(el, val); 191 } 192 if ((e.type === 'keyup' && e.keyCode === 27) || e.type === 'focusout') { 193 // We need 'keyup' event for Escape because keypress does not work with Escape. 194 turnEditingOff(el); 195 } 196 }); 197 }; 198 199 var turnEditingOn = function(el) { 200 el.addClass('inplaceeditingon'); 201 el.attr('data-oldcontent', el.html()); 202 203 var type = el.attr('data-type'); 204 var options = el.attr('data-options'); 205 206 if (type === 'toggle') { 207 turnEditingOnToggle(el, options); 208 } else if (type === 'select') { 209 turnEditingOnSelect(el, $.parseJSON(options)); 210 } else { 211 turnEditingOnText(el); 212 } 213 }; 214 215 // Turn editing on for the current element and register handler for Enter/Esc keys. 216 turnEditingOffEverywhere(); 217 turnEditingOn(mainelement); 218 219 }); 220 221 return {}; 222 });
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |