1/** 2 * @file 3 * JavaScript behaviors for the front-end display of webforms. 4 */ 5 6(function ($) { 7 8 "use strict"; 9 10 Drupal.behaviors.webform = Drupal.behaviors.webform || {}; 11 12 Drupal.behaviors.webform.attach = function (context) { 13 // Calendar datepicker behavior. 14 Drupal.webform.datepicker(context); 15 16 // Conditional logic. 17 if (Drupal.settings.webform && Drupal.settings.webform.conditionals) { 18 Drupal.webform.conditional(context); 19 } 20 }; 21 22 Drupal.webform = Drupal.webform || {}; 23 24 Drupal.webform.datepicker = function (context) { 25 $('div.webform-datepicker').each(function () { 26 var $webformDatepicker = $(this); 27 var $calendar = $webformDatepicker.find('input.webform-calendar'); 28 29 // Ensure the page we're on actually contains a datepicker. 30 if ($calendar.length == 0) { 31 return; 32 } 33 34 var startDate = $calendar[0].className.replace(/.*webform-calendar-start-(\d{4}-\d{2}-\d{2}).*/, '$1').split('-'); 35 var endDate = $calendar[0].className.replace(/.*webform-calendar-end-(\d{4}-\d{2}-\d{2}).*/, '$1').split('-'); 36 var firstDay = $calendar[0].className.replace(/.*webform-calendar-day-(\d).*/, '$1'); 37 // Convert date strings into actual Date objects. 38 startDate = new Date(startDate[0], startDate[1] - 1, startDate[2]); 39 endDate = new Date(endDate[0], endDate[1] - 1, endDate[2]); 40 41 // Ensure that start comes before end for datepicker. 42 if (startDate > endDate) { 43 var laterDate = startDate; 44 startDate = endDate; 45 endDate = laterDate; 46 } 47 48 var startYear = startDate.getFullYear(); 49 var endYear = endDate.getFullYear(); 50 51 // Set up the jQuery datepicker element. 52 $calendar.datepicker({ 53 dateFormat: 'yy-mm-dd', 54 yearRange: startYear + ':' + endYear, 55 firstDay: parseInt(firstDay), 56 minDate: startDate, 57 maxDate: endDate, 58 onSelect: function (dateText, inst) { 59 var date = dateText.split('-'); 60 $webformDatepicker.find('select.year, input.year').val(+date[0]).trigger('change'); 61 $webformDatepicker.find('select.month').val(+date[1]).trigger('change'); 62 $webformDatepicker.find('select.day').val(+date[2]).trigger('change'); 63 }, 64 beforeShow: function (input, inst) { 65 // Get the select list values. 66 var year = $webformDatepicker.find('select.year, input.year').val(); 67 var month = $webformDatepicker.find('select.month').val(); 68 var day = $webformDatepicker.find('select.day').val(); 69 70 // If empty, default to the current year/month/day in the popup. 71 var today = new Date(); 72 year = year ? year : today.getFullYear(); 73 month = month ? month : today.getMonth() + 1; 74 day = day ? day : today.getDate(); 75 76 // Make sure that the default year fits in the available options. 77 year = (year < startYear || year > endYear) ? startYear : year; 78 79 // jQuery UI Datepicker will read the input field and base its date off 80 // of that, even though in our case the input field is a button. 81 $(input).val(year + '-' + month + '-' + day); 82 } 83 }); 84 85 // Prevent the calendar button from submitting the form. 86 $calendar.click(function (event) { 87 $(this).focus(); 88 event.preventDefault(); 89 }); 90 }); 91 }; 92 93 Drupal.webform.conditional = function (context) { 94 // Add the bindings to each webform on the page. 95 $.each(Drupal.settings.webform.conditionals, function (formKey, settings) { 96 var $form = $('.' + formKey + ':not(.webform-conditional-processed)'); 97 $form.each(function (index, currentForm) { 98 var $currentForm = $(currentForm); 99 $currentForm.addClass('webform-conditional-processed'); 100 $currentForm.bind('change', {'settings': settings}, Drupal.webform.conditionalCheck); 101 102 // Trigger all the elements that cause conditionals on this form. 103 Drupal.webform.doConditions($currentForm, settings); 104 }); 105 }); 106 }; 107 108 /** 109 * Event handler to respond to field changes in a form. 110 * 111 * This event is bound to the entire form, not individual fields. 112 */ 113 Drupal.webform.conditionalCheck = function (e) { 114 var $triggerElement = $(e.target).closest('.webform-component'); 115 var $form = $triggerElement.closest('form'); 116 var triggerElementKey = $triggerElement.attr('class').match(/webform-component--[^ ]+/)[0]; 117 var settings = e.data.settings; 118 if (settings.sourceMap[triggerElementKey]) { 119 Drupal.webform.doConditions($form, settings); 120 } 121 }; 122 123 /** 124 * Processes all conditional. 125 */ 126 Drupal.webform.doConditions = function ($form, settings) { 127 128 var stackPointer; 129 var resultStack; 130 131 /** 132 * Initializes an execution stack for a conditional group's rules and 133 * sub-conditional rules. 134 */ 135 function executionStackInitialize(andor) { 136 stackPointer = -1; 137 resultStack = []; 138 executionStackPush(andor); 139 } 140 141 /** 142 * Starts a new subconditional for the given and/or operator. 143 */ 144 function executionStackPush(andor) { 145 resultStack[++stackPointer] = { 146 results: [], 147 andor: andor, 148 }; 149 } 150 151 /** 152 * Adds a rule's result to the current sub-conditional. 153 */ 154 function executionStackAccumulate(result) { 155 resultStack[stackPointer]['results'].push(result); 156 } 157 158 /** 159 * Finishes a sub-conditional and adds the result to the parent stack frame. 160 */ 161 function executionStackPop() { 162 // Calculate the and/or result. 163 var stackFrame = resultStack[stackPointer]; 164 // Pop stack and protect against stack underflow. 165 stackPointer = Math.max(0, stackPointer - 1); 166 var $conditionalResults = stackFrame['results']; 167 var filteredResults = $.map($conditionalResults, function (val) { 168 return val ? val : null; 169 }); 170 return stackFrame['andor'] === 'or' 171 ? filteredResults.length > 0 172 : filteredResults.length === $conditionalResults.length; 173 } 174 175 // Track what has be set/shown for each target component.
176 var targetLocked = []; 177 178 $.each(settings.ruleGroups, function (rgid_key, rule_group) { 179 var ruleGroup = settings.ruleGroups[rgid_key]; 180 181 // Perform the comparison callback and build the results for this group. 182 executionStackInitialize(ruleGroup['andor']); 183 $.each(ruleGroup['rules'], function (m, rule) { 184 switch (rule['source_type']) { 185 case 'component': 186 var elementKey = rule['source']; 187 var element = $form.find('.' + elementKey)[0]; 188 var existingValue = settings.values[elementKey] ? settings.values[elementKey] : null; 189 executionStackAccumulate(window['Drupal']['webform'][rule.callback](element, existingValue, rule['value'])); 190 break; 191 192 case 'conditional_start': 193 executionStackPush(rule['andor']); 194 break; 195 196 case 'conditional_end': 197 executionStackAccumulate(executionStackPop()); 198 break; 199 } 200 }); 201 var conditionalResult = executionStackPop(); 202 203 $.each(ruleGroup['actions'], function (aid, action) { 204 var $target = $form.find('.' + action['target']); 205 var actionResult = action['invert'] ? !conditionalResult : conditionalResult; 206 switch (action['action']) { 207 case 'show': 208 if (actionResult != Drupal.webform.isVisible($target)) { 209 var $targetElements = actionResult 210 ? $target.find('.webform-conditional-disabled').removeClass('webform-conditional-disabled') 211 : $target.find(':input').addClass('webform-conditional-disabled'); 212 $targetElements.webformProp('disabled', !actionResult); 213 $target.toggleClass('webform-conditional-hidden', !actionResult); 214 // Anything hidden needs to be disabled so that child elements of 215 // fieldsets do not block submission by being required. 216 $target.webformProp('disabled', !actionResult); 217 if (actionResult) { 218 $target.show(); 219 } 220 else { 221 $target.hide(); 222 // Record that the target was hidden. 223 targetLocked[action['target']] = 'hide'; 224 } 225 if ($target.is('tr')) { 226 Drupal.webform.restripeTable($target.closest('table').first()); 227 } 228 } 229 break; 230 231 case 'require': 232 var $requiredSpan = $target.find('.form-required, .form-optional').first(); 233 if (actionResult != $requiredSpan.hasClass('form-required')) { 234 var $targetInputElements = $target.find("input:text,textarea,input[type='email'],select,input:radio,input:file"); 235 // Rather than hide the required tag, remove it so that other jQuery can respond via Drupal behaviors. 236 Drupal.detachBehaviors($requiredSpan); 237 $targetInputElements 238 .webformProp('required', actionResult) 239 .toggleClass('required', actionResult); 240 if (actionResult) { 241 $requiredSpan.replaceWith('<span class="form-required" title="' + Drupal.t('This field is required.') + '">*</span>'); 242 } 243 else { 244 $requiredSpan.replaceWith('<span class="form-optional"></span>'); 245 } 246 Drupal.attachBehaviors($requiredSpan); 247 } 248 break; 249 250 case 'set':
251 var isLocked = targetLocked[action['target']]; 252 var $texts = $target.find("input:text,textarea,input[type='email']"); 253 var $selects = $target.find('select,select option,input:radio,input:checkbox'); 254 var $markups = $target.filter('.webform-component-markup'); 255 if (actionResult) { 256 var multiple = $.map(action['argument'].split(','), $.trim); 257 $selects.webformVal(multiple); 258 $texts.val([action['argument']]); 259 // A special case is made for markup. It is sanitized with filter_xss_admin on the server. 260 // otherwise text() should be used to avoid an XSS vulnerability. text() however would 261 // preclude the use of tags like <strong> or <a>. 262 $markups.html(action['argument']); 263 } 264 else { 265 // Markup not set? Then restore original markup as provided in 266 // the attribute data-webform-markup. 267 $markups.each(function () { 268 var $this = $(this); 269 var original = $this.data('webform-markup'); 270 if (original !== undefined) { 271 $this.html(original); 272 } 273 }); 274 } 275 if (!isLocked) { 276 // If not previously hidden or set, disable the element readonly or readonly-like behavior. 277 $selects.webformProp('disabled', actionResult); 278 $texts.webformProp('readonly', actionResult); 279 targetLocked[action['target']] = actionResult ? 'set' : false; 280 } 281 break; 282 } 283 }); // End look on each action for one conditional 284 }); // End loop on each conditional. 285 }; 286 287 /** 288 * Event handler to prevent propagation of events, typically click for disabling 289 * radio and checkboxes. 290 */ 291 Drupal.webform.stopEvent = function () { 292 return false; 293 }; 294 295 Drupal.webform.conditionalOperatorStringEqual = function (element, existingValue, ruleValue) { 296 var returnValue = false; 297 var currentValue = Drupal.webform.stringValue(element, existingValue); 298 $.each(currentValue, function (n, value) { 299 if (value.toLowerCase() === ruleValue.toLowerCase()) { 300 returnValue = true; 301 return false; // break. 302 } 303 }); 304 return returnValue; 305 }; 306 307 Drupal.webform.conditionalOperatorStringNotEqual = function (element, existingValue, ruleValue) { 308 var found = false; 309 var currentValue = Drupal.webform.stringValue(element, existingValue); 310 $.each(currentValue, function (n, value) { 311 if (value.toLowerCase() === ruleValue.toLowerCase()) { 312 found = true; 313 } 314 }); 315 return !found; 316 }; 317 318 Drupal.webform.conditionalOperatorStringContains = function (element, existingValue, ruleValue) { 319 var returnValue = false; 320 var currentValue = Drupal.webform.stringValue(element, existingValue); 321 $.each(currentValue, function (n, value) { 322 if (value.toLowerCase().indexOf(ruleValue.toLowerCase()) > -1) { 323 returnValue = true; 324 return false; // break. 325 } 326 }); 327 return returnValue; 328 }; 329 330 Drupal.webform.conditionalOperatorStringDoesNotContain = function (element, existingValue, ruleValue) { 331 var found = false; 332 var currentValue = Drupal.webform.stringValue(element, existingValue); 333 $.each(currentValue, function (n, value) { 334 if (value.toLowerCase().indexOf(ruleValue.toLowerCase()) > -1) { 335 found = true; 336 } 337 }); 338 return !found; 339 }; 340 341 Drupal.webform.conditionalOperatorStringBeginsWith = function (element, existingValue, ruleValue) { 342 var returnValue = false; 343 var currentValue = Drupal.webform.stringValue(element, existingValue); 344 $.each(currentValue, function (n, value) { 345 if (value.toLowerCase().indexOf(ruleValue.toLowerCase()) === 0) { 346 returnValue = true; 347 return false; // break. 348 } 349 }); 350 return returnValue; 351 }; 352 353 Drupal.webform.conditionalOperatorStringEndsWith = function (element, existingValue, ruleValue) { 354 var returnValue = false; 355 var currentValue = Drupal.webform.stringValue(element, existingV
355alue); 356 $.each(currentValue, function (n, value) { 357 if (value.toLowerCase().lastIndexOf(ruleValue.toLowerCase()) === value.length - ruleValue.length) { 358 returnValue = true; 359 return false; // break. 360 } 361 }); 362 return returnValue; 363 }; 364 365 Drupal.webform.conditionalOperatorStringEmpty = function (element, existingValue, ruleValue) { 366 var currentValue = Drupal.webform.stringValue(element, existingValue); 367 var returnValue = true; 368 $.each(currentValue, function (n, value) { 369 if (value !== '') { 370 returnValue = false; 371 return false; // break. 372 } 373 }); 374 return returnValue; 375 }; 376 377 Drupal.webform.conditionalOperatorStringNotEmpty = function (element, existingValue, ruleValue) { 378 return !Drupal.webform.conditionalOperatorStringEmpty(element, existingValue, ruleValue); 379 }; 380 381 Drupal.webform.conditionalOperatorSelectGreaterThan = function (element, existingValue, ruleValue) { 382 var currentValue = Drupal.webform.stringValue(element, existingValue); 383 return Drupal.webform.compare_select(currentValue[0], ruleValue, element) > 0; 384 }; 385 386 Drupal.webform.conditionalOperatorSelectGreaterThanEqual = function (element, existingValue, ruleValue) { 387 var currentValue = Drupal.webform.stringValue(element, existingValue); 388 var comparison = Drupal.webform.compare_select(currentValue[0], ruleValue, element); 389 return comparison > 0 || comparison === 0; 390 }; 391 392 Drupal.webform.conditionalOperatorSelectLessThan = function (element, existingValue, ruleValue) { 393 var currentValue = Drupal.webform.stringValue(element, existingValue); 394 return Drupal.webform.compare_select(currentValue[0], ruleValue, element) < 0; 395 }; 396 397 Drupal.webform.conditionalOperatorSelectLessThanEqual = function (element, existingValue, ruleValue) { 398 var currentValue = Drupal.webform.stringValue(element, existingValue); 399 var comparison = Drupal.webform.compare_select(currentValue[0], ruleValue, element); 400 return comparison < 0 || comparison === 0; 401 }; 402 403 Drupal.webform.conditionalOperatorNumericEqual = function (element, existingValue, ruleValue) { 404 // See float comparison: http://php.net/manual/en/language.types.float.php 405 var currentValue = Drupal.webform.stringValue(element, existingValue); 406 var epsilon = 0.000001; 407 // An empty string does not match any number. 408 return currentValue[0] === '' ? false : (Math.abs(parseFloat(currentValue[0]) - parseFloat(ruleValue)) < epsilon); 409 }; 410 411 Drupal.webform.conditionalOperatorNumericNotEqual = function (element, existingValue, ruleValue) { 412 // See float comparison: http://php.net/manual/en/language.types.float.php 413 var currentValue = Drupal.webform.stringValue(element, existingValue); 414 var epsilon = 0.000001; 415 // An empty string does not match any number. 416 return currentValue[0] === '' ? true : (Math.abs(parseFloat(currentValue[0]) - parseFloat(ruleValue)) >= epsilon); 417 }; 418 419 Drupal.webform.conditionalOperatorNumericGreaterThan = function (element, existingValue, ruleValue) { 420 var currentValue = Drupal.webform.stringValue(element, existingValue); 421 return parseFloat(currentValue[0]) > parseFloat(ruleValue); 422 }; 423 424 Drupal.webform.conditionalOperatorNumericGreaterThanEqual = function (element, existingValue, ruleValue) { 425 return Drupal.webform.conditionalOperatorNumericGreaterThan(element, existingValue, ruleValue) || 426 Drupal.webform.conditionalOperatorNumericEqual(element, existingValue, ruleValue); 427 }; 428 429 Drupal.webform.conditionalOperatorNumericLessThan = function (element, existingValue, ruleValue) { 430 var currentValue = Drupal.webform.stringValue(element, existingValue); 431 return parseFloat(currentValue[0]) < parseFloat(ruleValue); 432 }; 433 434 Drupal.webform.conditionalOperatorNumericLessThanEqual = function (element, existingValue, ruleValue) { 435 return Drupal.webform.conditionalOperatorNumericLessThan(element, existingValue, ruleValue) || 436 Drupal.webform.conditionalOperatorNumericEqual(element, existingValue, ruleValue); 437 }; 438 439 Drupal.webform.conditionalOperatorDateEqual = function (element, existingV
439alue, ruleValue) { 440 var currentValue = Drupal.webform.dateValue(element, existingValue); 441 return currentValue === ruleValue; 442 }; 443 444 Drupal.webform.conditionalOperatorDateNotEqual = function (element, existingValue, ruleValue) { 445 return !Drupal.webform.conditionalOperatorDateEqual(element, existingValue, ruleValue); 446 }; 447 448 Drupal.webform.conditionalOperatorDateBefore = function (element, existingValue, ruleValue) { 449 var currentValue = Drupal.webform.dateValue(element, existingValue); 450 return (currentValue !== false) && currentValue < ruleValue; 451 }; 452 453 Drupal.webform.conditionalOperatorDateBeforeEqual = function (element, existingValue, ruleValue) { 454 var currentValue = Drupal.webform.dateValue(element, existingValue); 455 return (currentValue !== false) && (currentValue < ruleValue || currentValue === ruleValue); 456 }; 457 458 Drupal.webform.conditionalOperatorDateAfter = function (element, existingValue, ruleValue) { 459 var currentValue = Drupal.webform.dateValue(element, existingValue); 460 return (currentValue !== false) && currentValue > ruleValue; 461 }; 462 463 Drupal.webform.conditionalOperatorDateAfterEqual = function (element, existingValue, ruleValue) { 464 var currentValue = Drupal.webform.dateValue(element, existingValue); 465 return (currentValue !== false) && (currentValue > ruleValue || currentValue === ruleValue); 466 }; 467 468 Drupal.webform.conditionalOperatorTimeEqual = function (element, existingValue, ruleValue) { 469 var currentValue = Drupal.webform.timeValue(element, existingValue); 470 return currentValue === ruleValue; 471 }; 472 473 Drupal.webform.conditionalOperatorTimeNotEqual = function (element, existingValue, ruleValue) { 474 return !Drupal.webform.conditionalOperatorTimeEqual(element, existingValue, ruleValue); 475 }; 476 477 Drupal.webform.conditionalOperatorTimeBefore = function (element, existingValue, ruleValue) { 478 // Date and time operators intentionally exclusive for "before". 479 var currentValue = Drupal.webform.timeValue(element, existingValue); 480 return (currentValue !== false) && (currentValue < ruleValue); 481 }; 482 483 Drupal.webform.conditionalOperatorTimeBeforeEqual = function (element, existingValue, ruleValue) { 484 // Date and time operators intentionally exclusive for "before". 485 var currentValue = Drupal.webform.timeValue(element, existingValue); 486 return (currentValue !== false) && (currentValue < ruleValue || currentValue === ruleValue); 487 }; 488 489 Drupal.webform.conditionalOperatorTimeAfter = function (element, existingValue, ruleValue) { 490 // Date and time operators intentionally inclusive for "after". 491 var currentValue = Drupal.webform.timeValue(element, existingValue); 492 return (currentValue !== false) && (currentValue > ruleValue); 493 }; 494 495 Drupal.webform.conditionalOperatorTimeAfterEqual = function (element, existingValue, ruleValue) { 496 // Date and time operators intentionally inclusive for "after". 497 var currentValue = Drupal.webform.timeValue(element, existingValue); 498 return (currentValue !== false) && (currentValue > ruleValue || currentValue === ruleValue); 499 }; 500 501 /** 502 * Utility function to compare values of a select component. 503 * 504 * @param string a 505 * First select option key to compare 506 * @param string b 507 * Second select option key to compare 508 * @param array options 509 * Associative array where the a and b are within the keys 510 * 511 * @return integer based upon position of $a and $b in $options 512 * -N if $a above (<) $b 513 * 0 if $a = $b 514 * +N if $a is below (>) $b 515 */ 516 Drupal.webform.compare_select = function (a, b, element) { 517 var optionList = []; 518 $('option,input:radio,input:checkbox', element).each(function () { 519 optionList.push($(this).val()); 520 }); 521 var a_position = optionList.indexOf(a); 522 var b_position = optionList.indexOf(b); 523 return (a_position < 0 || b_position < 0) ? null : a_position - b_position; 524 }; 525 526 /** 527 * Utility to return current visibility. Uses actual visibility, except for 528 * hidden components which use the applied disabled class. 529 */ 530 Drupal.webform.isVisible = function ($element) { 531 return $element.hasClass('webform-component-hidden') 532 ? !$element.find('input').first().hasClass('webform-conditional-disabled') 533 : $element.closest('.webform-conditional-hidden').length == 0; 534 }; 535 536 /** 537 * Utility function to get a string value from a select/radios/text/etc. field. 538 */
539 Drupal.webform.stringValue = function (element, existingValue) { 540 var value = []; 541 if (element) { 542 var $element = $(element); 543 if (Drupal.webform.isVisible($element)) { 544 // Checkboxes and radios. 545 $element.find('input[type=checkbox]:checked,input[type=radio]:checked').each(function () { 546 value.push(this.value); 547 }); 548 // Select lists. 549 if (!value.length) { 550 var selectValue = $element.find('select').val(); 551 if (selectValue) { 552 if ($.isArray(selectValue)) { 553 value = selectValue; 554 } 555 else { 556 value.push(selectValue); 557 } 558 } 559 } 560 // Simple text fields. This check is done last so that the select list in 561 // select-or-other fields comes before the "other" text field. 562 if (!value.length) { 563 $element.find('input:not([type=checkbox],[type=radio]),textarea').each(function () { 564 value.push(this.value); 565 }); 566 } 567 } 568 } 569 else { 570 switch ($.type(existingValue)) { 571 case 'array':
572 value = existingValue; 573 break; 574 575 case 'string': 576 value.push(existingValue); 577 break; 578 } 579 } 580 return value; 581 }; 582 583 /** 584 * Utility function to calculate a second-based timestamp from a time field. 585 */ 586 Drupal.webform.dateValue = function (element, existingValue) { 587 var value = false; 588 if (element) { 589 var $element = $(element); 590 if (Drupal.webform.isVisible($element)) { 591 var day = $element.find('[name*=day]').val(); 592 var month = $element.find('[name*=month]').val(); 593 var year = $element.find('[name*=year]').val(); 594 // Months are 0 indexed in JavaScript. 595 if (month) { 596 month--; 597 } 598 if (year !== '' && month !== '' && day !== '') { 599 value = Date.UTC(year, month, day) / 1000; 600 } 601 } 602 } 603 else { 604 if ($.type(existingValue) === 'array' && existingValue.length) { 605 existingValue = existingValue[0]; 606 } 607 if ($.type(existingValue) === 'string') { 608 existingValue = existingV
608alue.split('-'); 609 } 610 if (existingValue.length === 3) { 611 value = Date.UTC(existingValue[0], existingValue[1], existingValue[2]) / 1000; 612 } 613 } 614 return value; 615 }; 616 617 /** 618 * Utility function to calculate a millisecond timestamp from a time field. 619 */ 620 Drupal.webform.timeValue = function (element, existingValue) { 621 var value = false; 622 if (element) { 623 var $element = $(element); 624 if (Drupal.webform.isVisible($element)) { 625 var hour = $element.find('[name*=hour]').val(); 626 var minute = $element.find('[name*=minute]').val(); 627 var ampm = $element.find('[name*=ampm]:checked').val(); 628 629 // Convert to integers if set. 630 hour = (hour === '') ? hour : parseInt(hour); 631 minute = (minute === '') ? minute : parseInt(minute); 632 633 if (hour !== '') { 634 hour = (hour < 12 && ampm == 'pm') ? hour + 12 : hour; 635 hour = (hour === 12 && ampm == 'am') ? 0 : hour; 636 } 637 if (hour !== '' && minute !== '') { 638 value = Date.UTC(1970, 0, 1, hour, minute) / 1000; 639 } 640 } 641 } 642 else { 643 if ($.type(existingValue) === 'array' && existingValue.length) {
644 existingValue = existingValue[0]; 645 } 646 if ($.type(existingValue) === 'string') { 647 existingValue = existingValue.split(':'); 648 } 649 if (existingValue.length >= 2) { 650 value = Date.UTC(1970, 0, 1, existingValue[0], existingValue[1]) / 1000; 651 } 652 } 653 return value; 654 }; 655 656 /** 657 * Make a prop shim for jQuery < 1.9. 658 */ 659 $.fn.webformProp = $.fn.webformProp || function (name, value) { 660 if (value) { 661 return $.fn.prop ? this.prop(name, true) : this.attr(name, true); 662 } 663 else { 664 return $.fn.prop ? this.prop(name, false) : this.removeAttr(name); 665 } 666 }; 667 668 /** 669 * Make a multi-valued val() function for setting checkboxes, radios, and select 670 * elements. 671 */ 672 $.fn.webformVal = function (values) { 673 this.each(function () { 674 var $this = $(this); 675 var value = $this.val(); 676 var on = $.inArray($this.val(), values) != -1; 677 if (this.nodeName == 'OPTION') { 678 $this.webformProp('selected', on ? value : false); 679 } 680 else { 681 $this.val(on ? [value] : false); 682 } 683 }); 684 return this; 685 }; 686 687 /** 688 * Given a table's DOM element, restripe the odd/even classes. 689 */ 690 Drupal.webform.restripeTable = function (table) { 691 // :even and :odd are reversed because jQuery counts from 0 and 692 // we count from 1, so we're out of sync. 693 // Match immediate children of the parent element to allow nesting. 694 $('> tbody > tr, > tr', table) 695 .filter(':visible:odd').filter('.odd') 696 .removeClass('odd').addClass('even') 697 .end().end() 698 .filter(':visible:even').filter('.even') 699 .removeClass('even').addClass('odd'); 700 }; 701 702})(jQuery);
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.