1(function ($) { 2 Drupal.viewsSlideshow = Drupal.viewsSlideshow || {}; 3 4 /** 5 * Views Slideshow Controls 6 */ 7 Drupal.viewsSlideshowControls = Drupal.viewsSlideshowControls || {}; 8 9 /** 10 * Implement the play hook for controls. 11 */ 12 Drupal.viewsSlideshowControls.play = function (options) { 13 // Route the control call to the correct control type. 14 // Need to use try catch so we don't have to check to make sure every part 15 // of the object is defined. 16 try { 17 if (typeof Drupal.settings.viewsSlideshowControls[options.slideshowID].top.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].top.type].play == 'function') { 18 Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].top.type].play(options); 19 } 20 } 21 catch(err) { 22 // Don't need to do anything on error. 23 } 24 25 try { 26 if (typeof Drupal.settings.viewsSlideshowControls[options.slideshowID].bottom.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].bottom.type].play == 'function') { 27 Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].bottom.type].play(options); 28 } 29 } 30 catch(err) { 31 // Don't need to do anything on error. 32 } 33 }; 34 35 /** 36 * Implement the pause hook for controls. 37 */ 38 Drupal.viewsSlideshowControls.pause = function (options) { 39 // Route the control call to the correct control type. 40 // Need to use try catch so we don't have to check to make sure every part 41 // of the object is defined. 42 try { 43 if (typeof Drupal.settings.viewsSlideshowControls[options.slideshowID].top.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].top.type].pause == 'function') { 44 Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].top.type].pause(options); 45 } 46 } 47 catch(err) { 48 // Don't need to do anything on error. 49 } 50 51 try { 52 if (typeof Drupal.settings.viewsSlideshowControls[options.slideshowID].bottom.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].bottom.type].pause == 'function') { 53 Drupal[Drupal.settings.viewsSlideshowControls[options.slideshowID].bottom.type].pause(options); 54 } 55 } 56 catch(err) { 57 // Don't need to do anything on error. 58 } 59 }; 60 61 62 /** 63 * Views Slideshow Text Controls 64 */ 65 66 // Add views slideshow api calls for views slideshow text controls. 67 Drupal.behaviors.viewsSlideshowControlsText = { 68 attach: function (context) { 69 70 // Process previous link 71 $('.views_slideshow_controls_text_previous:not(.views-slideshow-controls-text-previous-processed)', context).addClass('views-slideshow-controls-text-previous-processed').each(function() { 72 var uniqueID = $(this).attr('id').replace('views_slideshow_controls_text_previous_', ''); 73 $(this).click(function() { 74 Drupal.viewsSlideshow.action({ "action": 'previousSlide', "slideshowID": uniqueID }); 75 return false; 76 }); 77 }); 78 79 // Process next link 80 $('.views_slideshow_controls_text_next:not(.views-slideshow-controls-text-next-processed)', context).addClass('views-slideshow-controls-text-next-processed').each(function() { 81 var uniqueID = $(this).attr('id').replace('views_slideshow_controls_text_next_', ''); 82 $(this).click(function() { 83 Drupal.viewsSlideshow.action({ "action": 'nextSlide', "slideshowID": uniqueID }); 84 return false; 85 }); 86 }); 87 88 // Process pause link 89 $('.views_slideshow_controls_text_pause:not(.views-slideshow-controls-text-pause-processed)', context).addClass('views-slideshow-controls-text-pause-processed').each(function() { 90 var uniqueID = $(this).attr('id').replace('views_slideshow_controls_text_pause_', ''); 91 $(this).click(function() { 92 if (Drupal.settings.viewsSlideshow[uniqueID].paused) { 93 Drupal.viewsSlideshow.action({ "action": 'play', "slideshowID": uniqueID, "force": true }); 94 } 95 else { 96 Drupal.viewsSlideshow.action({ "action": 'pause', "slideshowID": uniqueID, "force": true }); 97 } 98 return false;
99 }); 100 }); 101 } 102 }; 103 104 Drupal.viewsSlideshowControlsText = Drupal.viewsSlideshowControlsText || {}; 105 106 /** 107 * Implement the pause hook for text controls. 108 */ 109 Drupal.viewsSlideshowControlsText.pause = function (options) { 110 var pauseText = Drupal.theme.prototype['viewsSlideshowControlsPause'] ? Drupal.theme('viewsSlideshowControlsPause') : ''; 111 $('#views_slideshow_controls_text_pause_' + options.slideshowID + ' a').text(pauseText); 112 $('#views_slideshow_controls_text_pause_' + options.slideshowID).removeClass('views-slideshow-controls-text-status-play'); 113 $('#views_slideshow_controls_text_pause_' + options.slideshowID).addClass('views-slideshow-controls-text-status-pause'); 114 }; 115 116 /** 117 * Implement the play hook for text controls. 118 */ 119 Drupal.viewsSlideshowControlsText.play = function (options) { 120 var playText = Drupal.theme.prototype['viewsSlideshowControlsPlay'] ? Drupal.theme('viewsSlideshowControlsPlay') : ''; 121 $('#views_slideshow_controls_text_pause_' + options.slideshowID + ' a').text(playText); 122 $('#views_slideshow_controls_text_pause_' + options.slideshowID).removeClass('views-slideshow-controls-text-status-pause'); 123 $('#views_slideshow_controls_text_pause_' + options.slideshowID).addClass('views-slideshow-controls-text-status-play'); 124 }; 125 126 // Theme the resume control. 127 Drupal.theme.prototype.viewsSlideshowControlsPause = function () { 128 return Drupal.t('Resume'); 129 }; 130 131 // Theme the pause control. 132 Drupal.theme.prototype.viewsSlideshowControlsPlay = function () { 133 return Drupal.t('Pause'); 134 }; 135 136 /** 137 * Views Slideshow Pager 138 */ 139 Drupal.viewsSlideshowPager = Drupal.viewsSlideshowPager || {}; 140 141 /** 142 * Implement the transitionBegin hook for pagers. 143 */ 144 Drupal.viewsSlideshowPager.transitionBegin = function (options) { 145 // Route the pager call to the correct pager type. 146 // Need to use try catch so we don't have to check to make sure every part 147 // of the object is defined. 148 try { 149 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') { 150 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].transitionBegin(options); 151 if (Drupal.settings.viewsSlideshowPager[options.slideshowID].top.master_pager === 1) { 152 $.each(Drupal.settings.viewsSlideshow, function(i, obj) { 153 if (i != options.slideshowID) { 154 options.slideshowID = i; 155 options.action = 'goToSlide'; 156 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].goToSlide(options); 157 } 158 }); 159 } 160 } 161 } 162 catch(err) { 163 // Don't need to do anything on error. 164 } 165 166 try { 167 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') { 168 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].transitionBegin(options); 169 if (Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.master_pager === 1) { 170 $.each(Drupal.settings.viewsSlideshow, function(i, obj) { 171 if (i != options.slideshowID) { 172 options.slideshowID = i; 173 options.action = 'goToSlide'; 174 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].goToSlide(options); 175 } 176 }); 177 } 178 } 179 } 180 catch(err) { 181 // Don't need to do anything on error. 182 } 183 }; 184 185 /** 186 * Implement the goToSlide hook for pagers. 187 */ 188 Drupal.viewsSlideshowPager.goToSlide = function (options) { 189 // Route the pager call to the correct pager type. 190 // Need to use try catch so we don't have to check to make sure every part 191 // of the object is defined. 192 try { 193 if (typeof Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].goToSlide == 'function') { 194 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].goToSlide(options); 195 } 196 } 197 catch(err) { 198 // Don't need to do anything on error. 199 } 200 201 try { 202 if (typeof Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].goToSlide == 'function') { 203 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].goToSlide(options); 204 } 205 } 206 catch(err) { 207 // Don't need to do anything on error. 208 } 209 }; 210 211 /** 212 * Implement the previousSlide hook for pagers. 213 */ 214 Drupal.viewsSlideshowPager.previousSlide = function (options) { 215 // Route the pager call to the correct pager type. 216 // Need to use try catch so we don't have to check to make sure every part 217 // of the object is defined. 218 try { 219 if (typeof Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].previousSlide == 'function') { 220 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].previousSlide(options); 221 } 222 } 223 catch(err) { 224 // Don't need to do anything on error. 225 } 226 227 try { 228 if (typeof Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].previousSlide == 'function') { 229 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].previousSlide(options); 230 } 231 } 232 catch(err) { 233 // Don't need to do anything on error. 234 } 235 }; 236 237 /** 238 * Implement the nextSlide hook for pagers. 239 */ 240 Drupal.viewsSlideshowPager.nextSlide = function (options) { 241 // Route the pager call to the correct pager type. 242 // Need to use try catch so we don't have to check to make sure every part 243 // of the object is defined. 244 try { 245 if (typeof Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].nextSlide == 'function') { 246 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].top.type].nextSlide(options); 247 } 248 } 249 catch(err) { 250 // Don't need to do anything on error. 251 } 252 253 try { 254 if (typeof Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type != "undefined" && typeof Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].nextSlide == 'function') { 255 Drupal[Drupal.settings.viewsSlideshowPager[options.slideshowID].bottom.type].nextSlide(options); 256 } 257 } 258 catch(err) { 259 // Don't need to do anything on error. 260 } 261 }; 262 263 264 /** 265 * Views Slideshow Pager Fields 266 */ 267 268 // Add views slideshow api calls for views slideshow pager fields. 269 Drupal.behaviors.viewsSlideshowPagerFields = { 270 attach: function (context) { 271 // Process pause on hover.
272 $('.views_slideshow_pager_field:not(.views-slideshow-pager-field-processed)', context).addClass('views-slideshow-pager-field-processed').each(function() { 273 // Parse out the location and unique id from the full id. 274 var pagerInfo = $(this).attr('id').split('_'); 275 var location = pagerInfo[2]; 276 pagerInfo.splice(0, 3); 277 var uniqueID = pagerInfo.join('_'); 278 279 // Add the activate and pause on pager hover event to each pager item. 280 if (Drupal.settings.viewsSlideshowPagerFields[uniqueID][location].activatePauseOnHover) { 281 $(this).children().each(function(index, pagerItem) { 282 var mouseIn = function() { 283 Drupal.viewsSlideshow.action({ "action": 'goToSlide', "slideshowID": uniqueID, "slideNum": index }); 284 Drupal.viewsSlideshow.action({ "action": 'pause', "slideshowID": uniqueID }); 285 }; 286 287 var mouseOut = function() { 288 Drupal.viewsSlideshow.action({ "action": 'play', "slideshowID": uniqueID }); 289 }; 290 291 if (jQuery.fn.hoverIntent) { 292 $(pagerItem).hoverIntent(mouseIn, mouseOut); 293 } 294 else { 295 $(pagerItem).hover(mouseIn, mouseOut); 296 } 297 }); 298 } 299 else { 300 $(this).children().each(function(index, pagerItem) { 301 $(pagerItem).click(function() { 302 Drupal.viewsSlideshow.action({ "action": 'goToSlide', "slideshowID": uniqueID, "slideNum": index }); 303 }); 304 }); 305 } 306 }); 307 } 308 }; 309 310 Drupal.viewsSlideshowPagerFields = Drupal.viewsSlideshowPagerFields || {}; 311 312 /** 313 * Implement the transitionBegin hook for pager fields pager. 314 */ 315 Drupal.viewsSlideshowPagerFields.transitionBegin = function (options) {
316 for (pagerLocation in Drupal.settings.viewsSlideshowPager[options.slideshowID]) { 317 // Remove active class from pagers 318 $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').removeClass('active'); 319 320 // Add active class to active pager. 321 $('#views_slideshow_pager_field_item_'+ pagerLocation + '_' + options.slideshowID + '_' + options.slideNum).addClass('active'); 322 } 323 }; 324 325 /** 326 * Implement the goToSlide hook for pager fields pager. 327 */ 328 Drupal.viewsSlideshowPagerFields.goToSlide = function (options) { 329 for (pagerLocation in Drupal.settings.viewsSlideshowPager[options.slideshowID]) { 330 // Remove active class from pagers 331 $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').removeClass('active'); 332 333 // Add active class to active pager. 334 $('#views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_' + options.slideNum).addClass('active'); 335 } 336 }; 337 338 /** 339 * Implement the previousSlide hook for pager fields pager. 340 */ 341 Drupal.viewsSlideshowPagerFields.previousSlide = function (options) {
342 for (pagerLocation in Drupal.settings.viewsSlideshowPager[options.slideshowID]) { 343 // Get the current active pager. 344 var pagerNum = $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"].active').attr('id').replace('views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_', ''); 345 346 // If we are on the first pager then activate the last pager. 347 // Otherwise activate the previous pager. 348 if (pagerNum == 0) { 349 pagerNum = $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').length() - 1; 350 } 351 else { 352 pagerNum--; 353 } 354 355 // Remove active class from pagers 356 $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').removeClass('active'); 357 358 // Add active class to active pager. 359 $('#views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_' + pagerNum).addClass('active'); 360 } 361 }; 362 363 /** 364 * Implement the nextSlide hook for pager fields pager. 365 */ 366 Drupal.viewsSlideshowPagerFields.nextSlide = function (options) {
367 for (pagerLocation in Drupal.settings.viewsSlideshowPager[options.slideshowID]) { 368 // Get the current active pager. 369 var pagerNum = $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"].active').attr('id').replace('views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_', ''); 370 var totalPagers = $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').length(); 371 372 // If we are on the last pager then activate the first pager. 373 // Otherwise activate the next pager. 374 pagerNum++; 375 if (pagerNum == totalPagers) { 376 pagerNum = 0; 377 } 378 379 // Remove active class from pagers 380 $('[id^="views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '"]').removeClass('active'); 381 382 // Add active class to active pager. 383 $('#views_slideshow_pager_field_item_' + pagerLocation + '_' + options.slideshowID + '_' + slideNum).addClass('active'); 384 } 385 }; 386 387 388 /** 389 * Views Slideshow Slide Counter 390 */ 391 392 Drupal.viewsSlideshowSlideCounter = Drupal.viewsSlideshowSlideCounter || {}; 393 394 /** 395 * Implement the transitionBegin for the slide counter. 396 */ 397 Drupal.viewsSlideshowSlideCounter.transitionBegin = function (options) { 398 $('#views_slideshow_slide_counter_' + options.slideshowID + ' .num').text(options.slideNum + 1); 399 }; 400 401 /** 402 * This is used as a router to process actions for the slideshow. 403 */ 404 Drupal.viewsSlideshow.action = function (options) { 405 // Set default values for our return status. 406 var status = { 407 'value': true, 408 'text': '' 409 }; 410 411 // If an action isn't specified return false. 412 if (typeof options.action == 'undefined' || options.action == '') { 413 status.value = false; 414 status.text = Drupal.t('There was no action specified.'); 415 return error; 416 } 417 418 // If we are using pause or play switch paused state accordingly. 419 if (options.action == 'pause') { 420 Drupal.settings.viewsSlideshow[options.slideshowID].paused = 1; 421 // If the calling method is forcing a pause then mark it as such. 422 if (options.force) { 423 Drupal.settings.viewsSlideshow[options.slideshowID].pausedForce = 1; 424 } 425 } 426 else if (options.action == 'play') { 427 // If the slideshow isn't forced pause or we are forcing a play then play 428 // the slideshow. 429 // Otherwise return telling the calling method that it was forced paused. 430 if (!Drupal.settings.viewsSlideshow[options.slideshowID].pausedForce || options.force) { 431 Drupal.settings.viewsSlideshow[options.slideshowID].paused = 0; 432 Drupal.settings.viewsSlideshow[options.slideshowID].pausedForce = 0; 433 } 434 else { 435 status.value = false; 436 status.text += ' ' + Drupal.t('This slideshow is forced paused.'); 437 return status; 438 } 439 } 440 441 // We use a switch statement here mainly just to limit the type of actions 442 // that are available. 443 switch (options.action) { 444 case "goToSlide": 445 case "transitionBegin": 446 case "transitionEnd": 447 // The three methods above require a slide number. Checking if it is 448 // defined and it is a number that is an integer. 449 if (typeof options.slideNum == 'undefined' || typeof options.slideNum !== 'number' || parseInt(options.slideNum) != (options.slideNum - 0)) { 450 status.value = false; 451 status.text = Drupal.t('An invalid integer was specified for slideNum.'); 452 } 453 case "pause": 454 case "play": 455 case "nextSlide": 456 case "previousSlide": 457 // Grab our list of methods. 458 var methods = Drupal.settings.viewsSlideshow[options.slideshowID]['methods']; 459 460 // if the calling method specified methods that shouldn't be called then 461 // exclude calling them. 462 var excludeMethodsObj = {}; 463 if (typeof options.excludeMethods !== 'undefined') { 464 // We need to turn the excludeMethods array into an object so we can use the in 465 // function. 466 for (var i=0; i < excludeMethods.length; i++) { 467 excludeMethodsObj[excludeMethods[i]] = ''; 468 } 469 } 470 471 // Call every registered method and don't call excluded ones. 472 for (i = 0; i < methods[options.action].length; i++) { 473 if (Drupal[methods[options.action][i]] != undefined && typeof Drupal[methods[options.action][i]][options.action] == 'function' && !(methods[options.action][i] in excludeMethodsObj)) { 474 Drupal[methods[options.action][i]][options.action](options); 475 } 476 } 477 break; 478
479 // If it gets here it's because it's an invalid action. 480 default: 481 status.value = false; 482 status.text = Drupal.t('An invalid action "!action" was specified.', { "!action": options.action }); 483 } 484 return status; 485 }; 486})(jQuery); 487; 488/*jslint browser: true */ /*global jQuery: true */ 489 490/** 491 * jQuery Cookie plugin 492 * 493 * Copyright (c) 2010 Klaus Hartl (stilbuero.de) 494 * Dual licensed under the MIT and GPL licenses: 495 * http://www.opensource.org/licenses/mit-license.php 496 * http://www.gnu.org/licenses/gpl.html 497 * 498 */ 499 500// TODO JsDoc 501 502/** 503 * Create a cookie with the given key and value and other optional parameters. 504 * 505 * @example $.cookie('the_cookie', 'the_value'); 506 * @desc Set the value of a cookie. 507 * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true }); 508 * @desc Create a cookie with all available options. 509 * @example $.cookie('the_cookie', 'the_value'); 510 * @desc Create a session cookie. 511 * @example $.cookie('the_cookie', null); 512 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain 513 * used when the cookie was set. 514 * 515 * @param String key The key of the cookie. 516 * @param String value The value of the cookie. 517 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes. 518 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object. 519 * If a negative value is specified (e.g. a date in the past), the cookie will be deleted. 520 * If set to null or omitted, the cookie will be a session cookie and will not be retained 521 * when the the browser exits. 522 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie). 523 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie). 524 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will 525 * require a secure protocol (like HTTPS). 526 * @type undefined 527 * 528 * @name $.cookie 529 * @cat Plugins/Cookie 530 * @author Klaus Hartl/[email protected] 531 */ 532 533/** 534 * Get the value of a cookie with the given key. 535 * 536 * @example $.cookie('the_cookie'); 537 * @desc Get the value of a cookie. 538 * 539 * @param String key The key of the cookie. 540 * @return The value of the cookie. 541 * @type String 542 * 543 * @name $.cookie 544 * @cat Plugins/Cookie 545 * @author Klaus Hartl/[email protected] 546 */ 547jQuery.cookie = function (key, value, options) { 548 549 // key and value given, set cookie... 550 if (arguments.length > 1 && (value === null || typeof value !== "object")) { 551 options = jQuery.extend({}, options); 552 553 if (value === null) { 554 options.expires = -1; 555 } 556 557 if (typeof options.expires === 'number') { 558 var days = options.expires, t = options.expires = new Date(); 559 t.setDate(t.getDate() + days); 560 } 561 562 return (document.cookie = [ 563 encodeURIComponent(key), '=', 564 options.raw ? String(value) : encodeURIComponent(String(value)), 565 options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE 566 options.path ? '; path=' + options.path : '', 567 options.domain ? '; domain=' + options.domain : '', 568 options.secure ? '; secure' : '' 569 ].join('')); 570 } 571 572 // key and possibly options given, get cookie... 573 options = value || {}; 574 var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent; 575 return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null; 576}; 577; 578(function ($) { 579 580/** 581 * Prevents consecutive form submissions of identical form values. 582 * 583 * Repetitive form submissions that would submit the identical form values are 584 * prevented, unless the form values are different from the previously 585 * submitted values. 586 * 587 * This is a simplified re-implementation of a user-agent behavior that should 588 * be natively supported by major web browsers, but at this time, only Firefox 589 * has a built-in protection. 590 * 591 * A form value-based approach ensures that the constraint is triggered for 592 * consecutive, identical form submissions only. Compared to that, a form 593 * button-based approach would (1) rely on [visible] buttons to exist where 594 * technically not required and (2) require more complex state management if 595 * there are multiple buttons in a form. 596 * 597 * This implementation is based on form-level submit events only and relies on 598 * jQuery's serialize() method to determine submitted form values. As such, the 599 * following limitations exist: 600 * 601 * - Event handlers on form buttons that preventDefault() do not receive a 602 * double-submit protection. That is deemed to be fine, since such button 603 * events typically trigger reversible client-side or server-side operations 604 * that are local to the context of a form only. 605 * - Changed values in advanced form controls, such as file inputs, are not part 606 * of the form values being compared between consecutive form submits (due to 607 * limitations of jQuery.serialize()). That is deemed to be acceptable, 608 * because if the user forgot to attach a file, then the size of HTTP payload 609 * will most likely be small enough to be fully passed to the server endpoint 610 * within (milli)seconds. If a user mistakenly attached a wrong file and is
611 * technically versed enough to cancel the form submission (and HTTP payload) 612 * in order to attach a different file, then that edge-case is not supported 613 * here. 614 * 615 * Lastly, all forms submitted via HTTP GET are idempotent by definition of HTTP 616 * standards, so excluded in this implementation. 617 */ 618Drupal.behaviors.formSingleSubmit = { 619 attach: function () { 620 function onFormSubmit (e) { 621 var $form = $(e.currentTarget); 622 var formValues = $form.serialize(); 623 var previousValues = $form.attr('data-drupal-form-submit-last'); 624 if (previousValues === formValues) { 625 e.preventDefault(); 626 } 627 else { 628 $form.attr('data-drupal-form-submit-last', formValues); 629 } 630 } 631 632 $('body').once('form-single-submit') 633 .delegate('form:not([method~="GET"])', 'submit.singleSubmit', onFormSubmit); 634 } 635}; 636 637})(jQuery); 638;
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.