1/*jslint browser: true */ /*global jQuery: true */ 2 3/** 4 * jQuery Cookie plugin 5 * 6 * Copyright (c) 2010 Klaus Hartl (stilbuero.de) 7 * Dual licensed under the MIT and GPL licenses: 8 * http://www.opensource.org/licenses/mit-license.php 9 * http://www.gnu.org/licenses/gpl.html 10 * 11 */ 12 13// TODO JsDoc 14 15/** 16 * Create a cookie with the given key and value and other optional parameters. 17 * 18 * @example $.cookie('the_cookie', 'the_value'); 19 * @desc Set the value of a cookie. 20 * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true }); 21 * @desc Create a cookie with all available options. 22 * @example $.cookie('the_cookie', 'the_value'); 23 * @desc Create a session cookie. 24 * @example $.cookie('the_cookie', null); 25 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain 26 * used when the cookie was set. 27 * 28 * @param String key The key of the cookie. 29 * @param String value The value of the cookie. 30 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes. 31 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object. 32 * If a negative value is specified (e.g. a date in the past), the cookie will be deleted. 33 * If set to null or omitted, the cookie will be a session cookie and will not be retained 34 * when the the browser exits. 35 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie). 36 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie). 37 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will 38 * require a secure protocol (like HTTPS). 39 * @type undefined 40 * 41 * @name $.cookie 42 * @cat Plugins/Cookie 43 * @author Klaus Hartl/[email protected] 44 */ 45 46/** 47 * Get the value of a cookie with the given key. 48 * 49 * @example $.cookie('the_cookie'); 50 * @desc Get the value of a cookie. 51 * 52 * @param String key The key of the cookie. 53 * @return The value of the cookie. 54 * @type String 55 * 56 * @name $.cookie 57 * @cat Plugins/Cookie 58 * @author Klaus Hartl/[email protected] 59 */ 60jQuery.cookie = function (key, value, options) { 61 62 // key and value given, set cookie... 63 if (arguments.length > 1 && (value === null || typeof value !== "object")) { 64 options = jQuery.extend({}, options); 65 66 if (value === null) { 67 options.expires = -1; 68 } 69 70 if (typeof options.expires === 'number') { 71 var days = options.expires, t = options.expires = new Date(); 72 t.setDate(t.getDate() + days); 73 } 74 75 return (document.cookie = [ 76 encodeURIComponent(key), '=', 77 options.raw ? String(value) : encodeURIComponent(String(value)), 78 options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE 79 options.path ? '; path=' + options.path : '', 80 options.domain ? '; domain=' + options.domain : '', 81 options.secure ? '; secure' : '' 82 ].join('')); 83 } 84 85 // key and possibly options given, get cookie... 86 options = value || {}; 87 var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent; 88 return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null; 89}; 90; 91/*! 92 * jQuery Form Plugin 93 * version: 4.2.1 94 * Requires jQuery v1.7 or later 95 * Copyright 2017 Kevin Morris 96 * Copyright 2006 M. Alsup 97 * Project repository: https://github.com/jquery-form/form 98 * Dual licensed under the MIT and LGPLv3 licenses. 99 * https://github.com/jquery-form/form#license 100 */ 101/* global ActiveXObject */ 102 103/* eslint-disable */ 104(function (factory) { 105 if (typeof define === 'function' && define.amd) { 106 // AMD. Register as an anonymous module. 107 define(['jquery'], factory); 108 } else if (typeof module === 'object' && module.exports) { 109 // Node/CommonJS 110 module.exports = function( root, jQuery ) { 111 if (typeof jQuery === 'undefined') { 112 // require('jQuery') returns a factory that requires window to build a jQuery instance, we normalize how we use modules 113 // that require this pattern but the window provided is a noop if it's defined (how jquery works) 114 if (typeof window !== 'undefined') { 115 jQuery = require('jquery'); 116 } 117 else { 118 jQuery = require('jquery')(root); 119 } 120 } 121 factory(jQuery); 122 return jQuery; 123 }; 124 } else { 125 // Browser globals 126 factory(jQuery); 127 } 128 129}(function ($) { 130 /* eslint-enable */ 131 'use strict'; 132 133 /* 134 Usage Note: 135 ----------- 136 Do not use both ajaxSubmit and ajaxForm on the same form. These 137 functions are mutually exclusive. Use ajaxSubmit if you want 138 to bind your own submit handler to the form. For example, 139 140 $(document).ready(function() { 141 $('#myForm').on('submit', function(e) { 142 e.preventDefault(); // <-- important 143 $(this).ajaxSubmit({ 144 target: '#output' 145 }); 146 }); 147 }); 148 149 Use ajaxForm when you want the plugin to manage all the event binding 150 for you. For example, 151 152 $(document).ready(function() { 153 $('#myForm').ajaxForm({ 154 target: '#output' 155 }); 156 }); 157 158 You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
159 form does not have to exist when you invoke ajaxForm: 160 161 $('#myForm').ajaxForm({ 162 delegation: true, 163 target: '#output' 164 }); 165 166 When using ajaxForm, the ajaxSubmit function will be invoked for you 167 at the appropriate time. 168 */ 169 170 var rCRLF = /\r?\n/g; 171 172 /** 173 * Feature detection 174 */ 175 var feature = {}; 176 177 feature.fileapi = $('<input type="file">').get(0).files !== undefined; 178 feature.formdata = (typeof window.FormData !== 'undefined'); 179 180 var hasProp = !!$.fn.prop; 181 182 // attr2 uses prop when it can but checks the return type for 183 // an expected string. This accounts for the case where a form 184 // contains inputs with names like "action" or "method"; in those 185 // cases "prop" returns the element 186 $.fn.attr2 = function() { 187 if (!hasProp) { 188 return this.attr.apply(this, arguments); 189 } 190 191 var val = this.prop.apply(this, arguments); 192 193 if ((val && val.jquery) || typeof val === 'string') { 194 return val; 195 } 196 197 return this.attr.apply(this, arguments); 198 }; 199 200 /** 201 * ajaxSubmit() provides a mechanism for immediately submitting 202 * an HTML form using AJAX. 203 * 204 * @param {object|string} options jquery.form.js parameters or custom url for submission 205 * @param {object} data extraData 206 * @param {string} dataType ajax dataType 207 * @param {function} onSuccess ajax success callback function 208 */ 209 $.fn.ajaxSubmit = function(options, data, dataType, onSuccess) { 210 // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) 211 if (!this.length) { 212 log('ajaxSubmit: skipping submit process - no element selected'); 213 214 return this; 215 } 216 217 /* eslint consistent-this: ["error", "$form"] */ 218 var method, action, url, $form = this; 219 220 if (typeof options === 'function') { 221 options = {success: options}; 222 223 } else if (typeof options === 'string' || (options === false && arguments.length > 0)) { 224 options = { 225 'url' : options, 226 'data' : data, 227 'dataType' : dataType 228 }; 229 230 if (typeof onSuccess === 'function') { 231 options.success = onSuccess; 232 } 233 234 } else if (typeof options === 'undefined') { 235 options = {}; 236 } 237 238 method = options.method || options.type || this.attr2('method'); 239 action = options.url || this.attr2('action'); 240 241 url = (typeof action === 'string') ? $.trim(action) : ''; 242 url = url || window.location.href || ''; 243 if (url) { 244 // clean url (don't include hash vaue) 245 url = (url.match(/^([^#]+)/) || [])[1]; 246 } 247 248 options = $.extend(true, { 249 url : url, 250 success : $.ajaxSettings.success, 251 type : method || $.ajaxSettings.type, 252 iframeSrc : /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank' // eslint-disable-line no-script-url 253 }, options); 254 255 // hook for manipulating the form data before it is extracted; 256 // convenient for use with rich editors like tinyMCE or FCKEditor 257 var veto = {}; 258 259 this.trigger('form-pre-serialize', [this, options, veto]); 260 261 if (veto.veto) { 262 log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); 263 264 return this; 265 } 266 267 // provide opportunity to alter form data before it is serialized 268 if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { 269 log('ajaxSubmit: submit aborted via beforeSerialize callback'); 270 271 return this; 272 } 273 274 var traditional = options.traditional; 275 276 if (typeof traditional === 'undefined') { 277 traditional = $.ajaxSettings.traditional; 278 } 279 280 var elements = []; 281 var qx, a = this.formToArray(options.semantic, elements, options.filtering); 282 283 if (options.data) { 284 var optionsData = $.isFunction(options.data) ? options.data(a) : options.data; 285 286 options.extraData = optionsData; 287 qx = $.param(optionsData, traditional); 288 } 289 290 // give pre-submit callback an opportunity to abort the submit 291 if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { 292 log('ajaxSubmit: submit aborted via beforeSubmit callback'); 293 294 return this; 295 } 296 297 // fire vetoable 'validate' event 298 this.trigger('form-submit-validate', [a, this, options, veto]); 299 if (veto.veto) { 300 log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); 301 302 return this; 303 } 304 305 var q = $.param(a, traditional); 306 307 if (qx) { 308 q = (q ? (q + '&' + qx) : qx); 309 } 310 311 if (options.type.toUpperCase() === 'GET') { 312 options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; 313 options.data = null; // data is null for 'get' 314 } else { 315 options.data = q; // data is the query string for 'post' 316 } 317 318 var callbacks = []; 319 320 if (options.resetForm) { 321 callbacks.push(function() { 322 $form.resetForm(); 323 }); 324 } 325 326 if (options.clearForm) { 327 callbacks.push(function() { 328 $form.clearForm(options.includeHidden); 329 }); 330 } 331 332 // perform a load on the target only if dataType is not provided 333 if (!options.dataType && options.target) { 334 var oldSuccess = options.success || function(){}; 335 336 callbacks.push(function(data, textStatus, jqXHR) { 337 var successArguments = arguments, 338 fn = options.replaceTarget ? 'replaceWith' : 'html'; 339 340 $(options.target)[fn](data).each(function(){ 341 oldSuccess.apply(this, successArguments); 342 }); 343 }); 344 345 } else if (options.success) { 346 if ($.isArray(options.success)) { 347 $.merge(callbacks, options.success); 348 } else { 349 callbacks.push(options.success); 350 } 351 } 352 353 options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg 354 var context = options.context || this; // jQuery 1.4+ supports scope context 355 356 for (var i = 0, max = callbacks.length; i < max; i++) { 357 callbacks[i].apply(context, [data, status, xhr || $form, $form]); 358 } 359 }; 360 361 if (options.error) { 362 var oldError = options.error; 363 364 options.error = function(xhr, status, error) { 365 var context = options.context || this; 366 367 oldError.apply(context, [xhr, status, error, $form]); 368 }; 369 } 370 371 if (options.complete) { 372 var oldComplete = options.complete; 373 374 options.complete = function(xhr, status) { 375 var context = options.context || this; 376 377 oldComplete.apply(context, [xhr, status, $form]); 378 }; 379 } 380 381 // are there files to upload? 382 383 // [value] (issue #113), also see comment: 384 // https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219 385 var fileInputs = $('input[type=file]:enabled', this).filter(function() { 386 return $(this).val() !== ''; 387 }); 388 var hasFileInputs = fileInputs.length > 0; 389 var mp = 'multipart/form-data'; 390 var multipart = ($form.attr('enctype') === mp || $form.attr('encoding') === mp); 391 var fileAPI = feature.fileapi && feature.formdata; 392 393 log('fileAPI :' + fileAPI); 394 395 var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI; 396 var jqxhr; 397 398 // options.iframe allows user to force iframe mode 399 // 06-NOV-09: now defaulting to iframe mode if file input is detected 400 if (options.iframe !== false && (options.iframe || shouldUseFrame)) { 401 // hack to fix Safari hang (thanks to Tim Molendijk for this) 402 // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d 403 if (options.closeKeepAlive) { 404 $.get(options.closeKeepAlive, function() { 405 jqxhr = fileUploadIframe(a); 406 }); 407 408 } else { 409 jqxhr = fileUploadIframe(a); 410 } 411 412 } else if ((hasFileInputs || multipart) && fileAPI) { 413 jqxhr = fileUploadXhr(a); 414 415 } else { 416 jqxhr = $.ajax(options); 417 } 418 419 $form.removeData('jqxhr').data('jqxhr', jqxhr); 420 421 // clear element array 422 for (var k = 0; k < elements.length; k++) { 423 elements[k] = null; 424 } 425 426 // fire 'notify' event 427 this.trigger('form-submit-notify', [this, options]); 428 429 return this; 430 431 // utility fn for deep serialization 432 function deepSerialize(extraData) { 433 var serialized = $.param(extraData, options.traditional).split('&'); 434 var len = serialized.length; 435 var result = []; 436 var i, part; 437 438 for (i = 0; i < len; i++) { 439 // #252; undo param space replacement 440 serialized[i] = serialized[i].replace(/\+/g, ' '); 441 part = serialized[i].split('='); 442 // #278; use array instead of object storage, favoring array serializations 443 result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]); 444 } 445 446 return result; 447 } 448 449 // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz) 450 function fileUploadXhr(a) { 451 var formdata = new FormData(); 452 453 for (var i = 0; i < a.length; i++) { 454 formdata.append(a[i].name, a[i].value); 455 } 456 457 if (options.extraData) { 458 var serializedData = deepSerialize(options.extraData); 459 460 for (i = 0; i < serializedData.length; i++) { 461 if (serializedData[i]) { 462 formdata.append(serializedData[i][0], serializedData[i][1]); 463 } 464 } 465 } 466 467 options.data = null; 468 469 var s = $.extend(true, {}, $.ajaxSettings, options, { 470 contentType : false, 471 processData : false, 472 cache : false, 473 type : method || 'POST' 474 }); 475 476 if (options.uploadProgress) { 477 // workaround because jqXHR does not expose upload property 478 s.xhr = function() { 479 var xhr = $.ajaxSettings.xhr(); 480 481 if (xhr.upload) { 482 xhr.upload.addEventListener('progress', function(event) { 483 var percent = 0; 484 var position = event.loaded || event.position; /* event.position is deprecated */ 485 var total = event.total; 486 487 if (event.lengthComputable) {
488 percent = Math.ceil(position / total * 100); 489 } 490 491 options.uploadProgress(event, position, total, percent); 492 }, false); 493 } 494 495 return xhr; 496 }; 497 } 498 499 s.data = null; 500 501 var beforeSend = s.beforeSend; 502 503 s.beforeSend = function(xhr, o) { 504 // Send FormData() provided by user 505 if (options.formData) { 506 o.data = options.formData; 507 } else { 508 o.data = formdata; 509 } 510 511 if (beforeSend) { 512 beforeSend.call(this, xhr, o); 513 } 514 }; 515 516 return $.ajax(s); 517 } 518 519 // private function for handling file uploads (hat tip to YAHOO!) 520 function fileUploadIframe(a) { 521 var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle; 522 var deferred = $.Deferred(); 523 524 // #341 525 deferred.abort = function(status) { 526 xhr.abort(status); 527 }; 528 529 if (a) { 530 // ensure that every serialized input is still enabled 531 for (i = 0; i < elements.length; i++) { 532 el = $(elements[i]); 533 if (hasProp) { 534 el.prop('disabled', false); 535 } else { 536 el.removeAttr('disabled'); 537 } 538 } 539 } 540 541 s = $.extend(true, {}, $.ajaxSettings, options); 542 s.context = s.context || s; 543 id = 'jqFormIO' + new Date().getTime(); 544 var ownerDocument = form.ownerDocument; 545 var $body = $form.closest('body'); 546 547 if (s.iframeTarget) { 548 $io = $(s.iframeTarget, ownerDocument); 549 n = $io.attr2('name'); 550 if (!n) { 551 $io.attr2('name', id); 552 } else { 553 id = n; 554 } 555 556 } else { 557 $io = $('<iframe name="' + id + '" src="' + s.iframeSrc + '" />', ownerDocument); 558 $io.css({position: 'absolute', top: '-1000px', left: '-1000px'}); 559 } 560 io = $io[0]; 561 562 563 xhr = { // mock object 564 aborted : 0, 565 responseText : null, 566 responseXML : null, 567 status : 0, 568 statusText : 'n/a', 569 getAllResponseHeaders : function() {}, 570 getResponseHeader : function() {}, 571 setRequestHeader : function() {}, 572 abort : function(status) { 573 var e = (status === 'timeout' ? 'timeout' : 'aborted'); 574 575 log('aborting upload... ' + e); 576 this.aborted = 1; 577 578 try { // #214, #257 579 if (io.contentWindow.document.execCommand) { 580 io.contentWindow.document.execCommand('Stop'); 581 } 582 } catch (ignore) {} 583 584 $io.attr('src', s.iframeSrc); // abort op in progress 585 xhr.error = e; 586 if (s.error) { 587 s.error.call(s.context, xhr, e, status); 588 } 589 590 if (g) { 591 $.event.trigger('ajaxError', [xhr, s, e]); 592 } 593 594 if (s.complete) { 595 s.complete.call(s.context, xhr, e); 596 } 597 } 598 }; 599 600 g = s.global; 601 // trigger ajax global events so that activity/block indicators work like normal 602 if (g && $.active++ === 0) { 603 $.event.trigger('ajaxStart'); 604 } 605 if (g) { 606 $.event.trigger('ajaxSend', [xhr, s]); 607 } 608 609 if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) { 610 if (s.global) { 611 $.active--; 612 } 613 deferred.reject(); 614 615 return deferred; 616 } 617 618 if (xhr.aborted) { 619 deferred.reject(); 620 621 return deferred; 622 } 623 624 // add submitting element to data if we know it 625 sub = form.clk; 626 if (sub) { 627 n = sub.name; 628 if (n && !sub.disabled) { 629 s.extraData = s.extraData || {}; 630 s.extraData[n] = sub.value; 631 if (sub.type === 'image') { 632 s.extraData[n + '.x'] = form.clk_x; 633 s.extraData[n + '.y'] = form.clk_y; 634 } 635 } 636 } 637 638 var CLIENT_TIMEOUT_ABORT = 1; 639 var SERVER_ABORT = 2; 640 641 function getDoc(frame) { 642 /* it looks like contentWindow or contentDocument do not 643 * carry the protocol property in ie8, when running under ssl 644 * frame.document is the only valid response document, since 645 * the protocol is know but not on the other two objects. strange? 646 * "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy 647 */ 648 649 var doc = null; 650 651 // IE8 cascading access check 652 try { 653 if (frame.contentWindow) { 654 doc = frame.contentWindow.document; 655 } 656 } catch (err) { 657 // IE8 access denied under ssl & missing protocol 658 log('cannot get iframe.contentWindow document: ' + err); 659 } 660 661 if (doc) { // successful getting content 662 return doc; 663 } 664 665 try { // simply checking may throw in ie8 under ssl or mismatched protocol 666 doc = frame.contentDocument ? frame.contentDocument : frame.document; 667 } catch (err) { 668 // last attempt 669 log('cannot get iframe.contentDocument: ' + err); 670 doc = frame.document; 671 } 672 673 return doc; 674 } 675 676 // Rails CSRF hack (thanks to Yvan Barthelemy) 677 var csrf_token = $('meta[name=csrf-token]').attr('content'); 678 var csrf_param = $('meta[name=csrf-param]').attr('content'); 679 680 if (csrf_param && csrf_token) { 681 s.extraData = s.extraData || {}; 682 s.extraData[csrf_param] = csrf_token; 683 } 684 685 // take a breath so that pending repaints get some cpu time before the upload starts 686 function doSubmit() { 687 // make sure form attrs are set 688 var t = $form.attr2('target'), 689 a = $form.attr2('action'),
690 mp = 'multipart/form-data', 691 et = $form.attr('enctype') || $form.attr('encoding') || mp; 692 693 // update form attrs in IE friendly way 694 form.setAttribute('target', id); 695 if (!method || /post/i.test(method)) { 696 form.setAttribute('method', 'POST'); 697 } 698 if (a !== s.url) { 699 form.setAttribute('action', s.url); 700 } 701 702 // ie borks in some cases when setting encoding 703 if (!s.skipEncodingOverride && (!method || /post/i.test(method))) { 704 $form.attr({ 705 encoding : 'multipart/form-data', 706 enctype : 'multipart/form-data' 707 }); 708 } 709 710 // support timout 711 if (s.timeout) { 712 timeoutHandle = setTimeout(function() { 713 timedOut = true; cb(CLIENT_TIMEOUT_ABORT); 714 }, s.timeout); 715 } 716 717 // look for server aborts 718 function checkState() { 719 try { 720 var state = getDoc(io).readyState; 721 722 log('state = ' + state); 723 if (state && state.toLowerCase() === 'uninitialized') { 724 setTimeout(checkState, 50); 725 } 726 727 } catch (e) { 728 log('Server abort: ', e, ' (', e.name, ')'); 729 cb(SERVER_ABORT); // eslint-disable-line callback-return 730 if (timeoutHandle) { 731 clearTimeout(timeoutHandle); 732 } 733 timeoutHandle = undefined; 734 } 735 } 736 737 // add "extra" data to form if provided in options 738 var extraInputs = []; 739 740 try { 741 if (s.extraData) { 742 for (var n in s.extraData) { 743 if (s.extraData.hasOwnProperty(n)) { 744 // if using the $.param format that allows for multiple values with the same name 745 if ($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) { 746 extraInputs.push( 747 $('<input type="hidden" name="' + s.extraData[n].name + '">', ownerDocument).val(s.extraData[n].value) 748 .appendTo(form)[0]); 749 } else { 750 extraInputs.push( 751 $('<input type="hidden" name="' + n + '">', ownerDocument).val(s.extraData[n]) 752 .appendTo(form)[0]); 753 } 754 } 755 } 756 } 757 758 if (!s.iframeTarget) { 759 // add iframe to doc and submit the form 760 $io.appendTo($body); 761 } 762 763 if (io.attachEvent) { 764 io.attachEvent('onload', cb); 765 } else { 766 io.addEventListener('load', cb, false); 767 } 768 769 setTimeout(checkState, 15); 770 771 try { 772 form.submit(); 773 774 } catch (err) { 775 // just in case form has element with name/id of 'submit' 776 var submitFn = document.createElement('form').submit; 777 778 submitFn.apply(form); 779 } 780 781 } finally { 782 // reset attrs and remove "extra" input elements 783 form.setAttribute('action', a); 784 form.setAttribute('enctype', et); // #380 785 if (t) { 786 form.setAttribute('target', t); 787 } else { 788 $form.removeAttr('target'); 789 } 790 $(extraInputs).remove(); 791 } 792 } 793 794 if (s.forceSync) { 795 doSubmit(); 796 } else { 797 setTimeout(doSubmit, 10); // this lets dom updates render 798 } 799 800 var data, doc, domCheckCount = 50, callbackProcessed; 801 802 function cb(e) { 803 if (xhr.aborted || callbackProcessed) { 804 return; 805 } 806 807 doc = getDoc(io); 808 if (!doc) { 809 log('cannot access response document'); 810 e = SERVER_ABORT; 811 } 812 if (e === CLIENT_TIMEOUT_ABORT && xhr) { 813 xhr.abort('timeout'); 814 deferred.reject(xhr, 'timeout'); 815 816 return; 817 818 } else if (e === SERVER_ABORT && xhr) { 819 xhr.abort('server abort'); 820 deferred.reject(xhr, 'error', 'server abort'); 821 822 return; 823 } 824 825 if (!doc || doc.location.href === s.iframeSrc) { 826 // response not received yet 827 if (!timedOut) { 828 return; 829 } 830 } 831 832 if (io.detachEvent) { 833 io.detachEvent('onload', cb); 834 } else { 835 io.removeEventListener('load', cb, false); 836 } 837 838 var status = 'success', errMsg; 839 840 try { 841 if (timedOut) { 842 throw 'timeout'; 843 } 844 845 var isXml = s.dataType === 'xml' || doc.XMLDocument || $.isXMLDoc(doc); 846 847 log('isXml=' + isXml); 848 849 if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) { 850 if (--domCheckCount) { 851 // in some browsers (Opera) the iframe DOM is not always traversable when 852 // the onload callback fires, so we loop a bit to accommodate 853 log('requeing onLoad callback, DOM not available'); 854 setTimeout(cb, 250); 855 856 return; 857 } 858 // let this fall through because server response could be an empty document 859 // log('Could not access iframe DOM after mutiple tries.'); 860 // throw 'DOMException: not available'; 861 } 862 863 // log('response detected'); 864 var docRoot = doc.body ? doc.body : doc.documentElement; 865 866 xhr.responseText = docRoot ? docRoot.innerHTML : null; 867 xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc; 868 if (isXml) { 869 s.dataType = 'xml'; 870 } 871 xhr.getResponseHeader = function(header){ 872 var headers = {'content-type': s.dataType}; 873 874 return headers[header.toLowerCase()]; 875 }; 876 // support for XHR 'status' & 'statusText' emulation : 877 if (docRoot) { 878 xhr.status = Number(docRoot.getAttribute('status')) || xhr.status; 879 xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText; 880 } 881 882 var dt = (s.dataType || '').toLowerCase(); 883 var scr = /(json|script|text)/.test(dt); 884 885 if (scr || s.textarea) { 886 // see if user embedded response in textarea 887 var ta = doc.getElementsByTagName('textarea')[0]; 888 889 if (ta) { 890 xhr.responseText = ta.value; 891 // support for XHR 'status' & 'statusText' emulation : 892 xhr.status = Number(ta.getAttribute('status')) || xhr.status; 893 xhr.statusText = ta.getAttribute('statusText') || xhr.statusText; 894 895 } else if (scr) { 896 // account for browsers injecting pre around json response 897 var pre = doc.getElementsByTagName('pre')[0]; 898 var b = doc.getElementsByTagName('body')[0]; 899 900 if (pre) { 901 xhr.responseText = pre.textContent ? pre.textContent : pre.innerText; 902 } else if (b) { 903 xhr.responseText = b.textContent ? b.textContent : b.innerText; 904 } 905 } 906 907 } else if (dt === 'xml' && !xhr.responseXML && xhr.responseText) { 908 xhr.responseXML = toXml(xhr.responseText); // eslint-disable-line no-use-before-define 909 } 910 911 try { 912 data = httpData(xhr, dt, s); // eslint-disable-line no-use-before-define 913 914 } catch (err) { 915 status = 'parsererror'; 916 xhr.error = errMsg = (err || status); 917 } 918 919 } catch (err) { 920 log('error caught: ', err); 921 status = 'error'; 922 xhr.error = errMsg = (err || status); 923 } 924 925 if (xhr.aborted) { 926 log('upload aborted'); 927 status = null; 928 } 929 930 if (xhr.status) { // we've set xhr.status 931 status = ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) ? 'success' : 'error'; 932 } 933 934 // ordering of these callbacks/triggers is odd, but that's how $.ajax does it 935 if (status === 'success') { 936 if (s.success) { 937 s.success.call(s.context, data, 'success', xhr); 938 } 939 940 deferred.resolve(xhr.responseText, 'success', xhr); 941 942 if (g) {
943 $.event.trigger('ajaxSuccess', [xhr, s]); 944 } 945 946 } else if (status) { 947 if (typeof errMsg === 'undefined') { 948 errMsg = xhr.statusText; 949 } 950 if (s.error) { 951 s.error.call(s.context, xhr, status, errMsg); 952 } 953 deferred.reject(xhr, 'error', errMsg); 954 if (g) { 955 $.event.trigger('ajaxError', [xhr, s, errMsg]); 956 } 957 } 958 959 if (g) { 960 $.event.trigger('ajaxComplete', [xhr, s]); 961 } 962 963 if (g && !--$.active) { 964 $.event.trigger('ajaxStop'); 965 } 966 967 if (s.complete) { 968 s.complete.call(s.context, xhr, status); 969 } 970 971 callbackProcessed = true; 972 if (s.timeout) { 973 clearTimeout(timeoutHandle); 974 } 975 976 // clean up 977 setTimeout(function() { 978 if (!s.iframeTarget) { 979 $io.remove(); 980 } else { // adding else to clean up existing iframe response. 981 $io.attr('src', s.iframeSrc); 982 } 983 xhr.responseXML = null; 984 }, 100); 985 } 986 987 var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+) 988 if (window.ActiveXObject) { 989 doc = new ActiveXObject('Microsoft.XMLDOM'); 990 doc.async = 'false'; 991 doc.loadXML(s); 992 993 } else { 994 doc = (new DOMParser()).parseFromString(s, 'text/xml'); 995 } 996 997 return (doc && doc.documentElement && doc.documentElement.nodeName !== 'parsererror') ? doc : null; 998 }; 999 var parseJSON = $.parseJSON || function(s) { 1000 /* jslint evil:true */ 1001 return window['eval']('(' + s + ')'); // eslint-disable-line dot-notation 1002 }; 1003 1004 var httpData = function(xhr, type, s) { // mostly lifted from jq1.4.4 1005 1006 var ct = xhr.getResponseHeader('content-type') || '', 1007 xml = ((type === 'xml' || !type) && ct.indexOf('xml') >= 0), 1008 data = xml ? xhr.responseXML : xhr.responseText; 1009 1010 if (xml && data.documentElement.nodeName === 'parsererror') { 1011 if ($.error) { 1012 $.error('parsererror'); 1013 } 1014 } 1015 if (s && s.dataFilter) { 1016 data = s.dataFilter(data, type); 1017 } 1018 if (typeof data === 'string') { 1019 if ((type === 'json' || !type) && ct.indexOf('json') >= 0) { 1020 data = parseJSON(data); 1021 } else if ((type === 'script' || !type) && ct.indexOf('javascript') >= 0) { 1022 $.globalEval(data); 1023 } 1024 } 1025 1026 return data; 1027 }; 1028 1029 return deferred; 1030 } 1031 }; 1032 1033 /** 1034 * ajaxForm() provides a mechanism for fully automating form submission. 1035 * 1036 * The advantages of using this method instead of ajaxSubmit() are: 1037 * 1038 * 1: This method will include coordinates for <input type="image"> elements (if the element 1039 * is used to submit the form). 1040 * 2. This method will include the submit element's name/value data (for the element that was 1041 * used to submit the form). 1042 * 3. This method binds the submit() method to the form for you. 1043 * 1044 * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely 1045 * passes the options argument along after properly binding events for submit elements and 1046 * the form itself. 1047 */ 1048 $.fn.ajaxForm = function(options, data, dataType, onSuccess) { 1049 if (typeof options === 'string' || (options === false && arguments.length > 0)) { 1050 options = { 1051 'url' : options, 1052 'data' : data, 1053 'dataType' : dataType 1054 }; 1055 1056 if (typeof onSuccess === 'function') { 1057 options.success = onSuccess; 1058 } 1059 } 1060 1061 options = options || {}; 1062 options.delegation = options.delegation && $.isFunction($.fn.on); 1063 1064 // in jQuery 1.3+ we can fix mistakes with the ready state 1065 if (!options.delegation && this.length === 0) { 1066 var o = {s: this.selector, c: this.context}; 1067 1068 if (!$.isReady && o.s) { 1069 log('DOM not ready, queuing ajaxForm'); 1070 $(function() { 1071 $(o.s, o.c).ajaxForm(options); 1072 }); 1073 1074 return this; 1075 } 1076 1077 // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready() 1078 log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)')); 1079 1080 return this; 1081 } 1082 1083 if (options.delegation) { 1084 $(document) 1085 .off('submit.form-plugin', this.selector, doAjaxSubmit) 1086 .off('click.form-plugin', this.selector, captureSubmittingElement) 1087 .on('submit.form-plugin', this.selector, options, doAjaxSubmit) 1088 .on('click.form-plugin', this.selector, options, captureSubmittingElement); 1089 1090 return this; 1091 } 1092 1093 return this.ajaxFormUnbind() 1094 .on('submit.form-plugin', options, doAjaxSubmit) 1095 .on('click.form-plugin', options, captureSubmittingElement); 1096 }; 1097 1098 // private event handlers 1099 function doAjaxSubmit(e) { 1100 /* jshint validthis:true */ 1101 var options = e.data; 1102 1103 if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed 1104 e.preventDefault(); 1105 $(e.target).closest('form').ajaxSubmit(options); // #365 1106 } 1107 } 1108 1109 function captureSubmittingElement(e) { 1110 /* jshint validthis:true */ 1111 var target = e.target; 1112 var $el = $(target); 1113 1114 if (!$el.is('[type=submit],[type=image]')) { 1115 // is this a child element of the submit el? (ex: a span within a button) 1116 var t = $el.closest('[type=submit]'); 1117 1118 if (t.length === 0) { 1119 return; 1120 } 1121 target = t[0]; 1122 } 1123 1124 var form = target.form; 1125 1126 form.clk = target; 1127 1128 if (target.type === 'image') { 1129 if (typeof e.offsetX !== 'undefined') { 1130 form.clk_x = e.offsetX; 1131 form.clk_y = e.offsetY; 1132 1133 } else if (typeof $.fn.offset === 'function') { 1134 var offset = $el.offset(); 1135 1136 form.clk_x = e.pageX - offset.left; 1137 form.clk_y = e.pageY - offset.top; 1138 1139 } else { 1140 form.clk_x = e.pageX - target.offsetLeft; 1141 form.clk_y = e.pageY - target.offsetTop; 1142 } 1143 } 1144 // clear form vars 1145 setTimeout(function() { 1146 form.clk = form.clk_x = form.clk_y = null; 1147 }, 100); 1148 } 1149 1150 1151 // ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm 1152 $.fn.ajaxFormUnbind = function() { 1153 return this.off('submit.form-plugin click.form-plugin'); 1154 }; 1155 1156 /** 1157 * formToArray() gathers form element data into an array of objects that can 1158 * be passed to any of the following ajax functions: $.get, $.post, or load. 1159 * Each object in the array has both a 'name' and 'value' property. An example of 1160 * an array for a simple login form might be: 1161 * 1162 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ] 1163 * 1164 * It is this array that is passed to pre-submit callback functions provided to the 1165 * ajaxSubmit() and ajaxForm() methods. 1166 */ 1167 $.fn.formToArray = function(semantic, elements, filtering) { 1168 var a = []; 1169 1170 if (this.length === 0) { 1171 return a; 1172 } 1173 1174 var form = this[0]; 1175 var formId = this.attr('id'); 1176 var els = (semantic || typeof form.elements === 'undefined') ? form.getElementsByTagName('*') : form.elements; 1177 var els2; 1178 1179 if (els) { 1180 els = $.makeArray(els); // convert to standard array 1181 } 1182 1183 // #386; account for inputs outside the form which use the 'form' attribute 1184 // FinesseRus: in non-IE browsers outside fields are already included in form.elements. 1185 if (formId && (semantic || /(Edge|Trident)\//.test(navigator.userAgent))) { 1186 els2 = $(':input[form="' + formId + '"]').get(); // hat tip @thet 1187 if (els2.length) { 1188 els = (els || []).concat(els2); 1189 } 1190 } 1191 1192 if (!els || !els.length) { 1193 return a; 1194 } 1195
1196 if ($.isFunction(filtering)) { 1197 els = $.map(els, filtering); 1198 } 1199 1200 var i, j, n, v, el, max, jmax; 1201 1202 for (i = 0, max = els.length; i < max; i++) { 1203 el = els[i]; 1204 n = el.name; 1205 if (!n || el.disabled) { 1206 continue; 1207 } 1208 1209 if (semantic && form.clk && el.type === 'image') { 1210 // handle image inputs on the fly when semantic == true 1211 if (form.clk === el) { 1212 a.push({name: n, value: $(el).val(), type: el.type}); 1213 a.push({name: n + '.x', value: form.clk_x}, {name: n + '.y', value: form.clk_y}); 1214 } 1215 continue; 1216 } 1217 1218 v = $.fieldValue(el, true); 1219 if (v && v.constructor === Array) { 1220 if (elements) { 1221 elements.push(el); 1222 } 1223 for (j = 0, jmax = v.length; j < jmax; j++) { 1224 a.push({name: n, value: v[j]}); 1225 } 1226 1227 } else if (feature.fileapi && el.type === 'file') { 1228 if (elements) { 1229 elements.push(el); 1230 } 1231 1232 var files = el.files; 1233 1234 if (files.length) { 1235 for (j = 0; j < files.length; j++) { 1236 a.push({name: n, value: files[j], type: el.type}); 1237 } 1238 } else { 1239 // #180 1240 a.push({name: n, value: '', type: el.type}); 1241 } 1242 1243 } else if (v !== null && typeof v !== 'undefined') { 1244 if (elements) { 1245 elements.push(el); 1246 } 1247 a.push({name: n, value: v, type: el.type, required: el.required}); 1248 } 1249 } 1250 1251 if (!semantic && form.clk) { 1252 // input type=='image' are not found in elements array! handle it here 1253 var $input = $(form.clk), input = $input[0]; 1254 1255 n = input.name; 1256 1257 if (n && !input.disabled && input.type === 'image') { 1258 a.push({name: n, value: $input.val()}); 1259 a.push({name: n + '.x', value: form.clk_x}, {name: n + '.y', value: form.clk_y}); 1260 } 1261 } 1262 1263 return a; 1264 }; 1265 1266 /** 1267 * Serializes form data into a 'submittable' string. This method will return a string 1268 * in the format: name1=value1&name2=value2 1269 */ 1270 $.fn.formSerialize = function(semantic) { 1271 // hand off to jQuery.param for proper encoding 1272 return $.param(this.formToArray(semantic)); 1273 }; 1274 1275 /** 1276 * Serializes all field elements in the jQuery object into a query string. 1277 * This method will return a string in the format: name1=value1&name2=value2 1278 */ 1279 $.fn.fieldSerialize = function(successful) { 1280 var a = []; 1281 1282 this.each(function() { 1283 var n = this.name; 1284 1285 if (!n) { 1286 return; 1287 } 1288 1289 var v = $.fieldValue(this, successful); 1290 1291 if (v && v.constructor === Array) { 1292 for (var i = 0, max = v.length; i < max; i++) { 1293 a.push({name: n, value: v[i]}); 1294 } 1295 1296 } else if (v !== null && typeof v !== 'undefined') { 1297 a.push({name: this.name, value: v}); 1298 } 1299 }); 1300 1301 // hand off to jQuery.param for proper encoding 1302 return $.param(a); 1303 }; 1304 1305 /** 1306 * Returns the value(s) of the element in the matched set. For example, consider the following form: 1307 * 1308 * <form><fieldset> 1309 * <input name="A" type="text"> 1310 * <input name="A" type="text"> 1311 * <input name="B" type="checkbox" value="B1"> 1312 * <input name="B" type="checkbox" value="B2"> 1313 * <input name="C" type="radio" value="C1"> 1314 * <input name="C" type="radio" value="C2"> 1315 * </fieldset></form> 1316 * 1317 * var v = $('input[type=text]').fieldValue(); 1318 * // if no values are entered into the text inputs 1319 * v === ['',''] 1320 * // if values entered into the text inputs are 'foo' and 'bar' 1321 * v === ['foo','bar'] 1322 * 1323 * var v = $('input[type=checkbox]').fieldValue(); 1324 * // if neither checkbox is checked 1325 * v === undefined 1326 * // if both checkboxes are checked 1327 * v === ['B1', 'B2'] 1328 * 1329 * var v = $('input[type=radio]').fieldValue(); 1330 * // if neither radio is checked 1331 * v === undefined 1332 * // if first radio is checked 1333 * v === ['C1'] 1334 * 1335 * The successful argument controls whether or not the field element must be 'successful' 1336 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls). 1337 * The default value of the successful argument is true. If this value is false the value(s) 1338 * for each element is returned. 1339 * 1340 * Note: This method *always* returns an array. If no valid value can be determined the 1341 * array will be empty, otherwise it will contain one or more values. 1342 */ 1343 $.fn.fieldValue = function(successful) { 1344 for (var val = [], i = 0, max = this.length; i < max; i++) { 1345 var el = this[i]; 1346 var v = $.fieldValue(el, successful); 1347 1348 if (v === null || typeof v === 'undefined' || (v.constructor === Array && !v.length)) { 1349 continue; 1350 } 1351 1352 if (v.constructor === Array) { 1353 $.merge(val, v); 1354 } else { 1355 val.push(v); 1356 } 1357 } 1358 1359 return val; 1360 }; 1361 1362 /** 1363 * Returns the value of the field element. 1364 */ 1365 $.fieldValue = function(el, successful) { 1366 var n = el.name, t = el.type, tag = el.tagName.toLowerCase(); 1367 1368 if (typeof successful === 'undefined') { 1369 successful = true; 1370 } 1371 1372 /* eslint-disable no-mixed-operators */ 1373 if (successful && (!n || el.disabled || t === 'reset' || t === 'button' || 1374 (t === 'checkbox' || t === 'radio') && !el.checked || 1375 (t === 'submit' || t === 'image') && el.form && el.form.clk !== el || 1376 tag === 'select' && el.selectedIndex === -1)) { 1377 /* eslint-enable no-mixed-operators */ 1378 return null; 1379 } 1380 1381 if (tag === 'select') { 1382 var index = el.selectedIndex; 1383 1384 if (index < 0) { 1385 return null; 1386 } 1387 1388 var a = [], ops = el.options; 1389 var one = (t === 'select-one'); 1390 var max = (one ? index + 1 : ops.length); 1391 1392 for (var i = (one ? index : 0); i < max; i++) { 1393 var op = ops[i]; 1394 1395 if (op.selected && !op.disabled) { 1396 var v = op.value; 1397 1398 if (!v) { // extra pain for IE... 1399 v = (op.attributes && op.attributes.value && !(op.attributes.value.specified)) ? op.text : op.value; 1400 } 1401 1402 if (one) { 1403 return v; 1404 } 1405 1406 a.push(v); 1407 } 1408 } 1409 1410 return a; 1411 } 1412 1413 return $(el).val().replace(rCRLF, '\r\n'); 1414 }; 1415 1416 /** 1417 * Clears the form data. Takes the following actions on the form's input fields: 1418 * - input text fields will have their 'value' property set to the empty string 1419 * - select elements will have their 'selectedIndex' property set to -1 1420 * - checkbox and radio inputs will have their 'checked' property set to false 1421 * - inputs of type submit, button, reset, and hidden will *not* be effected 1422 * - button elements will *not* be effected 1423 */ 1424 $.fn.clearForm = function(includeHidden) { 1425 return this.each(function() { 1426 $('input,select,textarea', this).clearFields(includeHidden); 1427 }); 1428 }; 1429 1430 /** 1431 * Clears the selected form elements. 1432 */ 1433 $.fn.clearFields = $.fn.clearInputs = function(includeHidden) { 1434 var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list 1435 1436 return this.each(function() { 1437 var t = this.type, tag = this.tagName.toLowerCase(); 1438 1439 if (re.test(t) || tag === 'textarea') { 1440 this.value = ''; 1441 1442 } else if (t === 'checkbox' || t === 'radio') { 1443 this.checked = false;
1444 1445 } else if (tag === 'select') { 1446 this.selectedIndex = -1; 1447 1448 } else if (t === 'file') { 1449 if (/MSIE/.test(navigator.userAgent)) { 1450 $(this).replaceWith($(this).clone(true)); 1451 } else { 1452 $(this).val(''); 1453 } 1454 1455 } else if (includeHidden) { 1456 // includeHidden can be the value true, or it can be a selector string 1457 // indicating a special test; for example: 1458 // $('#myForm').clearForm('.special:hidden') 1459 // the above would clean hidden inputs that have the class of 'special' 1460 if ((includeHidden === true && /hidden/.test(t)) || 1461 (typeof includeHidden === 'string' && $(this).is(includeHidden))) { 1462 this.value = ''; 1463 } 1464 } 1465 }); 1466 }; 1467 1468 1469 /** 1470 * Resets the form data or individual elements. Takes the following actions 1471 * on the selected tags: 1472 * - all fields within form elements will be reset to their original value 1473 * - input / textarea / select fields will be reset to their original value 1474 * - option / optgroup fields (for multi-selects) will defaulted individually 1475 * - non-multiple options will find the right select to default 1476 * - label elements will be searched against its 'for' attribute 1477 * - all others will be searched for appropriate children to default 1478 */ 1479 $.fn.resetForm = function() { 1480 return this.each(function() { 1481 var el = $(this); 1482 var tag = this.tagName.toLowerCase(); 1483 1484 switch (tag) { 1485 case 'input': 1486 this.checked = this.defaultChecked; 1487 // fall through 1488 1489 case 'textarea': 1490 this.value = this.defaultValue; 1491 1492 return true; 1493 1494 case 'option': 1495 case 'optgroup': 1496 var select = el.parents('select'); 1497 1498 if (select.length && select[0].multiple) { 1499 if (tag === 'option') { 1500 this.selected = this.defaultSelected; 1501 } else { 1502 el.find('option').resetForm(); 1503 } 1504 } else { 1505 select.resetForm(); 1506 } 1507 1508 return true; 1509 1510 case 'select': 1511 el.find('option').each(function(i) { // eslint-disable-line consistent-return 1512 this.selected = this.defaultSelected; 1513 if (this.defaultSelected && !el[0].multiple) { 1514 el[0].selectedIndex = i; 1515 1516 return false; 1517 } 1518 }); 1519 1520 return true; 1521 1522 case 'label': 1523 var forEl = $(el.attr('for')); 1524 var list = el.find('input,select,textarea'); 1525 1526 if (forEl[0]) { 1527 list.unshift(forEl[0]); 1528 } 1529 1530 list.resetForm(); 1531 1532 return true; 1533 1534 case 'form': 1535 // guard against an input with the name of 'reset' 1536 // note that IE reports the reset function as an 'object' 1537 if (typeof this.reset === 'function' || (typeof this.reset === 'object' && !this.reset.nodeType)) { 1538 this.reset(); 1539 } 1540 1541 return true; 1542 1543 default: 1544 el.find('form,input,label,select,textarea').resetForm(); 1545 1546 return true; 1547 } 1548 }); 1549 }; 1550 1551 /** 1552 * Enables or disables any matching elements. 1553 */ 1554 $.fn.enable = function(b) { 1555 if (typeof b === 'undefined') { 1556 b = true; 1557 } 1558 1559 return this.each(function() { 1560 this.disabled = !b; 1561 }); 1562 }; 1563 1564 /** 1565 * Checks/unchecks any matching checkboxes or radio buttons and 1566 * selects/deselects and matching option elements. 1567 */ 1568 $.fn.selected = function(select) { 1569 if (typeof select === 'undefined') { 1570 select = true; 1571 } 1572 1573 return this.each(function() { 1574 var t = this.type; 1575 1576 if (t === 'checkbox' || t === 'radio') { 1577 this.checked = select; 1578 1579 } else if (this.tagName.toLowerCase() === 'option') { 1580 var $sel = $(this).parent('select'); 1581 1582 if (select && $sel[0] && $sel[0].type === 'select-one') { 1583 // deselect all other options 1584 $sel.find('option').selected(false); 1585 } 1586 1587 this.selected = select; 1588 } 1589 }); 1590 }; 1591 1592 // expose debug var 1593 $.fn.ajaxSubmit.debug = false; 1594 1595 // helper fn for console logging 1596 function log() { 1597 if (!$.fn.ajaxSubmit.debug) { 1598 return; 1599 } 1600 1601 var msg = '[jquery.form] ' + Array.prototype.join.call(arguments, ''); 1602 1603 if (window.console && window.console.log) { 1604 window.console.log(msg); 1605 1606 } else if (window.opera && window.opera.postError) { 1607 window.opera.postError(msg); 1608 } 1609 } 1610})); 1611; 1612(function ($) { 1613 Drupal.viewsSlideshow = Drupal.viewsSlideshow || {}; 1614 1615 /** 1616 * Views Slideshow Controls 1617 */ 1618 Drupal.viewsSlideshowControls = Drupal.viewsSlideshowControls || {}; 1619 1620 /**
1621 * Implement the play hook for controls. 1622 */ 1623 Drupal.viewsSlideshowControls.play = function (options) { 1624 // Route the control call to the correct control type. 1625 // Need to use try catch so we don't have to check to make sure every part 1626 // of the object is defined. 1627 try { 1628 if (typeof Drupal.settings.viewsSlideshowControls[options.slideshowID].top.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].top.type].play == 'function') { 1629 Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].top.type].play(options); 1630 } 1631 } 1632 catch(err) { 1633 // Don't need to do anything on error. 1634 } 1635 1636 try { 1637 if (typeof Drupal.settings.viewsSlideshowControls[options.slideshowID].bottom.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].bottom.type].play == 'function') { 1638 Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].bottom.type].play(options); 1639 } 1640 } 1641 catch(err) { 1642 // Don't need to do anything on error. 1643 } 1644 }; 1645 1646 /** 1647 * Implement the pause hook for controls. 1648 */ 1649 Drupal.viewsSlideshowControls.pause = function (options) { 1650 // Route the control call to the correct control type. 1651 // Need to use try catch so we don't have to check to make sure every part 1652 // of the object is defined. 1653 try { 1654 if (typeof Drupal.settings.viewsSlideshowControls[options.slideshowID].top.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].top.type].pause == 'function') { 1655 Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].top.type].pause(options); 1656 } 1657 } 1658 catch(err) { 1659 // Don't need to do anything on error. 1660 } 1661 1662 try { 1663 if (typeof Drupal.settings.viewsSlideshowControls[options.slideshowID].bottom.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].bottom.type].pause == 'function') { 1664 Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].bottom.type].pause(options); 1665 } 1666 } 1667 catch(err) { 1668 // Don't need to do anything on error. 1669 } 1670 }; 1671 1672 1673 /** 1674 * Views Slideshow Text Controls 1675 */ 1676 1677 // Add views slideshow api calls for views slideshow text controls. 1678 Drupal.behaviors.viewsSlideshowControlsText = { 1679 attach: function (context) { 1680 1681 // Process previous link 1682 $('.views_slideshow_controls_text_previous:not(.views-slideshow-controls-text-previous-processed)', context).addClass('views-slideshow-controls-text-previous-processed').each(function() { 1683 var uniqueID = $(this).attr('id').replace('views_slideshow_controls_text_previous_', ''); 1684 $(this).click(function() { 1685 Drupal.viewsSlideshow.action({ "action": 'previousSlide', "slideshowID": uniqueID }); 1686 return false; 1687 }); 1688 }); 1689 1690 // Process next link 1691 $('.views_slideshow_controls_text_next:not(.views-slideshow-controls-text-next-processed)', context).addClass('views-slideshow-controls-text-next-processed').each(function() { 1692 var uniqueID = $(this).attr('id').replace('views_slideshow_controls_text_next_', ''); 1693 $(this).click(function() { 1694 Drupal.viewsSlideshow.action({ "action": 'nextSlide', "slideshowID": uniqueID }); 1695 return false; 1696 }); 1697 }); 1698 1699 // Process pause link 1700 $('.views_slideshow_controls_text_pause:not(.views-slideshow-controls-text-pause-processed)', context).addClass('views-slideshow-controls-text-pause-processed').each(function() { 1701 var uniqueID = $(this).attr('id').replace('views_slideshow_controls_text_pause_', ''); 1702 $(this).click(function() { 1703 if (Drupal.settings.viewsSlideshow[uniqueID].paused) { 1704 Drupal.viewsSlideshow.action({ "action": 'play', "slideshowID": uniqueID, "force": true }); 1705 } 1706 else { 1707 Drupal.viewsSlideshow.action({ "action": 'pause', "slideshowID": uniqueID, "force": true }); 1708 } 1709 return false; 1710 }); 1711 }); 1712 } 1713 }; 1714 1715 Drupal.viewsSlideshowControlsText = Drupal.viewsSlideshowControlsText || {}; 1716 1717 /** 1718 * Implement the pause hook for text controls. 1719 */ 1720 Drupal.viewsSlideshowControlsText.pause = function (options) { 1721 var pauseText = Drupal.theme.prototype['viewsSlideshowControlsPause'] ? Drupal.theme('viewsSlideshowControlsPause') : ''; 1722 $('#views_slideshow_controls_text_pause_' + options.slideshowID + ' a').text(pauseText); 1723 $('#views_slideshow_controls_text_pause_' + options.slideshowID).removeClass('views-sli
1723deshow-controls-text-status-play'); 1724 $('#views_slideshow_controls_text_pause_' + options.slideshowID).addClass('views-slideshow-controls-text-status-pause'); 1725 }; 1726 1727 /** 1728 * Implement the play hook for text controls. 1729 */ 1730 Drupal.viewsSlideshowControlsText.play = function (options) { 1731 var playText = Drupal.theme.prototype['viewsSlideshowControlsPlay'] ? Drupal.theme('viewsSlideshowControlsPlay') : ''; 1732 $('#views_slideshow_controls_text_pause_' + options.slideshowID + ' a').text(playText); 1733 $('#views_slideshow_controls_text_pause_' + options.slideshowID).removeClass('views-slideshow-controls-text-status-pause'); 1734 $('#views_slideshow_controls_text_pause_' + options.slideshowID).addClass('views-slideshow-controls-text-status-play'); 1735 }; 1736 1737 // Theme the resume control. 1738 Drupal.theme.prototype.viewsSlideshowControlsPause = function () { 1739 return Drupal.t('Resume'); 1740 }; 1741 1742 // Theme the pause control. 1743 Drupal.theme.prototype.viewsSlideshowControlsPlay = function () { 1744 return Drupal.t('Pause'); 1745 }; 1746 1747 /** 1748 * Views Slideshow Pager 1749 */ 1750 Drupal.viewsSlideshowPager = Drupal.viewsSlideshowPager || {}; 1751 1752 /** 1753 * Implement the transitionBegin hook for pagers. 1754 */ 1755 Drupal.viewsSlideshowPager.transitionBegin = function (options) { 1756 // Route the pager call to the correct pager type. 1757 // Need to use try catch so we don't have to check to make sure every part 1758 // of the object is defined. 1759 try { 1760 if (typeof Drupal.settings.viewsSlideshowPager != "undefined" && typeof Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].transitionBegin == 'function') { 1761 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].transitionBegin(options); 1762 if (Drupal.settings.viewsSlideshowPager[options.slideshowID].top.master_pager === 1) { 1763 $.each(Drupal.settings.viewsSlideshow, function(i, obj) { 1764 if (i != options.slideshowID) { 1765 options.slideshowID = i; 1766 options.action = 'goToSlide'; 1767 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].goToSlide(options); 1768 } 1769 }); 1770 } 1771 } 1772 } 1773 catch(err) { 1774 // Don't need to do anything on error. 1775 } 1776 1777 try { 1778 if (typeof Drupal.settings.viewsSlideshowPager != "undefined" && typeof Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].transitionBegin == 'function') { 1779 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].transitionBegin(options); 1780 if (Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.master_pager === 1) { 1781 $.each(Drupal.settings.viewsSlideshow, function(i, obj) { 1782 if (i != options.slideshowID) { 1783 options.slideshowID = i; 1784 options.action = 'goToSlide'; 1785 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].goToSlide(options); 1786 } 1787 }); 1788 } 1789 } 1790 } 1791 catch(err) { 1792 // Don't need to do anything on error. 1793 } 1794 }; 1795 1796 /** 1797 * Implement the goToSlide hook for pagers. 1798 */ 1799 Drupal.viewsSlideshowPager.goToSlide = function (options) { 1800 // Route the pager call to the correct pager type. 1801 // Need to use try catch so we don't have to check to make sure every part 1802 // of the object is defined. 1803 try { 1804 if (typeof Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].goToSlide == 'function') { 1805 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].goToSlide(options); 1806 } 1807 } 1808 catch(err) { 1809 // Don't need to do anything on error. 1810 } 1811 1812 try { 1813 if (typeof Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].goToSlide == 'function') { 1814 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].goToSlide(options); 1815 } 1816 } 1817 catch(err) { 1818 // Don't need to do anything on error. 1819 } 1820 }; 1821 1822 /** 1823 * Implement the previousSlide hook for pagers. 1824 */ 1825 Drupal.viewsSlideshowPager.previousSlide = function (options) { 1826 // Route the pager call to the correct pager type. 1827 // Need to use try catch so we don't have to check to make sure every part 1828 // of the object is defined. 1829 try { 1830 if (typeof Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].previousSlide == 'function') { 1831 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].previousSlide(options); 1832 } 1833 } 1834 catch(err) { 1835 // Don't need to do anything on error. 1836 } 1837 1838 try { 1839 if (typeof Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].previousSlide == 'function') { 1840 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].previousSlide(options); 1841 } 1842 } 1843 catch(err) { 1844 // Don't need to do anything on error. 1845 } 1846 }; 1847 1848 /** 1849 * Implement the nextSlide hook for pagers. 1850 */ 1851 Drupal.viewsSlideshowPager.nextSlide = function (options) { 1852 // Route the pager call to the correct pager type. 1853 // Need to use try catch so we don't have to check to make sure every part 1854 // of the object is defined. 1855 try { 1856 if (typeof Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].nextSlide == 'function') { 1857 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].nextSlide(options); 1858 } 1859 } 1860 catch(err) { 1861 // Don't need to do anything on error. 1862 } 1863 1864 try { 1865 if (typeof Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].nextSlide == 'function') { 1866 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].nextSlide(options); 1867 } 1868 } 1869 catch(err) { 1870 // Don't need to do anything on error. 1871 } 1872 }; 1873 1874 1875 /** 1876 * Views Slideshow Pager Fields 1877 */ 1878 1879 // Add views slideshow api calls for views slideshow pager fields. 1880 Drupal.behaviors.viewsSlideshowPagerFields = { 1881 attach: function (context) { 1882 // Process pause on hover.
1883 $('.views_slideshow_pager_field:not(.views-slideshow-pager-field-processed)', context).addClass('views-slideshow-pager-field-processed').each(function() { 1884 // Parse out the location and unique id from the full id. 1885 var pagerInfo = $(this).attr('id').split('_'); 1886 var location = pagerInfo[2]; 1887 pagerInfo.splice(0, 3); 1888 var uniqueID = pagerInfo.join('_'); 1889 1890 // Add the activate and pause on pager hover event to each pager item. 1891 if (Drupal.settings.viewsSlideshowPagerFields[uniqueID][location].activatePauseOnHover) { 1892 $(this).children().each(function(index, pagerItem) { 1893 var mouseIn = function() { 1894 Drupal.viewsSlideshow.action({ "action": 'goToSlide', "slideshowID": uniqueID, "slideNum": index }); 1895 Drupal.viewsSlideshow.action({ "action": 'pause', "slideshowID": uniqueID }); 1896 }; 1897 1898 var mouseOut = function() { 1899 Drupal.viewsSlideshow.action({ "action": 'play', "slideshowID": uniqueID }); 1900 }; 1901 1902 if (jQuery.fn.hoverIntent) { 1903 $(pagerItem).hoverIntent(mouseIn, mouseOut); 1904 } 1905 else { 1906 $(pagerItem).hover(mouseIn, mouseOut); 1907 } 1908 }); 1909 } 1910 else { 1911 $(this).children().each(function(index, pagerItem) { 1912 $(pagerItem).click(function() { 1913 Drupal.viewsSlideshow.action({ "action": 'goToSlide', "slideshowID": uniqueID, "slideNum": index }); 1914 }); 1915 }); 1916 } 1917 }); 1918 } 1919 }; 1920 1921 Drupal.viewsSlideshowPagerFields = Drupal.viewsSlideshowPagerFields || {}; 1922 1923 /** 1924 * Implement the transitionBegin hook for pager fields pager. 1925 */ 1926 Drupal.viewsSlideshowPagerFields.transitionBegin = function (options) {
1927 for (pagerLocation in Drupal.settings.viewsSlideshowPager[options.slideshowID]) { 1928 // Remove active class from pagers 1929 $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').removeClass('active'); 1930 1931 // Add active class to active pager. 1932 $('#views_slideshow_pager_field_item_'+ pagerLocation + '_' + options.slideshowID + '_' + options.slideNum).addClass('active'); 1933 } 1934 }; 1935 1936 /** 1937 * Implement the goToSlide hook for pager fields pager. 1938 */ 1939 Drupal.viewsSlideshowPagerFields.goToSlide = function (options) { 1940 for (pagerLocation in Drupal.settings.viewsSlideshowPager[options.slideshowID]) { 1941 // Remove active class from pagers 1942 $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').removeClass('active'); 1943 1944 // Add active class to active pager. 1945 $('#views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_' + options.slideNum).addClass('active'); 1946 } 1947 }; 1948 1949 /** 1950 * Implement the previousSlide hook for pager fields pager. 1951 */ 1952 Drupal.viewsSlideshowPagerFields.previousSlide = function (options) {
1953 for (pagerLocation in Drupal.settings.viewsSlideshowPager[options.slideshowID]) { 1954 // Get the current active pager. 1955 var pagerNum = $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"].active').attr('id').replace('views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_', ''); 1956 1957 // If we are on the first pager then activate the last pager. 1958 // Otherwise activate the previous pager. 1959 if (pagerNum == 0) { 1960 pagerNum = $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').length() - 1; 1961 } 1962 else { 1963 pagerNum--; 1964 } 1965 1966 // Remove active class from pagers 1967 $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').removeClass('active'); 1968 1969 // Add active class to active pager. 1970 $('#views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_' + pagerNum).addClass('active'); 1971 } 1972 }; 1973 1974 /** 1975 * Implement the nextSlide hook for pager fields pager. 1976 */ 1977 Drupal.viewsSlideshowPagerFields.nextSlide = function (options) {
1978 for (pagerLocation in Drupal.settings.viewsSlideshowPager[options.slideshowID]) { 1979 // Get the current active pager. 1980 var pagerNum = $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"].active').attr('id').replace('views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_', ''); 1981 var totalPagers = $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').length(); 1982 1983 // If we are on the last pager then activate the first pager. 1984 // Otherwise activate the next pager. 1985 pagerNum++; 1986 if (pagerNum == totalPagers) { 1987 pagerNum = 0; 1988 } 1989 1990 // Remove active class from pagers 1991 $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').removeClass('active'); 1992 1993 // Add active class to active pager. 1994 $('#views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_' + slideNum).addClass('active'); 1995 } 1996 }; 1997 1998 1999 /** 2000 * Views Slideshow Slide Counter 2001 */ 2002 2003 Drupal.viewsSlideshowSlideCounter = Drupal.viewsSlideshowSlideCounter || {}; 2004 2005 /** 2006 * Implement the transitionBegin for the slide counter. 2007 */ 2008 Drupal.viewsSlideshowSlideCounter.transitionBegin = function (options) { 2009 $('#views_slideshow_slide_counter_' + options.slideshowID + ' .num').text(options.slideNum + 1); 2010 }; 2011 2012 /** 2013 * This is used as a router to process actions for the slideshow. 2014 */ 2015 Drupal.viewsSlideshow.action = function (options) { 2016 // Set default values for our return status. 2017 var status = { 2018 'value': true, 2019 'text': '' 2020 }; 2021 2022 // If an action isn't specified return false. 2023 if (typeof options.action == 'undefined' || options.action == '') { 2024 status.value = false; 2025 status.text = Drupal.t('There was no action specified.'); 2026 return error; 2027 } 2028 2029 // If we are using pause or play switch paused state accordingly. 2030 if (options.action == 'pause') { 2031 Drupal.settings.viewsSlideshow[options.slideshowID].paused = 1; 2032 // If the calling method is forcing a pause then mark it as such. 2033 if (options.force) { 2034 Drupal.settings.viewsSlideshow[options.slideshowID].pausedForce = 1; 2035 } 2036 } 2037 else if (options.action == 'play') { 2038 // If the slideshow isn't forced pause or we are forcing a play then play 2039 // the slideshow. 2040 // Otherwise return telling the calling method that it was forced paused. 2041 if (!Drupal.settings.viewsSlideshow[options.slideshowID].pausedForce || options.force) { 2042 Drupal.settings.viewsSlideshow[options.slideshowID].paused = 0; 2043 Drupal.settings.viewsSlideshow[options.slideshowID].pausedForce = 0; 2044 } 2045 else { 2046 status.value = false; 2047 status.text += ' ' + Drupal.t('This slideshow is forced paused.'); 2048 return status; 2049 } 2050 } 2051 2052 // We use a switch statement here mainly just to limit the type of actions 2053 // that are available. 2054 switch (options.action) { 2055 case "goToSlide": 2056 case "transitionBegin": 2057 case "transitionEnd": 2058 // The three methods above require a slide number. Checking if it is 2059 // defined and it is a number that is an integer. 2060 if (typeof options.slideNum == 'undefined' || typeof options.slideNum !== 'number' || parseInt(options.slideNum) != (options.slideNum - 0)) { 2061 status.value = false; 2062 status.text = Drupal.t('An invalid integer was specified for slideNum.'); 2063 } 2064 case "pause": 2065 case "play": 2066 case "nextSlide": 2067 case "previousSlide": 2068 // Grab our list of methods. 2069 var methods = Drupal.settings.viewsSlideshow[options.slideshowID]['methods']; 2070 2071 // if the calling method specified methods that shouldn't be called then 2072 // exclude calling them. 2073 var excludeMethodsObj = {}; 2074 if (typeof options.excludeMethods !== 'undefined') { 2075 // We need to turn the excludeMethods array into an object so we can use the in 2076 // function. 2077 for (var i=0; i < excludeMethods.length; i++) { 2078 excludeMethodsObj[excludeMethods[i]] = ''; 2079 } 2080 } 2081 2082 // Call every registered method and don't call excluded ones. 2083 for (i = 0; i < methods[options.action].length; i++) { 2084 if (Drupal[methods[options.action][i]] != undefined && typeof Drupal[methods[options.action][i]][options.action] == 'function' && !(methods[options.action][i] in excludeMethodsObj)) { 2085 Drupal[methods[options.action][i]][options.action](options); 2086 } 2087 } 2088 break; 2089
2090 // If it gets here it's because it's an invalid action. 2091 default: 2092 status.value = false; 2093 status.text = Drupal.t('An invalid action "!action" was specified.', { "!action": options.action }); 2094 } 2095 return status; 2096 }; 2097})(jQuery); 2098; 2099/*! 2100 * Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net) 2101 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php). 2102 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. 2103 * 2104 * $LastChangedDate: 2007-06-19 20:25:28 -0500 (Tue, 19 Jun 2007) $ 2105 * $Rev: 2111 $ 2106 * 2107 * Version 2.1 2108 */ 2109(function($){$.fn.bgIframe=$.fn.bgiframe=function(s){if($.browser.msie&&parseInt($.browser.version)<=6){s=$.extend({top:'auto',left:'auto',width:'auto',height:'auto',opacity:true,src:'javascript:false;'},s||{});var prop=function(n){return n&&n.constructor==Number?n+'px':n;},html='<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+'style="display:block;position:absolute;z-index:-1;'+(s.opacity!==false?'filter:Alpha(Opacity=\'0\');':'')+'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+'"/>';return this.each(function(){if($('> iframe.bgiframe',this).length==0)this.insertBefore(document.createElement(html),this.firstChild);});}return this;};if(!$.browser.version)$.browser.version=navigator.userAgent.toLowerCase().match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)[1];})(jQuery);; 2110/*! 2111* hoverIntent r5 // 2007.03.27 // jQuery 1.1.2+ 2112* <http://cherne.net/brian/resources/jquery.hoverIntent.html> 2113* 2114* @param f onMouseOver function || An object with configuration options 2115* @param g onMouseOut function || Nothing (use configuration options object) 2116* @author Brian Cherne <[email protected]> 2117*/ 2118(function($){$.fn.hoverIntent=function(f,g){var cfg={sensitivity:7,interval:100,timeout:0};cfg=$.extend(cfg,g?{over:f,out:g}:f);var cX,cY,pX,pY;var track=function(ev){cX=ev.pageX;cY=ev.pageY;};var compare=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);if((Math.abs(pX-cX)+Math.abs(pY-cY))<cfg.sensitivity){$(ob).unbind("mousemove",track);ob.hoverIntent_s=1;return cfg.over.apply(ob,[ev]);}else{pX=cX;pY=cY;ob.hoverIntent_t=setTimeout(function(){compare(ev,ob);},cfg.interval);}};var delay=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);ob.hoverIntent_s=0;return cfg.out.apply(ob,[ev]);};var handleHover=function(e){var p=(e.type=="mouseover"?e.fromElement:e.toElement)||e.relatedTarget;while(p&&p!=this){try{p=p.parentNode;}catch(e){p=this;}}if(p==this){return false;}var ev=jQuery.extend({},e);var ob=this;if(ob.hoverIntent_t){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);}if(e.type=="mouseover"){pX=ev.pageX;pY=ev.pageY;$(ob).bind("mousemove",track);if(ob.hoverIntent_s!=1){ob.hoverIntent_t=setTimeout(function(){compare(ev,ob);},cfg.interval);}}else{$(ob).unbind("mousemove",track);if(ob.hoverIntent_s==1){ob.hoverIntent_t=setTimeout(function(){delay(ev,ob);},cfg.timeout);}}};return this.mouseover(handleHover).mouseout(handleHover);};})(jQuery);; 2119; 2120/*! 2121 * Superfish v1.4.8 - jQuery menu widget 2122 * Copyright (c) 2008 Joel Birch 2123 * 2124 * Dual licensed under the MIT and GPL licenses: 2125 * http://www.opensource.org/licenses/mit-license.php 2126 * http://www.gnu.org/licenses/gpl.html 2127 * 2128 * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt 2129 */ 2130(function($){ 2131 $.fn.superfish = function(op){ 2132 2133 var sf = $.fn.superfish, 2134 c = sf.c, 2135 $arrow = $(['<span class="',c.arrowClass,'"> »</span>'].join('')), 2136 over = function(){ 2137 var $$ = $(this), menu = getMenu($$); 2138 clearTimeout(menu.sfTimer); 2139 $$.showSuperfishUl().siblings().hideSuperfishUl(); 2140 }, 2141 out = function(){ 2142 var $$ = $(this), menu = getMenu($$), o = sf.op; 2143 clearTimeout(menu.sfTimer); 2144 menu.sfTimer = setTimeout(function(){ 2145 o.retainPath = ($.inArray($$[0],o.$path) > -1);
2146 $$.hideSuperfishUl(); 2147 if (o.$path.length && $$.parents(['li.', o.hoverClass].join('')).length < 1){ 2148 over.call(o.$path); 2149 } 2150 }, o.delay); 2151 }, 2152 getMenu = function($menu){ 2153 var menu = $menu.parents(['ul.',c.menuClass,':first'].join(''))[0]; 2154 sf.op = sf.o[menu.serial]; 2155 return menu; 2156 }, 2157 addArrow = function($a){ 2158 $a.addClass(c.anchorClass).append($arrow.clone()); 2159 }; 2160 2161 return this.each(function() { 2162 var s = this.serial = sf.o.length; 2163 var o = $.extend({},sf.defaults,op); 2164 o.$path = $('li.' + o.pathClass,this).slice(0, o.pathLevels).each(function(){ 2165 $(this).addClass([o.hoverClass,c.bcClass].join(' ')) 2166 .filter('li:has(ul)').removeClass(o.pathClass); 2167 }); 2168 sf.o[s] = sf.op = o; 2169 2170 $('li:has(ul)',this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out).each(function() { 2171 if (o.autoArrows) { 2172 addArrow($('>a:first-child',this)); 2173 } 2174 }) 2175 .not('.' + c.bcClass) 2176 .hideSuperfishUl(); 2177 2178 var $a = $('a',this); 2179 $a.each(function(i){ 2180 var $li = $a.eq(i).parents('li'); 2181 $a.eq(i).focus(function(){ 2182 over.call($li); 2183 }).blur(function(){ 2184 out.call($li); 2185 }); 2186 }); 2187 o.onInit.call(this); 2188 2189 }).each(function() { 2190 var menuClasses = [c.menuClass]; 2191 if (sf.op.dropShadows && !($.browser.msie && $.browser.version < 7)) { 2192 menuClasses.push(c.shadowClass); 2193 } 2194 $(this).addClass(menuClasses.join(' ')); 2195 }); 2196 }; 2197 2198 var sf = $.fn.superfish; 2199 sf.o = []; 2200 sf.op = {}; 2201 sf.IE7fix = function(){ 2202 var o = sf.op; 2203 if ($.browser.msie && $.browser.version > 6 && o.dropShadows && o.animation.opacity != undefined) { 2204 this.toggleClass(sf.c.shadowClass + '-off'); 2205 } 2206 }; 2207 sf.c = { 2208 bcClass : 'sf-breadcrumb', 2209 menuClass : 'sf-js-enabled', 2210 anchorClass : 'sf-with-ul', 2211 arrowClass : 'sf-sub-indicator', 2212 shadowClass : 'sf-shadow' 2213 }; 2214 sf.defaults = { 2215 hoverClass : 'sfHover', 2216 pathClass : 'overideThisToUse', 2217 pathLevels : 1, 2218 delay : 800, 2219 animation : { 2220 opacity:'show' 2221 }, 2222 speed : 'normal', 2223 autoArrows : true, 2224 dropShadows : true, 2225 // true disables hoverIntent detection. 2226 disableHI : false, 2227 onInit : function(){}, // callback functions 2228 onBeforeShow: function(){}, 2229 onShow : function(){}, 2230 onHide : function(){} 2231 }; 2232 $.fn.extend({ 2233 hideSuperfishUl : function() { 2234 var o = sf.op, 2235 not = (o.retainPath === true) ? o.$path : ''; 2236 o.retainPath = false; 2237 var $ul = $(['li.',o.hoverClass].join(''),this).add(this).not(not).removeClass(o.hoverClass) 2238 .find('>ul').hide().css('visibility','hidden'); 2239 o.onHide.call($ul); 2240 return this; 2241 }, 2242 showSuperfishUl : function(){ 2243 var o = sf.op, 2244 sh = sf.c.shadowClass + '-off', 2245 $ul = this.addClass(o.hoverClass) 2246 .find('>ul:hidden').css('visibility','visible'); 2247 sf.IE7fix.call($ul); 2248 o.onBeforeShow.call($ul); 2249 $ul.animate(o.animation,o.speed,function(){ 2250 sf.IE7fix.call($ul); 2251 o.onShow.call($ul); 2252 }); 2253 return this; 2254 } 2255 }); 2256 2257})(jQuery); 2258; 2259/** 2260 * @file 2261 * Behaviours for the Nice Menus module. This uses Superfish 1.4.8. 2262 * 2263 * @link http://users.tpg.com.au/j_birch/plugins/superfish 2264 */ 2265 2266(function ($) { 2267 2268 /** 2269 * Add Superfish to all Nice Menus with some basic options. 2270 */ 2271 Drupal.behaviors.niceMenus = { 2272 attach: function (context, settings) { 2273 $('ul.nice-menu:not(.nice-menus-processed)').addClass('nice-menus-processed').each(function () { 2274 $(this).superfish({ 2275 // Apply a generic hover class. 2276 hoverClass: 'over', 2277 // Disable generation of arrow mark-up.
2278 autoArrows: false, 2279 // Disable drop shadows. 2280 dropShadows: false, 2281 // Mouse delay. 2282 delay: Drupal.settings.nice_menus_options.delay, 2283 // Animation speed. 2284 speed: Drupal.settings.nice_menus_options.speed 2285 }); 2286 2287 // Add in Brandon Aaron’s bgIframe plugin for IE select issues. 2288 // http://plugins.jquery.com/node/46/release 2289 $(this).find('ul').bgIframe({opacity:false}); 2290 2291 $('ul.nice-menu ul').css('display', 'none'); 2292 }); 2293 } 2294 }; 2295 2296})(jQuery); 2297; 2298(function ($) { 2299 2300/** 2301 * Prevents consecutive form submissions of identical form values. 2302 * 2303 * Repetitive form submissions that would submit the identical form values are 2304 * prevented, unless the form values are different from the previously 2305 * submitted values. 2306 * 2307 * This is a simplified re-implementation of a user-agent behavior that should 2308 * be natively supported by major web browsers, but at this time, only Firefox 2309 * has a built-in protection. 2310 * 2311 * A form value-based approach ensures that the constraint is triggered for 2312 * consecutive, identical form submissions only. Compared to that, a form 2313 * button-based approach would (1) rely on [visible] buttons to exist where 2314 * technically not required and (2) require more complex state management if 2315 * there are multiple buttons in a form. 2316 * 2317 * This implementation is based on form-level submit events only and relies on 2318 * jQuery's serialize() method to determine submitted form values. As such, the 2319 * following limitations exist: 2320 * 2321 * - Event handlers on form buttons that preventDefault() do not receive a 2322 * double-submit protection. That is deemed to be fine, since such button 2323 * events typically trigger reversible client-side or server-side operations 2324 * that are local to the context of a form only. 2325 * - Changed values in advanced form controls, such as file inputs, are not part 2326 * of the form values being compared between consecutive form submits (due to 2327 * limitations of jQuery.serialize()). That is deemed to be acceptable, 2328 * because if the user forgot to attach a file, then the size of HTTP payload 2329 * will most likely be small enough to be fully passed to the server endpoint 2330 * within (milli)seconds. If a user mistakenly attached a wrong file and is 2331 * technically versed enough to cancel the form submission (and HTTP payload) 2332 * in order to attach a different file, then that edge-case is not supported 2333 * here. 2334 * 2335 * Lastly, all forms submitted via HTTP GET are idempotent by definition of HTTP 2336 * standards, so excluded in this implementation. 2337 */ 2338Drupal.behaviors.formSingleSubmit = { 2339 attach: function () { 2340 function onFormSubmit (e) { 2341 var $form = $(e.currentTarget); 2342 var formValues = $form.serialize(); 2343 var previousValues = $form.attr('data-drupal-form-submit-last'); 2344 if (previousValues === formValues) { 2345 e.preventDefault(); 2346 } 2347 else { 2348 $form.attr('data-drupal-form-submit-last', formValues); 2349 } 2350 } 2351 2352 $('body').once('form-single-submit') 2353 .delegate('form:not([method~="GET"])', 'submit.singleSubmit', onFormSubmit); 2354 } 2355}; 2356 2357})(jQuery); 2358; 2359(function ($) { 2360 2361/** 2362 * Provides Ajax page updating via jQuery $.ajax (Asynchronous JavaScript and XML). 2363 * 2364 * Ajax is a method of making a request via JavaScript while viewing an HTML 2365 * page. The request returns an array of commands encoded in JSON, which is 2366 * then executed to make any changes that are necessary to the page. 2367 * 2368 * Drupal uses this file to enhance form elements with #ajax['path'] and 2369 * #ajax['wrapper'] properties. If set, this file will automatically be included 2370 * to provide Ajax capabilities. 2371 */ 2372 2373Drupal.ajax = Drupal.ajax || {}; 2374 2375Drupal.settings.urlIsAjaxTrusted = Drupal.settings.urlIsAjaxTrusted || {}; 2376 2377/** 2378 * Attaches the Ajax behavior to each Ajax form element. 2379 */ 2380Drupal.behaviors.AJAX = { 2381 attach: function (context, settings) { 2382 // Load all Ajax behaviors specified in the settings. 2383 for (var base in settings.ajax) { 2384 if (!$('#' + base + '.ajax-processed').length) { 2385 var element_settings = settings.ajax[base]; 2386 2387 if (typeof element_settings.selector == 'undefined') { 2388 element_settings.selector = '#' + base; 2389 } 2390 $(element_settings.selector).each(function () { 2391 element_settings.element = this; 2392 Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings); 2393 }); 2394 2395 $('#' + base).addClass('ajax-processed'); 2396 } 2397 } 2398 2399 // Bind Ajax behaviors to all items showing the class.
2400 $('.use-ajax:not(.ajax-processed)').addClass('ajax-processed').each(function () { 2401 var element_settings = {}; 2402 // Clicked links look better with the throbber than the progress bar. 2403 element_settings.progress = { 'type': 'throbber' }; 2404 2405 // For anchor tags, these will go to the target of the anchor rather 2406 // than the usual location. 2407 if ($(this).attr('href')) { 2408 element_settings.url = $(this).attr('href'); 2409 element_settings.event = 'click'; 2410 } 2411 var base = $(this).attr('id'); 2412 Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings); 2413 }); 2414 2415 // This class means to submit the form to the action using Ajax. 2416 $('.use-ajax-submit:not(.ajax-processed)').addClass('ajax-processed').each(function () { 2417 var element_settings = {}; 2418 2419 // Ajax submits specified in this manner automatically submit to the 2420 // normal form action. 2421 element_settings.url = $(this.form).attr('action'); 2422 // Form submit button clicks need to tell the form what was clicked so 2423 // it gets passed in the POST request. 2424 element_settings.setClick = true; 2425 // Form buttons use the 'click' event rather than mousedown. 2426 element_settings.event = 'click'; 2427 // Clicked form buttons look better with the throbber than the progress bar. 2428 element_settings.progress = { 'type': 'throbber' }; 2429 2430 var base = $(this).attr('id'); 2431 Drupal.ajax[base] = new Drupal.ajax(base, this, element_settings); 2432 }); 2433 } 2434}; 2435 2436/** 2437 * Ajax object. 2438 * 2439 * All Ajax objects on a page are accessible through the global Drupal.ajax 2440 * object and are keyed by the submit button's ID. You can access them from 2441 * your module's JavaScript file to override properties or functions. 2442 * 2443 * For example, if your Ajax enabled button has the ID 'edit-submit', you can 2444 * redefine the function that is called to insert the new content like this 2445 * (inside a Drupal.behaviors attach block): 2446 * @code 2447 * Drupal.behaviors.myCustomAJAXStuff = { 2448 * attach: function (context, settings) { 2449 * Drupal.ajax['edit-submit'].commands.insert = function (ajax, response, status) { 2450 * new_content = $(response.data); 2451 * $('#my-wrapper').append(new_content); 2452 * alert('New content was appended to #my-wrapper'); 2453 * } 2454 * } 2455 * }; 2456 * @endcode 2457 */ 2458Drupal.ajax = function (base, element, element_settings) { 2459 var defaults = { 2460 url: 'system/ajax', 2461 event: 'mousedown', 2462 keypress: true, 2463 selector: '#' + base, 2464 effect: 'none', 2465 speed: 'none', 2466 method: 'replaceWith', 2467 progress: { 2468 type: 'throbber', 2469 message: Drupal.t('Please wait...') 2470 }, 2471 submit: { 2472 'js': true 2473 } 2474 }; 2475 2476 $.extend(this, defaults, element_settings); 2477 2478 this.element = element; 2479 this.element_settings = element_settings; 2480 2481 // Replacing 'nojs' with 'ajax' in the URL allows for an easy method to let 2482 // the server detect when it needs to degrade gracefully. 2483 // There are five scenarios to check for: 2484 // 1. /nojs/ 2485 // 2. /nojs$ - The end of a URL string. 2486 // 3. /nojs? - Followed by a query (with clean URLs enabled). 2487 // E.g.: path/nojs?destination=foobar 2488 // 4. /nojs& - Followed by a query (without clean URLs enabled). 2489 // E.g.: ?q=path/nojs&destination=foobar 2490 // 5. /nojs# - Followed by a fragment. 2491 // E.g.: path/nojs#myfragment 2492 this.url = element_settings.url.replace(/\/nojs(\/|$|\?|&|#)/g, '/ajax$1'); 2493 // If the 'nojs' version of the URL is trusted, also trust the 'ajax' version. 2494 if (Drupal.settings.urlIsAjaxTrusted[element_settings.url]) { 2495 Drupal.settings.urlIsAjaxTrusted[this.url] = true; 2496 } 2497 2498 this.wrapper = '#' + element_settings.wrapper; 2499 2500 // If there isn't a form, jQuery.ajax() will be used instead, allowing us to 2501 // bind Ajax to links as well. 2502 if (this.element.form) { 2503 this.form = $(this.element.form); 2504 } 2505 2506 // Set the options for the ajaxSubmit function. 2507 // The 'this' variable will not persist inside of the options object. 2508 var ajax = this; 2509 ajax.options = { 2510 url: Drupal.sanitizeAjaxUrl(ajax.url), 2511 data: ajax.submit, 2512 beforeSerialize: function (element_settings, options) { 2513 return ajax.beforeSerialize(element_settings, options); 2514 }, 2515 beforeSubmit: function (form_values, element_settings, options) { 2516 ajax.ajaxing = true; 2517 return ajax.beforeSubmit(form_values, element_settings, options); 2518 }, 2519 beforeSend: function (xmlhttprequest, options) { 2520 ajax.ajaxing = true; 2521 return ajax.beforeSend(xmlhttprequest, options); 2522 }, 2523 success: function (response, status, xmlhttprequest) { 2524 // Sanity check for browser support (object expected). 2525 // When using iFrame uploads, responses must be returned as a string. 2526 if (typeof response == 'string') { 2527 response = $.parseJSON(response); 2528 } 2529 2530 // Prior to invoking the response's commands, verify that they can be 2531 // trusted by checking for a response header. See 2532 // ajax_set_verification_header() for details. 2533 // - Empty responses are harmless so can bypass verification. This avoids 2534 // an alert message for server-generated no-op responses that skip Ajax 2535 // rendering. 2536 // - Ajax objects with trusted URLs (e.g., ones defined server-side via 2537 // #ajax) can bypass header verification. This is especially useful for 2538 // Ajax with multipart forms. Because IFRAME transport is used, the 2539 // response headers cannot be accessed for verification. 2540 if (response !== null && !Drupal.settings.urlIsAjaxTrusted[ajax.url]) { 2541 if (xmlhttprequest.getResponseHeader('X-Drupal-Ajax-Token') !== '1') { 2542 var customMessage = Drupal.t("The response failed verification so will not be processed."); 2543 return ajax.error(xmlhttprequest, ajax.url, customMessage); 2544 } 2545 } 2546 2547 return ajax.success(response, status); 2548 }, 2549 complete: function (xmlhttprequest, status) { 2550 ajax.ajaxing = false;
2551 if (status == 'error' || status == 'parsererror') { 2552 return ajax.error(xmlhttprequest, ajax.url); 2553 } 2554 }, 2555 dataType: 'json', 2556 jsonp: false, 2557 type: 'POST' 2558 }; 2559 2560 // For multipart forms (e.g., file uploads), jQuery Form targets the form 2561 // submission to an iframe instead of using an XHR object. The initial "src" 2562 // of the iframe, prior to the form submission, is set to options.iframeSrc. 2563 // "about:blank" is the semantically correct, standards-compliant, way to 2564 // initialize a blank iframe; however, some old IE versions (possibly only 6) 2565 // incorrectly report a mixed content warning when iframes with an 2566 // "about:blank" src are added to a parent document with an https:// origin. 2567 // jQuery Form works around this by defaulting to "javascript:false" instead, 2568 // but that breaks on Chrome 83, so here we force the semantically correct 2569 // behavior for all browsers except old IE. 2570 // @see https://www.drupal.org/project/drupal/issues/3143016 2571 // @see https://github.com/jquery-form/form/blob/df9cb101b9c9c085c8d75ad980c7ff1cf62063a1/jquery.form.js#L68 2572 // @see https://bugs.chromium.org/p/chromium/issues/detail?id=1084874 2573 // @see https://html.spec.whatwg.org/multipage/browsers.html#creating-browsing-contexts 2574 // @see https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy 2575 if (navigator.userAgent.indexOf("MSIE") === -1) { 2576 ajax.options.iframeSrc = 'about:blank'; 2577 } 2578 2579 // Bind the ajaxSubmit function to the element event. 2580 $(ajax.element).bind(element_settings.event, function (event) { 2581 if (!Drupal.settings.urlIsAjaxTrusted[ajax.url] && !Drupal.urlIsLocal(ajax.url)) { 2582 throw new Error(Drupal.t('The callback URL is not local and not trusted: !url', {'!url': ajax.url})); 2583 } 2584 return ajax.eventResponse(this, event); 2585 }); 2586 2587 // If necessary, enable keyboard submission so that Ajax behaviors 2588 // can be triggered through keyboard input as well as e.g. a mousedown 2589 // action. 2590 if (element_settings.keypress) { 2591 $(ajax.element).keypress(function (event) { 2592 return ajax.keypressResponse(this, event); 2593 }); 2594 } 2595 2596 // If necessary, prevent the browser default action of an additional event. 2597 // For example, prevent the browser default action of a click, even if the 2598 // AJAX behavior binds to mousedown. 2599 if (element_settings.prevent) { 2600 $(ajax.element).bind(element_settings.prevent, false); 2601 } 2602}; 2603 2604/** 2605 * Handle a key press. 2606 * 2607 * The Ajax object will, if instructed, bind to a key press response. This 2608 * will test to see if the key press is valid to trigger this event and 2609 * if it is, trigger it for us and prevent other keypresses from triggering. 2610 * In this case we're handling RETURN and SPACEBAR keypresses (event codes 13 2611 * and 32. RETURN is often used to submit a form when in a textfield, and 2612 * SPACE is often used to activate an element without submitting. 2613 */ 2614Drupal.ajax.prototype.keypressResponse = function (element, event) { 2615 // Create a synonym for this to reduce code confusion. 2616 var ajax = this; 2617 2618 // Detect enter key and space bar and allow the standard response for them, 2619 // except for form elements of type 'text' and 'textarea', where the 2620 // spacebar activation causes inappropriate activation if #ajax['keypress'] is 2621 // TRUE. On a text-type widget a space should always be a space. 2622 if (event.which == 13 || (event.which == 32 && element.type != 'text' && element.type != 'textarea')) { 2623 $(ajax.element_settings.element).trigger(ajax.element_settings.event); 2624 return false; 2625 } 2626}; 2627 2628/** 2629 * Handle an event that triggers an Ajax response. 2630 * 2631 * When an event that triggers an Ajax response happens, this method will 2632 * perform the actual Ajax call. It is bound to the event using 2633 * bind() in the constructor, and it uses the options specified on the 2634 * ajax object. 2635 */ 2636Drupal.ajax.prototype.eventResponse = function (element, event) { 2637 // Create a synonym for this to reduce code confusion. 2638 var ajax = this; 2639 2640 // Do not perform another ajax command if one is already in progress. 2641 if (ajax.ajaxing) { 2642 return false; 2643 } 2644 2645 try { 2646 if (ajax.form) { 2647 // If setClick is set, we must set this to ensure that the button's 2648 // value is passed. 2649 if (ajax.setClick) { 2650 // Mark the clicked button. 'form.clk' is a special variable for 2651 // ajaxSubmit that tells the system which element got clicked to 2652 // trigger the submit. Without it there would be no 'op' or
2653 // equivalent. 2654 element.form.clk = element; 2655 } 2656 2657 ajax.form.ajaxSubmit(ajax.options); 2658 } 2659 else { 2660 ajax.beforeSerialize(ajax.element, ajax.options); 2661 $.ajax(ajax.options); 2662 } 2663 } 2664 catch (e) { 2665 // Unset the ajax.ajaxing flag here because it won't be unset during 2666 // the complete response. 2667 ajax.ajaxing = false; 2668 alert("An error occurred while attempting to process " + ajax.options.url + ": " + e.message); 2669 } 2670 2671 // For radio/checkbox, allow the default event. On IE, this means letting 2672 // it actually check the box. 2673 if (typeof element.type != 'undefined' && (element.type == 'checkbox' || element.type == 'radio')) { 2674 return true; 2675 } 2676 else { 2677 return false; 2678 } 2679 2680}; 2681 2682/** 2683 * Handler for the form serialization. 2684 * 2685 * Runs before the beforeSend() handler (see below), and unlike that one, runs 2686 * before field data is collected. 2687 */ 2688Drupal.ajax.prototype.beforeSerialize = function (element, options) { 2689 // Allow detaching behaviors to update field values before collecting them. 2690 // This is only needed when field values are added to the POST data, so only 2691 // when there is a form such that this.form.ajaxSubmit() is used instead of 2692 // $.ajax(). When there is no form and $.ajax() is used, beforeSerialize() 2693 // isn't called, but don't rely on that: explicitly check this.form. 2694 if (this.form) { 2695 var settings = this.settings || Drupal.settings; 2696 Drupal.detachBehaviors(this.form, settings, 'serialize'); 2697 } 2698 2699 // Prevent duplicate HTML ids in the returned markup. 2700 // @see drupal_html_id() 2701 options.data['ajax_html_ids[]'] = []; 2702 $('[id]').each(function () { 2703 options.data['ajax_html_ids[]'].push(this.id); 2704 }); 2705 2706 // Allow Drupal to return new JavaScript and CSS files to load without 2707 // returning the ones already loaded. 2708 // @see ajax_base_page_theme() 2709 // @see drupal_get_css() 2710 // @see drupal_get_js() 2711 options.data['ajax_page_state[theme]'] = Drupal.settings.ajaxPageState.theme; 2712 options.data['ajax_page_state[theme_token]'] = Drupal.settings.ajaxPageState.theme_token; 2713 for (var key in Drupal.settings.ajaxPageState.css) { 2714 options.data['ajax_page_state[css][' + key + ']'] = 1; 2715 } 2716 for (var key in Drupal.settings.ajaxPageState.js) { 2717 options.data['ajax_page_state[js][' + key + ']'] = 1; 2718 } 2719}; 2720 2721/** 2722 * Modify form values prior to form submission. 2723 */ 2724Drupal.ajax.prototype.beforeSubmit = function (form_values, element, options) { 2725 // This function is left empty to make it simple to override for modules 2726 // that wish to add functionality here. 2727}; 2728 2729/** 2730 * Prepare the Ajax request before it is sent. 2731 */ 2732Drupal.ajax.prototype.beforeSend = function (xmlhttprequest, options) { 2733 // For forms without file inputs, the jQuery Form plugin serializes the form 2734 // values, and then calls jQuery's $.ajax() function, which invokes this 2735 // handler. In this circumstance, options.extraData is never used. For forms 2736 // with file inputs, the jQuery Form plugin uses the browser's normal form 2737 // submission mechanism, but captures the response in a hidden IFRAME. In this 2738 // circumstance, it calls this handler first, and then appends hidden fields 2739 // to the form to submit the values in options.extraData. There is no simple 2740 // way to know which submission mechanism will be used, so we add to extraData 2741 // regardless, and allow it to be ignored in the former case. 2742 if (this.form) { 2743 options.extraData = options.extraData || {}; 2744 2745 // Let the server know when the IFRAME submission mechanism is used. The 2746 // server can use this information to wrap the JSON response in a TEXTAREA, 2747 // as per http://jquery.malsup.com/form/#file-upload. 2748 options.extraData.ajax_iframe_upload = '1'; 2749 2750 // The triggering element is about to be disabled (see below), but if it 2751 // contains a value (e.g., a checkbox, textfield, select, etc.), ensure that 2752 // value is included in the submission. As per above, submissions that use 2753 // $.ajax() are already serialized prior to the element being disabled, so 2754 // this is only needed for IFRAME submissions. 2755 var v = $.fieldValue(this.element); 2756 if (v !== null) { 2757 options.extraData[this.element.name] = Drupal.checkPlain(v); 2758 } 2759 } 2760 2761 // Disable the element that received the change to prevent user interface 2762 // interaction while the Ajax request is in progress. ajax.ajaxing prevents 2763 // the element from triggering a new request, but does not prevent the user 2764 // from changing its value. 2765 $(this.element).addClass('progress-disabled').attr('disabled', true); 2766 2767 // Insert progressbar or throbber. 2768 if (this.progress.type == 'bar') { 2769 var progressBar = new Drupal.progressBar('ajax-progress-' + this.element.i
2769d, $.noop, this.progress.method, $.noop); 2770 if (this.progress.message) { 2771 progressBar.setProgress(-1, this.progress.message); 2772 } 2773 if (this.progress.url) { 2774 progressBar.startMonitoring(this.progress.url, this.progress.interval || 1500); 2775 } 2776 this.progress.element = $(progressBar.element).addClass('ajax-progress ajax-progress-bar'); 2777 this.progress.object = progressBar; 2778 $(this.element).after(this.progress.element); 2779 } 2780 else if (this.progress.type == 'throbber') { 2781 this.progress.element = $('<div class="ajax-progress ajax-progress-throbber"><div class="throbber"> </div></div>'); 2782 if (this.progress.message) { 2783 $('.throbber', this.progress.element).after('<div class="message">' + this.progress.message + '</div>'); 2784 } 2785 $(this.element).after(this.progress.element); 2786 } 2787}; 2788 2789/** 2790 * Handler for the form redirection completion. 2791 */ 2792Drupal.ajax.prototype.success = function (response, status) { 2793 // Remove the progress element. 2794 if (this.progress.element) { 2795 $(this.progress.element).remove(); 2796 } 2797 if (this.progress.object) { 2798 this.progress.object.stopMonitoring(); 2799 } 2800 $(this.element).removeClass('progress-disabled').removeAttr('disabled'); 2801 2802 Drupal.freezeHeight(); 2803 2804 for (var i in response) { 2805 if (response.hasOwnProperty(i) && response[i]['command'] && this.commands[response[i]['command']]) { 2806 this.commands[response[i]['command']](this, response[i], status); 2807 } 2808 } 2809 2810 // Reattach behaviors, if they were detached in beforeSerialize(). The 2811 // attachBehaviors() called on the new content from processing the response 2812 // commands is not sufficient, because behaviors from the entire form need 2813 // to be reattached. 2814 if (this.form) { 2815 var settings = this.settings || Drupal.settings; 2816 Drupal.attachBehaviors(this.form, settings); 2817 } 2818 2819 Drupal.unfreezeHeight(); 2820 2821 // Remove any response-specific settings so they don't get used on the next 2822 // call by mistake. 2823 this.settings = null; 2824}; 2825 2826/** 2827 * Build an effect object which tells us how to apply the effect when adding new HTML. 2828 */ 2829Drupal.ajax.prototype.getEffect = function (response) { 2830 var type = response.effect || this.effect; 2831 var speed = response.speed || this.speed; 2832 2833 var effect = {}; 2834 if (type == 'none') { 2835 effect.showEffect = 'show'; 2836 effect.hideEffect = 'hide'; 2837 effect.showSpeed = ''; 2838 } 2839 else if (type == 'fade') { 2840 effect.showEffect = 'fadeIn'; 2841 effect.hideEffect = 'fadeOut'; 2842 effect.showSpeed = speed; 2843 } 2844 else { 2845 effect.showEffect = type + 'Toggle'; 2846 effect.hideEffect = type + 'Toggle'; 2847 effect.showSpeed = speed; 2848 } 2849 2850 return effect; 2851}; 2852 2853/** 2854 * Handler for the form redirection error. 2855 */ 2856Drupal.ajax.prototype.error = function (xmlhttprequest, uri, customMessage) { 2857 Drupal.displayAjaxError(Drupal.ajaxError(xmlhttprequest, uri, customMessage)); 2858 // Remove the progress element. 2859 if (this.progress.element) { 2860 $(this.progress.element).remove(); 2861 } 2862 if (this.progress.object) { 2863 this.progress.object.stopMonitoring(); 2864 } 2865 // Undo hide. 2866 $(this.wrapper).show(); 2867 // Re-enable the element. 2868 $(this.element).removeClass('progress-disabled').removeAttr('disabled'); 2869 // Reattach behaviors, if they were detached in beforeSerialize(). 2870 if (this.form) { 2871 var settings = this.settings || Drupal.settings; 2872 Drupal.attachBehaviors(this.form, settings); 2873 } 2874}; 2875 2876/** 2877 * Provide a series of commands that the server can request the client perform. 2878 */ 2879Drupal.ajax.prototype.commands = { 2880 /** 2881 * Command to insert new content into the DOM. 2882 */ 2883 insert: function (ajax, response, status) { 2884 // Get information from the response. If it is not there, default to 2885 // our presets. 2886 var wrapper = response.selector ? $(response.selector) : $(ajax.wrapper); 2887 var method = response.method || ajax.method; 2888 var effect = ajax.getEffect(response); 2889 2890 // We don't know what response.data contains: it might be a string of text 2891 // without HTML, so don't rely on jQuery correctly iterpreting 2892 // $(response.data) as new HTML rather than a CSS selector. Also, if 2893 // response.data contains top-level text nodes, they get lost with either 2894 // $(response.data) or $('<div></div>').replaceWith(response.data). 2895 var new_content_wrapped = $('<div></div>').html(response.data); 2896 var new_content = new_content_wrapped.contents(); 2897 2898 // For legacy reasons, the effects processing code assumes that new_content 2899 // consists of a single top-level element. Also, it has not been 2900 // sufficiently tested whether attachBehaviors() can be successfully called 2901 // with a context object that includes top-level text nodes. However, to 2902 // give developers full control of the HTML appearing in the page, and to 2903 // enable Ajax content to be inserted in places where DIV elements are not 2904 // allowed (e.g., within TABLE, TR, and SPAN parents), we check if the new 2905 // content satisfies the requirement of a single top-level element, and 2906 // only use the container DIV created above when it doesn't. For more 2907 // information, please see http://drupal.org/node/736066. 2908 if (new_content.length != 1 || new_content.get(0).nodeType != 1) { 2909 new_content = new_content_wrapped; 2910 } 2911 2912 // If removing content from the wrapper, detach behaviors first. 2913 switch (method) { 2914 case 'html': 2915 case 'replaceWith': 2916 case 'replaceAll': 2917 case 'empty': 2918 case 'remove': 2919 var settings = response.settings || ajax.settings || Drupal.settings; 2920 Drupal.detachBehaviors(wrapper, settings); 2921 } 2922 2923 // Add the new content to the page. 2924 wrapper[method](new_content); 2925 2926 // Immediately hide the new content if we're using any effects. 2927 if (effect.showEffect != 'show') { 2928 new_content.hide(); 2929 } 2930 2931 // Determine which effect to use and what content will receive the 2932 // effect, then show the new content. 2933 if ($('.ajax-new-content', new_content).length > 0) { 2934 $('.ajax-new-content', new_content).hide(); 2935 new_content.show(); 2936 $('.ajax-new-content', new_content)[effect.showEffect](effect.showSpeed); 2937 } 2938 else if (effect.showEffect != 'show') { 2939 new_content[effect.showEffect](effect.showSpeed); 2940 } 2941 2942 // Attach all JavaScript behaviors to the new content, if it was successfully 2943 // added to the page, this if statement allows #ajax['wrapper'] to be 2944 // optional. 2945 if (new_content.parents('html').length > 0) { 2946 // Apply any settings from the returned JSON if available. 2947 var settings = response.settings || ajax.settings || Drupal.settings; 2948 Drupal.attachBehaviors(new_content, settings); 2949 } 2950 }, 2951 2952 /** 2953 * Command to remove a chunk from the page. 2954 */ 2955 remove: function (ajax, response, status) { 2956 var settings = response.settings || ajax.settings || Drupal.settings; 2957 Drupal.detachBehaviors($(response.selector), settings); 2958 $(response.selector).remove(); 2959 }, 2960 2961 /** 2962 * Command to mark a chunk changed. 2963 */ 2964 changed: function (ajax, response, status) { 2965 if (!$(response.selector).hasClass('ajax-changed')) { 2966 $(response.selector).addClass('ajax-changed'); 2967 if (response.asterisk) { 2968 $(response.selector).find(response.asterisk).append(' <span class="ajax-changed">*</span> '); 2969 } 2970 } 2971 }, 2972 2973 /** 2974 * Command to provide an alert. 2975 */ 2976 alert: function (ajax, response, status) { 2977 alert(response.text, response.title); 2978 }, 2979 2980 /** 2981 * Command to provide the jQuery css() function. 2982 */ 2983 css: function (ajax, response, status) { 2984 $(response.selector).css(response.argument); 2985 }, 2986 2987 /** 2988 * Command to set the settings that will be used for other commands in this response. 2989 */ 2990 settings: function (ajax, response, status) { 2991 if (response.merge) { 2992 $.extend(true, Drupal.settings, response.settings); 2993 } 2994 else { 2995 ajax.settings = response.settings; 2996 } 2997 }, 2998 2999 /** 3000 * Command to attach data using jQuery's data API. 3001 */ 3002 data: function (ajax, response, status) { 3003 $(response.selector).data(response.name, response.value); 3004 }, 3005 3006 /** 3007 * Command to apply a jQuery method. 3008 */ 3009 invoke: function (ajax, response, status) { 3010 var $element = $(response.selector); 3011 $element[response.method].apply($element, response.arguments); 3012 }, 3013 3014 /** 3015 * Command to restripe a table. 3016 */ 3017 restripe: function (ajax, response, status) { 3018 // :even and :odd are reversed because jQuery counts from 0 and 3019 // we count from 1, so we're out of sync. 3020 // Match immediate children of the parent element to allow nesting. 3021 $('> tbody > tr:visible, > tr:visible', $(response.selector)) 3022 .removeClass('odd even') 3023 .filter(':even').addClass('odd').end() 3024 .filter(':odd').addClass('even'); 3025 }, 3026 3027 /** 3028 * Command to add css. 3029 * 3030 * Uses the proprietary addImport method if available as browsers which 3031 * support that method ignore @import statements in dynamically added 3032 * stylesheets. 3033 */ 3034 add_css: function (ajax, response, status) { 3035 // Add the styles in the normal way. 3036 $('head').prepend(response.data); 3037 // Add imports in the styles using the addImport method if available. 3038 var match, importMatch = /^@import url\("(.*)"\);$/igm; 3039 if (document.styleSheets[0].addImport && importMatch.test(response.data)) { 3040 importMatch.lastIndex = 0; 3041 while (match = importMatch.exec(response.data)) { 3042 document.styleSheets[0].addImport(match[1]); 3043 } 3044 } 3045 }, 3046 3047 /** 3048 * Command to update a form's build ID. 3049 */ 3050 updateBuildId: function(ajax, response, status) { 3051 $('input[name="form_build_id"][value="' + response['old'] + '"]').val(response['new']); 3052 } 3053}; 3054 3055})(jQuery); 3056; 3057(function (D) { 3058 var beforeSerialize = D.ajax.prototype.beforeSerialize;
3059 D.ajax.prototype.beforeSerialize = function (element, options) { 3060 beforeSerialize.call(this, element, options); 3061 options.data['ajax_page_state[jquery_version]'] = D.settings.ajaxPageState.jquery_version; 3062 options.data['ajax_page_state[jquery_version_token]'] = D.settings.ajaxPageState.jquery_version_token; 3063 } 3064})(Drupal); 3065;
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.