1/** 2 * Apply settings for jQuery Migrate from the jQuery Update module. 3 */ 4var Drupal = Drupal || { "settings": {}, "behaviors": {}, "locale": {} }; 5 6(function (jQuery, Drupal) { 7 Drupal.behaviors.jqueryUpdate = { 8 attach: function () { 9 if (Drupal.settings.jqueryUpdate !== undefined) { 10 jQuery.migrateMute = Drupal.settings.jqueryUpdate.migrateMute; 11 jQuery.migrateTrace = Drupal.settings.jqueryUpdate.migrateTrace; 12 } 13 } 14 }; 15})(jQuery, Drupal); 16; 17/*! jQuery Migrate v3.5.2 | (c) OpenJS Foundation and other contributors | jquery.com/license */ 18"undefined"==typeof jQuery.migrateMute&&(jQuery.migrateMute=!0),function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e,window)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery"),window):t(jQuery,window)}(function(s,n){"use strict";function e(e){return 0<=function(e,t){for(var r=/^(\d+)\.(\d+)\.(\d+)/,n=r.exec(e)||[],o=r.exec(t)||[],a=1;a<=3;a++){if(+o[a]<+n[a])return 1;if(+n[a]<+o[a])return-1}return 0}(s.fn.jquery,e)}s.migrateVersion="3.5.2";var t=Object.create(null);s.migrateDisablePatches=function(){for(var e=0;e<arguments.length;e++)t[arguments[e]]=!0},s.migrateEnablePatches=function(){for(var e=0;e<arguments.length;e++)delete t[arguments[e]]},s.migrateIsPatchEnabled=function(e){return!t[e]},n.console&&n.console.log&&(s&&e("3.0.0")&&!e("5.0.0")||n.console.log("JQMIGRATE: jQuery 3.x-4.x REQUIRED"),s.migrateWarnings&&n.console.log("JQMIGRATE: Migrate plugin loaded multiple times"),n.console.log("JQMIGRATE: Migrate is installed"+(s.migrateMute?"":" with logging active")+", version "+s.migrateVersion));var o={};function u(e,t){var r=n.console;!s.migrateIsPatchEnabled(e)||s.migrateDeduplicateWarnings&&o[t]||(o[t]=!0,s.migrateWarnings.push(t+" ["+e+"]"),r&&r.warn&&!s.migrateMute&&(r.warn("JQMIGRATE: "+t),s.migrateTrace&&r.trace&&r.trace()))}function r(e,t,r,n,o){Object.defineProperty(e,t,{configurable:!0,enumerable:!0,get:function(){return u(n,o),r},set:function(e){u(n,o),r=e}})}function a(e,t,r,n,o){var a=e[t];e[t]=function(){return o&&u(n,o),(s.migrateIsPatchEnabled(n)?r:a||s.noop).apply(this,arguments)}}function c(e,t,r,n,o){if(!o)throw new Error("No warning message provided");return a(e,t,r,n,o),0}function i(e,t,r,n){return a(e,t,r,n),0}s.migrateDeduplicateWarnings=!0,s.migrateWarnings=[],void 0===s.migrateTrace&&(s.migrateTrace=!0),s.migrateReset=function(){o={},s.migrateWarnings.length=0},"BackCompat"===n.document.compatMode&&u("quirks","jQuery is not compatible with Quirks Mode");var d,l,p,f={},m=s.fn.init,y=s.find,g=/\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/,h=/\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g,v=/^[\s\uFEFF\xA0]+|([^\s\uFEFF\xA0])[\s\uFEFF\xA0]+$/g;for(d in i(s.fn,"init",function(e){var t=Array.prototype.slice.call(arguments);return s.migrateIsPatchEnabled("selector-empty-id")&&"string"==typeof e&&"#"===e&&(u("selector-empty-id","jQuery( '#' ) is not a valid selector"),t[0]=[]),m.apply(this,t)},"selector-empty-id"),s.fn.init.prototype=s.fn,i(s,"find",function(t){var r=Array.prototype.slice.call(arguments);if("string"==typeof t&&g.test(t))try{n.document.querySelector(t)}catch(e){t=t.replace(h,function(e,t,r,n){return"["+t+r+'"'+n+'"]'});try{n.document.querySelector(t),u("selector-hash","Attribute selector with '#' must be quoted: "+r[0]),r[0]=t}catch(e){u("selector-hash","Attribute selector with '#' was not fixed: "+r[0])}}return y.apply(this,r)},"selector-hash"),y)Object.prototype.hasOwnProperty.call(y,d)&&(s.find[d]=y[d]);c(s.fn,"size",function(){return this.length},"size","jQuery.fn.size() is deprecated and removed; use the .length property"),c(s,"parseJSON",function(){return JSON.parse.apply(null,arguments)},"parseJSON","jQuery.parseJSON is deprecated; use JSON.parse"),c(s,"holdReady",s.holdReady,"holdReady","jQuery.holdReady is deprecated"),c(s,"unique",s.uniqueSort,"unique","jQuery.unique is deprecated; use jQuery.uniqueSort"),r(s.expr,"filters",s.expr.pseudos,"expr-pre-pseudos","jQuery.expr.filters is deprecated; use jQuery.expr.pseudos"),r(s.expr,":",s.expr.pseudos,"expr-pre-pseudos","jQuery.expr[':'] is deprecated; use jQuery.expr.pseudos"),e("3.1.1")&&c(s,"trim",function(e){return null==e?"":(e+"").replace(v,"$1")},"trim","jQuery.trim is deprecated; use String.prototype.trim"),e("3.2.0")&&(c(s,"nodeName",function(e,t){return e.no
18deName&&e.nodeName.toLowerCase()===t.toLowerCase()},"nodeName","jQuery.nodeName is deprecated"),c(s,"isArray",Array.isArray,"isArray","jQuery.isArray is deprecated; use Array.isArray")),e("3.3.0")&&(c(s,"isNumeric",function(e){var t=typeof e;return("number"==t||"string"==t)&&!isNaN(e-parseFloat(e))},"isNumeric","jQuery.isNumeric() is deprecated"),s.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){f["[object "+t+"]"]=t.toLowerCase()}),c(s,"type",function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?f[Object.prototype.toString.call(e)]||"object":typeof e},"type","jQuery.type is deprecated"),c(s,"isFunction",function(e){return"function"==typeof e},"isFunction","jQuery.isFunction() is deprecated"),c(s,"isWindow",function(e){return null!=e&&e===e.window},"isWindow","jQuery.isWindow() is deprecated")),s.ajax&&(l=s.ajax,p=/(=)\?(?=&|$)|\?\?/,i(s,"ajax",function(){var e=l.apply(this,arguments);return e.promise&&(c(e,"success",e.done,"jqXHR-methods","jQXHR.success is deprecated and removed"),c(e,"error",e.fail,"jqXHR-methods","jQXHR.error is deprecated and removed"),c(e,"complete",e.always,"jqXHR-methods","jQXHR.complete is deprecated and removed")),e},"jqXHR-methods"),e("4.0.0")||s.ajaxPrefilter("+json",function(e){!1!==e.jsonp&&(p.test(e.url)||"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&p.test(e.data))&&u("jsonp-promotion","JSON-to-JSONP auto-promotion is deprecated")}));var j=s.fn.removeAttr,b=s.fn.toggleClass,Q=/^(?:checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped)$/i,w=/\S+/g;function x(e){return e.replace(/-([a-z])/g,function(e,t){return t.toUpperCase()})}i(s.fn,"removeAttr",function(e){var r=this,n=!1;return s.each(e.match(w),function(e,t){Q.test(t)&&r.each(function(){if(!1!==s(this).prop(t))return!(n=!0)}),n&&(u("removeAttr-bool","jQuery.fn.removeAttr no longer sets boolean properties: "+t),r.prop(t,!1))}),j.apply(this,arguments)},"removeAttr-bool"),i(s.fn,"toggleClass",function(t){return void 0!==t&&"boolean"!=typeof t?b.apply(this,arguments):(u("toggleClass-bool","jQuery.fn.toggleClass( boolean ) is deprecated"),this.each(function(){var e=this.getAttribute&&this.getAttribute("class")||"";e&&s.data(this,"__className__",e),this.setAttribute&&this.setAttribute("class",!e&&!1!==t&&s.data(this,"__className__")||"")}))},"toggleClass-bool");var A,R,S=!1,k=/^[a-z]/,N=/^(?:Border(?:Top|Right|Bottom|Left)?(?:Width|)|(?:Margin|Padding)?(?:Top|Right|Bottom|Left)?|(?:Min|Max)?(?:Width|Height))$/;s.swap&&s.each(["height","width","reliableMarginRight"],function(e,t){var r=s.cssHooks[t]&&s.cssHooks[t].get;r&&(s.cssHooks[t].get=function(){var e;return S=!0,e=r.apply(this,arguments),S=!1,e})}),i(s,"swap",function(e,t,r,n){var o,a,i={};for(a in S||u("swap","jQuery.swap() is undocumented and deprecated"),t)i[a]=e.style[a],e.style[a]=t[a];for(a in o=r.apply(e,n||[]),t)e.style[a]=i[a];return o},"swap"),e("3.4.0")&&"undefined"!=typeof Proxy&&(s.cssProps=new Proxy(s.cssProps||{},{set:function(){return u("cssProps","jQuery.cssProps is deprecated"),Reflect.set.apply(this,arguments)}})),e("4.0.0")?(R={animationIterationCount:!0,aspectRatio:!0,borderImageSlice:!0,columnCount:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,scale:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeMiterlimit:!0,strokeOpacity:!0},"undefined"!=typeof Proxy?s.cssNumber=new Proxy(R,{get:function(){return u("css-number","jQuery.cssNumber is deprecated"),Reflect.get.apply(this,arguments)},set:function(){return u("css-number","jQuery.cssNumber is deprecated"),Reflect.set.apply(this,arguments)}}):s.cssNumber=R):R=s.cssNumber,A=s.fn.css,i(s.fn,"css",function(e,t){var r,n,o=this;return e&&"object"==typeof e&&!Array.isArray(e)?(s.each(e,function(e,t){s.fn.css.call(o,e,t)}),this):("number"==typeof t&&(r=x(e),n=r,k.test(n)&&N.test(n[0].toUpperCase()+n.slice(1))||R[r]||u("css-number",'Number-typed values are deprecated for jQuery.fn.css( "'+e+'", value )')),A.apply(this,arguments))},"css-number");var P,C,H,E,M=s.data;i(s,"data",function(e,t,r){var n,o,a;if(t&&"object"==typeof t&&2===arguments.length){for(a in n=s.hasData(e)&&M.call(this,e),o={},t)a!==x(a)?(u("data-camelCase","jQuery.data() always sets/gets camelCased names: "+a),n[a]=t[a]):o[a]=t[a];return M.call(this,e,o),t}return t&&"string"==typeof t&&t!==x(t)&&(n=s.hasData(e)&&M.call(this,e))&&t in n?(u("data-camelCase","jQuery.data() always sets/gets camelCased names: "+t),2<arguments.length&&(n[t]=r),n[t]):M.apply(this,arguments)},"data-camelCase"),s.fx&&(H=s.Tween.prototype.run,E=function(e){return e},i(s.Tween.prototype,"run",function(){1<s.easing[this.easing].length&&(u("easing-one-arg","'jQuery.easing."+this.easing.toString()+"' should use only one argument"),s.easing[this.easing]=E),H.apply(this,arguments)},"easing-one-arg"),P=s.fx.interval,C="jQuery.fx.interval is deprecated",n.requestAnimationFrame&&Object.defineProperty(s.fx,"interval",{configurable:!0,enumerable:!0,get:function(){return n.document.hidden||u("fx-interval",C),s.migrateIsPatchEnabled("fx-interval")&&void 0===P?13:P},set:function(e){u("fx-interval",C),P=e}}));var q=s.fn.load,O=s.event.add,F=s.event.fix;s.event.props=[],s.event.fixHooks={}
18,r(s.event.props,"concat",s.event.props.concat,"event-old-patch","jQuery.event.props.concat() is deprecated and removed"),i(s.event,"fix",function(e){var t,r=e.type,n=this.fixHooks[r],o=s.event.props;if(o.length){u("event-old-patch","jQuery.event.props are deprecated and removed: "+o.join());while(o.length)s.event.addProp(o.pop())}if(n&&!n._migrated_&&(n._migrated_=!0,u("event-old-patch","jQuery.event.fixHooks are deprecated and removed: "+r),(o=n.props)&&o.length))while(o.length)s.event.addProp(o.pop());return t=F.call(this,e),n&&n.filter?n.filter(t,e):t},"event-old-patch"),i(s.event,"add",function(e,t){return e===n&&"load"===t&&"complete"===n.document.readyState&&u("load-after-event","jQuery(window).on('load'...) called after load event occurred"),O.apply(this,arguments)},"load-after-event"),s.each(["load","unload","error"],function(e,t){i(s.fn,t,function(){var e=Array.prototype.slice.call(arguments,0);return"load"===t&&"string"==typeof e[0]?q.apply(this,e):(u("shorthand-removed-v3","jQuery.fn."+t+"() is deprecated"),e.splice(0,0,t),arguments.length?this.on.apply(this,e):(this.triggerHandler.apply(this,e),this))},"shorthand-removed-v3")}),s.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,r){c(s.fn,r,function(e,t){return 0<arguments.length?this.on(r,null,e,t):this.trigger(r)},"shorthand-deprecated-v3","jQuery.fn."+r+"() event shorthand is deprecated")}),s(function(){s(n.document).triggerHandler("ready")}),s.event.special.ready={setup:function(){this===n.document&&u("ready-event","'ready' event is deprecated")}},c(s.fn,"bind",function(e,t,r){return this.on(e,null,t,r)},"pre-on-methods","jQuery.fn.bind() is deprecated"),c(s.fn,"unbind",function(e,t){return this.off(e,null,t)},"pre-on-methods","jQuery.fn.unbind() is deprecated"),c(s.fn,"delegate",function(e,t,r,n){return this.on(t,e,r,n)},"pre-on-methods","jQuery.fn.delegate() is deprecated"),c(s.fn,"undelegate",function(e,t,r){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",r)},"pre-on-methods","jQuery.fn.undelegate() is deprecated"),c(s.fn,"hover",function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)},"pre-on-methods","jQuery.fn.hover() is deprecated");function T(e){var t=n.document.implementation.createHTMLDocument("");return t.body.innerHTML=e,t.body&&t.body.innerHTML}var D=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi;c(s,"UNSAFE_restoreLegacyHtmlPrefilter",function(){s.migrateEnablePatches("self-closed-tags")},"legacy-self-closed-tags",'jQuery.UNSAFE_restoreLegacyHtmlPrefilter deprecated; use `jQuery.migrateEnablePatches( "self-closed-tags" )`'),i(s,"htmlPrefilter",function(e){var t,r;return(r=(t=e).replace(D,"<$1></$2>"))!==t&&T(t)!==T(r)&&u("self-closed-tags","HTML tags must be properly nested and closed: "+t),e.replace(D,"<$1></$2>")},"self-closed-tags"),s.migrateDisablePatches("self-closed-tags");var _,I,W,J=s.fn.offset;return i(s.fn,"offset",function(){var e=this[0];return!e||e.nodeType&&e.getBoundingClientRect?J.apply(this,arguments):(u("offset-valid-elem","jQuery.fn.offset() requires a valid DOM element"),arguments.length?this:void 0)},"offset-valid-elem"),s.ajax&&(_=s.param,i(s,"param",function(e,t){var r=s.ajaxSettings&&s.ajaxSettings.traditional;return void 0===t&&r&&(u("param-ajax-traditional","jQuery.param() no longer uses jQuery.ajaxSettings.traditional"),t=r),_.call(this,e,t)},"param-ajax-traditional")),c(s.fn,"andSelf",s.fn.addBack,"andSelf","jQuery.fn.andSelf() is deprecated and removed, use jQuery.fn.addBack()"),s.Deferred&&(I=s.Deferred,W=[["resolve","done",s.Callbacks("once memory"),s.Callbacks("once memory"),"resolved"],["reject","fail",s.Callbacks("once memory"),s.Callbacks("once memory"),"rejected"],["notify","progress",s.Callbacks("memory"),s.Callbacks("memory")]],i(s,"Deferred",function(e){var a=I(),i=a.promise();function t(){var o=arguments;return s.Deferred(function(n){s.each(W,function(e,t){var r="function"==typeof o[e]&&o[e];a[t[1]](function(){var e=r&&r.apply(this,arguments);e&&"function"==typeof e.promise?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[t[0]+"With"](this===i?n.promise():this,r?[e]:arguments)})}),o=null}).promise()}return c(a,"pipe",t,"deferred-pipe","deferred.pipe() is deprecated"),c(i,"pipe",t,"deferred-pipe","deferred.pipe() is deprecated"),e&&e.call(a,a),a},"deferred-pipe"),s.Deferred.exceptionHook=I.exceptionHook),s}); 19; 20/** 21 * For jQuery versions less than 3.4.0, this replaces the jQuery.extend 22 * function with the one from jQuery 3.4.0, slightly modified (documented 23 * below) to be compatible with older jQuery versions and browsers. 24 * 25 * This provides the Object.prototype pollution vulnerability fix to Drupal 26 * installations running older jQuery versions, including the versions shipped 27 * with Drupal core and https://www.drupal.org/project/jquery_update. 28 * 29 * @see https://github.com/jquery/jquery/pull/4333 30 */ 31 32(function (jQuery) { 33 34// Do not override jQuery.extend() if the jQuery version is already >=3.4.0. 35var versionParts = jQuery.fn.jquery.split('.'); 36var majorVersion = parseInt(versionParts[0]); 37var minorVersion = parseInt(versionParts[1]); 38var patchVersion = parseInt(versionParts[2]); 39var isPreReleaseVersion = (patchVersion.toString() !== versionParts[2]); 40if ( 41 (majorVersion > 3) || 42 (majorVersion === 3 && minorVersion > 4) || 43 (majorVersion === 3 && minorVersion === 4 && patchVersion > 0) || 44 (majorVersion === 3 && minorVersion === 4 && patchVersion === 0 && !isPreReleaseVersion) 45) { 46 return; 47} 48 49/** 50 * This is almost verbatim copied from jQuery 3.4.0. 51 * 52 * Only two minor changes have been made: 53 * - The call to isFunction() is changed to jQuery.isFunction(). 54 * - The two calls to Array.isArray() is changed to jQuery.isArray(). 55 * 56 * The above two changes ensure compatibility with all older jQuery versions 57 * (1.4.4 - 3.3.1) and older browser versions (e.g., IE8). 58 */ 59jQuery.extend = jQuery.fn.extend = function() { 60 var options, name, src, copy, copyIsArray, clone, 61 target = arguments[ 0 ] || {}, 62 i = 1, 63 length = arguments.length, 64 deep = false;
65 66 // Handle a deep copy situation 67 if ( typeof target === "boolean" ) { 68 deep = target; 69 70 // Skip the boolean and the target 71 target = arguments[ i ] || {}; 72 i++; 73 } 74 75 // Handle case when target is a string or something (possible in deep copy) 76 if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { 77 target = {}; 78 } 79 80 // Extend jQuery itself if only one argument is passed 81 if ( i === length ) { 82 target = this; 83 i--; 84 } 85 86 for ( ; i < length; i++ ) { 87 88 // Only deal with non-null/undefined values 89 if ( ( options = arguments[ i ] ) != null ) { 90 91 // Extend the base object 92 for ( name in options ) { 93 copy = options[ name ]; 94 95 // Prevent Object.prototype pollution 96 // Prevent never-ending loop 97 if ( name === "__proto__" || target === copy ) { 98 continue; 99 } 100 101 // Recurse if we're merging plain objects or arrays 102 if ( deep && copy && ( jQuery.isPlainObject( copy ) || 103 ( copyIsArray = jQuery.isArray( copy ) ) ) ) { 104 src = target[ name ]; 105 106 // Ensure proper type for the source value 107 if ( copyIsArray && !jQuery.isArray( src ) ) { 108 clone = []; 109 } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { 110 clone = {}; 111 } else { 112 clone = src; 113 } 114 copyIsArray = false; 115 116 // Never move original objects, clone them 117 target[ name ] = jQuery.extend( deep, clone, copy ); 118 119 // Don't bring in undefined values 120 } else if ( copy !== undefined ) { 121 target[ name ] = copy; 122 } 123 } 124 } 125 } 126 127 // Return the modified object 128 return target; 129}; 130 131})(jQuery); 132; 133/** 134 * For jQuery versions less than 3.5.0, this replaces the jQuery.htmlPrefilter() 135 * function with one that fixes these security vulnerabilities while also 136 * retaining the pre-3.5.0 behavior where it's safe to do so. 137 * - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11022 138 * - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11023 139 * 140 * Additionally, for jQuery versions that do not have a jQuery.htmlPrefilter() 141 * function (1.x prior to 1.12 and 2.x prior to 2.2), this adds it, and 142 * extends the functions that need to call it to do so. 143 * 144 * Drupal core's jQuery version is 1.4.4, but jQuery Update can provide a 145 * different version, so this covers all versions between 1.4.4 and 3.4.1. 146 * The GitHub links in the code comments below link to jQuery 1.5 code, because 147 * 1.4.4 isn't on GitHub, but the referenced code didn't change from 1.4.4 to 148 * 1.5. 149 */ 150 151(function (jQuery) { 152 153 // Parts of this backport differ by jQuery version. 154 var versionParts = jQuery.fn.jquery.split('.'); 155 var majorVersion = parseInt(versionParts[0]); 156 var minorVersion = parseInt(versionParts[1]); 157 158 // No backport is needed if we're already on jQuery 3.5 or higher. 159 if ( (majorVersion > 3) || (majorVersion === 3 && minorVersion >= 5) ) { 160 return; 161 } 162 163 // Prior to jQuery 3.5, jQuery converted XHTML-style self-closing tags to 164 // their XML equivalent: e.g., "<div />" to "<div></div>". This is 165 // problematic for several reasons, including that it's vulnerable to XSS 166 // attacks. However, since this was jQuery's behavior for many years, many 167 // Drupal modules and jQuery plugins may be relying on it. Therefore, we 168 // preserve that behavior, but for a limited set of tags only, that we believe 169 // to not be vulnerable. This is the set of HTML tags that satisfy all of the 170 // following conditions: 171 // - In DOMPurify's list of HTML tags. If an HTML tag isn't safe enough to 172 // appear in that list, then we don't want to mess with it here either. 173 // @see https://github.com/cure53/DOMPurify/blob/2.0.11/dist/purify.js#L128 174 // - A normal element (not a void, template, text, or foreign element). 175 // @see https://html.spec.whatwg.org/multipage/syntax.html#elements-2 176 // - An element that is still defined by the current HTML specification 177 // (not a deprecated element), because we do not want to rely on how 178 // browsers parse deprecated elements. 179 // @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element 180 // - Not 'html', 'head', or 'body', because this pseudo-XHTML expansion is 181 // designed for fragments, not entire documents. 182 // - Not 'colgroup', because due to an idiosyncrasy of jQuery's original 183 // regular expression, it didn't match on colgroup, and we don't want to 184 // introduce a behavior change for that. 185 var selfClosingTagsToReplace = [ 186 'a', 'abbr', 'address', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 187 'blockquote', 'button', 'canvas', 'caption', 'cite', 'code', 'data', 188 'datalist', 'dd', 'del', 'details', 'dfn', 'div', 'dl', 'dt', 'em', 189 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 190 'h4', 'h5', 'h6', 'header', 'hgroup', 'i', 'ins', 'kbd', 'label', 'legend', 191 'li', 'main', 'map', 'mark', 'menu', 'meter', 'nav', 'ol', 'optgroup', 192 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 193 'ruby', 's', 'samp', 'section', 'select', 'small', 'source', 'span', 194 'strong', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 195 'thead', 'time', 'tr', 'u', 'ul', 'var', 'video' 196 ]; 197 198 // Define regular expressions for <TAG/> and <TAG ATTRIBUTES/>. Doing this as 199 // two expressions makes it easier to target <a/> without also targeting 200 // every tag that starts with "a". 201 var xhtmlRegExpGroup = '(' + selfClosingTagsToReplace.join('|') + ')'; 202 var whitespace = '[\\x20\\t\\r\\n\\f]'; 203 var rxhtmlTagWithoutSpaceOrAttributes = new RegExp('<' + xhtmlRegExpGroup + '\\/>', 'gi'); 204 var rxhtmlTagWithSpaceAndMaybeAttributes = new RegExp('<' + xhtmlRegExpGroup + '(' + whitespace + '[^>]*)\\/>', 'gi'); 205 206 // jQuery 3.5 also fixed a vulnerability for when </select> appears within 207 // an <option> or <optgroup>, but it did that in local code that we can't 208 // backport directly. Instead, we filter such cases out. To do so, we need to 209 // determine when jQuery would otherwise invoke the vulnerable code, which it 210 // uses this regular expression to determine. The regular expression changed 211 // for version 3.0.0 and changed again for 3.4.0. 212 // @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L4958 213 // @see https://github.com/jquery/jquery/blob/3.0.0/dist/jquery.js#L4584 214 // @see https://github.com/jquery/jquery/blob/3.4.0/dist/jquery.js#L4712 215 var rtagName; 216 if (majorVersion < 3) { 217 rtagName = /<([\w:]+)/; 218 } 219 else if (minorVersion < 4) { 220 rtagName = /<([a-z][^\/\0>\x20\t\r\n\f]+)/i; 221 } 222 else { 223 rtagName = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i; 224 } 225 226 // The regular expression that jQuery uses to determine which self-closing 227 // tags to expand to open and close tags. This is vulnerable, because it 228 // matches all tag names except the few excluded ones. We only use this 229 // expression for determining vulnerability. The expression changed for 230 // version 3, but we only need to check for vulnerability in versions 1 and 2, 231 // so we use the expression from those versions. 232 // @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L4957 233 var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi; 234 235 jQuery.extend({ 236 htmlPrefilter: function (html) { 237 // This is how jQuery determines the first tag in the HTML. 238 // @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L5521 239 var tag = ( rtagName.exec( html ) || [ "", "" ] )[ 1 ].toLowerCase(); 240
241 // It is not valid HTML for <option> or <optgroup> to have <select> as 242 // either a descendant or sibling, and attempts to inject one can cause 243 // XSS on jQuery versions before 3.5. Since this is invalid HTML and a 244 // possible XSS attack, reject the entire string. 245 // @see https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11023 246 if ((tag === 'option' || tag === 'optgroup') && html.match(/<\/?select/i)) { 247 html = ''; 248 } 249 250 // Retain jQuery's prior to 3.5 conversion of pseudo-XHTML, but for only 251 // the tags in the `selfClosingTagsToReplace` list defined above. 252 // @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L5518 253 // @see https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11022 254 html = html.replace(rxhtmlTagWithoutSpaceOrAttributes, "<$1></$1>"); 255 html = html.replace(rxhtmlTagWithSpaceAndMaybeAttributes, "<$1$2></$1>"); 256 257 // Prior to jQuery 1.12 and 2.2, this function gets called (via code later 258 // in this file) in addition to, rather than instead of, the unsafe 259 // expansion of self-closing tags (including ones not in the list above). 260 // We can't prevent that unsafe expansion from running, so instead we 261 // check to make sure that it doesn't affect the DOM returned by the 262 // browser's parsing logic. If it does affect it, then it's vulnerable to 263 // XSS, so we reject the entire string. 264 if ( (majorVersion === 1 && minorVersion < 12) || (majorVersion === 2 && minorVersion < 2) ) { 265 var htmlRisky = html.replace(rxhtmlTag, "<$1></$2>"); 266 if (htmlRisky !== html) { 267 // Even though htmlRisky and html are different strings, they might 268 // represent the same HTML structure once parsed, in which case, 269 // htmlRisky is actually safe. We can ask the browser to parse both 270 // to find out, but the browser can't parse table fragments (e.g., a 271 // root-level "<td>"), so we need to wrap them. We just need this 272 // technique to work on all supported browsers; we don't need to 273 // copy from the specific jQuery version we're using. 274 // @see https://github.com/jquery/jquery/blob/3.5.1/dist/jquery.js#L4939 275 var wrapMap = { 276 thead: [ 1, "<table>", "</table>" ], 277 col: [ 2, "<table><colgroup>", "</colgroup></table>" ], 278 tr: [ 2, "<table><tbody>", "</tbody></table>" ], 279 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], 280 }; 281 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; 282 wrapMap.th = wrapMap.td; 283 284 // Function to wrap HTML into something that a browser can parse. 285 // @see https://github.com/jquery/jquery/blob/3.5.1/dist/jquery.js#L5032 286 var getWrappedHtml = function (html) { 287 var wrap = wrapMap[tag]; 288 if (wrap) { 289 html = wrap[1] + html + wrap[2]; 290 } 291 return html; 292 }; 293 294 // Function to return canonical HTML after parsing it. This parses 295 // only; it doesn't execute scripts. 296 // @see https://github.com/jquery/jquery-migrate/blob/3.3.0/src/jquery/manipulation.js#L5 297 var getParsedHtml = function (html) { 298 var doc = window.document.implementation.createHTMLDocument( "" ); 299 doc.body.innerHTML = html; 300 return doc.body ? doc.body.innerHTML : ''; 301 }; 302 303 // If the browser couldn't parse either one successfully, or if 304 // htmlRisky parses differently than html, then html is vulnerable, 305 // so reject it. 306 var htmlParsed = getParsedHtml(getWrappedHtml(html)); 307 var htmlRiskyParsed = getParsedHtml(getWrappedHtml(htmlRisky)); 308 if (htmlRiskyParsed === '' || htmlParsed === '' || (htmlRiskyParsed !== htmlParsed)) { 309 html = ''; 310 } 311 } 312 } 313 314 return html; 315 } 316 }); 317 318 // Prior to jQuery 1.12 and 2.2, jQuery.clean(), jQuery.buildFragment(), and 319 // jQuery.fn.html() did not call jQuery.htmlPrefilter(), so we add that. 320 if ( (majorVersion === 1 && minorVersion < 12) || (majorVersion === 2 && minorVersion < 2) ) { 321 // Filter the HTML coming into jQuery.fn.html(). 322 var fnOriginalHtml = jQuery.fn.html; 323 jQuery.fn.extend({ 324 // @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L5147 325 html: function (value) { 326 if (typeof value === "string") { 327 value = jQuery.htmlPrefilter(value); 328 } 329 // .html() can be called as a setter (with an argument) or as a getter 330 // (without an argument), so invoke fnOriginalHtml() the same way that 331 // we were invoked. 332 return fnOriginalHtml.apply(this, arguments.length ? [value] : []); 333 } 334 }); 335 336 // The regular expression that jQuery uses to determine if a string is HTML. 337 // Used by both clean() and buildFragment(). 338 // @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L4960
339 var rhtml = /<|&#?\w+;/; 340 341 // Filter HTML coming into: 342 // - jQuery.clean() for versions prior to 1.9. 343 // - jQuery.buildFragment() for 1.9 and above. 344 // 345 // The looping constructs in the two functions might be essentially 346 // identical, but they're each expressed here in the way that most closely 347 // matches their original expression in jQuery, so that we filter all of 348 // the items and only the items that jQuery will treat as HTML strings. 349 if (majorVersion === 1 && minorVersion < 9) { 350 var originalClean = jQuery.clean; 351 jQuery.extend({ 352 // @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L5493 353 'clean': function (elems, context, fragment, scripts) { 354 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { 355 if ( typeof elem === "string" && rhtml.test( elem ) ) { 356 elems[i] = elem = jQuery.htmlPrefilter(elem); 357 } 358 } 359 return originalClean.call(this, elems, context, fragment, scripts); 360 } 361 }); 362 } 363 else { 364 var originalBuildFragment = jQuery.buildFragment; 365 jQuery.extend({ 366 // @see https://github.com/jquery/jquery/blob/1.9.0/jquery.js#L6419 367 'buildFragment': function (elems, context, scripts, selection) { 368 var l = elems.length; 369 for ( var i = 0; i < l; i++ ) { 370 var elem = elems[i]; 371 if (elem || elem === 0) { 372 if ( jQuery.type( elem ) !== "object" && rhtml.test( elem ) ) { 373 elems[i] = elem = jQuery.htmlPrefilter(elem); 374 } 375 } 376 } 377 return originalBuildFragment.call(this, elems, context, scripts, selection); 378 } 379 }); 380 } 381 } 382 383})(jQuery); 384; 385 386/** 387 * jQuery Once Plugin v1.2 388 * http://plugins.jquery.com/project/once 389 * 390 * Dual licensed under the MIT and GPL licenses: 391 * http://www.opensource.org/licenses/mit-license.php 392 * http://www.gnu.org/licenses/gpl.html 393 */ 394 395(function ($) { 396 var cache = {}, uuid = 0; 397 398 /** 399 * Filters elements by whether they have not yet been processed. 400 * 401 * @param id 402 * (Optional) If this is a string, then it will be used as the CSS class 403 * name that is applied to the elements for determining whether it has 404 * already been processed. The elements will get a class in the form of 405 * "id-processed". 406 * 407 * If the id parameter is a function, it will be passed off to the fn 408 * parameter and the id will become a unique identifier, represented as a 409 * number. 410 * 411 * When the id is neither a string or a function, it becomes a unique 412 * identifier, depicted as a number. The element's class will then be 413 * represented in the form of "jquery-once-#-processed". 414 * 415 * Take note that the id must be valid for usage as an element's class name. 416 * @param fn 417 * (Optional) If given, this function will be called for each element that 418 * has not yet been processed. The function's return value follows the same 419 * logic as $.each(). Returning true will continue to the next matched 420 * element in the set, while returning false will entirely break the 421 * iteration. 422 */ 423 $.fn.once = function (id, fn) { 424 if (typeof id != 'string') { 425 // Generate a numeric ID if the id passed can't be used as a CSS class. 426 if (!(id in cache)) { 427 cache[id] = ++uuid; 428 } 429 // When the fn parameter is not passed, we interpret it from the id. 430 if (!fn) { 431 fn = id; 432 } 433 id = 'jquery-once-' + cache[id]; 434 } 435 // Remove elements from the set that have already been processed. 436 var name = id + '-processed'; 437 var elements = this.not('.' + name).addClass(name); 438 439 return $.isFunction(fn) ? elements.each(fn) : elements; 440 }; 441 442 /** 443 * Filters elements that have been processed once already. 444 * 445 * @param id 446 * A required string representing the name of the class which should be used 447 * when filtering the elements. This only filters elements that have already 448 * been processed by the once function. The id should be the same id that 449 * was originally passed to the once() function. 450 * @param fn 451 * (Optional) If given, this function will be called for each element that 452 * has not yet been processed. The function's return value follows the same 453 * logic as $.each(). Returning true will continue to the next matched 454 * element in the set, while returning false will entirely break the 455 * iteration. 456 */ 457 $.fn.removeOnce = function (id, fn) { 458 var name = id + '-processed'; 459 var elements = this.filter('.' + name).removeClass(name); 460 461 return $.isFunction(fn) ? elements.each(fn) : elements; 462 }; 463})(jQuery); 464; 465 466var Drupal = Drupal || { 'settings': {}, 'behaviors': {}, 'locale': {} }; 467 468// Allow other JavaScript libraries to use $. 469jQuery.noConflict(); 470 471(function ($) { 472 473/** 474 * Override jQuery.fn.init to guard against XSS attacks. 475 * 476 * See http://bugs.jquery.com/ticket/9521 477 */ 478var jquery_init = $.fn.init; 479$.fn.init = function (selector, context, rootjQuery) { 480 // If the string contains a "#" before a "<", treat it as invali
480d HTML. 481 if (selector && typeof selector === 'string') { 482 var hash_position = selector.indexOf('#'); 483 if (hash_position >= 0) { 484 var bracket_position = selector.indexOf('<'); 485 if (bracket_position > hash_position) { 486 throw 'Syntax error, unrecognized expression: ' + selector; 487 } 488 } 489 } 490 return jquery_init.call(this, selector, context, rootjQuery); 491}; 492$.fn.init.prototype = jquery_init.prototype; 493 494/** 495 * Pre-filter Ajax requests to guard against XSS attacks. 496 * 497 * See https://github.com/jquery/jquery/issues/2432 498 */ 499if ($.ajaxPrefilter) { 500 // For newer versions of jQuery, use an Ajax prefilter to prevent 501 // auto-executing script tags from untrusted domains. This is similar to the 502 // fix that is built in to jQuery 3.0 and higher. 503 $.ajaxPrefilter(function (s) { 504 if (s.crossDomain) { 505 s.contents.script = false; 506 } 507 }); 508} 509else if ($.httpData) { 510 // For the version of jQuery that ships with Drupal core, override 511 // jQuery.httpData to prevent auto-detecting "script" data types from 512 // untrusted domains. 513 var jquery_httpData = $.httpData; 514 $.httpData = function (xhr, type, s) { 515 // @todo Consider backporting code from newer jQuery versions to check for 516 // a cross-domain request here, rather than using Drupal.urlIsLocal() to 517 // block scripts from all URLs that are not on the same site. 518 if (!type && !Drupal.urlIsLocal(s.url)) { 519 var content_type = xhr.getResponseHeader('content-type') || ''; 520 if (content_type.indexOf('javascript') >= 0) { 521 // Default to a safe data type. 522 type = 'text'; 523 } 524 } 525 return jquery_httpData.call(this, xhr, type, s); 526 }; 527 $.httpData.prototype = jquery_httpData.prototype; 528} 529 530/** 531 * Attach all registered behaviors to a page element. 532 * 533 * Behaviors are event-triggered actions that attach to page elements, enhancing 534 * default non-JavaScript UIs. Behaviors are registered in the Drupal.behaviors 535 * object using the method 'attach' and optionally also 'detach' as follows: 536 * @code 537 * Drupal.behaviors.behaviorName = { 538 * attach: function (context, settings) { 539 * ... 540 * }, 541 * detach: function (context, settings, trigger) { 542 * ... 543 * } 544 * }; 545 * @endcode 546 * 547 * Drupal.attachBehaviors is added below to the jQuery ready event and so 548 * runs on initial page load. Developers implementing AHAH/Ajax in their 549 * solutions should also call this function after new page content has been 550 * loaded, feeding in an element to be processed, in order to attach all 551 * behaviors to the new content. 552 * 553 * Behaviors should use 554 * @code 555 * $(selector).once('behavior-name', function () { 556 * ... 557 * }); 558 * @endcode 559 * to ensure the behavior is attached only once to a given element. (Doing so 560 * enables the reprocessing of given elements, which may be needed on occasion 561 * despite the ability to limit behavior attachment to a particular element.) 562 * 563 * @param context 564 * An element to attach behaviors to. If none is given, the document element 565 * is used. 566 * @param settings 567 * An object containing settings for the current context. If none given, the 568 * global Drupal.settings object is used. 569 */ 570Drupal.attachBehaviors = function (context, settings) { 571 context = context || document; 572 settings = settings || Drupal.settings; 573 // Execute all of them. 574 $.each(Drupal.behaviors, function () { 575 if ($.isFunction(this.attach)) { 576 this.attach(context, settings); 577 } 578 }); 579}; 580 581/** 582 * Detach registered behaviors from a page element. 583 * 584 * Developers implementing AHAH/Ajax in their solutions should call this 585 * function before page content is about to be removed, feeding in an element 586 * to be processed, in order to allow special behaviors to detach from the 587 * content. 588 * 589 * Such implementations should look for the class name that was added in their 590 * corresponding Drupal.behaviors.behaviorName.attach implementation, i.e. 591 * behaviorName-processed, to ensure the behavior is detached only from 592 * previously processed elements. 593 * 594 * @param context 595 * An element to detach behaviors from. If none is given, the document element 596 * is used. 597 * @param settings
598 * An object containing settings for the current context. If none given, the 599 * global Drupal.settings object is used. 600 * @param trigger 601 * A string containing what's causing the behaviors to be detached. The 602 * possible triggers are: 603 * - unload: (default) The context element is being removed from the DOM. 604 * - move: The element is about to be moved within the DOM (for example, 605 * during a tabledrag row swap). After the move is completed, 606 * Drupal.attachBehaviors() is called, so that the behavior can undo 607 * whatever it did in response to the move. Many behaviors won't need to 608 * do anything simply in response to the element being moved, but because 609 * IFRAME elements reload their "src" when being moved within the DOM, 610 * behaviors bound to IFRAME elements (like WYSIWYG editors) may need to 611 * take some action. 612 * - serialize: When an Ajax form is submitted, this is called with the 613 * form as the context. This provides every behavior within the form an 614 * opportunity to ensure that the field elements have correct content 615 * in them before the form is serialized. The canonical use-case is so 616 * that WYSIWYG editors can update the hidden textarea to which they are 617 * bound. 618 * 619 * @see Drupal.attachBehaviors 620 */ 621Drupal.detachBehaviors = function (context, settings, trigger) { 622 context = context || document; 623 settings = settings || Drupal.settings; 624 trigger = trigger || 'unload'; 625 // Execute all of them. 626 $.each(Drupal.behaviors, function () { 627 if ($.isFunction(this.detach)) { 628 this.detach(context, settings, trigger); 629 } 630 }); 631}; 632 633/** 634 * Encode special characters in a plain-text string for display as HTML. 635 * 636 * @ingroup sanitization 637 */ 638Drupal.checkPlain = function (str) { 639 var character, regex, 640 replace = { '&': '&', "'": ''', '"': '"', '<': '<', '>': '>' }; 641 str = String(str); 642 for (character in replace) { 643 if (replace.hasOwnProperty(character)) { 644 regex = new RegExp(character, 'g'); 645 str = str.replace(regex, replace[character]); 646 } 647 } 648 return str; 649}; 650 651/** 652 * Replace placeholders with sanitized values in a string. 653 * 654 * @param str 655 * A string with placeholders. 656 * @param args 657 * An object of replacements pairs to make. Incidences of any key in this 658 * array are replaced with the corresponding value. Based on the first 659 * character of the key, the value is escaped and/or themed: 660 * - !variable: inserted as is 661 * - @variable: escape plain text to HTML (Drupal.checkPlain) 662 * - %variable: escape text and theme as a placeholder for user-submitted 663 * content (checkPlain + Drupal.theme('placeholder')) 664 * 665 * @see Drupal.t() 666 * @ingroup sanitization 667 */ 668Drupal.formatString = function(str, args) { 669 // Transform arguments before inserting them. 670 for (var key in args) { 671 if (args.hasOwnProperty(key)) { 672 switch (key.charAt(0)) { 673 // Escaped only. 674 case '@': 675 args[key] = Drupal.checkPlain(args[key]); 676 break; 677 // Pass-through. 678 case '!': 679 break; 680 // Escaped and placeholder. 681 default: 682 args[key] = Drupal.theme('placeholder', args[key]); 683 break; 684 } 685 } 686 } 687 688 return Drupal.stringReplace(str, args, null); 689}; 690 691/** 692 * Replace substring. 693 * 694 * The longest keys will be tried first. Once a substring has been replaced, 695 * its new value will not be searched again. 696 * 697 * @param {String} str 698 * A string with placeholders. 699 * @param {Object} args 700 * Key-value pairs. 701 * @param {Array|null} keys 702 * Array of keys from the "args". Internal use only. 703 * 704 * @return {String} 705 * Returns the replaced string. 706 */ 707Drupal.stringReplace = function (str, args, keys) { 708 if (str.length === 0) { 709 return str; 710 } 711 712 // If the array of keys is not passed then collect the keys from the args. 713 if (!$.isArray(keys)) { 714 keys = []; 715 for (var k in args) { 716 if (args.hasOwnProperty(k)) { 717 keys.push(k); 718 } 719 } 720 721 // Order the keys by the character length. The shortest one is the first. 722 keys.sort(function (a, b) { return a.length - b.length; }); 723 } 724 725 if (keys.length === 0) { 726 return str; 727 } 728 729 // Take next longest one from the end. 730 var key = keys.pop(); 731 var fragments = str.split(key); 732 733 if (keys.length) { 734 for (var i = 0; i < fragments.length; i++) { 735 // Process each fragment with a copy of remaining keys. 736 fragments[i] = Drupal.stringReplace(fragments[i], args, keys.slice(0)); 737 } 738 } 739 740 return fragments.join(args[key]); 741}; 742 743/** 744 * Translate strings to the page language or a given language. 745 * 746 * See the documentation of the server-side t() function for further details. 747 * 748 * @param str 749 * A string containing the English string to translate. 750 * @param args 751 * An object of replacements pairs to make after translation. Incidences 752 * of any key in this array are replaced with the corresponding value. 753 * See Drupal.formatString(). 754 * 755 * @param options 756 * - 'context' (defaults to the empty context): The context the source string 757 * belongs to. 758 * 759 * @return 760 * The translated string. 761 */ 762Drupal.t = function (str, args, options) { 763 options = options || {}; 764 options.context = options.context || ''; 765 766 // Fetch the localized version of the string. 767 if (Drupal.locale.strings && Drupal.locale.strings[options.context] && Drupal.locale.strings[options.context][str]) { 768 str = Drupal.locale.strings[options.context][str]; 769 } 770 771 if (args) { 772 str = Drupal.formatString(str, args); 773 } 774 return str; 775}; 776 777/** 778 * Format a string containing a count of items. 779 * 780 * This function ensures that the string is pluralized correctly. Since Drupal.t() is 781 * called by this function, make sure not to pass already-localized strings to it. 782 * 783 * See the documentation of the server-side format_plural() function for further details. 784 * 785 * @param count 786 * The item count to display. 787 * @param singular 788 * The string for the singular case. Please make sure it is clear this is 789 * singular, to ease translation (e.g. use "1 new comment" instead of "1 new"). 790 * Do not use @count in the singular string. 791 * @param plural 792 * The string for the plural case. Please make sure it is clear this is plural, 793 * to ease translation. Use @count in place of the item count, as in "@count 794 * new comments". 795 * @param args 796 * An object of replacements pairs to make after translation. Incidences 797 * of any key in this array are replaced with the corresponding value. 798 * See Drupal.formatString(). 799 * Note that you do not need to include @count in this array.
800 * This replacement is done automatically for the plural case. 801 * @param options 802 * The options to pass to the Drupal.t() function. 803 * @return 804 * A translated string. 805 */ 806Drupal.formatPlural = function (count, singular, plural, args, options) { 807 args = args || {}; 808 args['@count'] = count; 809 // Determine the index of the plural form. 810 var index = Drupal.locale.pluralFormula ? Drupal.locale.pluralFormula(args['@count']) : ((args['@count'] == 1) ? 0 : 1); 811 812 if (index == 0) { 813 return Drupal.t(singular, args, options); 814 } 815 else if (index == 1) { 816 return Drupal.t(plural, args, options); 817 } 818 else { 819 args['@count[' + index + ']'] = args['@count']; 820 delete args['@count']; 821 return Drupal.t(plural.replace('@count', '@count[' + index + ']'), args, options); 822 } 823}; 824 825/** 826 * Returns the passed in URL as an absolute URL. 827 * 828 * @param url 829 * The URL string to be normalized to an absolute URL. 830 * 831 * @return 832 * The normalized, absolute URL. 833 * 834 * @see https://github.com/angular/angular.js/blob/v1.4.4/src/ng/urlUtils.js 835 * @see https://grack.com/blog/2009/11/17/absolutizing-url-in-javascript 836 * @see https://github.com/jquery/jquery-ui/blob/1.11.4/ui/tabs.js#L53 837 */ 838Drupal.absoluteUrl = function (url) { 839 var urlParsingNode = document.createElement('a'); 840 841 // Decode the URL first; this is required by IE <= 6. Decoding non-UTF-8 842 // strings may throw an exception. 843 try { 844 url = decodeURIComponent(url); 845 } catch (e) {} 846 847 urlParsingNode.setAttribute('href', url); 848 849 // IE <= 7 normalizes the URL when assigned to the anchor node similar to 850 // the other browsers. 851 return urlParsingNode.cloneNode(false).href; 852}; 853 854/** 855 * Returns true if the URL is within Drupal's base path. 856 * 857 * @param url 858 * The URL string to be tested. 859 * 860 * @return 861 * Boolean true if local. 862 * 863 * @see https://github.com/jquery/jquery-ui/blob/1.11.4/ui/tabs.js#L58 864 */ 865Drupal.urlIsLocal = function (url) { 866 // Always use browser-derived absolute URLs in the comparison, to avoid 867 // attempts to break out of the base path using directory traversal. 868 var absoluteUrl = Drupal.absoluteUrl(url); 869 var protocol = location.protocol; 870 871 // Consider URLs that match this site's base URL but use HTTPS instead of HTTP 872 // as local as well. 873 if (protocol === 'http:' && absoluteUrl.indexOf('https:') === 0) { 874 protocol = 'https:'; 875 } 876 var baseUrl = protocol + '//' + location.host + Drupal.settings.basePath.slice(0, -1); 877 878 // Decoding non-UTF-8 strings may throw an exception. 879 try { 880 absoluteUrl = decodeURIComponent(absoluteUrl); 881 } catch (e) {} 882 try { 883 baseUrl = decodeURIComponent(baseUrl); 884 } catch (e) {} 885 886 // The given URL matches the site's base URL, or has a path under the site's 887 // base URL. 888 return absoluteUrl === baseUrl || absoluteUrl.indexOf(baseUrl + '/') === 0; 889}; 890 891/** 892 * Sanitizes a URL for use with jQuery.ajax(). 893 * 894 * @param url 895 * The URL string to be sanitized. 896 * 897 * @return 898 * The sanitized URL. 899 */ 900Drupal.sanitizeAjaxUrl = function (url) { 901 var regex = /\=\?(&|$)/; 902 while (url.match(regex)) { 903 url = url.replace(regex, ''); 904 } 905 return url; 906} 907 908/** 909 * Generate the themed representation of a Drupal object. 910 * 911 * All requests for themed output must go through this function. It examines 912 * the request and routes it to the appropriate theme function. If the current 913 * theme does not provide an override function, the generic theme function is 914 * called. 915 * 916 * For example, to retrieve the HTML for text that should be emphasized and 917 * displayed as a placeholder inside a sentence, call 918 * Drupal.theme('placeholder', text). 919 * 920 * @param func 921 * The name of the theme function to call. 922 * @param ... 923 * Additional arguments to pass along to the theme function. 924 * @return 925 * Any data the theme function returns. This could be a plain HTML string, 926 * but also a complex object. 927 */ 928Drupal.theme = function (func) { 929 var args = Array.prototype.slice.apply(arguments, [1]); 930 931 return (Drupal.theme[func] || Drupal.theme.prototype[func]).apply(this, args); 932}; 933 934/** 935 * Freeze the current body height (as minimum height). Used to prevent 936 * unnecessary upwards scrolling when doing DOM manipulations. 937 */ 938Drupal.freezeHeight = function () { 939 Drupal.unfreezeHeight(); 940 $('<div id="freeze-height"></div>').css({ 941 position: 'absolute', 942 top: '0px', 943 left: '0px', 944 width: '1px', 945 height: $('body').css('height') 946 }).appendTo('body'); 947}; 948 949/** 950 * Unfreeze the body height. 951 */ 952Drupal.unfreezeHeight = function () { 953 $('#freeze-height').remove(); 954}; 955 956/** 957 * Encodes a Drupal path for use in a URL. 958 * 959 * For aesthetic reasons slashes are not escaped. 960 */ 961Drupal.encodePath = function (item, uri) { 962 uri = uri || location.href; 963 return encodeURIComponent(item).replace(/%2F/g, '/'); 964}; 965 966/** 967 * Get the text selection in a textarea. 968 */ 969Drupal.getSelection = function (element) { 970 if (typeof element.selectionStart != 'number' && document.selection) { 971 // The current selection. 972 var range1 = document.selection.createRange(); 973 var range2 = range1.duplicate(); 974 // Select all text. 975 range2.moveToElementText(element); 976 // Now move 'dummy' end point to end point of original range.
977 range2.setEndPoint('EndToEnd', range1); 978 // Now we can calculate start and end points. 979 var start = range2.text.length - range1.text.length; 980 var end = start + range1.text.length; 981 return { 'start': start, 'end': end }; 982 } 983 return { 'start': element.selectionStart, 'end': element.selectionEnd }; 984}; 985 986/** 987 * Add a global variable which determines if the window is being unloaded. 988 * 989 * This is primarily used by Drupal.displayAjaxError(). 990 */ 991Drupal.beforeUnloadCalled = false; 992$(window).bind('beforeunload pagehide', function () { 993 Drupal.beforeUnloadCalled = true; 994}); 995 996/** 997 * Displays a JavaScript error from an Ajax response when appropriate to do so. 998 */ 999Drupal.displayAjaxError = function (message) { 1000 // Skip displaying the message if the user deliberately aborted (for example, 1001 // by reloading the page or navigating to a different page) while the Ajax 1002 // request was still ongoing. See, for example, the discussion at 1003 // http://stackoverflow.com/questions/699941/handle-ajax-error-when-a-user-clicks-refresh. 1004 if (!Drupal.beforeUnloadCalled) { 1005 alert(message); 1006 } 1007}; 1008 1009/** 1010 * Build an error message from an Ajax response. 1011 */ 1012Drupal.ajaxError = function (xmlhttp, uri, customMessage) { 1013 var statusCode, statusText, pathText, responseText, readyStateText, message; 1014 if (xmlhttp.status) { 1015 statusCode = "\n" + Drupal.t("An AJAX HTTP error occurred.") + "\n" + Drupal.t("HTTP Result Code: !status", {'!status': xmlhttp.status}); 1016 } 1017 else { 1018 statusCode = "\n" + Drupal.t("An AJAX HTTP request terminated abnormally."); 1019 } 1020 statusCode += "\n" + Drupal.t("Debugging information follows."); 1021 pathText = "\n" + Drupal.t("Path: !uri", {'!uri': uri} ); 1022 statusText = ''; 1023 // In some cases, when statusCode == 0, xmlhttp.statusText may not be defined. 1024 // Unfortunately, testing for it with typeof, etc, doesn't seem to catch that 1025 // and the test causes an exception. So we need to catch the exception here. 1026 try { 1027 statusText = "\n" + Drupal.t("StatusText: !statusText", {'!statusText': $.trim(xmlhttp.statusText)}); 1028 } 1029 catch (e) {} 1030 1031 responseText = ''; 1032 // Again, we don't have a way to know for sure whether accessing 1033 // xmlhttp.responseText is going to throw an exception. So we'll catch it. 1034 try { 1035 responseText = "\n" + Drupal.t("ResponseText: !responseText", {'!responseText': $.trim(xmlhttp.responseText) } ); 1036 } catch (e) {} 1037 1038 // Make the responseText more readable by stripping HTML tags and newlines. 1039 responseText = responseText.replace(/<("[^"]*"|'[^']*'|[^'">])*>/gi,""); 1040 responseText = responseText.replace(/[\n]+\s+/g,"\n"); 1041 1042 // We don't need readyState except for status == 0. 1043 readyStateText = xmlhttp.status == 0 ? ("\n" + Drupal.t("ReadyState: !readyState", {'!readyState': xmlhttp.readyState})) : ""; 1044 1045 // Additional message beyond what the xmlhttp object provides. 1046 customMessage = customMessage ? ("\n" + Drupal.t("CustomMessage: !customMessage", {'!customMessage': customMessage})) : ""; 1047 1048 message = statusCode + pathText + statusText + customMessage + responseText + readyStateText; 1049 return message; 1050}; 1051 1052// Class indicating that JS is enabled; used for styling purpose. 1053$('html').addClass('js'); 1054 1055$(function () { 1056 if (Drupal.settings.setHasJsCookie === 1) { 1057 // 'js enabled' cookie. 1058 document.cookie = 'has_js=1; path=/; SameSite=Lax'; 1059 } 1060}); 1061 1062/** 1063 * Additions to jQuery.support. 1064 */ 1065$(function () { 1066 /** 1067 * Boolean indicating whether or not position:fixed is supported. 1068 */ 1069 if (jQuery.support.positionFixed === undefined) { 1070 var el = $('<div style="position:fixed; top:10px" />').appendTo(document.body); 1071 jQuery.support.positionFixed = el[0].offsetTop === 10; 1072 el.remove(); 1073 } 1074}); 1075 1076//Attach all behaviors. 1077$(function () { 1078 Drupal.attachBehaviors(document, Drupal.settings); 1079}); 1080 1081/** 1082 * The default themes. 1083 */ 1084Drupal.theme.prototype = { 1085 1086 /** 1087 * Formats text for emphasized display in a placeholder inside a sentence. 1088 * 1089 * @param str 1090 * The text to format (plain-text). 1091 * @return 1092 * The formatted text (html). 1093 */ 1094 placeholder: function (str) { 1095 return '<em class="placeholder">' + Drupal.checkPlain(str) + '</em>'; 1096 } 1097}; 1098 1099})(jQuery); 1100; 1101/** 1102 * Workaround for deprecated $.browser which was removed in jQuery 1.9 1103 * @see https://api.jquery.com/jquery.browser/ 1104 */ 1105(function ($) { 1106 if ($.browser===undefined) { 1107 $.browser={}; 1108 $.browser.msie=false; 1109 $.browser.version=0; 1110 if (navigator.userAgent.match(/MSIE ([0-9]+)\./)) { 1111 $.browser.msie=true; 1112 $.browser.version=RegExp.$1; 1113 } 1114 } 1115})(jQuery); 1116;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.