1 2/** 3 * Cookie plugin 1.0 4 * 5 * Copyright (c) 2006 Klaus Hartl (stilbuero.de) 6 * Dual licensed under the MIT and GPL licenses: 7 * http://www.opensource.org/licenses/mit-license.php 8 * http://www.gnu.org/licenses/gpl.html 9 * 10 */ 11jQuery.cookie=function(b,j,m){if(typeof j!="undefined"){m=m||{};if(j===null){j="";m.expires=-1}var e="";if(m.expires&&(typeof m.expires=="number"||m.expires.toUTCString)){var f;if(typeof m.expires=="number"){f=new Date();f.setTime(f.getTime()+(m.expires*24*60*60*1000))}else{f=m.expires}e="; expires="+f.toUTCString()}var l=m.path?"; path="+(m.path):"";var g=m.domain?"; domain="+(m.domain):"";var a=m.secure?"; secure":"";document.cookie=[b,"=",encodeURIComponent(j),e,l,g,a].join("")}else{var d=null;if(document.cookie&&document.cookie!=""){var k=document.cookie.split(";");for(var h=0;h<k.length;h++){var c=jQuery.trim(k[h]);if(c.substring(0,b.length+1)==(b+"=")){d=decodeURIComponent(c.substring(b.length+1));break}}}return d}}; 12; 13 14/*! 15 * jQuery Form Plugin 16 * version: 2.52 (07-DEC-2010) 17 * @requires jQuery v1.3.2 or later 18 * 19 * Examples and documentation at: http://malsup.com/jquery/form/ 20 * Dual licensed under the MIT and GPL licenses: 21 * http://www.opensource.org/licenses/mit-license.php 22 * http://www.gnu.org/licenses/gpl.html 23 */ 24;(function(b){function q(){if(b.fn.ajaxSubmit.debug){var a="[jquery.form] "+Array.prototype.join.call(arguments,"");if(window.console&&window.console.log)window.console.log(a);else window.opera&&window.opera.postError&&window.opera.postError(a)}}b.fn.ajaxSubmit=function(a){function f(){function t(){var o=i.attr("target"),m=i.attr("action");l.setAttribute("target",u);l.getAttribute("method")!="POST"&&l.setAttribute("method","POST");l.getAttribute("action")!=e.url&&l.setAttribute("action",e.url);e.skipEncodingOverride|| i.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"});e.timeout&&setTimeout(function(){F=true;s()},e.timeout);var v=[];try{if(e.extraData)for(var w in e.extraData)v.push(b('<input type="hidden" name="'+w+'" value="'+e.extraData[w]+'" />').appendTo(l)[0]);r.appendTo("body");r.data("form-plugin-onload",s);l.submit()}finally{l.setAttribute("action",m);o?l.setAttribute("target",o):i.removeAttr("target");b(v).remove()}}function s(){if(!G){r.removeData("form-plugin-onload");var o=true; try{if(F)throw"timeout";p=x.contentWindow?x.contentWindow.document:x.contentDocument?x.contentDocument:x.document;var m=e.dataType=="xml"||p.XMLDocument||b.isXMLDoc(p);q("isXml="+m);if(!m&&window.opera&&(p.body==null||p.body.innerHTML==""))if(--K){q("requeing onLoad callback, DOM not available");setTimeout(s,250);return}G=true;j.responseText=p.documentElement?p.documentElement.innerHTML:null;j.responseXML=p.XMLDocument?p.XMLDocument:p;j.getResponseHeader=function(L){return{"content-type":e.dataType}[L]}; var v=/(json|script)/.test(e.dataType);if(v||e.textarea){var w=p.getElementsByTagName("textarea")[0];if(w)j.responseText=w.value;else if(v){var H=p.getElementsByTagName("pre")[0],I=p.getElementsByTagName("body")[0];if(H)j.responseText=H.textContent;else if(I)j.responseText=I.innerHTML}}else if(e.dataType=="xml"&&!j.responseXML&&j.responseText!=null)j.responseXML=C(j.responseText);J=b.httpData(j,e.dataType)}catch(D){q("error caught:",D);o=false;j.error=D;b.handleError(e,j,"error",D)}if(j.aborted){q("upload aborted"); o=false}if(o){e.success.call(e.context,J,"success",j);y&&b.event.trigger("ajaxSuccess",[j,e])}y&&b.event.trigger("ajaxComplete",[j,e]);y&&!--b.active&&b.event.trigger("ajaxStop");if(e.complete)e.complete.call(e.context,j,o?"success":"error");setTimeout(function(){r.removeData("form-plugin-onload");r.remove();j.responseXML=null},100)}}function C(o,m){if(window.ActiveXObject){m=new ActiveXObject("Microsoft.XMLDOM");m.async="false";m.loadXML(o)}else m=(new DOMParser).parseFromString(o,"text/xml");return m&& m.documentElement&&m.documentElement.tagName!="parsererror"?m:null}var l=i[0];if(b(":input[name=submit],:input[id=submit]",l).length)alert('Error: Form elements must not have name or id of "submit".');else{var e=b.extend(true,{},b.ajaxSettings,a);e.context=e.context||e;var u="jqFormIO"+(new Date).getTime(),E="_"+u;window[E]=function(){var o=r.data("form-plugin-onload");if(o){o();window[E]=undefined;try{delete window[E]}catch(m){}}};var r=b('<iframe id="'+u+'" name="'+u+'" src="'+e.iframeSrc+'" onload="window[\'_\'+this.id]()" />'), x=r[0];r.css({position:"absolute",top:"-1000px",left:"-1000px"});var j={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(){this.aborted=1;r.attr("src",e.iframeSrc)}},y=e.global;y&&!b.active++&&b.event.trigger("ajaxStart");y&&b.event.trigger("ajaxSend",[j,e]);
24if(e.beforeSend&&e.beforeSend.call(e.context,j,e)===false)e.global&&b.active--;else if(!j.aborted){var G=false, F=0,z=l.clk;if(z){var A=z.name;if(A&&!z.disabled){e.extraData=e.extraData||{};e.extraData[A]=z.value;if(z.type=="image"){e.extraData[A+".x"]=l.clk_x;e.extraData[A+".y"]=l.clk_y}}}e.forceSync?t():setTimeout(t,10);var J,p,K=50}}}if(!this.length){q("ajaxSubmit: skipping submit process - no element selected");return this}if(typeof a=="function")a={success:a};var d=this.attr("action");if(d=typeof d==="string"?b.trim(d):"")d=(d.match(/^([^#]+)/)||[])[1];d=d||window.location.href||"";a=b.extend(true,{url:d, type:this.attr("method")||"GET",iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},a);d={};this.trigger("form-pre-serialize",[this,a,d]);if(d.veto){q("ajaxSubmit: submit vetoed via form-pre-serialize trigger");return this}if(a.beforeSerialize&&a.beforeSerialize(this,a)===false){q("ajaxSubmit: submit aborted via beforeSerialize callback");return this}var c,h,g=this.formToArray(a.semantic);if(a.data){a.extraData=a.data;for(c in a.data)if(a.data[c]instanceof Array)for(var k in a.data[c])g.push({name:c, value:a.data[c][k]});else{h=a.data[c];h=b.isFunction(h)?h():h;g.push({name:c,value:h})}}if(a.beforeSubmit&&a.beforeSubmit(g,this,a)===false){q("ajaxSubmit: submit aborted via beforeSubmit callback");return this}this.trigger("form-submit-validate",[g,this,a,d]);if(d.veto){q("ajaxSubmit: submit vetoed via form-submit-validate trigger");return this}c=b.param(g);if(a.type.toUpperCase()=="GET"){a.url+=(a.url.indexOf("?")>=0?"&":"?")+c;a.data=null}else a.data=c;var i=this,n=[];a.resetForm&&n.push(function(){i.resetForm()}); a.clearForm&&n.push(function(){i.clearForm()});if(!a.dataType&&a.target){var B=a.success||function(){};n.push(function(t){var s=a.replaceTarget?"replaceWith":"html";b(a.target)[s](t).each(B,arguments)})}else a.success&&n.push(a.success);a.success=function(t,s,C){for(var l=a.context||a,e=0,u=n.length;e<u;e++)n[e].apply(l,[t,s,C||i,i])};c=b("input:file",this).length>0;k=i.attr("enctype")=="multipart/form-data"||i.attr("encoding")=="multipart/form-data";if(a.iframe!==false&&(c||a.iframe||k))a.closeKeepAlive? b.get(a.closeKeepAlive,f):f();else b.ajax(a);this.trigger("form-submit-notify",[this,a]);return this};b.fn.ajaxForm=function(a){if(this.length===0){var f={s:this.selector,c:this.context};if(!b.isReady&&f.s){q("DOM not ready, queuing ajaxForm");b(function(){b(f.s,f.c).ajaxForm(a)});return this}q("terminating; zero elements found by selector"+(b.isReady?"":" (DOM not ready)"));return this}return this.ajaxFormUnbind().bind("submit.form-plugin",function(d){if(!d.isDefaultPrevented()){d.preventDefault(); b(this).ajaxSubmit(a)}}).bind("click.form-plugin",function(d){var c=d.target,h=b(c);if(!h.is(":submit,input:image")){c=h.closest(":submit");if(c.length==0)return;c=c[0]}var g=this;g.clk=c;if(c.type=="image")if(d.offsetX!=undefined){g.clk_x=d.offsetX;g.clk_y=d.offsetY}else if(typeof b.fn.offset=="function"){h=h.offset();g.clk_x=d.pageX-h.left;g.clk_y=d.pageY-h.top}else{g.clk_x=d.pageX-c.offsetLeft;g.clk_y=d.pageY-c.offsetTop}setTimeout(function(){g.clk=g.clk_x=g.clk_y=null},100)})};b.fn.ajaxFormUnbind= function(){return this.unbind("submit.form-plugin click.form-plugin")};b.fn.formToArray=function(a){var f=[];if(this.length===0)return f;var d=this[0],c=a?d.getElementsByTagName("*"):d.elements;if(!c)return f;var h,g,k,i,n,B;h=0;for(n=c.length;h<n;h++){g=c[h];if(k=g.name)if(a&&d.clk&&g.type=="image"){if(!g.disabled&&d.clk==g){f.push({name:k,value:b(g).val()});f.push({name:k+".x",value:d.clk_x},{name:k+".y",value:d.clk_y})}}else if((i=b.fieldValue(g,true))&&i.constructor==Array){g=0;for(B=i.length;g< B;g++)f.push({name:k,value:i[g]})}else i!==null&&typeof i!="undefined"&&f.push({name:k,value:i})}if(!a&&d.clk){a=b(d.clk);c=a[0];if((k=c.name)&&!c.disabled&&c.type=="image"){f.push({name:k,value:a.val()});f.push({name:k+".x",value:d.clk_x},{name:k+".y",value:d.clk_y})}}return f};b.fn.formSerialize=function(a){return b.param(this.formToArray(a))};b.fn.fieldSerialize=function(a){var f=[];this.each(function(){var d=this.name;if(d){var c=b.fieldValue(this,a);if(c&&c.constructor==Array)for(var h=0,g=c.length;h< g;h++)f.push({name:d,value:c[h]});
24else c!==null&&typeof c!="undefined"&&f.push({name:this.name,value:c})}});return b.param(f)};b.fn.fieldValue=function(a){for(var f=[],d=0,c=this.length;d<c;d++){var h=b.fieldValue(this[d],a);h===null||typeof h=="undefined"||h.constructor==Array&&!h.length||(h.constructor==Array?b.merge(f,h):f.push(h))}return f};b.fieldValue=function(a,f){var d=a.name,c=a.type,h=a.tagName.toLowerCase();if(f===undefined)f=true;if(f&&(!d||a.disabled||c=="reset"||c=="button"||(c=="checkbox"|| c=="radio")&&!a.checked||(c=="submit"||c=="image")&&a.form&&a.form.clk!=a||h=="select"&&a.selectedIndex==-1))return null;if(h=="select"){var g=a.selectedIndex;if(g<0)return null;d=[];h=a.options;var k=(c=c=="select-one")?g+1:h.length;for(g=c?g:0;g<k;g++){var i=h[g];if(i.selected){var n=i.value;n||(n=i.attributes&&i.attributes.value&&!i.attributes.value.specified?i.text:i.value);if(c)return n;d.push(n)}}return d}return b(a).val()};b.fn.clearForm=function(){return this.each(function(){b("input,select,textarea", this).clearFields()})};b.fn.clearFields=b.fn.clearInputs=function(){return this.each(function(){var a=this.type,f=this.tagName.toLowerCase();if(a=="text"||a=="password"||f=="textarea")this.value="";else if(a=="checkbox"||a=="radio")this.checked=false;else if(f=="select")this.selectedIndex=-1})};b.fn.resetForm=function(){return this.each(function(){if(typeof this.reset=="function"||typeof this.reset=="object"&&!this.reset.nodeType)this.reset()})};b.fn.enable=function(a){if(a===undefined)a=true;return this.each(function(){this.disabled= !a})};b.fn.selected=function(a){if(a===undefined)a=true;
24return this.each(function(){var f=this.type;if(f=="checkbox"||f=="radio")this.checked=a;else if(this.tagName.toLowerCase()=="option"){f=b(this).parent("select");a&&f[0]&&f[0].type=="select-one"&&f.find("option").selected(false);this.selected=a}})}})(jQuery);; 25(function ($) { 26 27/** 28 * Provides Ajax page updating via jQuery $.ajax (Asynchronous JavaScript and XML). 29 * 30 * Ajax is a method of making a request via JavaScript while viewing an HTML 31 * page. The request returns an array of commands encoded in JSON, which is 32 * then executed to make any changes that are necessary to the page. 33 * 34 * Drupal uses this file to enhance form elements with #ajax['path'] and 35 * #ajax['wrapper'] properties. If set, this file will automatically be included 36 * to provide Ajax capabilities. 37 */ 38 39Drupal.ajax = Drupal.ajax || {}; 40 41Drupal.settings.urlIsAjaxTrusted = Drupal.settings.urlIsAjaxTrusted || {}; 42 43/** 44 * Attaches the Ajax behavior to each Ajax form element. 45 */ 46Drupal.behaviors.AJAX = { 47 attach: function (context, settings) { 48 // Load all Ajax behaviors specified in the settings. 49 for (var base in settings.ajax) { 50 if (!$('#' + base + '.ajax-processed').length) { 51 var element_settings = settings.ajax[base]; 52 53 if (typeof element_settings.selector == 'undefined') { 54 element_settings.selector = '#' + base; 55 } 56 $(element_settings.selector).each(function () { 57 element_settings.element = this; 58 Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings); 59 }); 60 61 $('#' + base).addClass('ajax-processed'); 62 } 63 } 64 65 // Bind Ajax behaviors to all items showing the class. 66 $('.use-ajax:not(.ajax-processed)').addClass('ajax-processed').each(function () { 67 var element_settings = {}; 68 // Clicked links look better with the throbber than the progress bar. 69 element_settings.progress = { 'type': 'throbber' }; 70 71 // For anchor tags, these will go to the target of the anchor rather 72 // than the usual location. 73 if ($(this).attr('href')) { 74 element_settings.url = $(this).attr('href'); 75 element_settings.event = 'click'; 76 } 77 var base = $(this).attr('id'); 78 Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings); 79 }); 80 81 // This class means to submit the form to the action using Ajax. 82 $('.use-ajax-submit:not(.ajax-processed)').addClass('ajax-processed').each(function () { 83 var element_settings = {}; 84 85 // Ajax submits specified in this manner automatically submit to the 86 // normal form action. 87 element_settings.url = $(this.form).attr('action'); 88 // Form submit button clicks need to tell the form what was clicked so 89 // it gets passed in the POST request. 90 element_settings.setClick = true; 91 // Form buttons use the 'click' event rather than mousedown. 92 element_settings.event = 'click'; 93 // Clicked form buttons look better with the throbber than the progress bar. 94 element_settings.progress = { 'type': 'throbber' }; 95 96 var base = $(this).attr('id'); 97 Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings); 98 }); 99 } 100}; 101 102/** 103 * Ajax object. 104 * 105 * All Ajax objects on a page are accessible through the global Drupal.ajax 106 * object and are keyed by the submit button's ID. You can access them from 107 * your module's JavaScript file to override properties or functions. 108 * 109 * For example, if your Ajax enabled button has the ID 'edit-submit', you can 110 * redefine the function that is called to insert the new content like this 111 * (inside a Drupal.behaviors attach block): 112 * @code 113 * Drupal.behaviors.myCustomAJAXStuff = { 114 * attach: function (context, settings) { 115 * Drupal.ajax['edit-submit'].commands.insert = function (ajax, response, status) { 116 * new_content = $(response.data); 117 * $('#my-wrapper').append(new_content); 118 * alert('New content was appended to #my-wrapper'); 119 * } 120 * } 121 * }; 122 * @endcode 123 */ 124Drupal.ajax = function (base, element, element_settings) { 125 var defaults = { 126 url: 'system/ajax', 127 event: 'mousedown', 128 keypress: true, 129 selector: '#' + base, 130 effect: 'none', 131 speed: 'none', 132 method: 'replaceWith', 133 progress: { 134 type: 'throbber', 135 message: Drupal.t('Please wait...') 136 }, 137 submit: { 138 'js': true 139 } 140 }; 141 142 $.extend(this, defaults, element_settings); 143 144 this.element = element; 145 this.element_settings = element_settings; 146 147 // Replacing 'nojs' with 'ajax' in the URL allows for an easy method to let 148 // the server detect when it needs to degrade gracefully. 149 // There are five scenarios to check for: 150 // 1. /nojs/ 151 // 2. /nojs$ - The end of a URL string. 152 // 3. /nojs? - Followed by a query (with clean URLs enabled). 153 // E.g.: path/nojs?destination=foobar 154 // 4. /nojs& - Followed by a query (without clean URLs enabled). 155 // E.g.: ?q=path/nojs&destination=foobar 156 // 5. /nojs# - Followed by a fragment. 157 // E.g.: path/nojs#myfragment 158 this.url = element_settings.url.replace(/\/nojs(\/|$|\?|&|#)/g, '/ajax$1'); 159 // If the 'nojs' version of the URL is trusted, also trust the 'ajax' version. 160 if (Drupal.settings.urlIsAjaxTrusted[element_settings.url]) { 161 Drupal.settings.urlIsAjaxTrusted[this.url] = true; 162 } 163 164 this.wrapper = '#' + element_settings.wrapper; 165 166 // If there isn't a form, jQuery.ajax() will be used instead, allowing us to 167 // bind Ajax to links as well. 168 if (this.element.form) { 169 this.form = $(this.element.form); 170 } 171 172 // Set the options for the ajaxSubmit function. 173 // The 'this' variable will not persist inside of the options object. 174 var ajax = this; 175 ajax.options = { 176 url: Drupal.sanitizeAjaxUrl(ajax.url), 177 data: ajax.submit, 178 beforeSerialize: function (element_settings, options) { 179 return ajax.beforeSerialize(element_settings, options); 180 }, 181 beforeSubmit: function (form_values, element_settings, options) { 182 ajax.ajaxing = true; 183 return ajax.beforeSubmit(form_values, element_settings, options); 184 }, 185 beforeSend: function (xmlhttprequest, options) { 186 ajax.ajaxing = true; 187 return ajax.beforeSend(xmlhttprequest, options); 188 }, 189 success: function (response, status, xmlhttprequest) { 190 // Sanity check for browser support (object expected). 191 // When using iFrame uploads, responses must be returned as a string. 192 if (typeof response == 'string') { 193 response = $.parseJSON(response); 194 } 195 196 // Prior to invoking the response's commands, verify that they can be 197 // trusted by checking for a response header. See 198 // ajax_set_verification_header() for details. 199 // - Empty responses are harmless so can bypass verification. This avoids 200 // an alert message for server-generated no-op responses that skip Ajax 201 // rendering. 202 // - Ajax objects with trusted URLs (e.g., ones defined server-side via 203 // #ajax) can bypass header verification. This is especially useful for 204 // Ajax with multipart forms. Because IFRAME transport is used, the 205 // response headers cannot be accessed for verification. 206 if (response !== null && !Drupal.settings.urlIsAjaxTrusted[ajax.url]) { 207 if (xmlhttprequest.getResponseHeader('X-Drupal-Ajax-Token') !== '1') { 208 var customMessage = Drupal.t("The response failed verification so will not be processed."); 209 return ajax.error(xmlhttprequest, ajax.url, customMessage); 210 } 211 } 212 213 return ajax.success(response, status); 214 }, 215 complete: function (xmlhttprequest, status) { 216 ajax.ajaxing = false;
217 if (status == 'error' || status == 'parsererror') { 218 return ajax.error(xmlhttprequest, ajax.url); 219 } 220 }, 221 dataType: 'json', 222 jsonp: false, 223 type: 'POST' 224 }; 225 226 // For multipart forms (e.g., file uploads), jQuery Form targets the form 227 // submission to an iframe instead of using an XHR object. The initial "src" 228 // of the iframe, prior to the form submission, is set to options.iframeSrc. 229 // "about:blank" is the semantically correct, standards-compliant, way to 230 // initialize a blank iframe; however, some old IE versions (possibly only 6) 231 // incorrectly report a mixed content warning when iframes with an 232 // "about:blank" src are added to a parent document with an https:// origin. 233 // jQuery Form works around this by defaulting to "javascript:false" instead, 234 // but that breaks on Chrome 83, so here we force the semantically correct 235 // behavior for all browsers except old IE. 236 // @see https://www.drupal.org/project/drupal/issues/3143016 237 // @see https://github.com/jquery-form/form/blob/df9cb101b9c9c085c8d75ad980c7ff1cf62063a1/jquery.form.js#L68 238 // @see https://bugs.chromium.org/p/chromium/issues/detail?id=1084874 239 // @see https://html.spec.whatwg.org/multipage/browsers.html#creating-browsing-contexts 240 // @see https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy 241 if (navigator.userAgent.indexOf("MSIE") === -1) { 242 ajax.options.iframeSrc = 'about:blank'; 243 } 244 245 // Bind the ajaxSubmit function to the element event. 246 $(ajax.element).bind(element_settings.event, function (event) { 247 if (!Drupal.settings.urlIsAjaxTrusted[ajax.url] && !Drupal.urlIsLocal(ajax.url)) { 248 throw new Error(Drupal.t('The callback URL is not local and not trusted: !url', {'!url': ajax.url})); 249 } 250 return ajax.eventResponse(this, event); 251 }); 252 253 // If necessary, enable keyboard submission so that Ajax behaviors 254 // can be triggered through keyboard input as well as e.g. a mousedown 255 // action. 256 if (element_settings.keypress) { 257 $(ajax.element).keypress(function (event) { 258 return ajax.keypressResponse(this, event); 259 }); 260 } 261 262 // If necessary, prevent the browser default action of an additional event. 263 // For example, prevent the browser default action of a click, even if the 264 // AJAX behavior binds to mousedown. 265 if (element_settings.prevent) { 266 $(ajax.element).bind(element_settings.prevent, false); 267 } 268}; 269 270/** 271 * Handle a key press. 272 * 273 * The Ajax object will, if instructed, bind to a key press response. This 274 * will test to see if the key press is valid to trigger this event and 275 * if it is, trigger it for us and prevent other keypresses from triggering. 276 * In this case we're handling RETURN and SPACEBAR keypresses (event codes 13 277 * and 32. RETURN is often used to submit a form when in a textfield, and 278 * SPACE is often used to activate an element without submitting. 279 */ 280Drupal.ajax.prototype.keypressResponse = function (element, event) { 281 // Create a synonym for this to reduce code confusion. 282 var ajax = this; 283 284 // Detect enter key and space bar and allow the standard response for them, 285 // except for form elements of type 'text' and 'textarea', where the 286 // spacebar activation causes inappropriate activation if #ajax['keypress'] is 287 // TRUE. On a text-type widget a space should always be a space. 288 if (event.which == 13 || (event.which == 32 && element.type != 'text' && element.type != 'textarea')) { 289 $(ajax.element_settings.element).trigger(ajax.element_settings.event); 290 return false; 291 } 292}; 293 294/** 295 * Handle an event that triggers an Ajax response. 296 * 297 * When an event that triggers an Ajax response happens, this method will 298 * perform the actual Ajax call. It is bound to the event using 299 * bind() in the constructor, and it uses the options specified on the 300 * ajax object. 301 */ 302Drupal.ajax.prototype.eventResponse = function (element, event) { 303 // Create a synonym for this to reduce code confusion. 304 var ajax = this; 305 306 // Do not perform another ajax command if one is already in progress. 307 if (ajax.ajaxing) { 308 return false; 309 } 310 311 try { 312 if (ajax.form) { 313 // If setClick is set, we must set this to ensure that the button's 314 // value is passed. 315 if (ajax.setClick) { 316 // Mark the clicked button. 'form.clk' is a special variable for 317 // ajaxSubmit that tells the system which element got clicked to 318 // trigger the submit. Without it there would be no 'op' or
319 // equivalent. 320 element.form.clk = element; 321 } 322 323 ajax.form.ajaxSubmit(ajax.options); 324 } 325 else { 326 ajax.beforeSerialize(ajax.element, ajax.options); 327 $.ajax(ajax.options); 328 } 329 } 330 catch (e) { 331 // Unset the ajax.ajaxing flag here because it won't be unset during 332 // the complete response. 333 ajax.ajaxing = false; 334 alert("An error occurred while attempting to process " + ajax.options.url + ": " + e.message); 335 } 336 337 // For radio/checkbox, allow the default event. On IE, this means letting 338 // it actually check the box. 339 if (typeof element.type != 'undefined' && (element.type == 'checkbox' || element.type == 'radio')) { 340 return true; 341 } 342 else { 343 return false; 344 } 345 346}; 347 348/** 349 * Handler for the form serialization. 350 * 351 * Runs before the beforeSend() handler (see below), and unlike that one, runs 352 * before field data is collected. 353 */ 354Drupal.ajax.prototype.beforeSerialize = function (element, options) { 355 // Allow detaching behaviors to update field values before collecting them. 356 // This is only needed when field values are added to the POST data, so only 357 // when there is a form such that this.form.ajaxSubmit() is used instead of 358 // $.ajax(). When there is no form and $.ajax() is used, beforeSerialize() 359 // isn't called, but don't rely on that: explicitly check this.form. 360 if (this.form) { 361 var settings = this.settings || Drupal.settings; 362 Drupal.detachBehaviors(this.form, settings, 'serialize'); 363 } 364 365 // Prevent duplicate HTML ids in the returned markup. 366 // @see drupal_html_id() 367 options.data['ajax_html_ids[]'] = []; 368 $('[id]').each(function () { 369 options.data['ajax_html_ids[]'].push(this.id); 370 }); 371 372 // Allow Drupal to return new JavaScript and CSS files to load without 373 // returning the ones already loaded. 374 // @see ajax_base_page_theme() 375 // @see drupal_get_css() 376 // @see drupal_get_js() 377 options.data['ajax_page_state[theme]'] = Drupal.settings.ajaxPageState.theme; 378 options.data['ajax_page_state[theme_token]'] = Drupal.settings.ajaxPageState.theme_token; 379 for (var key in Drupal.settings.ajaxPageState.css) { 380 options.data['ajax_page_state[css][' + key + ']'] = 1; 381 } 382 for (var key in Drupal.settings.ajaxPageState.js) { 383 options.data['ajax_page_state[js][' + key + ']'] = 1; 384 } 385}; 386 387/** 388 * Modify form values prior to form submission. 389 */ 390Drupal.ajax.prototype.beforeSubmit = function (form_values, element, options) { 391 // This function is left empty to make it simple to override for modules 392 // that wish to add functionality here. 393}; 394 395/** 396 * Prepare the Ajax request before it is sent. 397 */ 398Drupal.ajax.prototype.beforeSend = function (xmlhttprequest, options) { 399 // For forms without file inputs, the jQuery Form plugin serializes the form 400 // values, and then calls jQuery's $.ajax() function, which invokes this 401 // handler. In this circumstance, options.extraData is never used. For forms 402 // with file inputs, the jQuery Form plugin uses the browser's normal form 403 // submission mechanism, but captures the response in a hidden IFRAME. In this 404 // circumstance, it calls this handler first, and then appends hidden fields 405 // to the form to submit the values in options.extraData. There is no simple 406 // way to know which submission mechanism will be used, so we add to extraData 407 // regardless, and allow it to be ignored in the former case. 408 if (this.form) { 409 options.extraData = options.extraData || {}; 410 411 // Let the server know when the IFRAME submission mechanism is used. The 412 // server can use this information to wrap the JSON response in a TEXTAREA, 413 // as per http://jquery.malsup.com/form/#file-upload. 414 options.extraData.ajax_iframe_upload = '1'; 415 416 // The triggering element is about to be disabled (see below), but if it 417 // contains a value (e.g., a checkbox, textfield, select, etc.), ensure that 418 // value is included in the submission. As per above, submissions that use 419 // $.ajax() are already serialized prior to the element being disabled, so 420 // this is only needed for IFRAME submissions. 421 var v = $.fieldValue(this.element); 422 if (v !== null) { 423 options.extraData[this.element.name] = Drupal.checkPlain(v); 424 } 425 } 426 427 // Disable the element that received the change to prevent user interface 428 // interaction while the Ajax request is in progress. ajax.ajaxing prevents 429 // the element from triggering a new request, but does not prevent the user 430 // from changing its value. 431 $(this.element).addClass('progress-disabled').attr('disabled', true); 432 433 // Insert progressbar or throbber. 434 if (this.progress.type == 'bar') { 435 var progressBar = new Drupal.progressBar('ajax-progress-' + this.element.i
435d, $.noop, this.progress.method, $.noop); 436 if (this.progress.message) { 437 progressBar.setProgress(-1, this.progress.message); 438 } 439 if (this.progress.url) { 440 progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500); 441 } 442 this.progress.element = $(progressBar.element).addClass('ajax-progress ajax-progress-bar'); 443 this.progress.object = progressBar; 444 $(this.element).after(this.progress.element); 445 } 446 else if (this.progress.type == 'throbber') { 447 this.progress.element = $('<div class="ajax-progress ajax-progress-throbber"><div class="throbber"> </div></div>'); 448 if (this.progress.message) { 449 $('.throbber', this.progress.element).after('<div class="message">' + this.progress.message + '</div>'); 450 } 451 $(this.element).after(this.progress.element); 452 } 453}; 454 455/** 456 * Handler for the form redirection completion. 457 */ 458Drupal.ajax.prototype.success = function (response, status) { 459 // Remove the progress element. 460 if (this.progress.element) { 461 $(this.progress.element).remove(); 462 } 463 if (this.progress.object) { 464 this.progress.object.stopMonitoring(); 465 } 466 $(this.element).removeClass('progress-disabled').removeAttr('disabled'); 467 468 Drupal.freezeHeight(); 469 470 for (var i in response) { 471 if (response.hasOwnProperty(i) && response[i]['command'] && this.commands[response[i]['command']]) { 472 this.commands[response[i]['command']](this, response[i], status); 473 } 474 } 475 476 // Reattach behaviors, if they were detached in beforeSerialize(). The 477 // attachBehaviors() called on the new content from processing the response 478 // commands is not sufficient, because behaviors from the entire form need 479 // to be reattached. 480 if (this.form) { 481 var settings = this.settings || Drupal.settings; 482 Drupal.attachBehaviors(this.form, settings); 483 } 484 485 Drupal.unfreezeHeight(); 486 487 // Remove any response-specific settings so they don't get used on the next 488 // call by mistake. 489 this.settings = null; 490}; 491 492/** 493 * Build an effect object which tells us how to apply the effect when adding new HTML. 494 */ 495Drupal.ajax.prototype.getEffect = function (response) { 496 var type = response.effect || this.effect; 497 var speed = response.speed || this.speed; 498 499 var effect = {}; 500 if (type == 'none') { 501 effect.showEffect = 'show'; 502 effect.hideEffect = 'hide'; 503 effect.showSpeed = ''; 504 } 505 else if (type == 'fade') { 506 effect.showEffect = 'fadeIn'; 507 effect.hideEffect = 'fadeOut'; 508 effect.showSpeed = speed; 509 } 510 else { 511 effect.showEffect = type + 'Toggle'; 512 effect.hideEffect = type + 'Toggle'; 513 effect.showSpeed = speed; 514 } 515 516 return effect; 517}; 518 519/** 520 * Handler for the form redirection error. 521 */ 522Drupal.ajax.prototype.error = function (xmlhttprequest, uri, customMessage) { 523 Drupal.displayAjaxError(Drupal.ajaxError(xmlhttprequest, uri, customMessage)); 524 // Remove the progress element. 525 if (this.progress.element) { 526 $(this.progress.element).remove(); 527 } 528 if (this.progress.object) { 529 this.progress.object.stopMonitoring(); 530 } 531 // Undo hide. 532 $(this.wrapper).show(); 533 // Re-enable the element. 534 $(this.element).removeClass('progress-disabled').removeAttr('disabled'); 535 // Reattach behaviors, if they were detached in beforeSerialize(). 536 if (this.form) { 537 var settings = this.settings || Drupal.settings; 538 Drupal.attachBehaviors(this.form, settings); 539 } 540}; 541 542/** 543 * Provide a series of commands that the server can request the client perform. 544 */ 545Drupal.ajax.prototype.commands = { 546 /** 547 * Command to insert new content into the DOM. 548 */ 549 insert: function (ajax, response, status) { 550 // Get information from the response. If it is not there, default to 551 // our presets. 552 var wrapper = response.selector ? $(response.selector) : $(ajax.wrapper); 553 var method = response.method || ajax.method; 554 var effect = ajax.getEffect(response); 555 556 // We don't know what response.data contains: it might be a string of text 557 // without HTML, so don't rely on jQuery correctly iterpreting 558 // $(response.data) as new HTML rather than a CSS selector. Also, if 559 // response.data contains top-level text nodes, they get lost with either 560 // $(response.data) or $('<div></div>').replaceWith(response.data). 561 var new_content_wrapped = $('<div></div>').html(response.data); 562 var new_content = new_content_wrapped.contents(); 563 564 // For legacy reasons, the effects processing code assumes that new_content 565 // consists of a single top-level element. Also, it has not been 566 // sufficiently tested whether attachBehaviors() can be successfully called 567 // with a context object that includes top-level text nodes. However, to 568 // give developers full control of the HTML appearing in the page, and to 569 // enable Ajax content to be inserted in places where DIV elements are not 570 // allowed (e.g., within TABLE, TR, and SPAN parents), we check if the new 571 // content satisfies the requirement of a single top-level element, and 572 // only use the container DIV created above when it doesn't. For more 573 // information, please see http://drupal.org/node/736066. 574 if (new_content.length != 1 || new_content.get(0).nodeType != 1) { 575 new_content = new_content_wrapped; 576 } 577 578 // If removing content from the wrapper, detach behaviors first. 579 switch (method) { 580 case 'html': 581 case 'replaceWith': 582 case 'replaceAll': 583 case 'empty': 584 case 'remove': 585 var settings = response.settings || ajax.settings || Drupal.settings; 586 Drupal.detachBehaviors(wrapper, settings); 587 } 588 589 // Add the new content to the page. 590 wrapper[method](new_content); 591 592 // Immediately hide the new content if we're using any effects. 593 if (effect.showEffect != 'show') { 594 new_content.hide(); 595 } 596 597 // Determine which effect to use and what content will receive the 598 // effect, then show the new content. 599 if ($('.ajax-new-content', new_content).length > 0) { 600 $('.ajax-new-content', new_content).hide(); 601 new_content.show(); 602 $('.ajax-new-content', new_content)[effect.showEffect](effect.showSpeed); 603 } 604 else if (effect.showEffect != 'show') { 605 new_content[effect.showEffect](effect.showSpeed); 606 } 607 608 // Attach all JavaScript behaviors to the new content, if it was successfully 609 // added to the page, this if statement allows #ajax['wrapper'] to be 610 // optional. 611 if (new_content.parents('html').length > 0) { 612 // Apply any settings from the returned JSON if available. 613 var settings = response.settings || ajax.settings || Drupal.settings; 614 Drupal.attachBehaviors(new_content, settings); 615 } 616 }, 617 618 /** 619 * Command to remove a chunk from the page. 620 */ 621 remove: function (ajax, response, status) { 622 var settings = response.settings || ajax.settings || Drupal.settings; 623 Drupal.detachBehaviors($(response.selector), settings); 624 $(response.selector).remove(); 625 }, 626 627 /** 628 * Command to mark a chunk changed. 629 */ 630 changed: function (ajax, response, status) { 631 if (!$(response.selector).hasClass('ajax-changed')) { 632 $(response.selector).addClass('ajax-changed'); 633 if (response.asterisk) { 634 $(response.selector).find(response.asterisk).append(' <span class="ajax-changed">*</span> '); 635 } 636 } 637 }, 638 639 /** 640 * Command to provide an alert. 641 */ 642 alert: function (ajax, response, status) { 643 alert(response.text, response.title); 644 }, 645 646 /** 647 * Command to provide the jQuery css() function. 648 */ 649 css: function (ajax, response, status) { 650 $(response.selector).css(response.argument); 651 }, 652 653 /** 654 * Command to set the settings that will be used for other commands in this response. 655 */ 656 settings: function (ajax, response, status) { 657 if (response.merge) { 658 $.extend(true, Drupal.settings, response.settings); 659 } 660 else { 661 ajax.settings = response.settings; 662 } 663 }, 664 665 /** 666 * Command to attach data using jQuery's data API. 667 */ 668 data: function (ajax, response, status) { 669 $(response.selector).data(response.name, response.value); 670 }, 671 672 /** 673 * Command to apply a jQuery method. 674 */ 675 invoke: function (ajax, response, status) { 676 var $element = $(response.selector); 677 $element[response.method].apply($element, response.arguments); 678 }, 679 680 /** 681 * Command to restripe a table. 682 */ 683 restripe: function (ajax, response, status) { 684 // :even and :odd are reversed because jQuery counts from 0 and 685 // we count from 1, so we're out of sync. 686 // Match immediate children of the parent element to allow nesting. 687 $('> tbody > tr:visible, > tr:visible', $(response.selector)) 688 .removeClass('odd even') 689 .filter(':even').addClass('odd').end() 690 .filter(':odd').addClass('even'); 691 }, 692 693 /** 694 * Command to add css. 695 * 696 * Uses the proprietary addImport method if available as browsers which 697 * support that method ignore @import statements in dynamically added 698 * stylesheets. 699 */ 700 add_css: function (ajax, response, status) { 701 // Add the styles in the normal way. 702 $('head').prepend(response.data); 703 // Add imports in the styles using the addImport method if available. 704 var match, importMatch = /^@import url\("(.*)"\);$/igm; 705 if (document.styleSheets[0].addImport && importMatch.test(response.data)) { 706 importMatch.lastIndex = 0; 707 while (match = importMatch.exec(response.data)) { 708 document.styleSheets[0].addImport(match[1]); 709 } 710 } 711 }, 712 713 /** 714 * Command to update a form's build ID. 715 */ 716 updateBuildId: function(ajax, response, status) { 717 $('input[name="form_build_id"][value="' + response['old'] + '"]').val(response['new']); 718 } 719}; 720 721})(jQuery); 722; 723(function (D) { 724 var beforeSerialize = D.ajax.prototype.beforeSerialize;
725 D.ajax.prototype.beforeSerialize = function (element, options) { 726 beforeSerialize.call(this, element, options); 727 options.data['ajax_page_state[jquery_version]'] = D.settings.ajaxPageState.jquery_version; 728 options.data['ajax_page_state[jquery_version_token]'] = D.settings.ajaxPageState.jquery_version_token; 729 } 730})(Drupal); 731;
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.