summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorAlex Pott <alex.a.pott@googlemail.com>2021-03-05 13:13:45 +0000
committerAlex Pott <alex.a.pott@googlemail.com>2021-03-05 13:13:45 +0000
commit5bce5eeb25f2f292e2059dfb51ca540d878233f3 (patch)
treea4ebead0da29f1fecc65501ca8f810a1d484dec5
parentdaf10a069572b2fb1d5ebcdf7cdb8400878e965d (diff)
downloaddrupal-5bce5eeb25f2f292e2059dfb51ca540d878233f3.tar.gz
drupal-5bce5eeb25f2f292e2059dfb51ca540d878233f3.zip
Issue #2402103 by nod_, bnjmnm, larowlan, flxa, anmolgoyal74, droplet, xjm, catch, gabesullice, lauriii, Dries, justafish: Add once.js to core
-rw-r--r--core/.eslintrc.json1
-rw-r--r--core/assets/vendor/once/once.js387
-rw-r--r--core/assets/vendor/once/once.min.js3
-rw-r--r--core/assets/vendor/once/once.min.js.map1
-rw-r--r--core/core.libraries.yml19
-rw-r--r--core/misc/date.es6.js37
-rw-r--r--core/misc/date.js17
-rw-r--r--core/misc/polyfills/element.matches.es6.js17
-rw-r--r--core/misc/polyfills/element.matches.js10
-rw-r--r--core/themes/claro/claro.libraries.yml2
-rw-r--r--core/themes/claro/js/autocomplete.es6.js13
-rw-r--r--core/themes/claro/js/autocomplete.js6
12 files changed, 456 insertions, 57 deletions
diff --git a/core/.eslintrc.json b/core/.eslintrc.json
index a133f542bb8..7cd9b27b375 100644
--- a/core/.eslintrc.json
+++ b/core/.eslintrc.json
@@ -20,6 +20,7 @@
"Modernizr": true,
"Popper": true,
"Sortable": true,
+ "once": true,
"CKEDITOR": true,
"tabbable": true
},
diff --git a/core/assets/vendor/once/once.js b/core/assets/vendor/once/once.js
new file mode 100644
index 00000000000..cf13eeced12
--- /dev/null
+++ b/core/assets/vendor/once/once.js
@@ -0,0 +1,387 @@
+/*! @drupal/once - v1.0.0 - 2021-03-04 */
+/**
+ * Mark DOM elements as processed to prevent multiple initializations.
+ *
+ * @module @drupal/once
+ *
+ * @example <!-- Use as a module -->
+ * <script type="module">
+ * import once from 'https://unpkg.com/@drupal/once/src/once.js';
+ * const elements = once('my-once-id', 'div');
+ * // Initialize elements.
+ * elements.forEach(el => el.innerHTML = 'processed');
+ * </script>
+ *
+ * @example <!-- Use as a regular script -->
+ * <script src="https://unpkg.com/@drupal/once"></script>
+ * <script>
+ * const elements = once('my-once-id', 'div');
+ * // Initialize elements.
+ * elements.forEach(el => el.innerHTML = 'processed');
+ * </script>
+ * @example <!-- Using a single element as input-->
+ * <script src="https://unpkg.com/@drupal/once"></script>
+ * <script>
+ * // once methods always return an array, to simplify the use with a single
+ * // element use destructuring or the shift method.
+ * const [myElement] = once('my-once-id', document.body);
+ * const myElement = once('my-once-id', document.body).shift();
+ * </script>
+ */
+
+/**
+ * Illegal spaces in ids.
+ *
+ * @private
+ *
+ * @type {RegExp}
+ */
+const wsRE = /[\11\12\14\15\40]+/;
+
+/**
+ * Name of the HTML attribute containing an element's once ids.
+ *
+ * @private
+ *
+ * @type {string}
+ */
+const attrName = 'data-once';
+
+/**
+ * Shortcut to access the html element.
+ *
+ * @private
+ *
+ * @type {HTMLElement}
+ */
+const doc = document;
+
+/**
+ * Helper to access element attributes.
+ *
+ * @private
+ *
+ * @param {Element} element
+ * The Element to access the data-once attribute from.
+ * @param {string} op
+ * The action to take on the element.
+ * @param {string} [value]
+ * Optional value for setAttribute.
+ *
+ * @return {string|undefined|null|boolean}
+ * Result of the attribute method.
+ */
+function attr(element, op, value) {
+ return element[`${op}Attribute`](attrName, value);
+}
+
+/**
+ * Return the attribute selector.
+ *
+ * @private
+ *
+ * @param {string} id
+ * The id passed by a call to a once() function.
+ *
+ * @return {string}
+ * The full CSS attribute selector.
+ *
+ * @throws {TypeError|RangeError}
+ */
+function attrSelector(id) {
+ // Verify the validity of the once id.
+ if (typeof id !== 'string') {
+ throw new TypeError('once ID must be a string');
+ }
+ if (id === '' || wsRE.test(id)) {
+ throw new RangeError('once ID must not be empty or contain spaces');
+ }
+ // The id is valid, return the full CSS selector.
+ return `[${attrName}~="${id}"]`;
+}
+
+/**
+ * Verifies that an item is an instance of Element.
+ *
+ * This function is used during filtering to ensure only DOM elements are
+ * processed. once() makes use of get/setAttribute, which are methods
+ * inherited from the Element object, so only of Element can be used.
+ *
+ * @private
+ *
+ * @param {*} itemToCheck
+ * The item to check.
+ *
+ * @return {boolean}
+ * True if the item is an instance of Element
+ *
+ * @throws {TypeError}
+ */
+function checkElement(itemToCheck) {
+ if (!(itemToCheck instanceof Element)) {
+ throw new TypeError('The element must be an instance of Element');
+ }
+ return true;
+}
+
+/**
+ * Process arguments, query the DOM if necessary.
+ *
+ * @private
+ *
+ * @param {NodeList|Array.<Element>|Element|string} selector
+ * A NodeList or array of elements.
+ * @param {Document|Element} [context=document]
+ * An element to use as context for querySelectorAll.
+ *
+ * @return {Array.<Element>}
+ * An array with the processed Id and the list of elements to process.
+ */
+function getElements(selector, context = doc) {
+ if (!selector) {
+ throw new TypeError('Selector must not be empty');
+ }
+ // Assume selector is an array-like value.
+ let elements = selector;
+
+ // This is a selector, query the elements.
+ if (
+ typeof selector === 'string' &&
+ (context === doc || checkElement(context))
+ ) {
+ elements = context.querySelectorAll(selector);
+ }
+ // This is a single element.
+ else if (selector instanceof Element) {
+ elements = [selector];
+ }
+
+ // Make sure an array is returned and not a NodeList or an Array-like object.
+ return Array.prototype.slice.call(elements);
+}
+
+/**
+ * A helper for applying DOM changes to a filtered set of elements.
+ *
+ * This makes it possible to filter items that are not instances of Element,
+ * then modify their DOM attributes in a single array traversal.
+ *
+ * @private
+ *
+ * @param {string} selector
+ * A CSS selector to check against to each element in the array.
+ * @param {Array.<Element>} elements
+ * A NodeList or array of elements passed by a call to a once() function.
+ * @param {function} [apply]
+ * An optional function to apply on all matched elements.
+ *
+ * @return {Array.<Element>}
+ * The array of elements that match the CSS selector.
+ */
+function filterAndModify(selector, elements, apply) {
+ return elements.filter(element => {
+ const selected = checkElement(element) && element.matches(selector);
+ if (selected && apply) {
+ apply(element);
+ }
+ return selected;
+ });
+}
+
+/**
+ * Add or remove an item from a list of once values.
+ *
+ * This function removes duplicates while adding or removing a once id in a
+ * single array traversal.
+ *
+ * @private
+ *
+ * @param {Element} element
+ * A space separated string of once ids from a data-drupal-once attribute.
+ * @param {string} [add]
+ * The once id to add to the list of values.
+ * @param {string} [remove]
+ * The once id to remove from the list of values.
+ *
+ * @return {undefined}
+ * Nothing to return this is a callback in a foreach.
+ */
+function updateAttribute(element, { add, remove }) {
+ const result = [];
+ if (attr(element, 'has')) {
+ attr(element, 'get')
+ .trim()
+ .split(wsRE)
+ .forEach(item => {
+ if (result.indexOf(item) < 0 && item !== remove) {
+ result.push(item);
+ }
+ });
+ }
+ if (add) {
+ result.push(add);
+ }
+ const attribute = result.join(' ');
+ attr(element, attribute === '' ? 'remove' : 'set', attribute);
+}
+
+/**
+ * Ensures a JavaScript callback is only executed once on a set of elements.
+ *
+ * Filters a NodeList or array of elements, removing those already processed
+ * by a callback with a given id.
+ * This method adds a `data-once` attribute on DOM elements. The value of
+ * this attribute identifies if a given callback has been executed on that
+ * element.
+ *
+ * @global
+ *
+ * @example <caption>Basic usage</caption>
+ * const elements = once('my-once-id', '[data-myelement]');
+ * @example <caption>Input parameters accepted</caption>
+ * // NodeList.
+ * once('my-once-id', document.querySelectorAll('[data-myelement]'));
+ * // Array or Array-like of Element.
+ * once('my-once-id', jQuery('[data-myelement]'));
+ * // A CSS selector without a context.
+ * once('my-once-id', '[data-myelement]');
+ * // A CSS selector with a context.
+ * once('my-once-id', '[data-myelement]', document.head);
+ * // Single Element.
+ * once('my-once-id', document.querySelector('#some-id'));
+ * @example <caption>Using a single element</caption>
+ * // Once always returns an array, even when passing a single element. Some
+ * // forms that can be used to keep code readable.
+ * // Destructuring:
+ * const [myElement] = once('my-once-id', document.body);
+ * // By changing the resulting array, es5 compatible.
+ * const myElement = once('my-once-id', document.body).shift();
+ *
+ * @param {string} id
+ * The id of the once call.
+ * @param {NodeList|Array.<Element>|Element|string} selector
+ * A NodeList or array of elements.
+ * @param {Document|Element} [context=document]
+ * An element to use as context for querySelectorAll.
+ *
+ * @return {Array.<Element>}
+ * An array of elements that have not yet been processed by a once call
+ * with a given id.
+ */
+function once(id, selector, context) {
+ return filterAndModify(
+ `:not(${attrSelector(id)})`,
+ getElements(selector, context),
+ element => updateAttribute(element, { add: id }),
+ );
+}
+
+/**
+ * Removes a once id from an element's data-drupal-once attribute value.
+ *
+ * If a once id is removed from an element's data-drupal-once attribute value,
+ * the JavaScript callback associated with that id can be executed on that
+ * element again.
+ *
+ * @method once.remove
+ *
+ * @example <caption>Basic usage</caption>
+ * const elements = once.remove('my-once-id', '[data-myelement]');
+ * @example <caption>Input parameters accepted</caption>
+ * // NodeList.
+ * once.remove('my-once-id', document.querySelectorAll('[data-myelement]'));
+ * // Array or Array-like of Element.
+ * once.remove('my-once-id', jQuery('[data-myelement]'));
+ * // A CSS selector without a context.
+ * once.remove('my-once-id', '[data-myelement]');
+ * // A CSS selector with a context.
+ * once.remove('my-once-id', '[data-myelement]', document.head);
+ * // Single Element.
+ * once.remove('my-once-id', document.querySelector('#some-id'));
+ *
+ * @param {string} id
+ * The id of a once call.
+ * @param {NodeList|Array.<Element>|Element|string} selector
+ * A NodeList or array of elements to remove the once id from.
+ * @param {Document|Element} [context=document]
+ * An element to use as context for querySelectorAll.
+ *
+ * @return {Array.<Element>}
+ * A filtered array of elements that had been processed by the provided id,
+ * and are now able to be processed again.
+ */
+once.remove = (id, selector, context) => {
+ return filterAndModify(
+ attrSelector(id),
+ getElements(selector, context),
+ element => updateAttribute(element, { remove: id }),
+ );
+};
+
+/**
+ * Finds elements that have been processed by a given once id.
+ *
+ * Behaves like {@link once} and {@link once.remove} without changing the DOM.
+ * To select all DOM nodes processed by a given id, use {@link once.find}.
+ *
+ * @method once.filter
+ *
+ * @example <caption>Basic usage</caption>
+ * const filteredElements = once.filter('my-once-id', '[data-myelement]');
+ * @example <caption>Input parameters accepted</caption>
+ * // NodeList.
+ * once.filter('my-once-id', document.querySelectorAll('[data-myelement]'));
+ * // Array or Array-like of Element.
+ * once.filter('my-once-id', jQuery('[data-myelement]'));
+ * // A CSS selector without a context.
+ * once.filter('my-once-id', '[data-myelement]');
+ * // A CSS selector with a context.
+ * once.filter('my-once-id', '[data-myelement]', document.head);
+ * // Single Element.
+ * once.filter('my-once-id', document.querySelector('#some-id'));
+ *
+ * @param {string} id
+ * The id of the once call.
+ * @param {NodeList|Array.<Element>|Element|string} selector
+ * A NodeList or array of elements to remove the once id from.
+ * @param {Document|Element} [context=document]
+ * An element to use as context for querySelectorAll.
+ *
+ * @return {Array.<Element>}
+ * A filtered array of elements that have already been processed by the
+ * provided once id.
+ */
+once.filter = (id, selector, context) =>
+ filterAndModify(attrSelector(id), getElements(selector, context));
+
+/**
+ * Finds elements that have been processed by a given once id.
+ *
+ * Query the 'context' element for elements that already have the
+ * corresponding once id value.
+ *
+ * @method once.find
+ *
+ * @example <caption>Basic usage</caption>
+ * const oncedElements = once.find('my-once-id');
+ * @example <caption>Input parameters accepted</caption>
+ * // Call without parameters, return all elements with a `data-once` attribute.
+ * once.find();
+ * // Call without a context.
+ * once.find('my-once-id');
+ * // Call with a context.
+ * once.find('my-once-id', document.head);
+ *
+ * @param {string} [id]
+ * The id of the once call.
+ * @param {Document|Element} [context=document]
+ * Scope of the search for matching elements.
+ *
+ * @return {Array.<Element>}
+ * A filtered array of elements that have already been processed by the
+ * provided once id.
+ */
+once.find = (id, context) =>
+ getElements(!id ? `[${attrName}]` : attrSelector(id), context);
+
+export default once;
diff --git a/core/assets/vendor/once/once.min.js b/core/assets/vendor/once/once.min.js
new file mode 100644
index 00000000000..b972c2a6c74
--- /dev/null
+++ b/core/assets/vendor/once/once.min.js
@@ -0,0 +1,3 @@
+/*! @drupal/once - v1.0.0 - 2021-03-04 */
+var once=function(){"use strict";var n=/[\11\12\14\15\40]+/,t="data-once",e=document;function r(n,e,r){return n[e+"Attribute"](t,r)}function o(t){if("string"!=typeof t)throw new TypeError("once ID must be a string");if(""===t||n.test(t))throw new RangeError("once ID must not be empty or contain spaces");return'[data-once~="'+t+'"]'}function u(n){if(!(n instanceof Element))throw new TypeError("The element must be an instance of Element");return!0}function i(n,t){if(void 0===t&&(t=e),!n)throw new TypeError("Selector must not be empty");var r=n;return"string"!=typeof n||t!==e&&!u(t)?n instanceof Element&&(r=[n]):r=t.querySelectorAll(n),Array.prototype.slice.call(r)}function c(n,t,e){return t.filter((function(t){var r=u(t)&&t.matches(n);return r&&e&&e(t),r}))}function f(t,e){var o=e.add,u=e.remove,i=[];r(t,"has")&&r(t,"get").trim().split(n).forEach((function(n){i.indexOf(n)<0&&n!==u&&i.push(n)})),o&&i.push(o);var c=i.join(" ");r(t,""===c?"remove":"set",c)}function a(n,t,e){return c(":not("+o(n)+")",i(t,e),(function(t){return f(t,{add:n})}))}return a.remove=function(n,t,e){return c(o(n),i(t,e),(function(t){return f(t,{remove:n})}))},a.filter=function(n,t,e){return c(o(n),i(t,e))},a.find=function(n,t){return i(n?o(n):"[data-once]",t)},a}();
+//# sourceMappingURL=once.min.js.map
diff --git a/core/assets/vendor/once/once.min.js.map b/core/assets/vendor/once/once.min.js.map
new file mode 100644
index 00000000000..2b29e5c1656
--- /dev/null
+++ b/core/assets/vendor/once/once.min.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"once.min.js","sources":["once.js"],"sourcesContent":null,"names":["const","wsRE","attrName","doc","document","attr","element","op","value","attrSelector","id","TypeError","test","RangeError","checkElement","itemToCheck","Element","getElements","selector","context","let","elements","querySelectorAll","Array","prototype","slice","call","filterAndModify","apply","filter","selected","matches","updateAttribute","result","trim","split","forEach","item","indexOf","remove","push","add","attribute","join","once","find"],"mappings":";iCAsCAA,IAAMC,EAAO,qBASPC,EAAW,YASXC,EAAMC,SAiBZ,SAASC,EAAKC,EAASC,EAAIC,GACzB,OAAOF,EAAWC,eAAeL,EAAUM,GAgB7C,SAASC,EAAaC,GAEpB,GAAkB,iBAAPA,EACT,MAAM,IAAIC,UAAU,4BAEtB,GAAW,KAAPD,GAAaT,EAAKW,KAAKF,GACzB,MAAM,IAAIG,WAAW,+CAGvB,sBAAyBH,OAoB3B,SAASI,EAAaC,GACpB,KAAMA,aAAuBC,SAC3B,MAAM,IAAIL,UAAU,8CAEtB,OAAO,EAgBT,SAASM,EAAYC,EAAUC,GAC7B,kBADuChB,IAClCe,EACH,MAAM,IAAIP,UAAU,8BAGtBS,IAAIC,EAAWH,EAef,MAXsB,iBAAbA,GACNC,IAAYhB,IAAOW,EAAaK,GAK1BD,aAAoBF,UAC3BK,EAAW,CAACH,IAJZG,EAAWF,EAAQG,iBAAiBJ,GAQ/BK,MAAMC,UAAUC,MAAMC,KAAKL,GAqBpC,SAASM,EAAgBT,EAAUG,EAAUO,GAC3C,OAAOP,EAASQ,iBAAOvB,GACrBN,IAAM8B,EAAWhB,EAAaR,IAAYA,EAAQyB,QAAQb,GAI1D,OAHIY,GAAYF,GACdA,EAAMtB,GAEDwB,KAsBX,SAASE,EAAgB1B,4BACjB2B,EAAS,GACX5B,EAAKC,EAAS,QAChBD,EAAKC,EAAS,OACX4B,OACAC,MAAMlC,GACNmC,kBAAQC,GACHJ,EAAOK,QAAQD,GAAQ,GAAKA,IAASE,GACvCN,EAAOO,KAAKH,MAIhBI,GACFR,EAAOO,KAAKC,GAEdzC,IAAM0C,EAAYT,EAAOU,KAAK,KAC9BtC,EAAKC,EAAuB,KAAdoC,EAAmB,SAAW,MAAOA,GA8CrD,SAASE,EAAKlC,EAAIQ,EAAUC,GAC1B,OAAOQ,UACGlB,EAAaC,OACrBO,EAAYC,EAAUC,aACtBb,UAAW0B,EAAgB1B,EAAS,CAAEmC,IAAK/B,cAsC/CkC,EAAKL,gBAAU7B,EAAIQ,EAAUC,GAC3B,OAAOQ,EACLlB,EAAaC,GACbO,EAAYC,EAAUC,aACtBb,UAAW0B,EAAgB1B,EAAS,CAAEiC,OAAQ7B,QAqClDkC,EAAKf,gBAAUnB,EAAIQ,EAAUC,UAC3BQ,EAAgBlB,EAAaC,GAAKO,EAAYC,EAAUC,KA6B1DyB,EAAKC,cAAQnC,EAAIS,UACfF,EAAaP,EAAuBD,EAAaC,iBAAKS"} \ No newline at end of file
diff --git a/core/core.libraries.yml b/core/core.libraries.yml
index f998d76c87d..2951aaaa7cc 100644
--- a/core/core.libraries.yml
+++ b/core/core.libraries.yml
@@ -181,7 +181,7 @@ drupal.date:
dependencies:
- core/drupal
- core/modernizr
- - core/jquery.once
+ - core/once
drupal.debounce:
version: VERSION
@@ -279,6 +279,11 @@ drupal.dropbutton:
- core/drupalSettings
- core/jquery.once
+drupal.element.matches:
+ version: VERSION
+ js:
+ misc/polyfills/element.matches.js: { weight: -20 }
+
drupal.entity-form:
version: VERSION
js:
@@ -705,6 +710,18 @@ normalize:
assets/vendor/normalize-css/normalize.css: { weight: -20 }
misc/normalize-fixes.css: { weight: -19 }
+once:
+ remote: https://git.drupalcode.org/project/once
+ version: "1.0.0"
+ license:
+ name: GNU-GPL-2.0-or-later
+ url: https://git.drupalcode.org/project/once/-/raw/v1.0.0/LICENSE.md
+ gpl-compatible: true
+ js:
+ assets/vendor/once/once.min.js: { weight: -19, minified: true }
+ dependencies:
+ - core/drupal.element.matches
+
picturefill:
remote: https://github.com/scottjehl/picturefill
version: "3.0.3"
diff --git a/core/misc/date.es6.js b/core/misc/date.es6.js
index 97fde1825fe..a1862133f68 100644
--- a/core/misc/date.es6.js
+++ b/core/misc/date.es6.js
@@ -3,7 +3,7 @@
* Polyfill for HTML5 date input.
*/
-(function ($, Modernizr, Drupal) {
+(function ($, Modernizr, Drupal, once) {
/**
* Attach datepicker fallback on date elements.
*
@@ -15,32 +15,10 @@
*/
Drupal.behaviors.date = {
attach(context, settings) {
- const dataFieldElements = 'data-drupal-field-elements';
- const dataDatepickerProcessed = 'data-datepicker-is-processed';
-
- /**
- * Returns a CSS selector for a date field to process.
- *
- * The dataDatepickerProcessed attribute prevents a field from being
- * selected and processed more than once.
- *
- * @param {string} elements
- * The data attribute value.
- *
- * @return {string}
- * A CSS Selector.
- */
- const getDateSelector = (elements) =>
- [
- `[${dataFieldElements}="${elements}"]`,
- `:not([${dataDatepickerProcessed}="${elements}"])`,
- ].join('');
-
// If the browser does not support a native datepicker, add date
// formatting instructions on date/time fields.
if (Modernizr.inputtypes.date === false) {
- Array.prototype.forEach.call(
- document.querySelectorAll(getDateSelector('date-time')),
+ once('datepicker', '[data-drupal-field-elements="date-time"]').forEach(
(dateTime) => {
const dateInput = dateTime.querySelector('input[type="date"]');
const timeInput = dateTime.querySelector('input[type="time"]');
@@ -63,14 +41,10 @@
});
Drupal.DatepickerPolyfill.attachDescription(dateTime, help);
-
- // Set attribute to prevent element from being processed again.
- dateTime.setAttribute(dataDatepickerProcessed, 'date-time');
},
);
- Array.prototype.forEach.call(
- document.querySelectorAll(getDateSelector('date')),
+ once('datepicker', '[data-drupal-field-elements="date"]').forEach(
(date) => {
const dateInput = date.querySelector('input[type="date"]');
const help = Drupal.theme.dateHelp({
@@ -86,9 +60,6 @@
// changed to reflect this.
dateInput.setAttribute('type', 'text');
Drupal.DatepickerPolyfill.attachDescription(date, help, id);
-
- // Set attribute to prevent element from selection on next run.
- date.setAttribute(dataDatepickerProcessed, 'date');
},
);
}
@@ -180,4 +151,4 @@
`<div class="no-native-datepicker-help">
<span id="${dateId}">${dateDesc}</span> <span id="${timeId}">${timeDesc}</span>
</div>`;
-})(jQuery, Modernizr, Drupal);
+})(jQuery, Modernizr, Drupal, once);
diff --git a/core/misc/date.js b/core/misc/date.js
index 4cfa477eb9d..4ae1e561986 100644
--- a/core/misc/date.js
+++ b/core/misc/date.js
@@ -11,18 +11,11 @@ function _defineProperties(target, props) { for (var i = 0; i < props.length; i+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
-(function ($, Modernizr, Drupal) {
+(function ($, Modernizr, Drupal, once) {
Drupal.behaviors.date = {
attach: function attach(context, settings) {
- var dataFieldElements = 'data-drupal-field-elements';
- var dataDatepickerProcessed = 'data-datepicker-is-processed';
-
- var getDateSelector = function getDateSelector(elements) {
- return ["[".concat(dataFieldElements, "=\"").concat(elements, "\"]"), ":not([".concat(dataDatepickerProcessed, "=\"").concat(elements, "\"])")].join('');
- };
-
if (Modernizr.inputtypes.date === false) {
- Array.prototype.forEach.call(document.querySelectorAll(getDateSelector('date-time')), function (dateTime) {
+ once('datepicker', '[data-drupal-field-elements="date-time"]').forEach(function (dateTime) {
var dateInput = dateTime.querySelector('input[type="date"]');
var timeInput = dateTime.querySelector('input[type="time"]');
var help = Drupal.theme.dateTimeHelp({
@@ -36,9 +29,8 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
input.setAttribute('type', 'text');
});
Drupal.DatepickerPolyfill.attachDescription(dateTime, help);
- dateTime.setAttribute(dataDatepickerProcessed, 'date-time');
});
- Array.prototype.forEach.call(document.querySelectorAll(getDateSelector('date')), function (date) {
+ once('datepicker', '[data-drupal-field-elements="date"]').forEach(function (date) {
var dateInput = date.querySelector('input[type="date"]');
var help = Drupal.theme.dateHelp({
dateDesc: dateInput.dataset.help
@@ -47,7 +39,6 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
dateInput.setAttribute('aria-describedby', id);
dateInput.setAttribute('type', 'text');
Drupal.DatepickerPolyfill.attachDescription(date, help, id);
- date.setAttribute(dataDatepickerProcessed, 'date');
});
}
}
@@ -100,4 +91,4 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
timeDesc = _ref2.timeDesc;
return "<div class=\"no-native-datepicker-help\">\n <span id=\"".concat(dateId, "\">").concat(dateDesc, "</span> <span id=\"").concat(timeId, "\">").concat(timeDesc, "</span>\n </div>");
};
-})(jQuery, Modernizr, Drupal); \ No newline at end of file
+})(jQuery, Modernizr, Drupal, once); \ No newline at end of file
diff --git a/core/misc/polyfills/element.matches.es6.js b/core/misc/polyfills/element.matches.es6.js
new file mode 100644
index 00000000000..0b456325a73
--- /dev/null
+++ b/core/misc/polyfills/element.matches.es6.js
@@ -0,0 +1,17 @@
+/**
+ * @file
+ * Provides a polyfill for Element.prototype.matches().
+ *
+ * This is needed for Internet Explorer 9+
+ *
+ * This has been copied from MDN Web Docs code samples. Code samples in the MDN
+ * Web Docs are licensed under CC0.
+ *
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element/matches#Polyfill
+ * @see https://developer.mozilla.org/en-US/docs/MDN/About#Code_samples_and_snippets
+ */
+if (!Element.prototype.matches) {
+ Element.prototype.matches =
+ Element.prototype.msMatchesSelector ||
+ Element.prototype.webkitMatchesSelector;
+}
diff --git a/core/misc/polyfills/element.matches.js b/core/misc/polyfills/element.matches.js
new file mode 100644
index 00000000000..8fc544b4b64
--- /dev/null
+++ b/core/misc/polyfills/element.matches.js
@@ -0,0 +1,10 @@
+/**
+* DO NOT EDIT THIS FILE.
+* See the following change record for more information,
+* https://www.drupal.org/node/2815083
+* @preserve
+**/
+
+if (!Element.prototype.matches) {
+ Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
+} \ No newline at end of file
diff --git a/core/themes/claro/claro.libraries.yml b/core/themes/claro/claro.libraries.yml
index 5b178612db8..cde2ce22db1 100644
--- a/core/themes/claro/claro.libraries.yml
+++ b/core/themes/claro/claro.libraries.yml
@@ -208,6 +208,8 @@ autocomplete:
version: VERSION
js:
js/autocomplete.js: {}
+ dependencies:
+ - core/once
drupal.shortcut:
version: VERSION
diff --git a/core/themes/claro/js/autocomplete.es6.js b/core/themes/claro/js/autocomplete.es6.js
index 245529ba2c3..a7abf4da18e 100644
--- a/core/themes/claro/js/autocomplete.es6.js
+++ b/core/themes/claro/js/autocomplete.es6.js
@@ -3,13 +3,11 @@
* Claro's enhancement for autocomplete form element.
*/
-(($, Drupal) => {
+(($, Drupal, once) => {
Drupal.behaviors.claroAutoCompete = {
attach(context) {
- $(context)
- .find('input.form-autocomplete')
- .once('claroAutoComplete')
- .each((index, value) => {
+ once('claroAutoComplete', 'input.form-autocomplete', context).forEach(
+ (value) => {
const $input = $(value);
const timeout = 400;
let classRemoveTimeout;
@@ -37,7 +35,8 @@
);
},
);
- });
+ },
+ );
},
};
-})(jQuery, Drupal);
+})(jQuery, Drupal, once);
diff --git a/core/themes/claro/js/autocomplete.js b/core/themes/claro/js/autocomplete.js
index d86cc300463..79db89081fc 100644
--- a/core/themes/claro/js/autocomplete.js
+++ b/core/themes/claro/js/autocomplete.js
@@ -5,10 +5,10 @@
* @preserve
**/
-(function ($, Drupal) {
+(function ($, Drupal, once) {
Drupal.behaviors.claroAutoCompete = {
attach: function attach(context) {
- $(context).find('input.form-autocomplete').once('claroAutoComplete').each(function (index, value) {
+ once('claroAutoComplete', 'input.form-autocomplete', context).forEach(function (value) {
var $input = $(value);
var timeout = 400;
var classRemoveTimeout;
@@ -30,4 +30,4 @@
});
}
};
-})(jQuery, Drupal); \ No newline at end of file
+})(jQuery, Drupal, once); \ No newline at end of file