Merge branch 'MDL-70990-master' of git://github.com/andrewnicols/moodle

This commit is contained in:
Jake Dallimore
2021-05-26 12:49:34 +08:00
70 changed files with 1322 additions and 479 deletions
+2
View File
@@ -0,0 +1,2 @@
define ("core_block/events",["exports","core/event_dispatcher"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.notifyBlockContentUpdated=a.eventTypes=void 0;var c={blockContentUpdated:"core_block/contentUpdated"};a.eventTypes=c;a.notifyBlockContentUpdated=function notifyBlockContentUpdated(a){return(0,b.dispatchEvent)(c.blockContentUpdated,{instanceId:a.dataset.instanceId},a)};var d=!1;if(!d){Y.use("event","moodle-core-event",function(a){document.addEventListener(c.blockContentUpdated,function(b){a.Global.fire(M.core.event.BLOCK_CONTENT_UPDATED,{instanceid:b.detail.instanceId})})});d=!0}});
//# sourceMappingURL=events.min.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../src/events.js"],"names":["eventTypes","blockContentUpdated","notifyBlockContentUpdated","element","instanceId","dataset","legacyEventsRegistered","Y","use","document","addEventListener","e","Global","fire","M","core","event","BLOCK_CONTENT_UPDATED","instanceid","detail"],"mappings":"4LA+BO,GAAMA,CAAAA,CAAU,CAAG,CAStBC,mBAAmB,CAAE,2BATC,CAAnB,C,2CAoBkC,QAA5BC,CAAAA,yBAA4B,CAAAC,CAAO,QAAI,oBAChDH,CAAU,CAACC,mBADqC,CAEhD,CACIG,UAAU,CAAED,CAAO,CAACE,OAAR,CAAgBD,UADhC,CAFgD,CAKhDD,CALgD,CAAJ,C,CAQhD,GAAIG,CAAAA,CAAsB,GAA1B,CACA,GAAI,CAACA,CAAL,CAA6B,CAKzBC,CAAC,CAACC,GAAF,CAAM,OAAN,CAAe,mBAAf,CAAoC,SAAAD,CAAC,CAAI,CAErCE,QAAQ,CAACC,gBAAT,CAA0BV,CAAU,CAACC,mBAArC,CAA0D,SAAAU,CAAC,CAAI,CAE3DJ,CAAC,CAACK,MAAF,CAASC,IAAT,CAAcC,CAAC,CAACC,IAAF,CAAOC,KAAP,CAAaC,qBAA3B,CAAkD,CAACC,UAAU,CAAEP,CAAC,CAACQ,MAAF,CAASf,UAAtB,CAAlD,CACH,CAHD,CAIH,CAND,EAQAE,CAAsB,GACzB,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/ //\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Javascript events for the `core_block` subsystem.\n *\n * @module core_block/events\n * @copyright 2021 Andrew Nicols <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n */\n\nimport {dispatchEvent} from 'core/event_dispatcher';\n\n/**\n * Events for `core_block`.\n *\n * @constant\n * @property {String} blockContentUpdated See {@link event:blockContentUpdated}\n */\nexport const eventTypes = {\n /**\n * An event triggered when the content of a block has changed.\n *\n * @event blockContentUpdated\n * @type {CustomEvent}\n * @property {HTMLElement} target The block element that was updated\n * @property {Number} instanceId The block instance id\n */\n blockContentUpdated: 'core_block/contentUpdated',\n};\n\n/**\n * Trigger an event to indicate that the content of a block was updated.\n *\n * @method notifyBlockContentUpdated\n * @param {HTMLElement} element The HTMLElement containing the updated block.\n * @returns {CustomEvent}\n * @fires blockContentUpdated\n */\nexport const notifyBlockContentUpdated = element => dispatchEvent(\n eventTypes.blockContentUpdated,\n {\n instanceId: element.dataset.instanceId,\n },\n element\n);\n\nlet legacyEventsRegistered = false;\nif (!legacyEventsRegistered) {\n // The following event triggers are legacy and will be removed in the future.\n // The following approach provides a backwards-compatability layer for the new events.\n // Code should be updated to make use of native events.\n\n Y.use('event', 'moodle-core-event', Y => {\n // Provide a backwards-compatability layer for YUI Events.\n document.addEventListener(eventTypes.blockContentUpdated, e => {\n // Trigger the legacy YUI event.\n Y.Global.fire(M.core.event.BLOCK_CONTENT_UPDATED, {instanceid: e.detail.instanceId});\n });\n });\n\n legacyEventsRegistered = true;\n}\n"],"file":"events.min.js"}
+75
View File
@@ -0,0 +1,75 @@
// This file is part of Moodle - http://moodle.org/ //
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Javascript events for the `core_block` subsystem.
*
* @module core_block/events
* @copyright 2021 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 4.0
*/
import {dispatchEvent} from 'core/event_dispatcher';
/**
* Events for `core_block`.
*
* @constant
* @property {String} blockContentUpdated See {@link event:blockContentUpdated}
*/
export const eventTypes = {
/**
* An event triggered when the content of a block has changed.
*
* @event blockContentUpdated
* @type {CustomEvent}
* @property {HTMLElement} target The block element that was updated
* @property {Number} instanceId The block instance id
*/
blockContentUpdated: 'core_block/contentUpdated',
};
/**
* Trigger an event to indicate that the content of a block was updated.
*
* @method notifyBlockContentUpdated
* @param {HTMLElement} element The HTMLElement containing the updated block.
* @returns {CustomEvent}
* @fires blockContentUpdated
*/
export const notifyBlockContentUpdated = element => dispatchEvent(
eventTypes.blockContentUpdated,
{
instanceId: element.dataset.instanceId,
},
element
);
let legacyEventsRegistered = false;
if (!legacyEventsRegistered) {
// The following event triggers are legacy and will be removed in the future.
// The following approach provides a backwards-compatability layer for the new events.
// Code should be updated to make use of native events.
Y.use('event', 'moodle-core-event', Y => {
// Provide a backwards-compatability layer for YUI Events.
document.addEventListener(eventTypes.blockContentUpdated, e => {
// Trigger the legacy YUI event.
Y.Global.fire(M.core.event.BLOCK_CONTENT_UPDATED, {instanceid: e.detail.instanceId});
});
});
legacyEventsRegistered = true;
}
+1 -1
View File
@@ -1,2 +1,2 @@
define ("block_navigation/navblock",["jquery","core/tree"],function(a,b){return{init:function init(a){var c=new b(".block_navigation .block_tree");c.finishExpandingGroup=function(c){b.prototype.finishExpandingGroup.call(this,c);Y.use("moodle-core-event",function(){Y.Global.fire(M.core.globalEvents.BLOCK_CONTENT_UPDATED,{instanceid:a})})};c.collapseGroup=function(c){b.prototype.collapseGroup.call(this,c);Y.use("moodle-core-event",function(){Y.Global.fire(M.core.globalEvents.BLOCK_CONTENT_UPDATED,{instanceid:a})})}}}});
define ("block_navigation/navblock",["exports","core_block/events","core/tree"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;c=function(a){return a&&a.__esModule?a:{default:a}}(c);var d=function(a){var d=new c.default(".block_navigation .block_tree"),e=document.querySelector("[data-instance-id=\"".concat(a,"\"]"));d.finishExpandingGroup=function(a){c.default.prototype.finishExpandingGroup.call(d,a);(0,b.notifyBlockContentUpdated)(e)};d.collapseGroup=function(a){c.default.prototype.collapseGroup.call(d,a);(0,b.notifyBlockContentUpdated)(e)}};a.init=d});
//# sourceMappingURL=navblock.min.js.map
@@ -1 +1 @@
{"version":3,"sources":["../src/navblock.js"],"names":["define","$","Tree","init","instanceid","navTree","finishExpandingGroup","item","prototype","call","Y","use","Global","fire","M","core","globalEvents","BLOCK_CONTENT_UPDATED","collapseGroup"],"mappings":"AAuBAA,OAAM,6BAAC,CAAC,QAAD,CAAW,WAAX,CAAD,CAA0B,SAASC,CAAT,CAAYC,CAAZ,CAAkB,CAC9C,MAAO,CACHC,IAAI,CAAE,cAASC,CAAT,CAAqB,CACvB,GAAIC,CAAAA,CAAO,CAAG,GAAIH,CAAAA,CAAJ,CAAS,+BAAT,CAAd,CACAG,CAAO,CAACC,oBAAR,CAA+B,SAASC,CAAT,CAAe,CAC1CL,CAAI,CAACM,SAAL,CAAeF,oBAAf,CAAoCG,IAApC,CAAyC,IAAzC,CAA+CF,CAA/C,EACAG,CAAC,CAACC,GAAF,CAAM,mBAAN,CAA2B,UAAW,CAClCD,CAAC,CAACE,MAAF,CAASC,IAAT,CAAcC,CAAC,CAACC,IAAF,CAAOC,YAAP,CAAoBC,qBAAlC,CAAyD,CACrDb,UAAU,CAAEA,CADyC,CAAzD,CAGH,CAJD,CAKH,CAPD,CAQAC,CAAO,CAACa,aAAR,CAAwB,SAASX,CAAT,CAAe,CACnCL,CAAI,CAACM,SAAL,CAAeU,aAAf,CAA6BT,IAA7B,CAAkC,IAAlC,CAAwCF,CAAxC,EACAG,CAAC,CAACC,GAAF,CAAM,mBAAN,CAA2B,UAAW,CAClCD,CAAC,CAACE,MAAF,CAASC,IAAT,CAAcC,CAAC,CAACC,IAAF,CAAOC,YAAP,CAAoBC,qBAAlC,CAAyD,CACrDb,UAAU,CAAEA,CADyC,CAAzD,CAGH,CAJD,CAKH,CACJ,CAnBE,CAqBV,CAtBK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Load the navigation tree javascript.\n *\n * @module block_navigation/navblock\n * @package core\n * @copyright 2015 John Okely <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/tree'], function($, Tree) {\n return {\n init: function(instanceid) {\n var navTree = new Tree(\".block_navigation .block_tree\");\n navTree.finishExpandingGroup = function(item) {\n Tree.prototype.finishExpandingGroup.call(this, item);\n Y.use('moodle-core-event', function() {\n Y.Global.fire(M.core.globalEvents.BLOCK_CONTENT_UPDATED, {\n instanceid: instanceid\n });\n });\n };\n navTree.collapseGroup = function(item) {\n Tree.prototype.collapseGroup.call(this, item);\n Y.use('moodle-core-event', function() {\n Y.Global.fire(M.core.globalEvents.BLOCK_CONTENT_UPDATED, {\n instanceid: instanceid\n });\n });\n };\n }\n };\n});\n"],"file":"navblock.min.js"}
{"version":3,"sources":["../src/navblock.js"],"names":["init","instanceId","navTree","Tree","blockNode","document","querySelector","finishExpandingGroup","item","prototype","call","collapseGroup"],"mappings":"4KAwBA,uDAQO,GAAMA,CAAAA,CAAI,CAAG,SAAAC,CAAU,CAAI,IACxBC,CAAAA,CAAO,CAAG,GAAIC,UAAJ,CAAS,+BAAT,CADc,CAExBC,CAAS,CAAGC,QAAQ,CAACC,aAAT,+BAA6CL,CAA7C,QAFY,CAW9BC,CAAO,CAACK,oBAAR,CAA+B,SAAAC,CAAI,CAAI,CACnCL,UAAKM,SAAL,CAAeF,oBAAf,CAAoCG,IAApC,CAAyCR,CAAzC,CAAkDM,CAAlD,EACA,gCAA0BJ,CAA1B,CACH,CAHD,CAYAF,CAAO,CAACS,aAAR,CAAwB,SAAAH,CAAI,CAAI,CAC5BL,UAAKM,SAAL,CAAeE,aAAf,CAA6BD,IAA7B,CAAkCR,CAAlC,CAA2CM,CAA3C,EACA,gCAA0BJ,CAA1B,CACH,CACJ,CA3BM,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Load the navigation tree javascript.\n *\n * @module block_navigation/navblock\n * @package core\n * @copyright 2015 John Okely <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {notifyBlockContentUpdated} from 'core_block/events';\nimport Tree from 'core/tree';\n\n/**\n * Initialise the navblock javascript for the specified block instance.\n *\n * @method\n * @param {Number} instanceId\n */\nexport const init = instanceId => {\n const navTree = new Tree(\".block_navigation .block_tree\");\n const blockNode = document.querySelector(`[data-instance-id=\"${instanceId}\"]`);\n\n /**\n * The method to call when then the navtree finishes expanding a group.\n *\n * @method finishExpandingGroup\n * @param {Object} item\n * @fires event:blockContentUpdated\n */\n navTree.finishExpandingGroup = item => {\n Tree.prototype.finishExpandingGroup.call(navTree, item);\n notifyBlockContentUpdated(blockNode);\n };\n\n /**\n * The method to call whe then the navtree collapses a group\n *\n * @method collapseGroup\n * @param {Object} item\n * @fires event:blockContentUpdated\n */\n navTree.collapseGroup = item => {\n Tree.prototype.collapseGroup.call(navTree, item);\n notifyBlockContentUpdated(blockNode);\n };\n};\n"],"file":"navblock.min.js"}
+36 -22
View File
@@ -21,26 +21,40 @@
* @copyright 2015 John Okely <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define(['jquery', 'core/tree'], function($, Tree) {
return {
init: function(instanceid) {
var navTree = new Tree(".block_navigation .block_tree");
navTree.finishExpandingGroup = function(item) {
Tree.prototype.finishExpandingGroup.call(this, item);
Y.use('moodle-core-event', function() {
Y.Global.fire(M.core.globalEvents.BLOCK_CONTENT_UPDATED, {
instanceid: instanceid
});
});
};
navTree.collapseGroup = function(item) {
Tree.prototype.collapseGroup.call(this, item);
Y.use('moodle-core-event', function() {
Y.Global.fire(M.core.globalEvents.BLOCK_CONTENT_UPDATED, {
instanceid: instanceid
});
});
};
}
import {notifyBlockContentUpdated} from 'core_block/events';
import Tree from 'core/tree';
/**
* Initialise the navblock javascript for the specified block instance.
*
* @method
* @param {Number} instanceId
*/
export const init = instanceId => {
const navTree = new Tree(".block_navigation .block_tree");
const blockNode = document.querySelector(`[data-instance-id="${instanceId}"]`);
/**
* The method to call when then the navtree finishes expanding a group.
*
* @method finishExpandingGroup
* @param {Object} item
* @fires event:blockContentUpdated
*/
navTree.finishExpandingGroup = item => {
Tree.prototype.finishExpandingGroup.call(navTree, item);
notifyBlockContentUpdated(blockNode);
};
});
/**
* The method to call whe then the navtree collapses a group
*
* @method collapseGroup
* @param {Object} item
* @fires event:blockContentUpdated
*/
navTree.collapseGroup = item => {
Tree.prototype.collapseGroup.call(navTree, item);
notifyBlockContentUpdated(blockNode);
};
};
+1 -1
View File
@@ -1,2 +1,2 @@
define ("block_settings/settingsblock",["jquery","core/tree"],function(a,b){return{init:function init(a,c){var d=new b(".block_settings .block_tree");if(c){var e=d.treeRoot.find("#"+c),f=e.children("a").first();f.replaceWith("<span tabindex=\"0\">"+f.html()+"</span>")}d.finishExpandingGroup=function(c){b.prototype.finishExpandingGroup.call(this,c);Y.use("moodle-core-event",function(){Y.Global.fire(M.core.globalEvents.BLOCK_CONTENT_UPDATED,{instanceid:a})})};d.collapseGroup=function(c){b.prototype.collapseGroup.call(this,c);Y.use("moodle-core-event",function(){Y.Global.fire(M.core.globalEvents.BLOCK_CONTENT_UPDATED,{instanceid:a})})}}}});
define ("block_settings/settingsblock",["exports","core_block/events","core/tree"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;c=function(a){return a&&a.__esModule?a:{default:a}}(c);var d=function(a,d){var e=new c.default(".block_settings .block_tree"),f=document.querySelector("[data-instance-id=\"".concat(a,"\"]"));if(d){var g=e.treeRoot.get(0).querySelector("#".concat(d," a")),h=document.createElement("span");h.setAttribute("tabindex","0");g.childNodes.forEach(function(a){return h.appendChild(a)});g.replaceWith(h)}e.finishExpandingGroup=function(a){c.default.prototype.finishExpandingGroup.call(e,a);(0,b.notifyBlockContentUpdated)(f)};e.collapseGroup=function(a){c.default.prototype.collapseGroup.call(e,a);(0,b.notifyBlockContentUpdated)(f)}};a.init=d});
//# sourceMappingURL=settingsblock.min.js.map
@@ -1 +1 @@
{"version":3,"sources":["../src/settingsblock.js"],"names":["define","$","Tree","init","instanceid","siteAdminNodeId","adminTree","siteAdminNode","treeRoot","find","siteAdminLink","children","first","replaceWith","html","finishExpandingGroup","item","prototype","call","Y","use","Global","fire","M","core","globalEvents","BLOCK_CONTENT_UPDATED","collapseGroup"],"mappings":"AAuBAA,OAAM,gCAAC,CAAC,QAAD,CAAW,WAAX,CAAD,CAA0B,SAASC,CAAT,CAAYC,CAAZ,CAAkB,CAC9C,MAAO,CACHC,IAAI,CAAE,cAASC,CAAT,CAAqBC,CAArB,CAAsC,CACxC,GAAIC,CAAAA,CAAS,CAAG,GAAIJ,CAAAA,CAAJ,CAAS,6BAAT,CAAhB,CACA,GAAIG,CAAJ,CAAqB,IACbE,CAAAA,CAAa,CAAGD,CAAS,CAACE,QAAV,CAAmBC,IAAnB,CAAwB,IAAMJ,CAA9B,CADH,CAEbK,CAAa,CAAGH,CAAa,CAACI,QAAd,CAAuB,GAAvB,EAA4BC,KAA5B,EAFH,CAGjBF,CAAa,CAACG,WAAd,CAA0B,wBAAwBH,CAAa,CAACI,IAAd,EAAxB,CAA+C,SAAzE,CACH,CACDR,CAAS,CAACS,oBAAV,CAAiC,SAASC,CAAT,CAAe,CAC5Cd,CAAI,CAACe,SAAL,CAAeF,oBAAf,CAAoCG,IAApC,CAAyC,IAAzC,CAA+CF,CAA/C,EACAG,CAAC,CAACC,GAAF,CAAM,mBAAN,CAA2B,UAAW,CAClCD,CAAC,CAACE,MAAF,CAASC,IAAT,CAAcC,CAAC,CAACC,IAAF,CAAOC,YAAP,CAAoBC,qBAAlC,CAAyD,CACrDtB,UAAU,CAAEA,CADyC,CAAzD,CAGH,CAJD,CAKH,CAPD,CAQAE,CAAS,CAACqB,aAAV,CAA0B,SAASX,CAAT,CAAe,CACrCd,CAAI,CAACe,SAAL,CAAeU,aAAf,CAA6BT,IAA7B,CAAkC,IAAlC,CAAwCF,CAAxC,EACAG,CAAC,CAACC,GAAF,CAAM,mBAAN,CAA2B,UAAW,CAClCD,CAAC,CAACE,MAAF,CAASC,IAAT,CAAcC,CAAC,CAACC,IAAF,CAAOC,YAAP,CAAoBC,qBAAlC,CAAyD,CACrDtB,UAAU,CAAEA,CADyC,CAAzD,CAGH,CAJD,CAKH,CACJ,CAxBE,CA0BV,CA3BK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Load the settings block tree javscript\n *\n * @module block_settings/settingsblock\n * @package core\n * @copyright 2015 John Okely <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/tree'], function($, Tree) {\n return {\n init: function(instanceid, siteAdminNodeId) {\n var adminTree = new Tree(\".block_settings .block_tree\");\n if (siteAdminNodeId) {\n var siteAdminNode = adminTree.treeRoot.find('#' + siteAdminNodeId);\n var siteAdminLink = siteAdminNode.children('a').first();\n siteAdminLink.replaceWith('<span tabindex=\"0\">' + siteAdminLink.html() + '</span>');\n }\n adminTree.finishExpandingGroup = function(item) {\n Tree.prototype.finishExpandingGroup.call(this, item);\n Y.use('moodle-core-event', function() {\n Y.Global.fire(M.core.globalEvents.BLOCK_CONTENT_UPDATED, {\n instanceid: instanceid\n });\n });\n };\n adminTree.collapseGroup = function(item) {\n Tree.prototype.collapseGroup.call(this, item);\n Y.use('moodle-core-event', function() {\n Y.Global.fire(M.core.globalEvents.BLOCK_CONTENT_UPDATED, {\n instanceid: instanceid\n });\n });\n };\n }\n };\n});\n"],"file":"settingsblock.min.js"}
{"version":3,"sources":["../src/settingsblock.js"],"names":["init","instanceId","siteAdminNodeId","adminTree","Tree","blockNode","document","querySelector","siteAdminLink","treeRoot","get","newContainer","createElement","setAttribute","childNodes","forEach","node","appendChild","replaceWith","finishExpandingGroup","item","prototype","call","collapseGroup"],"mappings":"+KAwBA,uDAEO,GAAMA,CAAAA,CAAI,CAAG,SAACC,CAAD,CAAaC,CAAb,CAAiC,IAC3CC,CAAAA,CAAS,CAAG,GAAIC,UAAJ,CAAS,6BAAT,CAD+B,CAE3CC,CAAS,CAAGC,QAAQ,CAACC,aAAT,+BAA6CN,CAA7C,QAF+B,CAIjD,GAAIC,CAAJ,CAAqB,IACXM,CAAAA,CAAa,CAAGL,CAAS,CAACM,QAAV,CAAmBC,GAAnB,CAAuB,CAAvB,EAA0BH,aAA1B,YAA4CL,CAA5C,OADL,CAEXS,CAAY,CAAGL,QAAQ,CAACM,aAAT,CAAuB,MAAvB,CAFJ,CAGjBD,CAAY,CAACE,YAAb,CAA0B,UAA1B,CAAsC,GAAtC,EACAL,CAAa,CAACM,UAAd,CAAyBC,OAAzB,CAAiC,SAAAC,CAAI,QAAIL,CAAAA,CAAY,CAACM,WAAb,CAAyBD,CAAzB,CAAJ,CAArC,EACAR,CAAa,CAACU,WAAd,CAA0BP,CAA1B,CACH,CASDR,CAAS,CAACgB,oBAAV,CAAiC,SAASC,CAAT,CAAe,CAC5ChB,UAAKiB,SAAL,CAAeF,oBAAf,CAAoCG,IAApC,CAAyCnB,CAAzC,CAAoDiB,CAApD,EACA,gCAA0Bf,CAA1B,CACH,CAHD,CAYAF,CAAS,CAACoB,aAAV,CAA0B,SAASH,CAAT,CAAe,CACrChB,UAAKiB,SAAL,CAAeE,aAAf,CAA6BD,IAA7B,CAAkCnB,CAAlC,CAA6CiB,CAA7C,EACA,gCAA0Bf,CAA1B,CACH,CACJ,CAnCM,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Load the settings block tree javscript\n *\n * @module block_settings/settingsblock\n * @package core\n * @copyright 2015 John Okely <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {notifyBlockContentUpdated} from 'core_block/events';\nimport Tree from 'core/tree';\n\nexport const init = (instanceId, siteAdminNodeId) => {\n const adminTree = new Tree(\".block_settings .block_tree\");\n const blockNode = document.querySelector(`[data-instance-id=\"${instanceId}\"]`);\n\n if (siteAdminNodeId) {\n const siteAdminLink = adminTree.treeRoot.get(0).querySelector(`#${siteAdminNodeId} a`);\n const newContainer = document.createElement('span');\n newContainer.setAttribute('tabindex', '0');\n siteAdminLink.childNodes.forEach(node => newContainer.appendChild(node));\n siteAdminLink.replaceWith(newContainer);\n }\n\n /**\n * The method to call when then the navtree finishes expanding a group.\n *\n * @method finishExpandingGroup\n * @param {Object} item\n * @fires event:blockContentUpdated\n */\n adminTree.finishExpandingGroup = function(item) {\n Tree.prototype.finishExpandingGroup.call(adminTree, item);\n notifyBlockContentUpdated(blockNode);\n };\n\n /**\n * The method to call whe then the navtree collapses a group\n *\n * @method collapseGroup\n * @param {Object} item\n * @fires event:blockContentUpdated\n */\n adminTree.collapseGroup = function(item) {\n Tree.prototype.collapseGroup.call(adminTree, item);\n notifyBlockContentUpdated(blockNode);\n };\n};\n"],"file":"settingsblock.min.js"}
+38 -27
View File
@@ -21,31 +21,42 @@
* @copyright 2015 John Okely <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define(['jquery', 'core/tree'], function($, Tree) {
return {
init: function(instanceid, siteAdminNodeId) {
var adminTree = new Tree(".block_settings .block_tree");
if (siteAdminNodeId) {
var siteAdminNode = adminTree.treeRoot.find('#' + siteAdminNodeId);
var siteAdminLink = siteAdminNode.children('a').first();
siteAdminLink.replaceWith('<span tabindex="0">' + siteAdminLink.html() + '</span>');
}
adminTree.finishExpandingGroup = function(item) {
Tree.prototype.finishExpandingGroup.call(this, item);
Y.use('moodle-core-event', function() {
Y.Global.fire(M.core.globalEvents.BLOCK_CONTENT_UPDATED, {
instanceid: instanceid
});
});
};
adminTree.collapseGroup = function(item) {
Tree.prototype.collapseGroup.call(this, item);
Y.use('moodle-core-event', function() {
Y.Global.fire(M.core.globalEvents.BLOCK_CONTENT_UPDATED, {
instanceid: instanceid
});
});
};
}
import {notifyBlockContentUpdated} from 'core_block/events';
import Tree from 'core/tree';
export const init = (instanceId, siteAdminNodeId) => {
const adminTree = new Tree(".block_settings .block_tree");
const blockNode = document.querySelector(`[data-instance-id="${instanceId}"]`);
if (siteAdminNodeId) {
const siteAdminLink = adminTree.treeRoot.get(0).querySelector(`#${siteAdminNodeId} a`);
const newContainer = document.createElement('span');
newContainer.setAttribute('tabindex', '0');
siteAdminLink.childNodes.forEach(node => newContainer.appendChild(node));
siteAdminLink.replaceWith(newContainer);
}
/**
* The method to call when then the navtree finishes expanding a group.
*
* @method finishExpandingGroup
* @param {Object} item
* @fires event:blockContentUpdated
*/
adminTree.finishExpandingGroup = function(item) {
Tree.prototype.finishExpandingGroup.call(adminTree, item);
notifyBlockContentUpdated(blockNode);
};
});
/**
* The method to call whe then the navtree collapses a group
*
* @method collapseGroup
* @param {Object} item
* @fires event:blockContentUpdated
*/
adminTree.collapseGroup = function(item) {
Tree.prototype.collapseGroup.call(adminTree, item);
notifyBlockContentUpdated(blockNode);
};
};
+1 -1
View File
@@ -1,2 +1,2 @@
define ("core_calendar/modal_event_form",["jquery","core/event","core/str","core/notification","core/templates","core/custom_interaction_events","core/modal","core/modal_registry","core/fragment","core_calendar/events","core_calendar/repository"],function(a,b,c,d,e,f,g,h,i,j,k){var l=!1,m={SAVE_BUTTON:"[data-action=\"save\"]",LOADING_ICON_CONTAINER:"[data-region=\"loading-icon-container\"]"},n=function(a){g.call(this,a);this.eventId=null;this.startTime=null;this.courseId=null;this.categoryId=null;this.contextId=null;this.reloadingBody=!1;this.reloadingTitle=!1;this.saveButton=this.getFooter().find(m.SAVE_BUTTON)};n.TYPE="core_calendar-modal_event_form";n.prototype=Object.create(g.prototype);n.prototype.constructor=n;n.prototype.setContextId=function(a){this.contextId=a};n.prototype.getContextId=function(){return this.contextId};n.prototype.setCourseId=function(a){this.courseId=a};n.prototype.getCourseId=function(){return this.courseId};n.prototype.setCategoryId=function(a){this.categoryId=a};n.prototype.getCategoryId=function(){return this.categoryId};n.prototype.hasCourseId=function(){return null!==this.courseId};n.prototype.hasCategoryId=function(){return null!==this.categoryId};n.prototype.setEventId=function(a){this.eventId=a};n.prototype.getEventId=function(){return this.eventId};n.prototype.hasEventId=function(){return null!==this.eventId};n.prototype.setStartTime=function(a){this.startTime=a};n.prototype.getStartTime=function(){return this.startTime};n.prototype.hasStartTime=function(){return null!==this.startTime};n.prototype.getForm=function(){return this.getBody().find("form")};n.prototype.disableButtons=function(){this.saveButton.prop("disabled",!0)};n.prototype.enableButtons=function(){this.saveButton.prop("disabled",!1)};n.prototype.reloadTitleContent=function(){if(this.reloadingTitle){return this.titlePromise}this.reloadingTitle=!0;if(this.hasEventId()){this.titlePromise=c.get_string("editevent","calendar")}else{this.titlePromise=c.get_string("newevent","calendar")}this.titlePromise.then(function(a){this.setTitle(a);return a}.bind(this)).always(function(){this.reloadingTitle=!1}.bind(this)).fail(d.exception);return this.titlePromise};n.prototype.reloadBodyContent=function(a){if(this.reloadingBody){return this.bodyPromise}this.reloadingBody=!0;this.disableButtons();var b={};if(this.hasEventId()){b.eventid=this.getEventId()}if(this.hasStartTime()){b.starttime=this.getStartTime()}if(this.hasCourseId()){b.courseid=this.getCourseId()}if(this.hasCategoryId()){b.categoryid=this.getCategoryId()}if("undefined"!=typeof a){b.formdata=a}this.bodyPromise=i.loadFragment("calendar","event_form",this.getContextId(),b);this.setBody(this.bodyPromise);this.bodyPromise.then(function(){this.enableButtons()}.bind(this)).fail(d.exception).always(function(){this.reloadingBody=!1}.bind(this)).fail(d.exception);return this.bodyPromise};n.prototype.reloadAllContent=function(){return a.when(this.reloadTitleContent(),this.reloadBodyContent())};n.prototype.show=function(){this.reloadAllContent();g.prototype.show.call(this)};n.prototype.hide=function(){g.prototype.hide.call(this);this.setEventId(null);this.setStartTime(null);this.setCourseId(null);this.setCategoryId(null)};n.prototype.getFormData=function(){return this.getForm().serialize()};n.prototype.save=function(){var b,c=this.saveButton.find(m.LOADING_ICON_CONTAINER);b=this.getForm().find("[aria-invalid=\"true\"]");if(b.length){b.first().focus();return}c.removeClass("hidden");this.disableButtons();var e=this.getFormData();return k.submitCreateUpdateForm(e).then(function(b){if(b.validationerror){this.reloadBodyContent(e)}else{var c=this.hasEventId();this.hide();if(c){a("body").trigger(j.updated,[b.event])}else{a("body").trigger(j.created,[b.event])}}}.bind(this)).always(function(){c.addClass("hidden");this.enableButtons()}.bind(this)).fail(d.exception)};n.prototype.registerEventListeners=function(){g.prototype.registerEventListeners.call(this);this.getModal().on(f.events.activate,m.SAVE_BUTTON,function(a,b){this.getForm().submit();b.originalEvent.preventDefault();a.stopPropagation()}.bind(this));this.getModal().on("submit",function(a){b.notifyFormSubmitAjax(this.getForm()[0]);this.save();a.preventDefault();a.stopPropagation()}.bind(this))};if(!l){h.register(n.TYPE,n,"calendar/modal_event_form");l=!0}return n});
define ("core_calendar/modal_event_form",["jquery","core_form/events","core/str","core/notification","core/templates","core/custom_interaction_events","core/modal","core/modal_registry","core/fragment","core_calendar/events","core_calendar/repository"],function(a,b,c,d,e,f,g,h,i,j,k){var l=!1,m={SAVE_BUTTON:"[data-action=\"save\"]",LOADING_ICON_CONTAINER:"[data-region=\"loading-icon-container\"]"},n=function(a){g.call(this,a);this.eventId=null;this.startTime=null;this.courseId=null;this.categoryId=null;this.contextId=null;this.reloadingBody=!1;this.reloadingTitle=!1;this.saveButton=this.getFooter().find(m.SAVE_BUTTON)};n.TYPE="core_calendar-modal_event_form";n.prototype=Object.create(g.prototype);n.prototype.constructor=n;n.prototype.setContextId=function(a){this.contextId=a};n.prototype.getContextId=function(){return this.contextId};n.prototype.setCourseId=function(a){this.courseId=a};n.prototype.getCourseId=function(){return this.courseId};n.prototype.setCategoryId=function(a){this.categoryId=a};n.prototype.getCategoryId=function(){return this.categoryId};n.prototype.hasCourseId=function(){return null!==this.courseId};n.prototype.hasCategoryId=function(){return null!==this.categoryId};n.prototype.setEventId=function(a){this.eventId=a};n.prototype.getEventId=function(){return this.eventId};n.prototype.hasEventId=function(){return null!==this.eventId};n.prototype.setStartTime=function(a){this.startTime=a};n.prototype.getStartTime=function(){return this.startTime};n.prototype.hasStartTime=function(){return null!==this.startTime};n.prototype.getForm=function(){return this.getBody().find("form")};n.prototype.disableButtons=function(){this.saveButton.prop("disabled",!0)};n.prototype.enableButtons=function(){this.saveButton.prop("disabled",!1)};n.prototype.reloadTitleContent=function(){if(this.reloadingTitle){return this.titlePromise}this.reloadingTitle=!0;if(this.hasEventId()){this.titlePromise=c.get_string("editevent","calendar")}else{this.titlePromise=c.get_string("newevent","calendar")}this.titlePromise.then(function(a){this.setTitle(a);return a}.bind(this)).always(function(){this.reloadingTitle=!1}.bind(this)).fail(d.exception);return this.titlePromise};n.prototype.reloadBodyContent=function(a){if(this.reloadingBody){return this.bodyPromise}this.reloadingBody=!0;this.disableButtons();var b={};if(this.hasEventId()){b.eventid=this.getEventId()}if(this.hasStartTime()){b.starttime=this.getStartTime()}if(this.hasCourseId()){b.courseid=this.getCourseId()}if(this.hasCategoryId()){b.categoryid=this.getCategoryId()}if("undefined"!=typeof a){b.formdata=a}this.bodyPromise=i.loadFragment("calendar","event_form",this.getContextId(),b);this.setBody(this.bodyPromise);this.bodyPromise.then(function(){this.enableButtons()}.bind(this)).fail(d.exception).always(function(){this.reloadingBody=!1}.bind(this)).fail(d.exception);return this.bodyPromise};n.prototype.reloadAllContent=function(){return a.when(this.reloadTitleContent(),this.reloadBodyContent())};n.prototype.show=function(){this.reloadAllContent();g.prototype.show.call(this)};n.prototype.hide=function(){g.prototype.hide.call(this);this.setEventId(null);this.setStartTime(null);this.setCourseId(null);this.setCategoryId(null)};n.prototype.getFormData=function(){return this.getForm().serialize()};n.prototype.save=function(){var b,c=this.saveButton.find(m.LOADING_ICON_CONTAINER);b=this.getForm().find("[aria-invalid=\"true\"]");if(b.length){b.first().focus();return Promise.resolve()}c.removeClass("hidden");this.disableButtons();var e=this.getFormData();return k.submitCreateUpdateForm(e).then(function(b){if(b.validationerror){this.reloadBodyContent(e)}else{var c=this.hasEventId();this.hide();if(c){a("body").trigger(j.updated,[b.event])}else{a("body").trigger(j.created,[b.event])}}}.bind(this)).always(function(){c.addClass("hidden");this.enableButtons()}.bind(this)).fail(d.exception)};n.prototype.registerEventListeners=function(){g.prototype.registerEventListeners.call(this);this.getModal().on(f.events.activate,m.SAVE_BUTTON,function(a,b){this.getForm().submit();b.originalEvent.preventDefault();a.stopPropagation()}.bind(this));this.getModal().on("submit",function(a){b.notifyFormSubmittedByJavascript(this.getForm()[0]);this.save();a.preventDefault();a.stopPropagation()}.bind(this))};if(!l){h.register(n.TYPE,n,"calendar/modal_event_form");l=!0}return n});
//# sourceMappingURL=modal_event_form.min.js.map
File diff suppressed because one or more lines are too long
+29 -28
View File
@@ -23,32 +23,31 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define([
'jquery',
'core/event',
'core/str',
'core/notification',
'core/templates',
'core/custom_interaction_events',
'core/modal',
'core/modal_registry',
'core/fragment',
'core_calendar/events',
'core_calendar/repository'
],
function(
$,
Event,
Str,
Notification,
Templates,
CustomEvents,
Modal,
ModalRegistry,
Fragment,
CalendarEvents,
Repository
) {
'jquery',
'core_form/events',
'core/str',
'core/notification',
'core/templates',
'core/custom_interaction_events',
'core/modal',
'core/modal_registry',
'core/fragment',
'core_calendar/events',
'core_calendar/repository'
],
function(
$,
FormEvents,
Str,
Notification,
Templates,
CustomEvents,
Modal,
ModalRegistry,
Fragment,
CalendarEvents,
Repository
) {
var registered = false;
var SELECTORS = {
SAVE_BUTTON: '[data-action="save"]',
@@ -416,7 +415,7 @@ define([
// If we found invalid fields, focus on the first one and do not submit via ajax.
if (invalid.length) {
invalid.first().focus();
return;
return Promise.resolve();
}
loadingContainer.removeClass('hidden');
@@ -465,6 +464,8 @@ define([
* Set up all of the event handling for the modal.
*
* @method registerEventListeners
* @fires event:uploadStarted
* @fires event:formSubmittedByJavascript
*/
ModalEventForm.prototype.registerEventListeners = function() {
// Apply parent event listeners.
@@ -482,7 +483,7 @@ define([
// Catch the submit event before it is actually processed by the browser and
// prevent the submission. We'll take it from here.
this.getModal().on('submit', function(e) {
Event.notifyFormSubmitAjax(this.getForm()[0]);
FormEvents.notifyFormSubmittedByJavascript(this.getForm()[0]);
this.save();
+6 -6
View File
@@ -765,7 +765,7 @@ M.course_dndupload = {
this.originalUnloadEvent = window.onbeforeunload;
// Trigger form upload start events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadStarted(section.get('id'));
FormEvent.notifyUploadStarted(section.get('id'));
});
}
if (xhr.readyState == 4) {
@@ -796,7 +796,7 @@ M.course_dndupload = {
}
// Trigger form upload complete events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadCompleted(section.get('id'));
FormEvent.notifyUploadCompleted(section.get('id'));
});
}
};
@@ -1031,7 +1031,7 @@ M.course_dndupload = {
this.originalUnloadEvent = window.onbeforeunload;
// Trigger form upload start events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadStarted(section.get('id'));
FormEvent.notifyUploadStarted(section.get('id'));
});
}
if (xhr.readyState == 4) {
@@ -1052,7 +1052,7 @@ M.course_dndupload = {
resel.parent.removeChild(resel.li);
// Trigger form upload complete events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadCompleted(section.get('id'));
FormEvent.notifyUploadCompleted(section.get('id'));
});
new M.core.alert({message: result.error});
}
@@ -1060,13 +1060,13 @@ M.course_dndupload = {
} else {
// Trigger form upload complete events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadCompleted(section.get('id'));
FormEvent.notifyUploadCompleted(section.get('id'));
});
new M.core.alert({message: M.util.get_string('servererror', 'moodle')});
}
// Trigger form upload complete events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadCompleted(section.get('id'));
FormEvent.notifyUploadCompleted(section.get('id'));
});
}
};
+2
View File
@@ -0,0 +1,2 @@
define ("core_filters/events",["exports","core/event_dispatcher","core/normalise","jquery"],function(a,b,c,d){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.notifyFilterContentUpdated=a.eventTypes=void 0;d=function(a){return a&&a.__esModule?a:{default:a}}(d);var e={filterContentUpdated:"core_filters/contentUpdated"};a.eventTypes=e;a.notifyFilterContentUpdated=function notifyFilterContentUpdated(a){a=(0,c.getList)(a);return(0,b.dispatchEvent)(e.filterContentUpdated,{nodes:a})};var f=!1;if(!f){Y.use("event","moodle-core-event",function(){document.addEventListener(e.filterContentUpdated,function(a){(0,d.default)(document).trigger(M.core.event.FILTER_CONTENT_UPDATED,[(0,d.default)(a.detail.nodes)]);Y.fire(M.core.event.FILTER_CONTENT_UPDATED,{nodes:new Y.NodeList(a.detail.nodes)})})});f=!0}});
//# sourceMappingURL=events.min.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../src/events.js"],"names":["eventTypes","filterContentUpdated","notifyFilterContentUpdated","nodes","legacyEventsRegistered","Y","use","document","addEventListener","e","trigger","M","core","event","FILTER_CONTENT_UPDATED","detail","fire","NodeList"],"mappings":"6NAyBA,uDAQO,GAAMA,CAAAA,CAAU,CAAG,CAWtBC,oBAAoB,CAAE,6BAXA,CAAnB,C,4CAsBmC,QAA7BC,CAAAA,0BAA6B,CAAAC,CAAK,CAAI,CAG/CA,CAAK,CAAG,cAAkBA,CAAlB,CAAR,CAEA,MAAO,oBAAcH,CAAU,CAACC,oBAAzB,CAA+C,CAACE,KAAK,CAALA,CAAD,CAA/C,CACV,C,CAED,GAAIC,CAAAA,CAAsB,GAA1B,CACA,GAAI,CAACA,CAAL,CAA6B,CAKzBC,CAAC,CAACC,GAAF,CAAM,OAAN,CAAe,mBAAf,CAAoC,UAAM,CAEtCC,QAAQ,CAACC,gBAAT,CAA0BR,CAAU,CAACC,oBAArC,CAA2D,SAAAQ,CAAC,CAAI,CAE5D,cAAOF,QAAP,EAAiBG,OAAjB,CAAyBC,CAAC,CAACC,IAAF,CAAOC,KAAP,CAAaC,sBAAtC,CAA8D,CAAC,cAAOL,CAAC,CAACM,MAAF,CAASZ,KAAhB,CAAD,CAA9D,EAGAE,CAAC,CAACW,IAAF,CAAOL,CAAC,CAACC,IAAF,CAAOC,KAAP,CAAaC,sBAApB,CAA4C,CAACX,KAAK,CAAE,GAAIE,CAAAA,CAAC,CAACY,QAAN,CAAeR,CAAC,CAACM,MAAF,CAASZ,KAAxB,CAAR,CAA5C,CACH,CAND,CAOH,CATD,EAWAC,CAAsB,GACzB,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/ //\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Javascript events for the `core_filter` subsystem.\n *\n * @module core_filters/events\n * @copyright 2021 Andrew Nicols <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n */\n\nimport {dispatchEvent} from 'core/event_dispatcher';\nimport {getList as normalistNodeList} from 'core/normalise';\nimport jQuery from 'jquery';\n\n/**\n * Events for the `core_filter` subsystem.\n *\n * @constant\n * @property {String} filterContentUpdated See {@link event:filterContentUpdated}\n */\nexport const eventTypes = {\n /**\n * An event triggered when page content is updated and must be processed by the filter system.\n *\n * An example of this is loading user text that could have equations in it. MathJax can typeset the equations but\n * only if it is notified that there are new nodes in the page that need processing.\n *\n * @event filterContentUpdated\n * @type {CustomEvent}\n * @property {Array} nodes The list of parent nodes which were updated\n */\n filterContentUpdated: 'core_filters/contentUpdated',\n};\n\n/**\n * Trigger an event to indicate that the specified nodes were updated and should be processed by the filter system.\n *\n * @method notifyFilterContentUpdated\n * @param {jQuery|Array} nodes\n * @returns {CustomEvent}\n * @fires filterContentUpdated\n */\nexport const notifyFilterContentUpdated = nodes => {\n // Historically this could be a jQuery Object.\n // Normalise the list of nodes to a NodeList.\n nodes = normalistNodeList(nodes);\n\n return dispatchEvent(eventTypes.filterContentUpdated, {nodes});\n};\n\nlet legacyEventsRegistered = false;\nif (!legacyEventsRegistered) {\n // The following event triggers are legacy and will be removed in the future.\n // The following approach provides a backwards-compatability layer for the new events.\n // Code should be updated to make use of native events.\n\n Y.use('event', 'moodle-core-event', () => {\n // Provide a backwards-compatability layer for YUI Events.\n document.addEventListener(eventTypes.filterContentUpdated, e => {\n // Trigger the legacy jQuery event.\n jQuery(document).trigger(M.core.event.FILTER_CONTENT_UPDATED, [jQuery(e.detail.nodes)]);\n\n // Trigger the legacy YUI event.\n Y.fire(M.core.event.FILTER_CONTENT_UPDATED, {nodes: new Y.NodeList(e.detail.nodes)});\n });\n });\n\n legacyEventsRegistered = true;\n}\n"],"file":"events.min.js"}
+82
View File
@@ -0,0 +1,82 @@
// This file is part of Moodle - http://moodle.org/ //
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Javascript events for the `core_filter` subsystem.
*
* @module core_filters/events
* @copyright 2021 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 4.0
*/
import {dispatchEvent} from 'core/event_dispatcher';
import {getList as normalistNodeList} from 'core/normalise';
import jQuery from 'jquery';
/**
* Events for the `core_filter` subsystem.
*
* @constant
* @property {String} filterContentUpdated See {@link event:filterContentUpdated}
*/
export const eventTypes = {
/**
* An event triggered when page content is updated and must be processed by the filter system.
*
* An example of this is loading user text that could have equations in it. MathJax can typeset the equations but
* only if it is notified that there are new nodes in the page that need processing.
*
* @event filterContentUpdated
* @type {CustomEvent}
* @property {Array} nodes The list of parent nodes which were updated
*/
filterContentUpdated: 'core_filters/contentUpdated',
};
/**
* Trigger an event to indicate that the specified nodes were updated and should be processed by the filter system.
*
* @method notifyFilterContentUpdated
* @param {jQuery|Array} nodes
* @returns {CustomEvent}
* @fires filterContentUpdated
*/
export const notifyFilterContentUpdated = nodes => {
// Historically this could be a jQuery Object.
// Normalise the list of nodes to a NodeList.
nodes = normalistNodeList(nodes);
return dispatchEvent(eventTypes.filterContentUpdated, {nodes});
};
let legacyEventsRegistered = false;
if (!legacyEventsRegistered) {
// The following event triggers are legacy and will be removed in the future.
// The following approach provides a backwards-compatability layer for the new events.
// Code should be updated to make use of native events.
Y.use('event', 'moodle-core-event', () => {
// Provide a backwards-compatability layer for YUI Events.
document.addEventListener(eventTypes.filterContentUpdated, e => {
// Trigger the legacy jQuery event.
jQuery(document).trigger(M.core.event.FILTER_CONTENT_UPDATED, [jQuery(e.detail.nodes)]);
// Trigger the legacy YUI event.
Y.fire(M.core.event.FILTER_CONTENT_UPDATED, {nodes: new Y.NodeList(e.detail.nodes)});
});
});
legacyEventsRegistered = true;
}
+1 -1
View File
@@ -1,2 +1,2 @@
define ("core/event",["jquery","core/yui"],function(a,b){return{Events:{FORM_FIELD_VALIDATION:"core_form-field-validation"},getLegacyEvents:function getLegacyEvents(){var c=a.Deferred();b.use("event","moodle-core-event",function(){c.resolve(window.M.core.event)});return c.promise()},notifyFilterContentUpdated:function notifyFilterContentUpdated(c){c=a(c);b.use("event","moodle-core-event",function(b){a(document).trigger(M.core.event.FILTER_CONTENT_UPDATED,[c]);var d=new b.NodeList(c.get());b.fire(M.core.event.FILTER_CONTENT_UPDATED,{nodes:d})})},notifyFormSubmitAjax:function notifyFormSubmitAjax(c,d){d=d||!1;b.use("event","moodle-core-event",function(b){if(d){window.skipClientValidation=!0}a(c).trigger(M.core.event.FORM_SUBMIT_AJAX);b.one(c).fire(M.core.event.FORM_SUBMIT_AJAX,{currentTarget:b.one(c)});if(d){window.skipClientValidation=!1}})},notifyEditorContentRestored:function notifyEditorContentRestored(){b.use("event","moodle-core-event",function(b){a(document).trigger(M.core.event.EDITOR_CONTENT_RESTORED);b.fire(M.core.event.EDITOR_CONTENT_RESTORED)})}}});
define ("core/event",["exports","core_editor/events","core_filters/events","core_form/events","jquery","core/yui"],function(a,b,c,d,e,f){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;e=g(e);f=g(f);function g(a){return a&&a.__esModule?a:{default:a}}var h=function(){var a=e.default.Deferred();window.console.warn("The getLegacyEvents function has been deprecated. Please update your code to use native events.");f.default.use("event","moodle-core-event",function(){a.resolve(window.M.core.event)});return a.promise()},i=function(a,b,c,d){return function(){window.console.warn("The core/event::".concat(a,"() function has been moved to ").concat(b,"::").concat(c,". ")+"Please update your code to use the new module.");return d.apply(void 0,arguments)}},j={Events:{FORM_FIELD_VALIDATION:"core_form-field-validation"},getLegacyEvents:h,notifyEditorContentRestored:i("notifyEditorContentRestored","core_editor/events","notifyEditorContentRestored",b.notifyEditorContentRestored),notifyFilterContentUpdated:i("notifyFilterContentUpdated","core_filters/events","notifyFilterContentUpdated",c.notifyFilterContentUpdated),notifyFormSubmitAjax:i("notifyFormSubmitAjax","core_form/events","notifyFormSubmittedByJavascript",d.notifyFormSubmittedByJavascript)};a.default=j;return a.default});
//# sourceMappingURL=event.min.js.map
File diff suppressed because one or more lines are too long
+2
View File
@@ -0,0 +1,2 @@
define ("core/event_dispatcher",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.dispatchEvent=void 0;a.dispatchEvent=function dispatchEvent(a){var b=1<arguments.length&&arguments[1]!==void 0?arguments[1]:{},c=2<arguments.length&&arguments[2]!==void 0?arguments[2]:document,d=3<arguments.length&&arguments[3]!==void 0?arguments[3]:{},e=d.bubbles,f=void 0===e?!0:e,g=d.cancelable,h=void 0===g?!1:g,i=d.composed,j=void 0===i?!1:i,k=new CustomEvent(a,{bubbles:f,cancelable:h,composed:j,detail:b});c.dispatchEvent(k);return k}});
//# sourceMappingURL=event_dispatcher.min.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../src/event_dispatcher.js"],"names":["dispatchEvent","eventName","detail","container","document","bubbles","cancelable","composed","customEvent","CustomEvent"],"mappings":"6JAyD6B,QAAhBA,CAAAA,aAAgB,CACzBC,CADyB,CASxB,IAPDC,CAAAA,CAOC,wDAPQ,EAOR,CANDC,CAMC,wDANWC,QAMX,0DADG,EACH,KAJGC,OAIH,CAJGA,CAIH,qBAHGC,UAGH,CAHGA,CAGH,qBAFGC,QAEH,CAFGA,CAEH,iBACKC,CAAW,CAAG,GAAIC,CAAAA,WAAJ,CAChBR,CADgB,CAEhB,CACII,OAAO,CAAPA,CADJ,CAEIC,UAAU,CAAVA,CAFJ,CAGIC,QAAQ,CAARA,CAHJ,CAIIL,MAAM,CAANA,CAJJ,CAFgB,CADnB,CAWDC,CAAS,CAACH,aAAV,CAAwBQ,CAAxB,EAEA,MAAOA,CAAAA,CACV,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/ //\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Event dispatcher used to dispatch Native JS CustomEvent objects.\n *\n * @module core/event_dispatcher\n * @copyright 2021 Andrew Nicols <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n */\n\n/**\n * Dispatch an event as a CustomEvent on the specified container.\n * By default events are bubbled, and cancelable.\n *\n * The eventName should typically by sourced using a constant, for example:\n *\n * // mod/example/amd/src/events.js\n *\n * import {dispatchEvent} from 'core/event_dispatcher';\n *\n * export const eventTypes = {\n * exampleDataDisplayed: 'mod_example/exampleDataDisplayed',\n * };\n *\n * export const notifyExampleDisplayed = someArgument => dispatchEvent(eventTypes.exampleDataDisplayed, {\n * someArgument,\n * }, document, {\n * cancelable: false,\n * });\n *\n * Note: This function uses native events. Any additional details are passed to the function in event.detail.\n *\n * This function mimics the behaviour of EventTarget.dispatchEvent but bubbles by default.\n *\n * @method dispatchEvent\n * @param {String} eventName The name of the event\n * @param {Object} detail Any additional details to pass into the eveent\n * @param {HTMLElement} container The point at which to dispatch the event\n * @param {Object} options\n * @param {Boolean} options.bubbles Whether to bubble up the DOM\n * @param {Boolean} options.cancelable Whether preventDefault() can be called\n * @param {Boolean} options.composed Whether the event can bubble across the ShadowDOM bounadry\n * @returns {CustomEvent}\n */\nexport const dispatchEvent = (\n eventName,\n detail = {},\n container = document,\n {\n bubbles = true,\n cancelable = false,\n composed = false,\n } = {}\n) => {\n const customEvent = new CustomEvent(\n eventName,\n {\n bubbles,\n cancelable,\n composed,\n detail,\n }\n );\n\n container.dispatchEvent(customEvent);\n\n return customEvent;\n};\n"],"file":"event_dispatcher.min.js"}
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+64 -82
View File
@@ -17,100 +17,82 @@
* Global registry of core events that can be triggered/listened for.
*
* @module core/event
* @package core
* @class event
* @copyright 2015 Damyon Wiese <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.0
*/
define(['jquery', 'core/yui'],
function($, Y) {
return /** @alias module:core/event */ {
import {notifyEditorContentRestored} from 'core_editor/events';
import {notifyFilterContentUpdated} from 'core_filters/events';
import {notifyFormSubmittedByJavascript} from 'core_form/events';
// These are only imported for legacy.
import $ from 'jquery';
import Y from 'core/yui';
// Public variables and functions.
// These are AMD only events - no backwards compatibility for new things.
Events: {
FORM_FIELD_VALIDATION: "core_form-field-validation"
},
// These are AMD only events - no backwards compatibility for new things.
// Note: No new events should be created here.
const Events = {
FORM_FIELD_VALIDATION: "core_form-field-validation"
};
/**
* Load the legacy YUI module which defines events in M.core.event and return it.
*
* @method getLegacyEvents
* @return {Promise}
*/
getLegacyEvents: function() {
var result = $.Deferred();
Y.use('event', 'moodle-core-event', function() {
result.resolve(window.M.core.event);
});
return result.promise();
},
/**
* Load the legacy YUI module which defines events in M.core.event and return it.
*
* @method getLegacyEvents
* @return {Promise}
* @deprecated
*/
const getLegacyEvents = () => {
const result = $.Deferred();
window.console.warn("The getLegacyEvents function has been deprecated. Please update your code to use native events.");
/**
* Trigger an event using both JQuery and YUI
*
* @method notifyFilterContentUpdated
* @param {string|JQuery} nodes - Selector or list of elements that were inserted.
*/
notifyFilterContentUpdated: function(nodes) {
nodes = $(nodes);
Y.use('event', 'moodle-core-event', function(Y) {
// Trigger it the JQuery way.
$(document).trigger(M.core.event.FILTER_CONTENT_UPDATED, [nodes]);
Y.use('event', 'moodle-core-event', function() {
result.resolve(window.M.core.event);
});
return result.promise();
};
// Create a YUI NodeList from our JQuery Object.
var yuiNodes = new Y.NodeList(nodes.get());
/**
* Get a curried function to warn that a function has been moved and renamed
*
* @param {String} oldFunctionName
* @param {String} newModule
* @param {String} newFunctionName
* @param {Function} newFunctionRef
* @returns {Function}
*/
const getRenamedLegacyFunction = (oldFunctionName, newModule, newFunctionName, newFunctionRef) => (...args) => {
window.console.warn(
`The core/event::${oldFunctionName}() function has been moved to ${newModule}::${newFunctionName}. ` +
`Please update your code to use the new module.`
);
// And again for YUI.
Y.fire(M.core.event.FILTER_CONTENT_UPDATED, {nodes: yuiNodes});
});
},
return newFunctionRef(...args);
};
/**
* Trigger an event using both JQuery and YUI
*
* @method notifyFormSubmittedAjax
* @param {DOMElement} form
* @param {boolean} skipValidation Submit the form without validation. E.g. "Cancel".
*/
notifyFormSubmitAjax: function(form, skipValidation) {
export default {
Events,
getLegacyEvents,
// Argument is optional.
skipValidation = skipValidation || false;
notifyEditorContentRestored: getRenamedLegacyFunction(
'notifyEditorContentRestored',
'core_editor/events',
'notifyEditorContentRestored',
notifyEditorContentRestored
),
Y.use('event', 'moodle-core-event', function(Y) {
if (skipValidation) {
window.skipClientValidation = true;
}
// Trigger it the JQuery way.
$(form).trigger(M.core.event.FORM_SUBMIT_AJAX);
notifyFilterContentUpdated: getRenamedLegacyFunction(
'notifyFilterContentUpdated',
'core_filters/events',
'notifyFilterContentUpdated',
notifyFilterContentUpdated
),
// And again for YUI.
Y.one(form).fire(M.core.event.FORM_SUBMIT_AJAX, {currentTarget: Y.one(form)});
if (skipValidation) {
window.skipClientValidation = false;
}
});
},
/**
* Trigger an event using both JQuery and YUI
* This event alerts the world that the editor has restored some content.
*
* @method notifyEditorContentRestored
*/
notifyEditorContentRestored: function() {
Y.use('event', 'moodle-core-event', function(Y) {
// Trigger it the JQuery way.
$(document).trigger(M.core.event.EDITOR_CONTENT_RESTORED);
// And again for YUI.
Y.fire(M.core.event.EDITOR_CONTENT_RESTORED);
});
},
};
});
notifyFormSubmitAjax: getRenamedLegacyFunction(
'notifyFormSubmitAjax',
'core_form/events',
'notifyFormSubmittedByJavascript',
notifyFormSubmittedByJavascript
),
};
+81
View File
@@ -0,0 +1,81 @@
// This file is part of Moodle - http://moodle.org/ //
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Event dispatcher used to dispatch Native JS CustomEvent objects.
*
* @module core/event_dispatcher
* @copyright 2021 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 4.0
*/
/**
* Dispatch an event as a CustomEvent on the specified container.
* By default events are bubbled, and cancelable.
*
* The eventName should typically by sourced using a constant, for example:
*
* // mod/example/amd/src/events.js
*
* import {dispatchEvent} from 'core/event_dispatcher';
*
* export const eventTypes = {
* exampleDataDisplayed: 'mod_example/exampleDataDisplayed',
* };
*
* export const notifyExampleDisplayed = someArgument => dispatchEvent(eventTypes.exampleDataDisplayed, {
* someArgument,
* }, document, {
* cancelable: false,
* });
*
* Note: This function uses native events. Any additional details are passed to the function in event.detail.
*
* This function mimics the behaviour of EventTarget.dispatchEvent but bubbles by default.
*
* @method dispatchEvent
* @param {String} eventName The name of the event
* @param {Object} detail Any additional details to pass into the eveent
* @param {HTMLElement} container The point at which to dispatch the event
* @param {Object} options
* @param {Boolean} options.bubbles Whether to bubble up the DOM
* @param {Boolean} options.cancelable Whether preventDefault() can be called
* @param {Boolean} options.composed Whether the event can bubble across the ShadowDOM bounadry
* @returns {CustomEvent}
*/
export const dispatchEvent = (
eventName,
detail = {},
container = document,
{
bubbles = true,
cancelable = false,
composed = false,
} = {}
) => {
const customEvent = new CustomEvent(
eventName,
{
bubbles,
cancelable,
composed,
detail,
}
);
container.dispatchEvent(customEvent);
return customEvent;
};
+5 -4
View File
@@ -29,7 +29,7 @@ define([
'core/key_codes',
'core/custom_interaction_events',
'core/modal_backdrop',
'core/event',
'core_filters/events',
'core/modal_events',
'core/local/aria/focuslock',
'core/pending',
@@ -42,7 +42,7 @@ define([
KeyCodes,
CustomEvents,
ModalBackdrop,
Event,
FilterEvents,
ModalEvents,
FocusLock,
Pending,
@@ -322,6 +322,7 @@ define([
*
* @method setBody
* @param {(string|object)} value The body string or jQuery promise which resolves to the body.
* @fires event:filterContentUpdated
*/
Modal.prototype.setBody = function(value) {
this.bodyPromise = $.Deferred();
@@ -331,7 +332,7 @@ define([
if (typeof value === 'string') {
// Just set the value if it's a string.
body.html(value);
Event.notifyFilterContentUpdated(body);
FilterEvents.notifyFilterContentUpdated(body);
this.getRoot().trigger(ModalEvents.bodyRendered, this);
this.bodyPromise.resolve(body);
} else {
@@ -422,7 +423,7 @@ define([
return result;
}.bind(this))
.then(function(result) {
Event.notifyFilterContentUpdated(body);
FilterEvents.notifyFilterContentUpdated(body);
this.getRoot().trigger(ModalEvents.bodyRendered, this);
return result;
}.bind(this))
+39 -21
View File
@@ -24,24 +24,39 @@
* @since 2.9
*/
define([
'core/mustache',
'jquery',
'core/ajax',
'core/str',
'core/notification',
'core/url',
'core/config',
'core/localstorage',
'core/icon_system',
'core/event',
'core/yui',
'core/log',
'core/truncate',
'core/user_date',
'core/pending',
],
function(mustache, $, ajax, str, notification, coreurl, config, storage, IconSystem, event, Y, Log, Truncate, UserDate,
Pending) {
'core/mustache',
'jquery',
'core/ajax',
'core/str',
'core/notification',
'core/url',
'core/config',
'core/localstorage',
'core/icon_system',
'core_filters/events',
'core/yui',
'core/log',
'core/truncate',
'core/user_date',
'core/pending',
],
function(
mustache,
$,
ajax,
str,
notification,
coreurl,
config,
storage,
IconSystem,
filterEvents,
Y,
Log,
Truncate,
UserDate,
Pending
) {
// Module variables.
/** @var {Number} uniqInstances Count of times this constructor has been called. */
@@ -909,6 +924,7 @@ define([
* @param {String} newJS - Javascript to run after the insertion.
* @param {Boolean} replaceChildNodes - Replace only the childnodes, alternative is to replace the entire node.
* @return {Array} The list of new DOM Nodes
* @fires event:filterContentUpdated
*/
var domReplace = function(element, newHTML, newJS, replaceChildNodes) {
var replaceNode = $(element);
@@ -936,7 +952,7 @@ define([
// Run any javascript associated with the new HTML.
runTemplateJS(newJS);
// Notify all filters about the new content.
event.notifyFilterContentUpdated(newNodes);
filterEvents.notifyFilterContentUpdated(newNodes);
return newNodes.get();
}
@@ -1081,6 +1097,7 @@ define([
* @param {String} html - HTML to prepend
* @param {String} js - Javascript to run after we prepend the html
* @return {Array} The list of new DOM Nodes
* @fires event:filterContentUpdated
*/
var domPrepend = function(element, html, js) {
var node = $(element);
@@ -1091,7 +1108,7 @@ define([
// Run any javascript associated with the new HTML.
runTemplateJS(js);
// Notify all filters about the new content.
event.notifyFilterContentUpdated(node);
filterEvents.notifyFilterContentUpdated(node);
return newContent.get();
}
@@ -1108,6 +1125,7 @@ define([
* @param {String} html - HTML to append
* @param {String} js - Javascript to run after we append the html
* @return {Array} The list of new DOM Nodes
* @fires event:filterContentUpdated
*/
var domAppend = function(element, html, js) {
var node = $(element);
@@ -1118,7 +1136,7 @@ define([
// Run any javascript associated with the new HTML.
runTemplateJS(js);
// Notify all filters about the new content.
event.notifyFilterContentUpdated(node);
filterEvents.notifyFilterContentUpdated(node);
return newContent.get();
}
+2
View File
@@ -0,0 +1,2 @@
define ("core_editor/events",["exports","core/event_dispatcher","jquery","core/yui"],function(a,b,c,d){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.notifyEditorContentRestored=a.eventTypes=void 0;c=e(c);d=e(d);function e(a){return a&&a.__esModule?a:{default:a}}var f={editorContentRestored:"core_editor/contentRestored"};a.eventTypes=f;a.notifyEditorContentRestored=function notifyEditorContentRestored(a){if(!a){window.console.warn("The HTMLElement representing the editor that was modified should be provided to notifyEditorContentRestored.")}return(0,b.dispatchEvent)(f.editorContentRestored,{},a||document)};var g=!1;if(!g){d.default.use("event","moodle-core-event",function(){document.addEventListener(f.editorContentRestored,function(){(0,c.default)(document).trigger(M.core.event.EDITOR_CONTENT_RESTORED);d.default.fire(M.core.event.EDITOR_CONTENT_RESTORED)})});g=!0}});
//# sourceMappingURL=events.min.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["../src/events.js"],"names":["eventTypes","editorContentRestored","notifyEditorContentRestored","editor","window","console","warn","document","legacyEventsRegistered","Y","use","addEventListener","trigger","M","core","event","EDITOR_CONTENT_RESTORED","fire"],"mappings":"uNAwBA,OACA,O,mDAQO,GAAMA,CAAAA,CAAU,CAAG,CAMtBC,qBAAqB,CAAE,6BAND,CAAnB,C,6CAiBoC,QAA9BC,CAAAA,2BAA8B,CAAAC,CAAM,CAAI,CACjD,GAAI,CAACA,CAAL,CAAa,CACTC,MAAM,CAACC,OAAP,CAAeC,IAAf,gHAGH,CACD,MAAO,oBACHN,CAAU,CAACC,qBADR,CAEH,EAFG,CAGHE,CAAM,EAAII,QAHP,CAKV,C,CAED,GAAIC,CAAAA,CAAsB,GAA1B,CACA,GAAI,CAACA,CAAL,CAA6B,CAKzBC,UAAEC,GAAF,CAAM,OAAN,CAAe,mBAAf,CAAoC,UAAM,CAEtCH,QAAQ,CAACI,gBAAT,CAA0BX,CAAU,CAACC,qBAArC,CAA4D,UAAM,CAE9D,cAAOM,QAAP,EAAiBK,OAAjB,CAAyBC,CAAC,CAACC,IAAF,CAAOC,KAAP,CAAaC,uBAAtC,EAGAP,UAAEQ,IAAF,CAAOJ,CAAC,CAACC,IAAF,CAAOC,KAAP,CAAaC,uBAApB,CACH,CAND,CAOH,CATD,EAWAR,CAAsB,GACzB,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/ //\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Javascript events for the `core_editor` subsystem.\n *\n * @module core_editor/events\n * @copyright 2021 Andrew Nicols <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n */\n\nimport {dispatchEvent} from 'core/event_dispatcher';\nimport jQuery from 'jquery';\nimport Y from 'core/yui';\n\n/**\n * Events for the `core_editor` subsystem.\n *\n * @constant\n * @property {String} editorContentRestored See {@link event:editorContentRestored}\n */\nexport const eventTypes = {\n /**\n * An event triggered when an editor restores auto-saved content.\n *\n * @event editorContentRestored\n */\n editorContentRestored: 'core_editor/contentRestored',\n};\n\n/**\n * Trigger an event to indicate that editor content was restored.\n *\n * @method notifyEditorContentRestored\n * @param {HTMLElement|null} editor The element that was modified\n * @returns {CustomEvent}\n * @fires editorContentRestored\n */\nexport const notifyEditorContentRestored = editor => {\n if (!editor) {\n window.console.warn(\n `The HTMLElement representing the editor that was modified should be provided to notifyEditorContentRestored.`\n );\n }\n return dispatchEvent(\n eventTypes.editorContentRestored,\n {},\n editor || document\n );\n};\n\nlet legacyEventsRegistered = false;\nif (!legacyEventsRegistered) {\n // The following event triggers are legacy and will be removed in the future.\n // The following approach provides a backwards-compatability layer for the new events.\n // Code should be updated to make use of native events.\n\n Y.use('event', 'moodle-core-event', () => {\n // Provide a backwards-compatability layer for YUI Events.\n document.addEventListener(eventTypes.editorContentRestored, () => {\n // Trigger a legacy AMD event.\n jQuery(document).trigger(M.core.event.EDITOR_CONTENT_RESTORED);\n\n // Trigger a legacy YUI event.\n Y.fire(M.core.event.EDITOR_CONTENT_RESTORED);\n });\n });\n\n legacyEventsRegistered = true;\n}\n"],"file":"events.min.js"}
+82
View File
@@ -0,0 +1,82 @@
// This file is part of Moodle - http://moodle.org/ //
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Javascript events for the `core_editor` subsystem.
*
* @module core_editor/events
* @copyright 2021 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 4.0
*/
import {dispatchEvent} from 'core/event_dispatcher';
import jQuery from 'jquery';
import Y from 'core/yui';
/**
* Events for the `core_editor` subsystem.
*
* @constant
* @property {String} editorContentRestored See {@link event:editorContentRestored}
*/
export const eventTypes = {
/**
* An event triggered when an editor restores auto-saved content.
*
* @event editorContentRestored
*/
editorContentRestored: 'core_editor/contentRestored',
};
/**
* Trigger an event to indicate that editor content was restored.
*
* @method notifyEditorContentRestored
* @param {HTMLElement|null} editor The element that was modified
* @returns {CustomEvent}
* @fires editorContentRestored
*/
export const notifyEditorContentRestored = editor => {
if (!editor) {
window.console.warn(
`The HTMLElement representing the editor that was modified should be provided to notifyEditorContentRestored.`
);
}
return dispatchEvent(
eventTypes.editorContentRestored,
{},
editor || document
);
};
let legacyEventsRegistered = false;
if (!legacyEventsRegistered) {
// The following event triggers are legacy and will be removed in the future.
// The following approach provides a backwards-compatability layer for the new events.
// Code should be updated to make use of native events.
Y.use('event', 'moodle-core-event', () => {
// Provide a backwards-compatability layer for YUI Events.
document.addEventListener(eventTypes.editorContentRestored, () => {
// Trigger a legacy AMD event.
jQuery(document).trigger(M.core.event.EDITOR_CONTENT_RESTORED);
// Trigger a legacy YUI event.
Y.fire(M.core.event.EDITOR_CONTENT_RESTORED);
});
});
legacyEventsRegistered = true;
}
@@ -360,7 +360,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
// Trigger form upload start events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadStarted(self.editor.get('id'));
FormEvent.notifyUploadStarted(self.editor.get('id'));
});
var options = host.get('filepickeroptions').image,
@@ -419,7 +419,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
}
// Trigger form upload complete events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadCompleted(self.editor.get('id'));
FormEvent.notifyUploadCompleted(self.editor.get('id'));
});
throw new M.core.ajaxException(result);
}
@@ -450,7 +450,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
Y.use('moodle-core-notification-alert', function() {
// Trigger form upload complete events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadCompleted(self.editor.get('id'));
FormEvent.notifyUploadCompleted(self.editor.get('id'));
});
new M.core.alert({message: M.util.get_string('servererror', 'moodle')});
});
@@ -460,7 +460,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
}
// Trigger form upload complete events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadCompleted(self.editor.get('id'));
FormEvent.notifyUploadCompleted(self.editor.get('id'));
});
}
};
File diff suppressed because one or more lines are too long
@@ -360,7 +360,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
// Trigger form upload start events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadStarted(self.editor.get('id'));
FormEvent.notifyUploadStarted(self.editor.get('id'));
});
var options = host.get('filepickeroptions').image,
@@ -419,7 +419,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
}
// Trigger form upload complete events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadCompleted(self.editor.get('id'));
FormEvent.notifyUploadCompleted(self.editor.get('id'));
});
throw new M.core.ajaxException(result);
}
@@ -450,7 +450,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
Y.use('moodle-core-notification-alert', function() {
// Trigger form upload complete events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadCompleted(self.editor.get('id'));
FormEvent.notifyUploadCompleted(self.editor.get('id'));
});
new M.core.alert({message: M.util.get_string('servererror', 'moodle')});
});
@@ -460,7 +460,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
}
// Trigger form upload complete events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadCompleted(self.editor.get('id'));
FormEvent.notifyUploadCompleted(self.editor.get('id'));
});
}
};
+4 -4
View File
@@ -358,7 +358,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
// Trigger form upload start events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadStarted(self.editor.get('id'));
FormEvent.notifyUploadStarted(self.editor.get('id'));
});
var options = host.get('filepickeroptions').image,
@@ -417,7 +417,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
}
// Trigger form upload complete events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadCompleted(self.editor.get('id'));
FormEvent.notifyUploadCompleted(self.editor.get('id'));
});
throw new M.core.ajaxException(result);
}
@@ -448,7 +448,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
Y.use('moodle-core-notification-alert', function() {
// Trigger form upload complete events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadCompleted(self.editor.get('id'));
FormEvent.notifyUploadCompleted(self.editor.get('id'));
});
new M.core.alert({message: M.util.get_string('servererror', 'moodle')});
});
@@ -458,7 +458,7 @@ Y.namespace('M.atto_image').Button = Y.Base.create('button', Y.M.editor_atto.Edi
}
// Trigger form upload complete events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadCompleted(self.editor.get('id'));
FormEvent.notifyUploadCompleted(self.editor.get('id'));
});
}
};
@@ -979,9 +979,9 @@ EditorAutosave.prototype = {
NOTIFY_INFO, RECOVER_MESSAGE_TIMEOUT);
// Fire an event that the editor content has changed.
require(['core/event'], function(event) {
event.notifyEditorContentRestored();
});
require(['core_editor/events'], function(editorEvents) {
editorEvents.notifyEditorContentRestored(this.editor.getDOMNode());
}.bind(this));
return this;
},
File diff suppressed because one or more lines are too long
@@ -971,9 +971,9 @@ EditorAutosave.prototype = {
NOTIFY_INFO, RECOVER_MESSAGE_TIMEOUT);
// Fire an event that the editor content has changed.
require(['core/event'], function(event) {
event.notifyEditorContentRestored();
});
require(['core_editor/events'], function(editorEvents) {
editorEvents.notifyEditorContentRestored(this.editor.getDOMNode());
}.bind(this));
return this;
},
+3 -3
View File
@@ -216,9 +216,9 @@ EditorAutosave.prototype = {
NOTIFY_INFO, RECOVER_MESSAGE_TIMEOUT);
// Fire an event that the editor content has changed.
require(['core/event'], function(event) {
event.notifyEditorContentRestored();
});
require(['core_editor/events'], function(editorEvents) {
editorEvents.notifyEditorContentRestored(this.editor.getDOMNode());
}.bind(this));
return this;
},
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,2 +1,2 @@
define ("core_form/events",["exports","core/str"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.triggerUploadCompleted=a.triggerUploadStarted=a.types=void 0;var c;(0,b.get_string)("changesmadereallygoaway","moodle").then(function(a){c=a;return a}).catch();var d=function(a){if(a){a.returnValue=c}},e={uploadStarted:"core_form/uploadStarted",uploadCompleted:"core_form/uploadCompleted"};a.types=e;a.triggerUploadStarted=function triggerUploadStarted(a){window.addEventListener("beforeunload",d);var b=new CustomEvent(e.uploadStarted,{bubbles:!0,cancellable:!1}),c=document.getElementById(a);c.dispatchEvent(b);return b};a.triggerUploadCompleted=function triggerUploadCompleted(a){window.removeEventListener("beforeunload",d);var b=new CustomEvent(e.uploadCompleted,{bubbles:!0,cancellable:!1}),c=document.getElementById(a);c.dispatchEvent(b);return b}});
define ("core_form/events",["exports","core/str","core/event_dispatcher","jquery","core/yui"],function(a,b,c,d,f){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.types=a.triggerUploadCompleted=a.triggerUploadStarted=a.notifyUploadCompleted=a.notifyUploadStarted=a.notifyFieldValidationFailure=a.notifyFormSubmittedByJavascript=a.notifyFormError=a.eventTypes=void 0;d=g(d);f=g(f);function g(a){return a&&a.__esModule?a:{default:a}}var h;(0,b.get_string)("changesmadereallygoaway","moodle").then(function(a){h=a;return a}).catch();var i=function(a){if(a){a.returnValue=h}},j={formError:"core_form/error",formSubmittedByJavascript:"core_form/submittedByJavascript",formFieldValidationFailed:"core_form/fieldValidationFailed",uploadStarted:"core_form/uploadStarted",uploadCompleted:"core_form/uploadCompleted"};a.eventTypes=j;a.notifyFormError=function notifyFormError(a){return(0,c.dispatchEvent)(j.formError,{},a)};a.notifyFormSubmittedByJavascript=function notifyFormSubmittedByJavascript(a){var b=1<arguments.length&&arguments[1]!==void 0?arguments[1]:!1,d=2<arguments.length&&arguments[2]!==void 0?arguments[2]:!1;if(b){window.skipClientValidation=!0}var e=(0,c.dispatchEvent)(j.formSubmittedByJavascript,{skipValidation:b,fallbackHandled:d},a);if(b){window.skipClientValidation=!1}return e};a.notifyFieldValidationFailure=function notifyFieldValidationFailure(a,b){return(0,c.dispatchEvent)(j.formFieldValidationFailed,{message:b},a,{cancelable:!0})};var k=function(a){window.addEventListener("beforeunload",i);return(0,c.dispatchEvent)(j.uploadStarted,{},document.getElementById(a),{bubbles:!0,cancellable:!1})};a.notifyUploadStarted=k;var l=function(a){window.removeEventListener("beforeunload",i);return(0,c.dispatchEvent)(j.uploadCompleted,{},document.getElementById(a),{bubbles:!0,cancellable:!1})};a.notifyUploadCompleted=l;a.triggerUploadStarted=k;a.triggerUploadCompleted=l;a.types={uploadStarted:"core_form/uploadStarted",uploadCompleted:"core_form/uploadCompleted"};var m=!1;if(!m){f.default.use("event","moodle-core-event",function(){document.addEventListener(j.formError,function(a){var b=f.default.one(a.target),c=f.default.one(a.target.closest("form"));f.default.Global.fire(M.core.globalEvents.FORM_ERROR,{formid:c.generateID(),elementid:b.generateID()})});document.addEventListener(j.formSubmittedByJavascript,function(a){if(a.detail.fallbackHandled){return}if(a.skipValidation){window.skipClientValidation=!0}var b=f.default.one(a.target);b.fire(M.core.event.FORM_SUBMIT_AJAX,{currentTarget:b,fallbackHandled:!0});if(a.skipValidation){window.skipClientValidation=!1}})});document.addEventListener(j.formFieldValidationFailed,function(a){var b=d.default.Event("core_form-field-validation");(0,d.default)(a.target).trigger(b,a.detail.message)});m=!0}});
//# sourceMappingURL=events.min.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,2 +1,2 @@
define ("core_form/submit",["exports","core_form/events"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;var c=0,d=[],e=function(a){d.push(a);if(!c){c=setInterval(function(){var a=document.cookie.split(f()+"=");if(2==a.length){g();clearInterval(c);c=0;d.forEach(function(a){a.disabled=!1})}},500)}},f=function(){return"moodledownload_"+M.cfg.sesskey},g=function(){document.cookie=encodeURIComponent(f())+"=deleted; expires="+new Date(0).toUTCString()};a.init=function init(a){var c=document.getElementById(a);document.addEventListener(b.types.uploadStarted,function(a){window.console.log(a.target);c.disabled=!0});document.addEventListener(b.types.uploadCompleted,function(a){window.console.log(a.target);c.disabled=!1});if("off"===c.form.dataset.doubleSubmitProtection){return}c.form.addEventListener("submit",function(a){var b=function(){if(a.defaultPrevented||c.disabled){return}c.disabled=!0;g();e(c)};window.addEventListener("beforeunload",b);setTimeout(function(){window.removeEventListener("beforeunload",b)},0)},!1)}});
define ("core_form/submit",["exports","core_form/events"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;var c=0,d=[],e=function(a){d.push(a);if(!c){c=setInterval(function(){var a=document.cookie.split(f()+"=");if(2==a.length){g();clearInterval(c);c=0;d.forEach(function(a){a.disabled=!1})}},500)}},f=function(){return"moodledownload_"+M.cfg.sesskey},g=function(){document.cookie=encodeURIComponent(f())+"=deleted; expires="+new Date(0).toUTCString()};a.init=function init(a){var c=document.getElementById(a);document.addEventListener(b.eventTypes.uploadStarted,function(a){window.console.log(a.target);c.disabled=!0});document.addEventListener(b.eventTypes.uploadCompleted,function(a){window.console.log(a.target);c.disabled=!1});if("off"===c.form.dataset.doubleSubmitProtection){return}c.form.addEventListener("submit",function(a){var b=function(){if(a.defaultPrevented||c.disabled){return}c.disabled=!0;g();e(c)};window.addEventListener("beforeunload",b);setTimeout(function(){window.removeEventListener("beforeunload",b)},0)},!1)}});
//# sourceMappingURL=submit.min.js.map
File diff suppressed because one or more lines are too long
+36 -43
View File
@@ -36,13 +36,13 @@
*/
import Ajax from 'core/ajax';
import Notification from 'core/notification';
import Templates from 'core/templates';
import Event from 'core/event';
import {get_strings as getStrings} from 'core/str';
import Y from 'core/yui';
import * as FormEvents from 'core_form/events';
import Fragment from 'core/fragment';
import Notification from 'core/notification';
import Pending from 'core/pending';
import Templates from 'core/templates';
import Y from 'core/yui';
import {get_strings as getStrings} from 'core/str';
export default class DynamicForm {
@@ -228,53 +228,45 @@ export default class DynamicForm {
*
* @method submitButtonPressed
* @param {Element} button that was pressed
* @fires event:formSubmittedByJavascript
*/
processNoSubmitButton(button) {
const pendingPromise = new Pending('core_form/dynamicform:nosubmit');
const form = this.container.querySelector('form');
const form = this.getFormNode();
const formData = new URLSearchParams([...(new FormData(form)).entries()]);
formData.append(button.getAttribute('name'), button.getAttribute('value'));
this.notifyFormSubmitAjax(true)
.then(() => {
// Add the button name to the form data and submit it.
this.disableButtons();
return this.getBody(formData.toString());
})
.then((resp) => this.updateForm(resp))
.finally(pendingPromise.resolve)
FormEvents.notifyFormSubmittedByJavascript(form, true);
// Add the button name to the form data and submit it.
this.disableButtons();
this.getBody(formData.toString())
.then(this.updateForm)
.then(pendingPromise.resolve)
.catch(this.onSubmitError);
}
/**
* Wrapper for Event.notifyFormSubmitAjax that waits for the module to load
* Get the form node from the Dialogue.
*
* We often destroy the form right after calling this function and we need to make sure that it actually
* completes before it, or otherwise it will try to work with a form that does not exist.
*
* @param {Boolean} skipValidation
* @return {Promise}
* @returns {HTMLFormElement}
*/
notifyFormSubmitAjax(skipValidation = false) {
const form = this.container.querySelector('form');
return new Promise(resolve => {
Y.use('event', 'moodle-core-event', 'moodle-core-formchangechecker', function() {
Event.notifyFormSubmitAjax(form, skipValidation);
resolve();
});
});
getFormNode() {
return this.container.querySelector('form');
}
/**
* Notifies listeners that form dirty state should be reset.
*
* @return {Promise<unknown>}
* @fires event:formSubmittedByJavascript
*/
notifyResetFormChanges() {
const form = this.container.querySelector('form');
FormEvents.notifyFormSubmittedByJavascript(this.getFormNode(), true);
return new Promise(resolve => {
Y.use('event', 'moodle-core-event', 'moodle-core-formchangechecker', () => {
Event.notifyFormSubmitAjax(form, true);
M.core_formchangechecker.reset_form_dirty_state();
resolve();
});
@@ -303,30 +295,31 @@ export default class DynamicForm {
*
* @param {string} html
* @param {string} js
* @returns {Promise}
*/
updateForm({html, js}) {
Templates.replaceNodeContents(this.container, html, js);
return Templates.replaceNodeContents(this.container, html, js);
}
/**
* Validate form elements
* @return {Promise} promise that returns true if client-side validation has passed, false if there are errors
* @return {Boolean} Whether client-side validation has passed, false if there are errors
* @fires event:formSubmittedByJavascript
*/
validateElements() {
// Notify listeners that the form is about to be submitted (this will reset atto autosave).
return this.notifyFormSubmitAjax()
.then(() => {
// Now the change events have run, see if there are any "invalid" form fields.
const invalid = [...this.container.querySelectorAll('[aria-invalid="true"], .error')];
FormEvents.notifyFormSubmittedByJavascript(this.getFormNode());
// If we found invalid fields, focus on the first one and do not submit via ajax.
if (invalid.length) {
invalid[0].focus();
return false;
}
// Now the change events have run, see if there are any "invalid" form fields.
const invalid = [...this.container.querySelectorAll('[aria-invalid="true"], .error')];
return true;
});
// If we found invalid fields, focus on the first one and do not submit via ajax.
if (invalid.length) {
invalid[0].focus();
return false;
}
return true;
}
/**
+250 -33
View File
@@ -14,7 +14,7 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Contain the events the form component can trigger.
* Javascript events for the `core_form` subsystem.
*
* @module core_form/events
* @package core_form
@@ -24,6 +24,7 @@
*/
import {get_string as getString} from 'core/str';
import {dispatchEvent} from 'core/event_dispatcher';
let changesMadeString;
getString('changesmadereallygoaway', 'moodle').then(string => {
@@ -41,48 +42,264 @@ const changesMadeCheck = e => {
}
};
/**
* Events for `core_form`.
*
* @constant
* @property {String} formError See {@link event:formError}
* @property {String} formFieldValidationFailed See {@link event:formFieldValidationFailed}
* @property {String} formSubmittedByJavascript See {@link event:formSubmittedByJavascript}
*/
export const eventTypes = {
/**
* An event triggered when a form contains an error
*
* @event formError
* @type {CustomEvent}
* @property {HTMLElement} target The form field which errored
*/
formError: 'core_form/error',
/**
* An event triggered when an mform is about to be submitted via javascript.
*
* @event formSubmittedByJavascript
* @type {CustomEvent}
* @property {HTMLElement} target The form that was submitted
* @property {Boolean} skipValidation Whether the form was submitted without validation (i.e. via a Cancel button)
* @property {Boolean} fallbackHandled Whether the legacy YUI event has been handled
*/
formSubmittedByJavascript: 'core_form/submittedByJavascript',
/**
* An event triggered upon form field validation failure.
*
* @event formFieldValidationFailed
* @type {CustomEvent}
* @property {HTMLElement} target The field that failed validation
* @property {String} message The message displayed upon failure
*/
formFieldValidationFailed: 'core_form/fieldValidationFailed',
/**
* An event triggered when an upload is started
*
* @event uploadStarted
* @type {CustomEvent}
* @property {HTMLElement} target The location where the upload began
*/
uploadStarted: 'core_form/uploadStarted',
/**
* An event triggered when an upload completes
*
* @event uploadCompleted
* @type {CustomEvent}
* @property {HTMLElement} target The location where the upload completd
*/
uploadCompleted: 'core_form/uploadCompleted',
};
// These are only imported for legacy.
import jQuery from 'jquery';
import Y from 'core/yui';
/**
* Trigger an event to indicate that a form field contained an error.
*
* @method notifyFormError
* @param {HTMLElement} field The form field causing the error
* @returns {CustomEvent}
* @fires formError
*/
export const notifyFormError = field => dispatchEvent(eventTypes.formError, {}, field);
/**
* Trigger an event to indiciate that a form was submitted by Javascript.
*
* @method
* @param {HTMLElement} form The form that was submitted
* @param {Boolean} skipValidation Submit the form without validation. E.g. "Cancel".
* @param {Boolean} fallbackHandled The legacy YUI event has been handled
* @returns {CustomEvent}
* @fires formSubmittedByJavascript
*/
export const notifyFormSubmittedByJavascript = (form, skipValidation = false, fallbackHandled = false) => {
if (skipValidation) {
window.skipClientValidation = true;
}
const customEvent = dispatchEvent(
eventTypes.formSubmittedByJavascript,
{
skipValidation,
fallbackHandled,
},
form
);
if (skipValidation) {
window.skipClientValidation = false;
}
return customEvent;
};
/**
* Trigger an event to indicate that a form field contained an error.
*
* @method notifyFieldValidationFailure
* @param {HTMLElement} field The field which failed validation
* @param {String} message The message displayed
* @returns {CustomEvent}
* @fires formFieldValidationFailed
*/
export const notifyFieldValidationFailure = (field, message) => dispatchEvent(
eventTypes.formFieldValidationFailed,
{
message,
},
field,
{
cancelable: true
}
);
/**
* Trigger an event to indicate that an upload was started.
*
* @method
* @param {String} elementId The element which was uploaded to
* @returns {CustomEvent}
* @fires uploadStarted
*/
export const notifyUploadStarted = elementId => {
// Add an additional check for changes made.
window.addEventListener('beforeunload', changesMadeCheck);
return dispatchEvent(
eventTypes.uploadStarted,
{},
document.getElementById(elementId),
{
bubbles: true,
cancellable: false,
}
);
};
/**
* Trigger an event to indicate that an upload was completed.
*
* @method
* @param {String} elementId The element which was uploaded to
* @returns {CustomEvent}
* @fires uploadCompleted
*/
export const notifyUploadCompleted = elementId => {
// Remove the additional check for changes made.
window.removeEventListener('beforeunload', changesMadeCheck);
return dispatchEvent(
eventTypes.uploadCompleted,
{},
document.getElementById(elementId),
{
bubbles: true,
cancellable: false,
}
);
};
/**
* Trigger upload start event.
*
* @method
* @param {String} elementId
* @returns {CustomEvent}
* @fires uploadStarted
* @deprecated Since Moodle 4.0 See {@link notifyUploadStarted}
*/
export const triggerUploadStarted = notifyUploadStarted;
/**
* Trigger upload complete event.
*
* @method
* @param {String} elementId
* @returns {CustomEvent}
* @fires uploadCompleted
* @deprecated Since Moodle 4.0 See {@link notifyUploadCompleted}
*/
export const triggerUploadCompleted = notifyUploadCompleted;
/**
* List of the events.
*
* @deprecated since Moodle 4.0. See {@link eventTypes} instead.
**/
export const types = {
uploadStarted: 'core_form/uploadStarted',
uploadCompleted: 'core_form/uploadCompleted',
};
/**
* Trigger upload start event.
*
* @param {String} elementId
* @returns {CustomEvent<unknown>}
*/
export const triggerUploadStarted = elementId => {
// Add an additional check for changes made.
window.addEventListener('beforeunload', changesMadeCheck);
const customEvent = new CustomEvent(types.uploadStarted, {
bubbles: true,
cancellable: false
let legacyEventsRegistered = false;
if (!legacyEventsRegistered) {
// The following event triggers are legacy and will be removed in the future.
// The following approach provides a backwards-compatability layer for the new events.
// Code should be updated to make use of native events.
Y.use('event', 'moodle-core-event', () => {
// Watch for the new native formError event, and trigger the legacy YUI event.
document.addEventListener(eventTypes.formError, e => {
const element = Y.one(e.target);
const formElement = Y.one(e.target.closest('form'));
Y.Global.fire(
M.core.globalEvents.FORM_ERROR,
{
formid: formElement.generateID(),
elementid: element.generateID(),
}
);
});
// Watch for the new native formSubmittedByJavascript event, and trigger the legacy YUI event.
document.addEventListener(eventTypes.formSubmittedByJavascript, e => {
if (e.detail.fallbackHandled) {
// This event was originally generated by a YUI event.
// Do not generate another as this will recurse.
return;
}
if (e.skipValidation) {
window.skipClientValidation = true;
}
// Trigger the legacy YUI event.
const form = Y.one(e.target);
form.fire(
M.core.event.FORM_SUBMIT_AJAX,
{
currentTarget: form,
fallbackHandled: true,
}
);
if (e.skipValidation) {
window.skipClientValidation = false;
}
});
});
const element = document.getElementById(elementId);
element.dispatchEvent(customEvent);
return customEvent;
};
// Watch for the new native formFieldValidationFailed event, and trigger the legacy jQuery event.
document.addEventListener(eventTypes.formFieldValidationFailed, e => {
// Note: The "core_form-field-validation" event is hard-coded in core/event.
// This is not included to prevent cyclic module dependencies.
const legacyEvent = jQuery.Event("core_form-field-validation");
/**
* Trigger upload complete event.
*
* @param {String} elementId
* @returns {CustomEvent<unknown>}
*/
export const triggerUploadCompleted = elementId => {
// Remove the additional check for changes made.
window.removeEventListener('beforeunload', changesMadeCheck);
const customEvent = new CustomEvent(types.uploadCompleted, {
bubbles: true,
cancellable: false
jQuery(e.target).trigger(legacyEvent, e.detail.message);
});
const element = document.getElementById(elementId);
element.dispatchEvent(customEvent);
return customEvent;
};
legacyEventsRegistered = true;
}
+47 -49
View File
@@ -36,14 +36,14 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import ModalFactory from 'core/modal_factory';
import ModalEvents from 'core/modal_events';
import Ajax from 'core/ajax';
import Notification from 'core/notification';
import Y from 'core/yui';
import Event from 'core/event';
import * as FormEvents from 'core_form/events';
import Fragment from 'core/fragment';
import ModalEvents from 'core/modal_events';
import ModalFactory from 'core/modal_factory';
import Notification from 'core/notification';
import Pending from 'core/pending';
import Y from 'core/yui';
export default class ModalForm {
@@ -268,80 +268,78 @@ export default class ModalForm {
* Notifies listeners that form dirty state should be reset.
*
* @return {Promise<unknown>}
* @fires event:formSubmittedByJavascript
*/
notifyResetFormChanges() {
const form = this.getFormNode();
FormEvents.notifyFormSubmittedByJavascript(this.getFormNode(), true);
if (!form) {
return Promise.resolve();
}
return new Promise(resolve => {
Y.use('event', 'moodle-core-event', 'moodle-core-formchangechecker', () => {
// Ensure that modal contains a form element (it may not if the form class threw an early exception).
const form = this.modal.getRoot().find('form')[0];
if (form) {
Event.notifyFormSubmitAjax(form, true);
M.core_formchangechecker.reset_form_dirty_state();
}
M.core_formchangechecker.reset_form_dirty_state();
resolve();
});
});
}
/**
* Wrapper for Event.notifyFormSubmitAjax that waits for the module to load
* Get the form node from the Dialogue.
*
* We often destroy the form right after calling this function and we need to make sure that it actually
* completes before it, or otherwise it will try to work with a form that does not exist.
*
* @param {Boolean} skipValidation
* @return {Promise}
* @returns {HTMLFormElement}
*/
notifyFormSubmitAjax(skipValidation = false) {
return new Promise(resolve => {
Y.use('event', 'moodle-core-event', 'moodle-core-formchangechecker', () => {
Event.notifyFormSubmitAjax(this.modal.getRoot().find('form')[0], skipValidation);
resolve();
});
});
getFormNode() {
return this.modal.getRoot().find('form')[0];
}
/**
* Click on a "submit" button that is marked in the form as registerNoSubmitButton()
*
* @param {Element} button button that was pressed
* @fires event:formSubmittedByJavascript
*/
processNoSubmitButton(button) {
this.notifyFormSubmitAjax(true)
.then(() => {
// Add the button name to the form data and submit it.
let formData = this.modal.getRoot().find('form').serialize();
formData = formData + '&' + encodeURIComponent(button.getAttribute('name')) + '=' +
encodeURIComponent(button.getAttribute('value'));
const form = this.getFormNode();
if (!form) {
return;
}
const bodyContent = this.getBody(formData);
this.modal.setBodyContent(bodyContent);
bodyContent.catch(Notification.exception);
FormEvents.notifyFormSubmittedByJavascript(form, true);
return null;
})
.catch(null);
// Add the button name to the form data and submit it.
let formData = this.modal.getRoot().find('form').serialize();
formData = formData + '&' + encodeURIComponent(button.getAttribute('name')) + '=' +
encodeURIComponent(button.getAttribute('value'));
const bodyContent = this.getBody(formData);
this.modal.setBodyContent(bodyContent);
bodyContent.catch(Notification.exception);
}
/**
* Validate form elements
* @return {Promise} promise that returns true if client-side validation has passed, false if there are errors
* @return {Boolean} Whether client-side validation has passed, false if there are errors
* @fires event:formSubmittedByJavascript
*/
validateElements() {
return this.notifyFormSubmitAjax()
.then(() => {
// Now the change events have run, see if there are any "invalid" form fields.
/** @var {jQuery} list of elements with errors */
const invalid = this.modal.getRoot().find('[aria-invalid="true"], .error');
FormEvents.notifyFormSubmittedByJavascript(this.getFormNode());
// If we found invalid fields, focus on the first one and do not submit via ajax.
if (invalid.length) {
invalid.first().focus();
return false;
}
// Now the change events have run, see if there are any "invalid" form fields.
/** @var {jQuery} list of elements with errors */
const invalid = this.modal.getRoot().find('[aria-invalid="true"], .error');
return true;
});
// If we found invalid fields, focus on the first one and do not submit via ajax.
if (invalid.length) {
invalid.first().focus();
return false;
}
return true;
}
/**
@@ -363,7 +361,7 @@ export default class ModalForm {
*/
async submitFormAjax() {
// If we found invalid fields, focus on the first one and do not submit via ajax.
if (!await this.validateElements()) {
if (!this.validateElements()) {
this.trigger(this.events.CLIENT_VALIDATION_ERROR, null, false);
return;
}
+5 -3
View File
@@ -24,7 +24,7 @@
* @since 3.8
*/
import {types} from 'core_form/events';
import {eventTypes} from 'core_form/events';
/** @type {number} ID for setInterval used when polling for download cookie */
let cookieListener = 0;
@@ -84,18 +84,20 @@ const clearDownloadCookie = () => {
* Initialises submit buttons.
*
* @param {String} elementId Form element
* @listens event:uploadStarted
* @listens event:uploadCompleted
*/
export const init = (elementId) => {
const button = document.getElementById(elementId);
// Add event listener for file upload start.
document.addEventListener(types.uploadStarted, e => {
document.addEventListener(eventTypes.uploadStarted, e => {
window.console.log(e.target); // This will be the element/section where the file is uploaded to.
button.disabled = true;
});
// Add event listener for file upload complete.
document.addEventListener(types.uploadCompleted, e => {
document.addEventListener(eventTypes.uploadCompleted, e => {
window.console.log(e.target); // This will be the element/section where the file is uploaded to.
button.disabled = false;
});
+2 -2
View File
@@ -542,7 +542,7 @@ M.form_dndupload.init = function(Y, options) {
// Trigger form upload start events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadStarted(this.filemanagerhelper.filemanager.get('id'));
FormEvent.notifyUploadStarted(this.filemanagerhelper.filemanager.get('id'));
}.bind(this));
},
@@ -858,7 +858,7 @@ M.form_dndupload.init = function(Y, options) {
uploadfinished: function(lastresult) {
// Trigger form upload complete events.
require(['core_form/events'], function(FormEvent) {
FormEvent.triggerUploadCompleted(this.filemanagerhelper.filemanager.get('id'));
FormEvent.notifyUploadCompleted(this.filemanagerhelper.filemanager.get('id'));
}.bind(this));
this.callback(lastresult);
},
+17 -12
View File
@@ -2463,12 +2463,17 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless {
$js = '
require(["core/event", "jquery"], function(Event, $) {
require([
"core_form/events",
"jquery",
], function(
FormEvents,
$
) {
function qf_errorHandler(element, _qfMsg, escapedName) {
var event = $.Event(Event.Events.FORM_FIELD_VALIDATION);
$(element).trigger(event, _qfMsg);
if (event.isDefaultPrevented()) {
const event = FormEvents.notifyFieldValidationFailure(element, _qfMsg);
if (event.defaultPrevented) {
return _qfMsg == \'\';
} else {
// Legacy mforms.
@@ -2584,11 +2589,11 @@ require(["core/event", "jquery"], function(Event, $) {
ret = validate_' . $this->_formName . '_' . $escapedElementName.'(frm.elements[\''.$elementName.'\'], \''.$escapedElementName.'\') && ret;
if (!ret && !first_focus) {
first_focus = true;
Y.use(\'moodle-core-event\', function() {
Y.Global.fire(M.core.globalEvents.FORM_ERROR, {formid: \'' . $this->_attributes['id'] . '\',
elementid: \'' . $errorid. '\'});
document.getElementById(\'' . $errorid . '\').focus();
});
const element = document.getElementById("' . $errorid . '");
if (element) {
FormEvents.notifyFormError(element);
element.focus();
}
}
';
@@ -2616,12 +2621,12 @@ require(["core/event", "jquery"], function(Event, $) {
return ret;
}
var form = $(document.getElementById(\'' . $this->_attributes['id'] . '\')).closest(\'form\');
form.on(M.core.event.FORM_SUBMIT_AJAX, function() {
var form = document.getElementById(\'' . $this->_attributes['id'] . '\').closest(\'form\');
form.addEventListener(FormEvents.eventTypes.formSubmittedByJavascript, () => {
try {
var myValidator = validate_' . $this->_formName . ';
} catch(e) {
return true;
return;
}
if (myValidator) {
myValidator();
+18 -3
View File
@@ -7847,15 +7847,30 @@ function get_list_of_plugins($directory='mod', $exclude='', $basedir='') {
unset($subtypes);
}
$ignorelist = array_flip(array_filter([
'CVS',
'_vti_cnf',
'amd',
'classes',
'simpletest',
'tests',
'yui',
$exclude,
]));
if (file_exists($basedir) && filetype($basedir) == 'dir') {
if (!$dirhandle = opendir($basedir)) {
debugging("Directory permission error for plugin ({$directory}). Directory exists but cannot be read.", DEBUG_DEVELOPER);
return array();
}
while (false !== ($dir = readdir($dirhandle))) {
// Func: strpos is marginally but reliably faster than substr($dir, 0, 1).
if (strpos($dir, '.') === 0 or $dir === 'CVS' or $dir === '_vti_cnf' or $dir === 'simpletest' or $dir === 'yui' or
$dir === 'tests' or $dir === 'classes' or $dir === $exclude) {
if (strpos($dir, '.') === 0) {
// Ignore directories starting with .
// These are treated as hidden directories.
continue;
}
if (array_key_exists($dir, $ignorelist)) {
// This directory features on the ignore list.
continue;
}
if (filetype($basedir .'/'. $dir) != 'dir') {
+1
View File
@@ -24,6 +24,7 @@
class="{{#hidden}}hidden{{/hidden}} {{class}} {{#hascontrols}}block_with_controls{{/hascontrols}} card mb-3"
role="{{ariarole}}"
data-block="{{type}}"
data-instance-id="{{blockinstanceid}}"
{{#arialabel}}
aria-label={{#quote}}{{{arialabel}}}{{/quote}}
{{/arialabel}}
+94
View File
@@ -5019,4 +5019,98 @@ EOF;
$result = display_size($size);
$this->assertEquals($expected, $result);
}
/**
* Test that the get_list_of_plugins function includes/excludes directories as appropriate.
*
* @dataProvider get_list_of_plugins_provider
* @param array $expectedlist The expected list of folders
* @param array $content The list of file content to set up in the virtual file root
* @param string $dir The base dir to look at in the virtual file root
* @param string $exclude Any additional folder to exclude
*/
public function test_get_list_of_plugins(array $expectedlist, array $content, string $dir, string $exclude): void {
$vfileroot = \org\bovigo\vfs\vfsStream::setup('root', null, $content);
$base = \org\bovigo\vfs\vfsStream::url('root');
$this->assertEquals($expectedlist, get_list_of_plugins($dir, $exclude, $base));
}
/**
* Data provider for get_list_of_plugins checks.
*
* @return array
*/
public function get_list_of_plugins_provider(): array {
return [
'Standard excludes' => [
['amdd', 'class', 'local', 'test'],
[
'.' => [],
'..' => [],
'amd' => [],
'amdd' => [],
'class' => [],
'classes' => [],
'local' => [],
'test' => [],
'tests' => [],
'yui' => [],
],
'',
'',
],
'Standard excludes with addition' => [
['amdd', 'local', 'test'],
[
'.' => [],
'..' => [],
'amd' => [],
'amdd' => [],
'class' => [],
'classes' => [],
'local' => [],
'test' => [],
'tests' => [],
'yui' => [],
],
'',
'class',
],
'Files excluded' => [
['def'],
[
'.' => [],
'..' => [],
'abc' => 'File with filename abc',
'def' => [
'.' => [],
'..' => [],
'example.txt' => 'In a directory called "def"',
],
],
'',
'',
],
'Subdirectories only' => [
['abc'],
[
'.' => [],
'..' => [],
'foo' => [
'.' => [],
'..' => [],
'abc' => [],
],
'bar' => [
'.' => [],
'..' => [],
'def' => [],
],
],
'foo',
'',
],
];
}
}
+14
View File
@@ -6,6 +6,20 @@ information provided here is intended especially for developers.
will be called. The following behaviour will be the new standard for nodes added via callbacks:
- Module nodes added will be appended to the end and will appear within the hamburger option.
- Course nodes added will also be appended and appear within the 'More' option/page.
* The core/event events have been renamed and now fire native events, in addition to the legacy YUI and jQuery events.
The following events have been renamed:
- The BLOCK_CONTENT_UPDATED event has been replaced with a new native event in the `core_block/events` AMD module
eventTypes.blockContentUpdated.
- The EDITOR_CONTENT_RESTORED event has been replaced with a new native event in the `core_editor/events` AMD module
eventTypes.editorContentRestored.
- The FILTER_CONTENT_UPDATED event has been replaced with a new native event in the `core_filters/events` AMD module
eventTypes.filterContentUpdated.
- The FORM_FIELD_VALIDATION event has been replaced with a new native event in the `core_form/events` AMD module
eventTypes.formFieldValidationFailed.
- The FORM_SUBMIT_AJAX event has been replaced with a new native event in the `core_form/events` AMD module
eventTypes.formSubmittedByJavascript.
* The block template now includues a block-instanceid data attribute.
* The core/event::getLegacyEvents() function has been deprecated and should no longer be used.
=== 3.11 ===
* PHPUnit has been upgraded to 9.5 (see MDL-71036 for details).
+67 -25
View File
@@ -30,6 +30,8 @@ var LOGNAME = 'moodle-core-event';
*/
M.core = M.core || {};
var eventsConfigured = !!M.core.event;
M.core.event = M.core.event || {
/**
@@ -82,36 +84,76 @@ M.core.globalEvents = M.core.globalEvents || {
};
var eventDefaultConfig = {
emitFacade: true,
defaultFn: function(e) {
Y.log('Event fired: ' + e.type, 'debug', LOGNAME);
},
preventedFn: function(e) {
Y.log('Event prevented: ' + e.type, 'debug', LOGNAME);
},
stoppedFn: function(e) {
Y.log('Event stopped: ' + e.type, 'debug', LOGNAME);
}
};
if (!eventsConfigured) {
var eventDefaultConfig = {
emitFacade: true,
defaultFn: function(e) {
Y.log('Event fired: ' + e.type, 'debug', LOGNAME);
},
preventedFn: function(e) {
Y.log('Event prevented: ' + e.type, 'debug', LOGNAME);
},
stoppedFn: function(e) {
Y.log('Event stopped: ' + e.type, 'debug', LOGNAME);
}
};
// Publish events with a custom config here.
// Publish events with a custom config here.
// Publish all the events with a standard config.
var key;
for (key in M.core.event) {
if (M.core.event.hasOwnProperty(key) && Y.getEvent(M.core.event[key]) === null) {
Y.publish(M.core.event[key], eventDefaultConfig);
// Publish all the events with a standard config.
var key;
for (key in M.core.event) {
if (M.core.event.hasOwnProperty(key) && Y.getEvent(M.core.event[key]) === null) {
Y.publish(M.core.event[key], eventDefaultConfig);
}
}
}
// Publish global events.
for (key in M.core.globalEvents) {
// Make sure the key exists and that the event has not yet been published. Otherwise, skip publishing.
if (M.core.globalEvents.hasOwnProperty(key) && Y.Global.getEvent(M.core.globalEvents[key]) === null) {
Y.Global.publish(M.core.globalEvents[key], Y.merge(eventDefaultConfig, {broadcast: true}));
Y.log('Global event published: ' + key, 'debug', LOGNAME);
// Publish global events.
for (key in M.core.globalEvents) {
// Make sure the key exists and that the event has not yet been published. Otherwise, skip publishing.
if (M.core.globalEvents.hasOwnProperty(key) && Y.Global.getEvent(M.core.globalEvents[key]) === null) {
Y.Global.publish(M.core.globalEvents[key], Y.merge(eventDefaultConfig, {broadcast: true}));
Y.log('Global event published: ' + key, 'debug', LOGNAME);
}
}
/**
* Apply a callback when the DOM is modified and matchecs the supplied targetSelector.
*
* @method listen
* @param {String} targetSelector The selector to apply
* @param {Function} applyCallback The function to call on the found node
*/
var listenForMutation = function(targetSelector, applyCallback) {
// Add a MutationObserver to check for new children to the tree.
var newNodeObserver = new MutationObserver(function(mutationList) {
mutationList.forEach(function(mutation) {
mutation.addedNodes.forEach(function(node) {
if (node instanceof Element && node.matches(targetSelector)) {
applyCallback(node);
}
});
});
});
newNodeObserver.observe(document, {childList: true, subtree: true});
};
// YUI Custom Events do not bubble up the DOM, only up the inheritance path of custom classes.
// We have to add a Node Observer to watch for new forms that may need to be watched in future.
require(['core_form/events'], function(formEvents) {
listenForMutation('form', function(form) {
Y.one(form).on(M.core.event.FORM_SUBMIT_AJAX, function(e) {
// Prevent cyclical calls.
if (e && e.fallbackHandled) {
return;
}
formEvents.notifyFormSubmittedByJavascript(form, window.skipValidation, true);
});
});
});
}
+1 -1
View File
@@ -1 +1 @@
YUI.add("moodle-core-event",function(e,o){var t,n;for(n in M.core=M.core||{},M.core.event=M.core.event||{FILTER_CONTENT_UPDATED:"filter-content-updated",EDITOR_CONTENT_RESTORED:"editor-content-restored",FORM_SUBMIT_AJAX:"form-submit-ajax"},M.core.globalEvents=M.core.globalEvents||{FORM_ERROR:"form_error",BLOCK_CONTENT_UPDATED:"block_content_updated"},t={emitFacade:!0,defaultFn:function(e){},preventedFn:function(e){},stoppedFn:function(e){}},M.core.event)M.core.event.hasOwnProperty(n)&&null===e.getEvent(M.core.event[n])&&e.publish(M.core.event[n],t);for(n in M.core.globalEvents)M.core.globalEvents.hasOwnProperty(n)&&null===e.Global.getEvent(M.core.globalEvents[n])&&e.Global.publish(M.core.globalEvents[n],e.merge(t,{broadcast:!0}))},"@VERSION@",{requires:["event-custom"]});
YUI.add("moodle-core-event",function(e,o){var n,t,r,c;if(M.core=M.core||{},n=!!M.core.event,M.core.event=M.core.event||{FILTER_CONTENT_UPDATED:"filter-content-updated",EDITOR_CONTENT_RESTORED:"editor-content-restored",FORM_SUBMIT_AJAX:"form-submit-ajax"},M.core.globalEvents=M.core.globalEvents||{FORM_ERROR:"form_error",BLOCK_CONTENT_UPDATED:"block_content_updated"},!n){for(r in t={emitFacade:!0,defaultFn:function(e){},preventedFn:function(e){},stoppedFn:function(e){}},M.core.event)M.core.event.hasOwnProperty(r)&&null===e.getEvent(M.core.event[r])&&e.publish(M.core.event[r],t);for(r in M.core.globalEvents)M.core.globalEvents.hasOwnProperty(r)&&null===e.Global.getEvent(M.core.globalEvents[r])&&e.Global.publish(M.core.globalEvents[r],e.merge(t,{broadcast:!0}));c=function(o,n){new MutationObserver(function(e){e.forEach(function(e){e.addedNodes.forEach(function(e){e instanceof Element&&e.matches(o)&&n(e)})})}).observe(document,{childList:!0,subtree:!0})},require(["core_form/events"],function(n){c("form",function(o){e.one(o).on(M.core.event.FORM_SUBMIT_AJAX,function(e){e&&e.fallbackHandled||n.notifyFormSubmittedByJavascript(o,window.skipValidation,!0)})})})}},"@VERSION@",{requires:["event-custom"]});
+63 -21
View File
@@ -30,6 +30,8 @@ var LOGNAME = 'moodle-core-event';
*/
M.core = M.core || {};
var eventsConfigured = !!M.core.event;
M.core.event = M.core.event || {
/**
@@ -82,32 +84,72 @@ M.core.globalEvents = M.core.globalEvents || {
};
var eventDefaultConfig = {
emitFacade: true,
defaultFn: function(e) {
},
preventedFn: function(e) {
},
stoppedFn: function(e) {
}
};
if (!eventsConfigured) {
var eventDefaultConfig = {
emitFacade: true,
defaultFn: function(e) {
},
preventedFn: function(e) {
},
stoppedFn: function(e) {
}
};
// Publish events with a custom config here.
// Publish events with a custom config here.
// Publish all the events with a standard config.
var key;
for (key in M.core.event) {
if (M.core.event.hasOwnProperty(key) && Y.getEvent(M.core.event[key]) === null) {
Y.publish(M.core.event[key], eventDefaultConfig);
// Publish all the events with a standard config.
var key;
for (key in M.core.event) {
if (M.core.event.hasOwnProperty(key) && Y.getEvent(M.core.event[key]) === null) {
Y.publish(M.core.event[key], eventDefaultConfig);
}
}
}
// Publish global events.
for (key in M.core.globalEvents) {
// Make sure the key exists and that the event has not yet been published. Otherwise, skip publishing.
if (M.core.globalEvents.hasOwnProperty(key) && Y.Global.getEvent(M.core.globalEvents[key]) === null) {
Y.Global.publish(M.core.globalEvents[key], Y.merge(eventDefaultConfig, {broadcast: true}));
// Publish global events.
for (key in M.core.globalEvents) {
// Make sure the key exists and that the event has not yet been published. Otherwise, skip publishing.
if (M.core.globalEvents.hasOwnProperty(key) && Y.Global.getEvent(M.core.globalEvents[key]) === null) {
Y.Global.publish(M.core.globalEvents[key], Y.merge(eventDefaultConfig, {broadcast: true}));
}
}
/**
* Apply a callback when the DOM is modified and matchecs the supplied targetSelector.
*
* @method listen
* @param {String} targetSelector The selector to apply
* @param {Function} applyCallback The function to call on the found node
*/
var listenForMutation = function(targetSelector, applyCallback) {
// Add a MutationObserver to check for new children to the tree.
var newNodeObserver = new MutationObserver(function(mutationList) {
mutationList.forEach(function(mutation) {
mutation.addedNodes.forEach(function(node) {
if (node instanceof Element && node.matches(targetSelector)) {
applyCallback(node);
}
});
});
});
newNodeObserver.observe(document, {childList: true, subtree: true});
};
// YUI Custom Events do not bubble up the DOM, only up the inheritance path of custom classes.
// We have to add a Node Observer to watch for new forms that may need to be watched in future.
require(['core_form/events'], function(formEvents) {
listenForMutation('form', function(form) {
Y.one(form).on(M.core.event.FORM_SUBMIT_AJAX, function(e) {
// Prevent cyclical calls.
if (e && e.fallbackHandled) {
return;
}
formEvents.notifyFormSubmittedByJavascript(form, window.skipValidation, true);
});
});
});
}
+69 -27
View File
@@ -28,6 +28,8 @@ var LOGNAME = 'moodle-core-event';
*/
M.core = M.core || {};
var eventsConfigured = !!M.core.event;
M.core.event = M.core.event || {
/**
@@ -80,34 +82,74 @@ M.core.globalEvents = M.core.globalEvents || {
};
var eventDefaultConfig = {
emitFacade: true,
defaultFn: function(e) {
Y.log('Event fired: ' + e.type, 'debug', LOGNAME);
},
preventedFn: function(e) {
Y.log('Event prevented: ' + e.type, 'debug', LOGNAME);
},
stoppedFn: function(e) {
Y.log('Event stopped: ' + e.type, 'debug', LOGNAME);
}
};
if (!eventsConfigured) {
var eventDefaultConfig = {
emitFacade: true,
defaultFn: function(e) {
Y.log('Event fired: ' + e.type, 'debug', LOGNAME);
},
preventedFn: function(e) {
Y.log('Event prevented: ' + e.type, 'debug', LOGNAME);
},
stoppedFn: function(e) {
Y.log('Event stopped: ' + e.type, 'debug', LOGNAME);
}
};
// Publish events with a custom config here.
// Publish events with a custom config here.
// Publish all the events with a standard config.
var key;
for (key in M.core.event) {
if (M.core.event.hasOwnProperty(key) && Y.getEvent(M.core.event[key]) === null) {
Y.publish(M.core.event[key], eventDefaultConfig);
}
}
// Publish global events.
for (key in M.core.globalEvents) {
// Make sure the key exists and that the event has not yet been published. Otherwise, skip publishing.
if (M.core.globalEvents.hasOwnProperty(key) && Y.Global.getEvent(M.core.globalEvents[key]) === null) {
Y.Global.publish(M.core.globalEvents[key], Y.merge(eventDefaultConfig, {broadcast: true}));
Y.log('Global event published: ' + key, 'debug', LOGNAME);
// Publish all the events with a standard config.
var key;
for (key in M.core.event) {
if (M.core.event.hasOwnProperty(key) && Y.getEvent(M.core.event[key]) === null) {
Y.publish(M.core.event[key], eventDefaultConfig);
}
}
// Publish global events.
for (key in M.core.globalEvents) {
// Make sure the key exists and that the event has not yet been published. Otherwise, skip publishing.
if (M.core.globalEvents.hasOwnProperty(key) && Y.Global.getEvent(M.core.globalEvents[key]) === null) {
Y.Global.publish(M.core.globalEvents[key], Y.merge(eventDefaultConfig, {broadcast: true}));
Y.log('Global event published: ' + key, 'debug', LOGNAME);
}
}
/**
* Apply a callback when the DOM is modified and matchecs the supplied targetSelector.
*
* @method listen
* @param {String} targetSelector The selector to apply
* @param {Function} applyCallback The function to call on the found node
*/
var listenForMutation = function(targetSelector, applyCallback) {
// Add a MutationObserver to check for new children to the tree.
var newNodeObserver = new MutationObserver(function(mutationList) {
mutationList.forEach(function(mutation) {
mutation.addedNodes.forEach(function(node) {
if (node instanceof Element && node.matches(targetSelector)) {
applyCallback(node);
}
});
});
});
newNodeObserver.observe(document, {childList: true, subtree: true});
};
// YUI Custom Events do not bubble up the DOM, only up the inheritance path of custom classes.
// We have to add a Node Observer to watch for new forms that may need to be watched in future.
require(['core_form/events'], function(formEvents) {
listenForMutation('form', function(form) {
Y.one(form).on(M.core.event.FORM_SUBMIT_AJAX, function(e) {
// Prevent cyclical calls.
if (e && e.fallbackHandled) {
return;
}
formEvents.notifyFormSubmittedByJavascript(form, window.skipValidation, true);
});
});
});
}
+1 -1
View File
@@ -1,2 +1,2 @@
define ("media_videojs/loader",["exports","core/config","core/event","jquery","core/ajax","core/localstorage","core/notification"],function(a,b,c,d,e,f,g){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.setUp=void 0;b=h(b);c=h(c);d=h(d);e=h(e);f=h(f);g=h(g);var o="undefined"!=typeof window?window:"undefined"!=typeof self?self:"undefined"!=typeof global?global:{};function h(a){return a&&a.__esModule?a:{default:a}}function i(a,b){return n(a)||m(a,b)||k(a,b)||j()}function j(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function k(a,b){if(!a)return;if("string"==typeof a)return l(a,b);var c=Object.prototype.toString.call(a).slice(8,-1);if("Object"===c&&a.constructor)c=a.constructor.name;if("Map"===c||"Set"===c)return Array.from(c);if("Arguments"===c||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(c))return l(a,b)}function l(a,b){if(null==b||b>a.length)b=a.length;for(var c=0,d=Array(b);c<b;c++){d[c]=a[c]}return d}function m(a,b){if("undefined"==typeof Symbol||!(Symbol.iterator in Object(a)))return;var c=[],d=!0,e=!1,f=void 0;try{for(var g=a[Symbol.iterator](),h;!(d=(h=g.next()).done);d=!0){c.push(h.value);if(b&&c.length===b)break}}catch(a){e=!0;f=a}finally{try{if(!d&&null!=g["return"])g["return"]()}finally{if(e)throw f}}return c}function n(a){if(Array.isArray(a))return a}var p,q,r,s=function(a){q=a;p=!0;t(null,(0,d.default)("body"));c.default.getLegacyEvents().done(function(a){(0,d.default)(document).on(a.FILTER_CONTENT_UPDATED,t)})};a.setUp=s;var t=function(a,c){var e=u();c.find(".mediaplugin_videojs").addBack(".mediaplugin_videojs").find("audio, video").each(function(a,c){var f=(0,d.default)(c).attr("id"),h=(0,d.default)(c).data("setup-lazy"),j=["function"==typeof o.define&&o.define.amd?new Promise(function(a,b){o.require(["media_videojs/video-lazy"],a,b)}):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&o.require&&"component"===o.require.loader?Promise.resolve(require(("media_videojs/video-lazy"))):Promise.resolve(o["media_videojs/video-lazy"])];if(h.techOrder&&-1!==h.techOrder.indexOf("youtube")){j.push("function"==typeof o.define&&o.define.amd?new Promise(function(a,b){o.require(["media_videojs/Youtube-lazy"],a,b)}):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&o.require&&"component"===o.require.loader?Promise.resolve(require(("media_videojs/Youtube-lazy"))):Promise.resolve(o["media_videojs/Youtube-lazy"]))}if(h.techOrder&&-1!==h.techOrder.indexOf("flash")){j.push("function"==typeof o.define&&o.define.amd?new Promise(function(a,b){o.require(["media_videojs/videojs-flash-lazy"],a,b)}):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&o.require&&"component"===o.require.loader?Promise.resolve(require(("media_videojs/videojs-flash-lazy"))):Promise.resolve(o["media_videojs/videojs-flash-lazy"]))}Promise.all([e].concat(j)).then(function(a){var c=i(a,2),d=c[0],e=c[1];if(p){e.options.flash.swf="".concat(b.default.wwwroot,"/media/player/videojs/videojs/video-js.swf");e.options.playbackRates=[.5,.75,1,1.25,1.5,1.75,2];e.options.userActions={hotkeys:!0};e.addLanguage(q,d);p=!1}e(f,h)}).catch(g.default.exception)})},u=function(){if(r){return Promise.resolve(r)}var a="media_videojs/".concat(q),b=f.default.get(a);if(b){var d=JSON.parse(b);r=d;return Promise.resolve(r)}var c={methodname:"media_videojs_get_language",args:{lang:q}};return e.default.call([c])[0].then(function(b){f.default.set(a,b);return b}).then(function(a){return JSON.parse(a)}).then(function(a){r=a;return a})}});
define ("media_videojs/loader",["exports","core/ajax","core/config","core_filters/events","core/localstorage","core/notification","jquery"],function(a,b,c,d,e,f,g){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.setUp=void 0;b=h(b);c=h(c);e=h(e);f=h(f);g=h(g);var o="undefined"!=typeof window?window:"undefined"!=typeof self?self:"undefined"!=typeof global?global:{};function h(a){return a&&a.__esModule?a:{default:a}}function i(a,b){return n(a)||m(a,b)||k(a,b)||j()}function j(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function k(a,b){if(!a)return;if("string"==typeof a)return l(a,b);var c=Object.prototype.toString.call(a).slice(8,-1);if("Object"===c&&a.constructor)c=a.constructor.name;if("Map"===c||"Set"===c)return Array.from(c);if("Arguments"===c||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(c))return l(a,b)}function l(a,b){if(null==b||b>a.length)b=a.length;for(var c=0,d=Array(b);c<b;c++){d[c]=a[c]}return d}function m(a,b){if("undefined"==typeof Symbol||!(Symbol.iterator in Object(a)))return;var c=[],d=!0,e=!1,f=void 0;try{for(var g=a[Symbol.iterator](),h;!(d=(h=g.next()).done);d=!0){c.push(h.value);if(b&&c.length===b)break}}catch(a){e=!0;f=a}finally{try{if(!d&&null!=g["return"])g["return"]()}finally{if(e)throw f}}return c}function n(a){if(Array.isArray(a))return a}var p,q,r;a.setUp=function setUp(a){q=a;p=!0;s({detail:{nodes:document.body}});document.addEventListener(d.eventTypes.filterContentUpdated,s)};var s=function(a){var b=(0,g.default)(a.detail.nodes),d=".mediaplugin_videojs",e=t();b.find(d).addBack(d).find("audio, video").each(function(a,b){var d=(0,g.default)(b).attr("id"),h=(0,g.default)(b).data("setup-lazy"),j=["function"==typeof o.define&&o.define.amd?new Promise(function(a,b){o.require(["media_videojs/video-lazy"],a,b)}):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&o.require&&"component"===o.require.loader?Promise.resolve(require(("media_videojs/video-lazy"))):Promise.resolve(o["media_videojs/video-lazy"])];if(h.techOrder&&-1!==h.techOrder.indexOf("youtube")){j.push("function"==typeof o.define&&o.define.amd?new Promise(function(a,b){o.require(["media_videojs/Youtube-lazy"],a,b)}):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&o.require&&"component"===o.require.loader?Promise.resolve(require(("media_videojs/Youtube-lazy"))):Promise.resolve(o["media_videojs/Youtube-lazy"]))}if(h.techOrder&&-1!==h.techOrder.indexOf("flash")){j.push("function"==typeof o.define&&o.define.amd?new Promise(function(a,b){o.require(["media_videojs/videojs-flash-lazy"],a,b)}):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&o.require&&"component"===o.require.loader?Promise.resolve(require(("media_videojs/videojs-flash-lazy"))):Promise.resolve(o["media_videojs/videojs-flash-lazy"]))}Promise.all([e].concat(j)).then(function(a){var b=i(a,2),e=b[0],f=b[1];if(p){f.options.flash.swf="".concat(c.default.wwwroot,"/media/player/videojs/videojs/video-js.swf");f.options.playbackRates=[.5,.75,1,1.25,1.5,1.75,2];f.options.userActions={hotkeys:!0};f.addLanguage(q,e);p=!1}f(d,h)}).catch(f.default.exception)})},t=function(){if(r){return Promise.resolve(r)}var a="media_videojs/".concat(q),c=e.default.get(a);if(c){var f=JSON.parse(c);r=f;return Promise.resolve(r)}var d={methodname:"media_videojs_get_language",args:{lang:q}};return b.default.call([d])[0].then(function(b){e.default.set(a,b);return b}).then(function(a){return JSON.parse(a)}).then(function(a){r=a;return a})}});
//# sourceMappingURL=loader.min.js.map
File diff suppressed because one or more lines are too long
+17 -10
View File
@@ -24,12 +24,12 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Config from 'core/config';
import Event from 'core/event';
import jQuery from 'jquery';
import Ajax from 'core/ajax';
import Config from 'core/config';
import {eventTypes} from 'core_filters/events';
import LocalStorage from 'core/localstorage';
import Notification from 'core/notification';
import jQuery from 'jquery';
/** @var {bool} Whether this is the first load of videojs module */
let firstLoad;
@@ -41,29 +41,36 @@ let language;
let langStringCache;
/**
* Set-up.
* Initialisei teh videojs Loader.
*
* Adds the listener for the event to then notify video.js.
*
* @method
* @param {string} lang Language to be used in the player
* @listens event:filterContentUpdated
*/
export const setUp = (lang) => {
language = lang;
firstLoad = true;
// Notify Video.js about the nodes already present on the page.
notifyVideoJS(null, jQuery('body'));
// We need to call popover automatically if nodes are added to the page later.
Event.getLegacyEvents().done((events) => {
jQuery(document).on(events.FILTER_CONTENT_UPDATED, notifyVideoJS);
notifyVideoJS({
detail: {
nodes: document.body,
}
});
// We need to call popover automatically if nodes are added to the page later.
document.addEventListener(eventTypes.filterContentUpdated, notifyVideoJS);
};
/**
* Notify video.js of new nodes.
*
* @param {Event} e The event.
* @param {NodeList} nodes List of new nodes.
*/
const notifyVideoJS = (e, nodes) => {
const notifyVideoJS = e => {
const nodes = jQuery(e.detail.nodes);
const selector = '.mediaplugin_videojs';
const langStrings = getLanguageJson();
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+8 -5
View File
@@ -23,10 +23,12 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.1
*/
define(['jquery', 'core/yui', 'core/notification', 'core/templates', 'core/fragment',
'core/ajax', 'core/str', 'mod_assign/grading_form_change_checker',
'mod_assign/grading_events', 'core/event', 'core/toast'],
function($, Y, notification, templates, fragment, ajax, str, checker, GradingEvents, Event, Toast) {
define([
'jquery', 'core/yui', 'core/notification', 'core/templates', 'core/fragment',
'core/ajax', 'core/str', 'mod_assign/grading_form_change_checker',
'mod_assign/grading_events', 'core_form/events', 'core/toast'
],
function($, Y, notification, templates, fragment, ajax, str, checker, GradingEvents, FormEvents, Toast) {
/**
* GradingPanel class.
@@ -102,6 +104,7 @@ define(['jquery', 'core/yui', 'core/notification', 'core/templates', 'core/fragm
* @param {Integer} nextUserId
* @param {Boolean} nextUser optional. Load next user in the grading list.
* @method _submitForm
* @fires event:formSubmittedByJavascript
*/
GradingPanel.prototype._submitForm = function(event, nextUserId, nextUser) {
// If the form has data in comment-area, then we need to save that comment
@@ -123,7 +126,7 @@ define(['jquery', 'core/yui', 'core/notification', 'core/templates', 'core/fragm
form.trigger('save-form-state');
// Tell all form fields we are about to submit the form.
Event.notifyFormSubmitAjax(form[0]);
FormEvents.notifyFormSubmittedByJavascript(form[0]);
// Now we get all the current values from the form.
var data = form.serialize();
+1 -1
View File
@@ -1,2 +1,2 @@
define ("theme_boost/form-display-errors",["jquery","core/event"],function(a,b){return{enhance:function enhance(c){var d=document.getElementById(c);if(!d){return}a(d).on(b.Events.FORM_FIELD_VALIDATION,function(b,c){b.preventDefault();var e=a(d).closest(".form-group"),f=e.find(".form-control-feedback"),g=f.attr("id"),h=a(d).attr("aria-describedby");if("undefined"==typeof h){h=""}var i=[];if(h.length){i=h.split(" ")}var j=i.indexOf(g);if("TEXTAREA"==a(d).prop("tagName")&&e.find("[contenteditable]")){d=e.find("[contenteditable]")}if(""!==c){e.addClass("has-danger");e.data("client-validation-error",!0);a(d).addClass("is-invalid");if(-1===j){i.push(g);a(d).attr("aria-describedby",i.join(" "))}a(d).attr("aria-invalid",!0);f.attr("tabindex",0);f.html(c);if(!f.is(":visible")){f.show();f.focus()}}else{if(!0===e.data("client-validation-error")){e.removeClass("has-danger");e.data("client-validation-error",!1);a(d).removeClass("is-invalid");if(-1<j){i.splice(j,1)}if(i.length){h=i.join(" ");a(d).attr("aria-describedby",h)}else{a(d).removeAttr("aria-describedby")}a(d).attr("aria-invalid",!1);f.hide()}}});var e=d.closest("form");if(e&&!("boostFormErrorsEnhanced"in e.dataset)){e.addEventListener("submit",function(){var b=a(".form-control-feedback:visible");if(b.length){b[0].focus()}});e.dataset.boostFormErrorsEnhanced=1}}}});
define ("theme_boost/form-display-errors",["jquery","core_form/events"],function(a,b){return{enhance:function enhance(c){var d=document.getElementById(c);if(!d){return}d.addEventListener(b.eventTypes.formFieldValidationFailed,function(b){var c=b.detail.message;b.preventDefault();var e=a(d).closest(".form-group"),f=e.find(".form-control-feedback"),g=f.attr("id"),h=a(d).attr("aria-describedby");if("undefined"==typeof h){h=""}var i=[];if(h.length){i=h.split(" ")}var j=i.indexOf(g);if("TEXTAREA"==a(d).prop("tagName")&&e.find("[contenteditable]")){d=e.find("[contenteditable]")}if(""!==c){e.addClass("has-danger");e.data("client-validation-error",!0);a(d).addClass("is-invalid");if(-1===j){i.push(g);a(d).attr("aria-describedby",i.join(" "))}a(d).attr("aria-invalid",!0);f.attr("tabindex",0);f.html(c);if(!f.is(":visible")){f.show();f.focus()}}else{if(!0===e.data("client-validation-error")){e.removeClass("has-danger");e.data("client-validation-error",!1);a(d).removeClass("is-invalid");if(-1<j){i.splice(j,1)}if(i.length){h=i.join(" ");a(d).attr("aria-describedby",h)}else{a(d).removeAttr("aria-describedby")}a(d).attr("aria-invalid",!1);f.hide()}}});var e=d.closest("form");if(e&&!("boostFormErrorsEnhanced"in e.dataset)){e.addEventListener("submit",function(){var b=a(".form-control-feedback:visible");if(b.length){b[0].focus()}});e.dataset.boostFormErrorsEnhanced=1}}}});
//# sourceMappingURL=form-display-errors.min.js.map
File diff suppressed because one or more lines are too long
+12 -3
View File
@@ -21,8 +21,15 @@
* @copyright 2016 Damyon Wiese <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define(['jquery', 'core/event'], function($, Event) {
define(['jquery', 'core_form/events'], function($, FormEvent) {
return {
/**
* Enhance the supplied element to handle form field errors.
*
* @method
* @param {String} elementid
* @listens event:formFieldValidationFailed
*/
enhance: function(elementid) {
var element = document.getElementById(elementid);
if (!element) {
@@ -31,8 +38,10 @@ define(['jquery', 'core/event'], function($, Event) {
return;
}
$(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
event.preventDefault();
element.addEventListener(FormEvent.eventTypes.formFieldValidationFailed, e => {
const msg = e.detail.message;
e.preventDefault();
var parent = $(element).closest('.form-group');
var feedback = parent.find('.form-control-feedback');
const feedbackId = feedback.attr('id');