PageSourceSearch

https://hotline.org.tw/sites/hotline.org.tw/modules/webform/js/webform.js?tm8c9t

js hotline.org.tw collected 2026-10-02 04:17:57 UTC 27,943 bytes, 720 lines download raw bytes

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.