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 80 // off 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. 133 * 134 * Also initializes sub-conditional rules. 135 */ 136 function executionStackInitialize(andor) { 137 stackPointer = -1; 138 resultStack = []; 139 executionStackPush(andor); 140 } 141 142 /** 143 * Starts a new subconditional for the given and/or operator. 144 */ 145 function executionStackPush(andor) { 146 resultStack[++stackPointer] = { 147 results: [], 148 andor: andor, 149 }; 150 } 151 152 /** 153 * Adds a rule's result to the current sub-conditional. 154 */ 155 function executionStackAccumulate(result) { 156 resultStack[stackPointer]['results'].push(result); 157 } 158 159 /** 160 * Finishes a sub-conditional and adds the result to the parent stack frame. 161 */ 162 function executionStackPop() { 163 // Calculate the and/or result. 164 var stackFrame = resultStack[stackPointer]; 165 // Pop stack and protect against stack underflow. 166 stackPointer = Math.max(0, stackPointer - 1); 167 var $conditionalResults = stackFrame['results']; 168 var filteredResults = $.map($conditionalResults, function (val) { 169 return val ? val : null; 170 }); 171 return stackFrame['andor'] === 'or' 172 ? filteredResults.length > 0 173 : filteredResults.length === $conditionalResults.length; 174 } 175 176 // Track what has been set/hidden for each target component's elements. 177 // Hidden elements must be disabled because if they are required and don't 178 // have a value, they will prevent submission due to html5 validation. 179 // Each execution of the conditionals adds a temporary class 180 // webform-disabled-flag so that elements hidden or set can be disabled and 181 // also be prevented from being re-enabled by another conditional (such as a 182 // parent fieldset). After processing conditionals, this temporary class 183 // must be removed in preparation for the next execution of the 184 // conditionals. 185 $.each(settings.ruleGroups, function (rgid_key, rule_group) { 186 var ruleGroup = settings.ruleGroups[rgid_key]; 187 188 // Perform the comparison callback and build the results for this group. 189 executionStackInitialize(ruleGroup['andor']); 190 $.each(ruleGroup['rules'], function (m, rule) { 191 switch (rule['source_type']) { 192 case 'component':
193 var elementKey = rule['source']; 194 var element = $form.find('.' + elementKey)[0]; 195 var existingValue = settings.values[elementKey] ? settings.values[elementKey] : null; 196 executionStackAccumulate(window['Drupal']['webform'][rule.callback](element, existingValue, rule['value'])); 197 break; 198 199 case 'conditional_start': 200 executionStackPush(rule['andor']); 201 break; 202 203 case 'conditional_end': 204 executionStackAccumulate(executionStackPop()); 205 break; 206 } 207 }); 208 var conditionalResult = executionStackPop(); 209 210 $.each(ruleGroup['actions'], function (aid, action) { 211 var $target = $form.find('.' + action['target']); 212 var actionResult = action['invert'] ? !conditionalResult : conditionalResult; 213 switch (action['action']) { 214 case 'show': 215 var changed = actionResult != Drupal.webform.isVisible($target); 216 if (actionResult) { 217 $target.find('.webform-conditional-disabled:not(.webform-disabled-flag)') 218 .removeClass('webform-conditional-disabled') 219 .webformProp('disabled', false); 220 $target 221 .removeClass('webform-conditional-hidden') 222 .show(); 223 $form.find('.chosen-disabled').prev().trigger('chosen:updated.chosen'); 224 } 225 else { 226 $target 227 .hide() 228 .addClass('webform-conditional-hidden') 229 .find(':input') 230 .addClass('webform-conditional-disabled webform-disabled-flag') 231 .webformProp('disabled', true); 232 } 233 if (changed && $target.is('tr')) { 234 Drupal.webform.restripeTable($target.closest('table').first()); 235 } 236 break; 237 238 case 'require': 239 var $requiredSpan = $target.find('.form-required, .form-optional').first(); 240 if (actionResult != $requiredSpan.hasClass('form-required')) { 241 var $targetInputElements = $target.find("input:text,textarea,input[type='email'],select,input:radio,input:file"); 242 // Rather than hide the required tag, remove it so that other 243 // jQuery can respond via Drupal behaviors. 244 Drupal.detachBehaviors($requiredSpan); 245 $targetInputElements 246 .webformProp('required', actionResult) 247 .toggleClass('required', actionResult); 248 if (actionResult) { 249 $requiredSpan.replaceWith('<span class="form-required" title="' + Drupal.t('This field is required.') + '">*</span>'); 250 } 251 else { 252 $requiredSpan.replaceWith('<span class="form-optional"></span>'); 253 } 254 Drupal.attachBehaviors($requiredSpan); 255 } 256 break; 257 258 case 'set': 259 var $texts = $target.find("input:text,textarea,input[type='email']"); 260 var $selects = $target.find('select,select option,input:radio,input:checkbox'); 261 var $markups = $target.filter('.webform-component-markup'); 262 if (actionResult) { 263 var multiple = $.map(action['argument'].split(','), $.trim); 264 $selects 265 .webformVal(multiple) 266 .webformProp('disabled', true) 267 .addClass('webform-disabled-flag'); 268 $texts 269 .val([action['argument']]) 270 .webformProp('readonly', true) 271 .addClass('webform-disabled-flag'); 272 // A special case is made for markup. It is sanitized with 273 // filter_xss_admin on the server. otherwise text() should be used 274 // to avoid an XSS vulnerability. text() however would preclude 275 // the use of tags like <strong> or <a>. 276 $markups.html(action['argument']); 277 } 278 else { 279 $selects.not('.webform-disabled-flag') 280 .webformProp('disabled', false); 281 $texts.not('.webform-disabled-flag') 282 .webformProp('readonly', false); 283 // Markup not set? Then restore original markup as provided in 284 // the attribute data-webform-markup. 285 $markups.each(function () { 286 var $this = $(this); 287 var original = $this.data('webform-markup'); 288 if (original !== undefined) { 289 $this.html(original); 290 } 291 }); 292 } 293 break; 294 } 295 }); // End look on each action for one conditional. 296 }); // End loop on each conditional. 297 298 $form.find('.webform-disabled-flag').removeClass('webform-disabled-flag'); 299 }; 300 301 /** 302 * Event handler to prevent propagation of events. 303 * 304 * Typically click for disabling radio and checkboxes. 305 */ 306 Drupal.webform.stopEvent = function () { 307 return false;
308 }; 309 310 Drupal.webform.conditionalOperatorStringEqual = function (element, existingValue, ruleValue) { 311 var returnValue = false; 312 var currentValue = Drupal.webform.stringValue(element, existingValue); 313 $.each(currentValue, function (n, value) { 314 if (value.toLowerCase() === ruleValue.toLowerCase()) { 315 returnValue = true; 316 return false; // break. 317 } 318 }); 319 return returnValue; 320 }; 321 322 Drupal.webform.conditionalOperatorStringNotEqual = function (element, existingValue, ruleValue) { 323 var found = false; 324 var currentValue = Drupal.webform.stringValue(element, existingValue); 325 $.each(currentValue, function (n, value) { 326 if (value.toLowerCase() === ruleValue.toLowerCase()) { 327 found = true; 328 } 329 }); 330 return !found; 331 }; 332 333 Drupal.webform.conditionalOperatorStringContains = function (element, existingValue, ruleValue) { 334 var returnValue = false; 335 var currentValue = Drupal.webform.stringValue(element, existingValue); 336 $.each(currentValue, function (n, value) { 337 if (value.toLowerCase().indexOf(ruleValue.toLowerCase()) > -1) { 338 returnValue = true; 339 return false; // break. 340 } 341 }); 342 return returnValue; 343 }; 344 345 Drupal.webform.conditionalOperatorStringDoesNotContain = function (element, existingValue, ruleValue) { 346 var found = false; 347 var currentValue = Drupal.webform.stringValue(element, existingValue); 348 $.each(currentValue, function (n, value) { 349 if (value.toLowerCase().indexOf(ruleValue.toLowerCase()) > -1) { 350 found = true; 351 } 352 }); 353 return !found; 354 }; 355 356 Drupal.webform.conditionalOperatorStringBeginsWith = function (element, existingValue, ruleValue) { 357 var returnValue = false; 358 var currentValue = Drupal.webform.stringValue(element, existingValue); 359 $.each(currentValue, function (n, value) { 360 if (value.toLowerCase().indexOf(ruleValue.toLowerCase()) === 0) { 361 returnValue = true; 362 return false; // break. 363 } 364 }); 365 return returnValue; 366 }; 367 368 Drupal.webform.conditionalOperatorStringEndsWith = function (element, existingValue, ruleValue) { 369 var returnValue = false; 370 var currentValue = Drupal.webform.stringValue(element, existingValue); 371 $.each(currentValue, function (n, value) { 372 if (value.toLowerCase().lastIndexOf(ruleValue.toLowerCase()) === value.length - ruleValue.length) { 373 returnValue = true; 374 return false; // break. 375 } 376 }); 377 return returnValue; 378 }; 379 380 Drupal.webform.conditionalOperatorStringEmpty = function (element, existingValue, ruleValue) { 381 var currentValue = Drupal.webform.stringValue(element, existingValue); 382 var returnValue = true; 383 $.each(currentValue, function (n, value) { 384 if (value !== '') { 385 returnValue = false; 386 return false; // break. 387 } 388 }); 389 return returnValue; 390 }; 391 392 Drupal.webform.conditionalOperatorStringNotEmpty = function (element, existingValue, ruleValue) { 393 return !Drupal.webform.conditionalOperatorStringEmpty(element, existingValue, ruleValue); 394 }; 395 396 Drupal.webform.conditionalOperatorSelectGreaterThan = function (element, existingValue, ruleValue) { 397 var currentValue = Drupal.webform.stringValue(element, existingValue); 398 return Drupal.webform.compare_select(currentValue[0], ruleValue, element) > 0; 399 }; 400 401 Drupal.webform.conditionalOperatorSelectGreaterThanEqual = function (element, existingValue, ruleValue) { 402 var currentValue = Drupal.webform.stringValue(element, existingValue); 403 var comparison = Drupal.webform.compare_select(currentValue[0], ruleValue, element); 404 return comparison > 0 || comparison === 0; 405 }; 406 407 Drupal.webform.conditionalOperatorSelectLessThan = function (element, existingValue, ruleValue) { 408 var currentValue = Drupal.webform.stringValue(element, existingValue); 409 return Drupal.webform.compare_select(currentValue[0], ruleValue, element) < 0; 410 }; 411 412 Drupal.webform.conditionalOperatorSelectLessThanEqual = function (element, existingValue, ruleValue) { 413 var currentValue = Drupal.webform.stringValue(element, existingV
413alue); 414 var comparison = Drupal.webform.compare_select(currentValue[0], ruleValue, element); 415 return comparison < 0 || comparison === 0; 416 }; 417 418 Drupal.webform.conditionalOperatorNumericEqual = function (element, existingValue, ruleValue) { 419 // See float comparison: http://php.net/manual/en/language.types.float.php 420 var currentValue = Drupal.webform.stringValue(element, existingValue); 421 var epsilon = 0.000001; 422 // An empty string does not match any number. 423 return currentValue[0] === '' ? false : (Math.abs(parseFloat(currentValue[0]) - parseFloat(ruleValue)) < epsilon); 424 }; 425 426 Drupal.webform.conditionalOperatorNumericNotEqual = function (element, existingValue, ruleValue) { 427 // See float comparison: http://php.net/manual/en/language.types.float.php 428 var currentValue = Drupal.webform.stringValue(element, existingValue); 429 var epsilon = 0.000001; 430 // An empty string does not match any number. 431 return currentValue[0] === '' ? true : (Math.abs(parseFloat(currentValue[0]) - parseFloat(ruleValue)) >= epsilon); 432 }; 433 434 Drupal.webform.conditionalOperatorNumericGreaterThan = function (element, existingValue, ruleValue) { 435 var currentValue = Drupal.webform.stringValue(element, existingValue); 436 return parseFloat(currentValue[0]) > parseFloat(ruleValue); 437 }; 438 439 Drupal.webform.conditionalOperatorNumericGreaterThanEqual = function (element, existingValue, ruleValue) { 440 return Drupal.webform.conditionalOperatorNumericGreaterThan(element, existingValue, ruleValue) || 441 Drupal.webform.conditionalOperatorNumericEqual(element, existingValue, ruleValue); 442 }; 443 444 Drupal.webform.conditionalOperatorNumericLessThan = function (element, existingValue, ruleValue) { 445 var currentValue = Drupal.webform.stringValue(element, existingValue); 446 return parseFloat(currentValue[0]) < parseFloat(ruleValue); 447 }; 448 449 Drupal.webform.conditionalOperatorNumericLessThanEqual = function (element, existingValue, ruleValue) { 450 return Drupal.webform.conditionalOperatorNumericLessThan(element, existingValue, ruleValue) || 451 Drupal.webform.conditionalOperatorNumericEqual(element, existingValue, ruleValue); 452 }; 453 454 Drupal.webform.conditionalOperatorDateEqual = function (element, existingValue, ruleValue) { 455 var currentValue = Drupal.webform.dateValue(element, existingValue); 456 return currentValue === ruleValue; 457 }; 458 459 Drupal.webform.conditionalOperatorDateNotEqual = function (element, existingValue, ruleValue) { 460 return !Drupal.webform.conditionalOperatorDateEqual(element, existingValue, ruleValue); 461 }; 462 463 Drupal.webform.conditionalOperatorDateBefore = function (element, existingValue, ruleValue) { 464 var currentValue = Drupal.webform.dateValue(element, existingValue); 465 return (currentValue !== false) && currentValue < ruleValue; 466 }; 467 468 Drupal.webform.conditionalOperatorDateBeforeEqual = function (element, existingValue, ruleValue) { 469 var currentValue = Drupal.webform.dateValue(element, existingValue); 470 return (currentValue !== false) && (currentValue < ruleValue || currentValue === ruleValue); 471 }; 472 473 Drupal.webform.conditionalOperatorDateAfter = function (element, existingValue, ruleValue) { 474 var currentValue = Drupal.webform.dateValue(element, existingValue); 475 return (currentValue !== false) && currentValue > ruleValue; 476 }; 477 478 Drupal.webform.conditionalOperatorDateAfterEqual = function (element, existingValue, ruleValue) { 479 var currentValue = Drupal.webform.dateValue(element, existingValue); 480 return (currentValue !== false) && (currentValue > ruleValue || currentValue === ruleValue); 481 }; 482 483 Drupal.webform.conditionalOperatorTimeEqual = function (element, existingValue, ruleValue) { 484 var currentValue = Drupal.webform.timeValue(element, existingValue); 485 return currentValue === ruleValue; 486 }; 487 488 Drupal.webform.conditionalOperatorTimeNotEqual = function (element, existingValue, ruleValue) { 489 return !Drupal.webform.conditionalOperatorTimeEqual(element, existingValue, ruleValue); 490 }; 491 492 Drupal.webform.conditionalOperatorTimeBefore = function (element, existingV
492alue, ruleValue) { 493 // Date and time operators intentionally exclusive for "before". 494 var currentValue = Drupal.webform.timeValue(element, existingValue); 495 return (currentValue !== false) && (currentValue < ruleValue); 496 }; 497 498 Drupal.webform.conditionalOperatorTimeBeforeEqual = function (element, existingValue, ruleValue) { 499 // Date and time operators intentionally exclusive for "before". 500 var currentValue = Drupal.webform.timeValue(element, existingValue); 501 return (currentValue !== false) && (currentValue < ruleValue || currentValue === ruleValue); 502 }; 503 504 Drupal.webform.conditionalOperatorTimeAfter = function (element, existingValue, ruleValue) { 505 // Date and time operators intentionally inclusive for "after". 506 var currentValue = Drupal.webform.timeValue(element, existingValue); 507 return (currentValue !== false) && (currentValue > ruleValue); 508 }; 509 510 Drupal.webform.conditionalOperatorTimeAfterEqual = function (element, existingValue, ruleValue) { 511 // Date and time operators intentionally inclusive for "after". 512 var currentValue = Drupal.webform.timeValue(element, existingValue); 513 return (currentValue !== false) && (currentValue > ruleValue || currentValue === ruleValue); 514 }; 515 516 /** 517 * Utility function to compare values of a select component. 518 * 519 * @param string a 520 * First select option key to compare 521 * @param string b 522 * Second select option key to compare 523 * @param array options 524 * Associative array where the a and b are within the keys 525 * 526 * @return integer based upon position of $a and $b in $options 527 * -N if $a above (<) $b 528 * 0 if $a = $b 529 * +N if $a is below (>) $b 530 */ 531 Drupal.webform.compare_select = function (a, b, element) { 532 var optionList = []; 533 $('option,input:radio,input:checkbox', element).each(function () { 534 optionList.push($(this).val()); 535 }); 536 var a_position = optionList.indexOf(a); 537 var b_position = optionList.indexOf(b); 538 return (a_position < 0 || b_position < 0) ? null : a_position - b_position; 539 }; 540 541 /** 542 * Utility to return current visibility. 543 * 544 * Uses actual visibility, except for hidden components which use the applied 545 * disabled class. 546 */ 547 Drupal.webform.isVisible = function ($element) { 548 return $element.hasClass('webform-component-hidden') 549 ? !$element.find('input').first().hasClass('webform-conditional-disabled') 550 : $element.closest('.webform-conditional-hidden').length == 0; 551 }; 552 553 /** 554 * Function to get a string value from a select/radios/text/etc. field. 555 */ 556 Drupal.webform.stringValue = function (element, existingValue) { 557 var value = []; 558 if (element) { 559 var $element = $(element); 560 if (Drupal.webform.isVisible($element)) { 561 // Checkboxes and radios. 562 $element.find('input[type=checkbox]:checked,input[type=radio]:checked').each(function () { 563 value.push(this.value); 564 }); 565 // Select lists. 566 if (!value.length) { 567 var selectValue = $element.find('select').val(); 568 if (selectValue) { 569 if ($.isArray(selectValue)) { 570 value = selectValue; 571 } 572 else { 573 value.push(selectValue); 574 } 575 } 576 } 577 // Simple text fields. This check is done last so that the select list 578 // in select-or-other fields comes before the "other" text field. 579 if (!value.length) { 580 $element.find('input:not([type=checkbox],[type=radio]),textarea').each(function () { 581 value.push(this.value); 582 }); 583 } 584 } 585 } 586 else { 587 switch ($.type(existingValue)) { 588 case 'array':
589 value = existingValue; 590 break; 591 592 case 'string': 593 value.push(existingValue); 594 break; 595 } 596 } 597 return value; 598 }; 599 600 /** 601 * Utility function to calculate a second-based timestamp from a time field. 602 */ 603 Drupal.webform.dateValue = function (element, existingValue) { 604 var value = false; 605 if (element) { 606 var $element = $(element); 607 if (Drupal.webform.isVisible($element)) { 608 var day = $element.find('[name*=day]').val(); 609 var month = $element.find('[name*=month]').val(); 610 var year = $element.find('[name*=year]').val(); 611 // Months are 0 indexed in JavaScript. 612 if (month) { 613 month--; 614 } 615 if (year !== '' && month !== '' && day !== '') { 616 value = Date.UTC(year, month, day) / 1000; 617 } 618 } 619 } 620 else { 621 if ($.type(existingValue) === 'array' && existingValue.length) { 622 existingValue = existingValue[0]; 623 } 624 if ($.type(existingValue) === 'string') { 625 existingValue = existingV
625alue.split('-'); 626 } 627 if (existingValue.length === 3) { 628 value = Date.UTC(existingValue[0], existingValue[1], existingValue[2]) / 1000; 629 } 630 } 631 return value; 632 }; 633 634 /** 635 * Utility function to calculate a millisecond timestamp from a time field. 636 */ 637 Drupal.webform.timeValue = function (element, existingValue) { 638 var value = false; 639 if (element) { 640 var $element = $(element); 641 if (Drupal.webform.isVisible($element)) { 642 var hour = $element.find('[name*=hour]').val(); 643 var minute = $element.find('[name*=minute]').val(); 644 var ampm = $element.find('[name*=ampm]:checked').val(); 645 646 // Convert to integers if set. 647 hour = (hour === '') ? hour : parseInt(hour); 648 minute = (minute === '') ? minute : parseInt(minute); 649 650 if (hour !== '') { 651 hour = (hour < 12 && ampm == 'pm') ? hour + 12 : hour; 652 hour = (hour === 12 && ampm == 'am') ? 0 : hour; 653 } 654 if (hour !== '' && minute !== '') { 655 value = Date.UTC(1970, 0, 1, hour, minute) / 1000; 656 } 657 } 658 } 659 else { 660 if ($.type(existingValue) === 'array' && existingValue.length) {
661 existingValue = existingValue[0]; 662 } 663 if ($.type(existingValue) === 'string') { 664 existingValue = existingValue.split(':'); 665 } 666 if (existingValue.length >= 2) { 667 value = Date.UTC(1970, 0, 1, existingValue[0], existingValue[1]) / 1000; 668 } 669 } 670 return value; 671 }; 672 673 /** 674 * Make a prop shim for jQuery < 1.9. 675 */ 676 $.fn.webformProp = $.fn.webformProp || function (name, value) { 677 if (value) { 678 return $.fn.prop ? this.prop(name, true) : this.attr(name, true); 679 } 680 else { 681 return $.fn.prop ? this.prop(name, false) : this.removeAttr(name); 682 } 683 }; 684 685 /** 686 * Make a multi-valued val() function. 687 * 688 * This is for setting checkboxes, radios, and select elements. 689 */ 690 $.fn.webformVal = function (values) { 691 this.each(function () { 692 var $this = $(this); 693 var value = $this.val(); 694 var on = $.inArray($this.val(), values) != -1; 695 if (this.nodeName == 'OPTION') { 696 $this.webformProp('selected', on ? value : false); 697 } 698 else { 699 $this.val(on ? [value] : false); 700 } 701 }); 702 return this; 703 }; 704 705 /** 706 * Given a table's DOM element, restripe the odd/even classes. 707 */ 708 Drupal.webform.restripeTable = function (table) { 709 // :even and :odd are reversed because jQuery counts from 0 and 710 // we count from 1, so we're out of sync. 711 // Match immediate children of the parent element to allow nesting. 712 $('> tbody > tr, > tr', table) 713 .filter(':visible:odd').filter('.odd') 714 .removeClass('odd').addClass('even') 715 .end().end() 716 .filter(':visible:even').filter('.even') 717 .removeClass('even').addClass('odd'); 718 }; 719 720})(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.