PageSourceSearch

https://gradat.bg/sites/default/files/js/js_j7Ek_J4xJMiin8pBX6WBsSqR5URqAMM_TLevLcyZako.js

js gradat.bg collected 2026-09-25 06:24:11 UTC 50,946 bytes, 1,152 lines download raw bytes

1Drupal.locale = { 'pluralFormula': function ($n) { return Number(($n!=1)); }, 'strings': {"":{"An AJAX HTTP error occurred.":"\u0412\u044a\u0437\u043d\u0438\u043a\u043d\u0430 AJAX HTTP \u0433\u0440\u0435\u0448\u043a\u0430","HTTP Result Code: !status":"\u041f\u043e\u043b\u0443\u0447\u0435\u043d \u0435 HTTP \u043a\u043e\u0434 :!status","An AJAX HTTP request terminated abnormally.":"HTTP \u0437\u0430\u044f\u0432\u043a\u0430\u0442\u0430 \u043d\u0430 AJAX \u043d\u0435 \u0437\u0430\u0432\u044a\u0440\u0448\u0438 \u043d\u043e\u0440\u043c\u0430\u043b\u043d\u043e","Debugging information follows.":"\u0421\u043b\u0435\u0434\u0432\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0437\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430","Path: !uri":"\u041f\u044a\u0442: !uri","StatusText: !statusText":"\u0421\u0442\u0430\u0442\u0443\u0441 \u0442\u0435\u043a\u0441\u0442: !statusText","ResponseText: !responseText":"ResponseText: !responseText","ReadyState: !readyState":"ReadyState: !readyState","Next":"\u041a\u0430\u0447\u0438","Status":"\u0421\u0442\u0430\u0442\u0443\u0441","Cancel":"\u041e\u0442\u043c\u0435\u043d\u0438","Disabled":"\u0414\u0435\u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d","Enabled":"\u0410\u043a\u0442\u0438\u0432\u0438\u0440\u0430\u043d","Edit":"\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0430\u0439","Date":"\u0414\u0430\u0442\u0430","Size":"\u0420\u0430\u0437\u043c\u0435\u0440","Search":"\u0422\u044a\u0440\u0441\u0438","none":"\u043d\u0435","Sunday":"\u043d\u0435\u0434\u0435\u043b\u044f","Monday":"\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u043d\u0438\u043a","Tuesday":"\u0432\u0442\u043e\u0440\u043d\u0438\u043a","Wednesday":"\u0441\u0440\u044f\u0434\u0430","Thursday":"\u0447\u0435\u0442\u0432\u044a\u0440\u0442\u044a\u043a","Friday":"\u043f\u0435\u0442\u044a\u043a","Saturday":"\u0441\u044a\u0431\u043e\u0442\u0430","Add":"\u0414\u043e\u0431\u0430\u0432\u0438","Filename":"\u0418\u043c\u0435 \u043d\u0430 \u0444\u0430\u0439\u043b\u0430","Menu":"\u041c\u0435\u043d\u044e","Configure":"\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u0439","All":"\u0412\u0441\u0438\u0447\u043a\u0438","Done":"\u0413\u043e\u0442\u043e\u0432\u043e","N\/A":"N\/A","OK":"OK","This field is required.":"\u0417\u0430\u0434\u044a\u043b\u0436\u0438\u0442\u0435\u043b\u043d\u043e \u043f\u043e\u043b\u0435.","Mon":"\u041f\u043e\u043d.","Tue":"\u0412\u0442.","Wed":"\u0421\u0440.","Thu":"\u0412\u0442.","Fri":"\u041f\u0435\u0442.","Sat":"\u0421\u044a\u0431.","Sun":"\u041d\u0435\u0434.","January":"\u042f\u043d\u0443\u0430\u0440\u0438","February":"\u0424\u0435\u0432\u0440\u0443\u0430\u0440\u0438","March":"\u041c\u0430\u0440\u0442","April":"\u0410\u043f\u0440\u0438\u043b","May":"\u041c\u0430\u0439","June":"\u042e\u043d\u0438","July":"\u042e\u043b\u0438","August":"\u0410\u0432\u0433\u0443\u0441\u0442","September":"\u0421\u0435\u043f\u0442\u0435\u043c\u0432\u0440\u0438","October":"\u041e\u043a\u0442\u043e\u043c\u0432\u0440\u0438","November":"\u041d\u043e\u0435\u043c\u0432\u0440\u0438","December":"\u0414\u0435\u043a\u0435\u043c\u0432\u0440\u0438","Show":"\u041f\u043e\u043a\u0430\u0436\u0438","Select all rows in this table":"\u0418\u0437\u0431\u0435\u0440\u0435\u0442\u0435 \u0432\u0441\u0438\u0447\u043a\u0438 \u0440\u0435\u0434\u043e\u0432\u0435 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0442\u0430","Deselect all rows in this table":"\u041e\u0442\u043a\u0430\u0436\u0438 \u0432\u0441\u0438\u0447\u043a\u0438 \u0440\u0435\u0434\u043e\u0432\u0435 \u043e\u0442 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0442\u0430","Jan":"\u042f\u043d.","Feb":"\u0424\u0435\u0432\u0440.","Mar":"\u041c\u0430\u0440\u0442","Apr":"\u0410\u043f\u0440.","Jun":"\u042e\u043d\u0438","Jul":"\u042e\u043b\u0438","Aug":"\u0410\u0432\u0433.","Sep":"\u0421\u0435\u043f\u0442.","Oct":"\u041e\u043a\u0442.","Nov":"\u041d\u043e\u0435\u043c.","Dec":"\u0414\u0435\u043a.","Not published":"\u041d\u0435\u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0432\u0430\u043d\u043e","Shortcuts":"\u041f\u0440\u0435\u043a\u0438 \u043f\u044a\u0442\u0438\u0449\u0430","Please wait...":"\u041c\u043e\u043b\u044f \u0438\u0437\u0447\u0430\u043a\u0430\u0439\u0442\u0435...","Hide":"\u0421\u043a\u0440\u0438\u0439","Loading":"\u0417\u0430\u0440\u0435\u0436\u0434\u0430\u043d\u0435","By @name on @date":"\u
1041e\u0442 @name \u043d\u0430 @date","By @name":"\u041e\u0442 @name","Not in menu":"\u041d\u0435 \u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d \u0432 \u043c\u0435\u043d\u044e\u0442\u043e","Alias: @alias":"\u0421\u0438\u043d\u043e\u043d\u0438\u043c: @alias","No alias":"\u041b\u0438\u043f\u0441\u0432\u0430 \u0441\u0438\u043d\u043e\u043d\u0438\u043c","New revision":"\u041d\u043e\u0432\u0430 \u0432\u0435\u0440\u0441\u0438\u044f","Drag to re-order":"\u0412\u043b\u0430\u0447\u0438 \u0437\u0430 \u043f\u0440\u043e\u043c\u044f\u043d\u0430 \u043d\u0430 \u043f\u043e\u0434\u0440\u0435\u0434\u0431\u0430\u0442\u0430","Changes made in this table will not be saved until the form is submitted.":"\u041f\u0440\u043e\u043c\u0435\u043d\u0438\u0442\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u0435\u043d\u0438 \u0432 \u0442\u0430\u0437\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0430, \u043d\u044f\u043c\u0430 \u0434\u0430 \u0441\u0435 \u0437\u0430\u043f\u0438\u0448\u0430\u0442 \u043f\u0440\u0435\u0434\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0434\u0430 \u0435 \u0438\u0437\u043f\u0440\u0430\u0442\u0435\u043d\u0430.","The changes to these blocks will not be saved until the \u003Cem\u003ESave blocks\u003C\/em\u003E button is clicked.":"\u041f\u0440\u043e\u043c\u0435\u043d\u0438\u0442\u0435 \u0432 \u0442\u0435\u0437\u0438 \u0431\u043b\u043e\u043a\u043e\u0432\u0435 \u043d\u044f\u043c\u0430 \u0434\u0430 \u0431\u044a\u0434\u0430\u0442 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u0438, \u0434\u043e\u043a\u0430\u0442\u043e \u043d\u0435 \u0431\u044a\u0434\u0435 \u043d\u0430\u0442\u0438\u0441\u043d\u0430\u0442 \u0431\u0443\u0442\u043e\u043d\u0430 \u003Cem\u003E\u0417\u0430\u043f\u0438\u0448\u0438 \u0431\u043b\u043e\u043a\u043e\u0432\u0435\u003C\/em\u003E.","Show shortcuts":"\u041f\u043e\u043a\u0430\u0436\u0438 \u043f\u0440\u0435\u043a\u0438\u0442\u0435 \u043f\u044a\u0442\u0438\u0449\u0430","No revision":"\u041d\u044f\u043c\u0430 \u0432\u0435\u0440\u0441\u0438\u044f","@number comments per page":"@number \u043a\u043e\u043c\u0435\u043d\u0442\u0430\u0440\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430","(active tab)":"(\u0430\u043a\u0442\u0438\u0432\u0435\u043d \u0440\u0430\u0437\u0434\u0435\u043b)","Customize dashboard":"\u041e\u0444\u043e\u0440\u043c\u0438 \u0442\u0430\u0431\u043b\u043e\u0442\u043e","Hide summary":"\u0421\u043a\u0440\u0438\u0432\u0430\u043d\u0435 \u043d\u0430 \u0440\u0435\u0437\u044e\u043c\u0435","Edit summary":"\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0440\u0435\u0437\u044e\u043c\u0435","@title dialog":"@title \u0434\u0438\u0430\u043b\u043e\u0433","The selected file %filename cannot be uploaded. Only files with the following extensions are allowed: %extensions.":"\u0418\u0437\u0431\u0440\u0430\u043d\u0438\u044f\u0442 \u0444\u0430\u0439\u043b  %filename \u043d\u0435 \u043c\u043e\u0436\u0435 \u0434\u0430 \u0431\u044a\u0434\u0435 \u043a\u0430\u0447\u0435\u043d. \u0421\u0430\u043c\u043e \u0444\u0430\u0439\u043b\u043e\u0432\u0435 \u0441\u044a\u0441\u0441\u043b\u0435\u0434\u043d\u0438\u0442\u0435 \u0440\u0430\u0437\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0441\u0430 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438: %extensions.","Re-order rows by numerical weight instead of dragging.":"\u041f\u0440\u0435\u043d\u0430\u0440\u0435\u0434\u0438 \u0440\u0435\u0434\u043e\u0432\u0435\u0442\u0435 \u043f\u043e \u0442\u0435\u0433\u043b\u043e, \u0432\u043c\u0435\u0441\u0442\u043e \u0441 \u0432\u043b\u0430\u0447\u0435\u043d\u0435","Show row weights":"\u041f\u043e\u043a\u0430\u0436\u0438 \u0442\u0435\u0433\u043b\u043e\u0442\u043e \u043d\u0430 \u0440\u0435\u0434\u043e\u0432\u0435\u0442\u0435","Hide row weights":"\u0421\u043a\u0440\u0438\u0439 \u0440\u0435\u0434\u043e\u0432\u0435\u0442\u0435 \u0441 \u0442\u0435\u0433\u043b\u043e","Autocomplete popup":"\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u043e \u0437\u0430\u043f\u044a\u043b\u0432\u0430\u043d\u0435 \u043d\u0430 \u0438\u0437\u0441\u043a\u0430\u0447\u0430\u0449\u0438 \u043f\u0440\u043e\u0437\u043e\u0440\u0446\u0438","Searching for matches...":"\u0422\u044a\u0440\u0441\u0435\u043d\u0435 \u043d\u0430 \u0441\u044a\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f...","Hide shortcuts":"\u0421\u043a\u0440\u0438\u0439 \u043f\u0440\u0435\u043a\u0438\u0442\u0435 \u043f\u044a\u0442\u0438\u0449\u0430","Submit":"\u0418\u0437\u043f\u0440\u0430\u0442\u0438","Apply (all displays)":"\u0418\u0437\u043f\u0440\u0430\u0442\u0438","Apply (this display)":"\u0418\u0437\u043f\u0440\u0430\u0442\u0438","Select":"\u0418\u0437\u0431\u0435\u0440\u0435\u0442\u0435"}} };;
2function getParameterByName(name, url) {
3    if (!url) url = window.location.href;
4    name = name.replace(/[\[\]]/g, '\\$&');
5    var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
6        results = regex.exec(url);
7    if (!results) return null;
8    if (!results[2]) return '';
9    return decodeURIComponent(results[2].replace(/\+/g, ' '));
10}
11function urlencode(text) {
12    return encodeURIComponent(text).replace(/!/g,  '%21')
13        .replace(/'/g,  '%27')
14        .replace(/\(/g, '%28')
15        .replace(/\)/g, '%29')
16        .replace(/\*/g, '%2A')
17        .replace(/%20/g, '+');
18}
19jQuery(document).ready(function () {
20    console.log('encode url 2.0');
21
22    var destination = getParameterByName('destination');
23    var sid = getParameterByName('sid')
24    if(!destination) {
25        return;
26    }
27    jQuery('.tabs a').each(function () {
28        console.log(jQuery(this).attr('href'));
29        jQuery(this).attr('href', jQuery(this).attr('href') + '?sid=' + sid + '&destination=' + urlencode(destination))
30    })
31});
32(function ($) {
33
34  Drupal.behaviors.captcha = {
35    attach: function (context) {
36
37      // Turn off autocompletion for the CAPTCHA response field.
38      // We do it here with JavaScript (instead of directly in the markup)
39      // because this autocomplete attribute is not standard and
40      // it would break (X)HTML compliance.
41      $("#edit-captcha-response").attr("autocomplete", "off");
42
43    }
44  };
45
46  Drupal.behaviors.captchaAdmin = {
47    attach: function (context) {
48      // Add onclick handler to checkbox for adding a CAPTCHA description
49      // so that the textfields for the CAPTCHA description are hidden
50      // when no description should be added.
51      // @todo: div.form-item-captcha-description depends on theming, maybe
52      // it's better to add our own wrapper with id (instead of a class).
53      $("#edit-captcha-add-captcha-description").click(function() {
54        if ($("#edit-captcha-add-captcha-description").is(":checked")) {
55          // Show the CAPTCHA description textfield(s).
56          $("div.form-item-captcha-description").show('slow');
57        }
58        else {
59          // Hide the CAPTCHA description textfield(s).
60          $("div.form-item-captcha-description").hide('slow');
61        }
62      });
63      // Hide the CAPTCHA description textfields if option is disabled on page load.
64      if (!$("#edit-captcha-add-captcha-description").is(":checked")) {
65        $("div.form-item-captcha-description").hide();
66      }
67    }
68
69  };
70
71})(jQuery);
72;
73(function ($) {
74
75Drupal.behaviors.textarea = {
76  attach: function (context, settings) {
77    $('.form-textarea-wrapper.resizable', context).once('textarea', function () {
78      var staticOffset = null;
79      var textarea = $(this).addClass('resizable-textarea').find('textarea');
80      var grippie = $('<div class="grippie"></div>').mousedown(startDrag);
81
82      grippie.insertAfter(textarea);
83
84      function startDrag(e) {
85        staticOffset = textarea.height() - e.pageY;
86        textarea.css('opacity', 0.25);
87        $(document).mousemove(performDrag).mouseup(endDrag);
88        return false;
89      }
90
91      function performDrag(e) {
92        textarea.height(Math.max(32, staticOffset + e.pageY) + 'px');
93        return false;
94      }
95
96      function endDrag(e) {
97        $(document).unbind('mousemove', performDrag).unbind('mouseup', endDrag);
98        textarea.css('opacity', 1);
99      }
100    });
101  }
102};
103
104})(jQuery);
105;
106(function ($) {
107
108/**
109 * Attach handlers to evaluate the strength of any password fields and to check
110 * that its confirmation is correct.
111 */
112Drupal.behaviors.password = {
113  attach: function (context, settings) {
114    var translate = settings.password;
115    $('input.password-field', context).once('password', function () {
116      var passwordInput = $(this);
117      var innerWrapper = $(this).parent();
118      var outerWrapper = $(this).parent().parent();
119
120      // Add identifying class to password element parent.
121      innerWrapper.addClass('password-parent');
122
123      // Add the password confirmation layer.
124      $('input.password-confirm', outerWrapper).parent().prepend('<div class="password-confirm">' + translate['confirmTitle'] + ' <span></span></div>').addClass('confirm-parent');
125      var confirmInput = $('input.password-confirm', outerWrapper);
126      var confirmResult = $('div.password-confirm', outerWrapper);
127      var confirmChild = $('span', confirmResult);
128
129      // Add the description box.
130      var passwordMeter = '<div class="password-strength"><div class="password-strength-text" aria-live="assertive"></div><div class="password-strength-title">' + translate['strengthTitle'] + '</div><div class="password-indicator"><div class="indicator"></div></div></div>';
131      $(confirmInput).parent().after('<div class="password-suggestions description"></div>');
132      $(innerWrapper).prepend(passwordMeter);
133      var passwordDescription = $('div.password-suggestions', outerWrapper).hide();
134
135      // Check the password strength.
136      var passwordCheck = function () {
137
138        // Evaluate the password strength.
139        var result = Drupal.evaluatePasswordStrength(passwordInput.val(), settings.password);
140
141        // Update the suggestions for how to improve the password.
142        if (passwordDescription.html() != result.message) {
143          passwordDescription.html(result.message);
144        }
145
146        // Only show the description box if there is a weakness in the password.
147        if (result.strength == 100) {
148          passwordDescription.hide();
149        }
150        else {
151          passwordDescription.show();
152        }
153
154        // Adjust the length of the strength indicator.
155        $(innerWrapper).find('.indicator').css('width', result.strength + '%');
156
157        // Update the strength indication text.
158        $(innerWrapper).find('.password-strength-text').html(result.indicatorText);
159
160        passwordCheckMatch();
161      };
162
163      // Check that password and confirmation inputs match.
164      var passwordCheckMatch = function () {
165
166        if (confirmInput.val()) {
167          var success = passwordInput.val() === confirmInput.val();
168
169          // Show the confirm result.
170          confirmResult.css({ visibility: 'visible' });
171
172          // Remove the previous styling if any exists.
173          if (this.confirmClass) {
174            confirmChild.removeClass(this.confirmClass);
175          }
176
177          // Fill in the success message and set the class accordingly.
178          var confirmClass = success ? 'ok' : 'error';
179          confirmChild.html(translate['confirm' + (success ? 'Success' : 'Failure')]).addClass(confirmClass);
180          this.confirmClass = confirmClass;
181        }
182        else {
183          confirmResult.css({ visibility: 'hidden' });
184        }
185      };
186
187      // Monitor keyup and blur events.
188      // Blur must be used because a mouse paste does not trigger keyup.
189      passwordInput.keyup(passwordCheck).focus(passwordCheck).blur(passwordCheck);
190      confirmInput.keyup(passwordCheckMatch).blur(passwordCheckMatch);
191    });
192  }
193};
194
195/**
196 * Evaluate the strength of a user's password.
197 *
198 * Returns the estimated strength and the relevant output message.
199 */
200Drupal.evaluatePasswordStrength = function (password, translate) {
201  password = $.trim(password);
202
203  var weaknesses = 0, strength = 100, msg = [];
204
205  var hasLowercase = /[a-z]+/.test(password);
206  var hasUppercase = /[A-Z]+/.test(password);
207  var hasNumbers = /[0-9]+/.test(password);
208  var hasPunctuation = /[^a-zA-Z0-9]+/.test(password);
209
210  // If there is a username edit box on the page, compare password to that, otherwise
211  // use value from the database.
212  var usernameBox = $('input.username');
213  var username = (usernameBox.length > 0) ? usernameBox.val() : translate.username;
214
215  // Lose 5 points for every character less than 6, plus a 30 point penalty.
216  if (password.length < 6) {
217    msg.push(translate.tooShort);
218    strength -= ((6 - password.length) * 5) + 30;
219  }
220
221  // Count weaknesses.
222  if (!hasLowercase) {
223    msg.push(translate.addLowerCase);
224    weaknesses++;
225  }
226  if (!hasUppercase) {
227    msg.push(translate.addUpperCase);
228    weaknesses++;
229  }
230  if (!hasNumbers) {
231    msg.push(translate.addNumbers);
232    weaknesses++;
233  }
234  if (!hasPunctuation) {
235    msg.push(translate.addPunctuation);
236    weaknesses++;
237  }
238
239  // Apply penalty for each weakness (balanced against length penalty).
240  switch (weaknesses) {
241    case 1:
242      strength -= 12.5;
243      break;
244
245    case 2:
246      strength -= 25;
247      break;
248
249    case 3:
250      strength -= 40;
251      break;
252
253    case 4:
254      strength -= 40;
255      break;
256  }
257
258  // Check if password is the same as the username.
259  if (password !== '' && password.toLowerCase() === username.toLowerCase()) {
260    msg.push(translate.sameAsUsername);
261    // Passwords the same as username are always very weak.
262    strength = 5;
263  }
264
265  // Based on the strength, work out what text should be shown by the password strength meter.
266  if (strength < 60) {
267    indicatorText = translate.weak;
268  } else if (strength < 70) {
269    indicatorText = translate.fair;
270  } else if (strength < 80) {
271    indicatorText = translate.good;
272  } else if (strength <= 100) {
273    indicatorText = translate.strong;
274  }
275
276  // Assemble the final message.
277  msg = translate.hasWeaknesses + '<ul><li>' + msg.join('</li><li>') + '</li></ul>';
278  return { strength: strength, message: msg, indicatorText: indicatorText };
279
280};
281
282/**
283 * Field instance settings screen: force the 'Display on registration form'
284 * checkbox checked whenever 'Required' is checked.
285 */
286Drupal.behaviors.fieldUserRegistration = {
287  attach: function (context, settings) {
288    var $checkbox = $('form#field-ui-field-edit-form input#edit-instance-settings-user-register-form');
289
290    if ($checkbox.length) {
291      $('input#edit-instance-required', context).once('user-register-form-checkbox', function () {
292        $(this).bind('change', function (e) {
293          if ($(this).attr('checked')) {
294            $checkbox.attr('checked', true);
295          }
296        });
297      });
298
299    }
300  }
301};
302
303})(jQuery);
304;
305(function ($) {
306
307/**
308 * A progressbar object. Initialized with the given id. Must be inserted into
309 * the DOM afterwards through progressBar.element.
310 *
311 * method is the function which will perform the HTTP request to get the
312 * progress bar state. Either "GET" or "POST".
313 *
314 * e.g. pb = new progressBar('myProgressBar');
315 *      some_element.appendChild(pb.element);
316 */
317Drupal.progressBar = function (id, updateCallback, method, errorCallback) {
318  var pb = this;
319  this.id = id;
320  this.method = method || 'GET';
321  this.updateCallback = updateCallback;
322  this.errorCallback = errorCallback;
323
324  // The WAI-ARIA setting aria-live="polite" will announce changes after users
325  // have completed their current activity and not interrupt the screen reader.
326  this.element = $('<div class="progress" aria-live="polite"></div>').attr('id', id);
327  this.element.html('<div class="bar"><div class="filled"></div></div>' +
328                    '<div class="percentage"></div>' +
329                    '<div class="message">&nbsp;</div>');
330};
331
332/**
333 * Set the percentage and status message for the progressbar.
334 */
335Drupal.progressBar.prototype.setProgress = function (percentage, message) {
336  if (percentage >= 0 && percentage <= 100) {
337    $('div.filled', this.element).css('width', percentage + '%');
338    $('div.percentage', this.element).html(percentage + '%');
339  }
340  $('div.message', this.element).html(message);
341  if (this.updateCallback) {
342    this.updateCallback(percentage, message, this);
343  }
344};
345
346/**
347 * Start monitoring progress via Ajax.
348 */
349Drupal.progressBar.prototype.startMonitoring = function (uri, delay) {
350  this.delay = delay;
351  this.uri = uri;
352  this.sendPing();
353};
354
355/**
356 * Stop monitoring progress via Ajax.
357 */
358Drupal.progressBar.prototype.stopMonitoring = function () {
359  clearTimeout(this.timer);
360  // This allows monitoring to be stopped from within the callback.
361  this.uri = null;
362};
363
364/**
365 * Request progress data from server.
366 */
367Drupal.progressBar.prototype.sendPing = function () {
368  if (this.timer) {
369    clearTimeout(this.timer);
370  }
371  if (this.uri) {
372    var pb = this;
373    // When doing a post request, you need non-null data. Otherwise a
374    // HTTP 411 or HTTP 406 (with Apache mod_security) error may result.
375    $.ajax({
376      type: this.method,
377      url: this.uri,
378      data: '',
379      dataType: 'json',
380      success: function (progress) {
381        // Display errors.
382        if (progress.status == 0) {
383          pb.displayError(progress.data);
384          return;
385        }
386        // Update display.
387        pb.setProgress(progress.percentage, progress.message);
388        // Schedule next timer.
389        pb.timer = setTimeout(function () { pb.sendPing(); }, pb.delay);
390      },
391      error: function (xmlhttp) {
392        pb.displayError(Drupal.ajaxError(xmlhttp, pb.uri));
393      }
394    });
395  }
396};
397
398/**
399 * Display errors on the page.
400 */
401Drupal.progressBar.prototype.displayError = function (string) {
402  var error = $('<div class="messages error"></div>').html(string);
403  $(this.element).before(error).hide();
404
405  if (this.errorCallback) {
406    this.errorCallback(this);
407  }
408};
409
410})(jQuery);
411;
412/**
413 * @file
414 * JavaScript behaviors for the front-end display of webforms.
415 */
416
417(function ($) {
418
419  "use strict";
420
421  Drupal.behaviors.webform = Drupal.behaviors.webform || {};
422
423  Drupal.behaviors.webform.attach = function (context) {
424    // Calendar datepicker behavior.
425    Drupal.webform.datepicker(context);
426
427    // Conditional logic.
428    if (Drupal.settings.webform && Drupal.settings.webform.conditionals) {
429      Drupal.webform.conditional(context);
430    }
431  };
432
433  Drupal.webform = Drupal.webform || {};
434
435  Drupal.webform.datepicker = function (context) {
436    $('div.webform-datepicker').each(function () {
437      var $webformDatepicker = $(this);
438      var $calendar = $webformDatepicker.find('input.webform-calendar');
439
440      // Ensure the page we're on actually contains a datepicker.
441      if ($calendar.length == 0) {
442        return;
443      }
444
445      var startDate = $calendar[0].className.replace(/.*webform-calendar-start-(\d{4}-\d{2}-\d{2}).*/, '$1').split('-');
446      var endDate = $calendar[0].className.replace(/.*webform-calendar-end-(\d{4}-\d{2}-\d{2}).*/, '$1').split('-');
447      var firstDay = $calendar[0].className.replace(/.*webform-calendar-day-(\d).*/, '$1');
448      // Convert date strings into actual Date objects.
449      startDate = new Date(startDate[0], startDate[1] - 1, startDate[2]);
450      endDate = new Date(endDate[0], endDate[1] - 1, endDate[2]);
451
452      // Ensure that start comes before end for datepicker.
453      if (startDate > endDate) {
454        var laterDate = startDate;
455        startDate = endDate;
456        endDate = laterDate;
457      }
458
459      var startYear = startDate.getFullYear();
460      var endYear = endDate.getFullYear();
461
462      // Set up the jQuery datepicker element.
463      $calendar.datepicker({
464        dateFormat: 'yy-mm-dd',
465        yearRange: startYear + ':' + endYear,
466        firstDay: parseInt(firstDay),
467        minDate: startDate,
468        maxDate: endDate,
469        onSelect: function (dateText, inst) {
470          var date = dateText.split('-');
471          $webformDatepicker.find('select.year, input.year').val(+date[0]).trigger('change');
472          $webformDatepicker.find('select.month').val(+date[1]).trigger('change');
473          $webformDatepicker.find('select.day').val(+date[2]).trigger('change');
474        },
475        beforeShow: function (input, inst) {
476          // Get the select list values.
477          var year = $webformDatepicker.find('select.year, input.year').val();
478          var month = $webformDatepicker.find('select.month').val();
479          var day = $webformDatepicker.find('select.day').val();
480
481          // If empty, default to the current year/month/day in the popup.
482          var today = new Date();
483          year = year ? year : today.getFullYear();
484          month = month ? month : today.getMonth() + 1;
485          day = day ? day : today.getDate();
486
487          // Make sure that the default year fits in the available options.
488          year = (year < startYear || year > endYear) ? startYear : year;
489
490          // jQuery UI Datepicker will read the input field and base its date
491          // off of that, even though in our case the input field is a button.
492          $(input).val(year + '-' + month + '-' + day);
493        }
494      });
495
496      // Prevent the calendar button from submitting the form.
497      $calendar.click(function (event) {
498        // This event is triggered also when pressing enter when the focus is on
499        // previous webform components, but we only want to do something when
500        // we are on the calendar component. By checking the event client x/y
501        // position we known if it was the user clicking. For keyboard navigators
502        // simply the focus handles the date picker so we don't have to do
503        // anything special for them.
504        if (event.clientX !== 0 && event.clientY !== 0) {
505          // Focus is only necessary for Safari. But it has no impact on other
506          // browsers.
507          $(this).focus();
508          event.preventDefault();
509        }
510      });
511
512      // Clear date on backspace or delete.
513      $calendar.keyup(function (e) {
514        if (e.keyCode == 8 || e.keyCode == 46) {
515          $.datepicker._clearDate(this);
516        }
517      });
518    });
519  };
520
521  Drupal.webform.conditional = function (context) {
522    // Add the bindings to each webform on the page.
523    $.each(Drupal.settings.webform.conditionals, function (formKey, settings) {
524      var $form = $('.' + formKey + ':not(.webform-conditional-processed)');
525      $form.each(function (index, currentForm) {
526        var $currentForm = $(currentForm);
527        $currentForm.addClass('webform-conditional-processed');
528        $currentForm.bind('change', {'settings': settings}, Drupal.webform.conditionalCheck);
529
530        // Trigger all the elements that cause conditionals on this form.
531        Drupal.webform.doConditions($currentForm, settings);
532      });
533    });
534  };
535
536  /**
537   * Event handler to respond to field changes in a form.
538   *
539   * This event is bound to the entire form, not individual fields.
540   */
541  Drupal.webform.conditionalCheck = function (e) {
542    var $triggerElement = $(e.target).closest('.webform-component');
543    if (!$triggerElement.length) {
544      return;
545    }
546    var $form = $triggerElement.closest('form');
547    var triggerElementKey = $triggerElement.attr('class').match(/webform-component--[^ ]+/)[0];
548    var settings = e.data.settings;
549    if (settings.sourceMap[triggerElementKey]) {
550      Drupal.webform.doConditions($form, settings);
551    }
552  };
553
554  /**
555   * Processes all conditional.
556   */
557  Drupal.webform.doConditions = function ($form, settings) {
558
559    var stackPointer;
560    var resultStack;
561
562    /**
563     * Initializes an execution stack for a conditional group's rules.
564     *
565     * Also initializes sub-conditional rules.
566     */
567    function executionStackInitialize(andor) {
568      stackPointer = -1;
569      resultStack = [];
570      executionStackPush(andor);
571    }
572
573    /**
574     * Starts a new subconditional for the given and/or operator.
575     */
576    function executionStackPush(andor) {
577      resultStack[++stackPointer] = {
578        results: [],
579        andor: andor,
580      };
581    }
582
583    /**
584     * Adds a rule's result to the current sub-conditional.
585     */
586    function executionStackAccumulate(result) {
587      resultStack[stackPointer]['results'].push(result);
588    }
589
590    /**
591     * Finishes a sub-conditional and adds the result to the parent stack frame.
592     */
593    function executionStackPop() {
594      // Calculate the and/or result.
595      var stackFrame = resultStack[stackPointer];
596      // Pop stack and protect against stack underflow.
597      stackPointer = Math.max(0, stackPointer - 1);
598      var $conditionalResults = stackFrame['results'];
599      var filteredResults = $.map($conditionalResults, function (val) {
600        return val ? val : null;
601      });
602      return stackFrame['andor'] === 'or'
603                ? filteredResults.length > 0
604                : filteredResults.length === $conditionalResults.length;
605    }
606
607    // Track what has been set/hidden for each target component's elements.
608    // Hidden elements must be disabled because if they are required and don't
609    // have a value, they will prevent submission due to html5 validation.
610    // Each execution of the conditionals adds a temporary class
611    // webform-disabled-flag so that elements hidden or set can be disabled and
612    // also be prevented from being re-enabled by another conditional (such as a
613    // parent fieldset). After processing conditionals, this temporary class
614    // must be removed in preparation for the next execution of the
615    // conditionals.
616    $.each(settings.ruleGroups, function (rgid_key, rule_group) {
617      var ruleGroup = settings.ruleGroups[rgid_key];
618
619      // Perform the comparison callback and build the results for this group.
620      executionStackInitialize(ruleGroup['andor']);
621      $.each(ruleGroup['rules'], function (m, rule) {
622        switch (rule['source_type']) {
623          case 'component':
624            var elementKey = rule['source'];
625            var element = $form.find('.' + elementKey)[0];
626            var existingValue = settings.values[elementKey] ? settings.values[elementKey] : null;
627            executionStackAccumulate(window['Drupal']['webform'][rule.callback](element, existingValue, rule['value']));
628            break;
629
630          case 'conditional_start':
631            executionStackPush(rule['andor']);
632            break;
633
634          case 'conditional_end':
635            executionStackAccumulate(executionStackPop());
636            break;
637        }
638      });
639      var conditionalResult = executionStackPop();
640
641      $.each(ruleGroup['actions'], function (aid, action) {
642        var $target = $form.find('.' + action['target']);
643        var actionResult = action['invert'] ? !conditionalResult : conditionalResult;
644        switch (action['action']) {
645          case 'show':
646            var changed = actionResult != Drupal.webform.isVisible($target);
647            if (actionResult) {
648              $target.find('.webform-conditional-disabled:not(.webform-disabled-flag)')
649                .removeClass('webform-conditional-disabled')
650                .webformProp('disabled', false);
651              $target
652                .removeClass('webform-conditional-hidden')
653                .show();
654              $form.find('.chosen-disabled').prev().trigger('chosen:updated.chosen');
655            }
656            else {
657              $target
658                .hide()
659                .addClass('webform-conditional-hidden')
660                .find(':input')
661                  .addClass('webform-conditional-disabled webform-disabled-flag')
662                  .webformProp('disabled', true);
663            }
664            if (changed && $target.is('tr')) {
665              Drupal.webform.restripeTable($target.closest('table').first());
666            }
667            break;
668
669          case 'require':
670            var $requiredSpan = $target.find('.form-required, .form-optional').first();
671            if (actionResult != $requiredSpan.hasClass('form-required')) {
672              var $targetInputElements = $target.find("input:text,textarea,input[type='email'],select,input:radio,input:checkbox,input:file");
673              // Rather than hide the required tag, remove it so that other
674              // jQuery can respond via Drupal behaviors.
675              Drupal.detachBehaviors($requiredSpan);
676              $targetInputElements
677                .webformProp('required', actionResult)
678                .toggleClass('required', actionResult);
679              if (actionResult) {
680                $requiredSpan.replaceWith('<span class="form-required" title="' + Drupal.t('This field is required.') + '">*</span>');
681              }
682              else {
683                $requiredSpan.replaceWith('<span class="form-optional"></span>');
684              }
685              Drupal.attachBehaviors($requiredSpan);
686            }
687            break;
688
689          case 'set':
690            var $texts = $target.find("input:text,textarea,input[type='email']");
691            var $selects = $target.find('select,select option,input:radio,input:checkbox');
692            var $markups = $target.filter('.webform-component-markup');
693            if (actionResult) {
694              var multiple = $.map(action['argument'].split(','), $.trim);
695              $selects
696                .webformVal(multiple)
697                .webformProp('disabled', true)
698                  .addClass('webform-disabled-flag');
699              $texts
700                .val([action['argument']])
701                .webformProp('readonly', true)
702                .addClass('webform-disabled-flag');
703              // A special case is made for markup. It is sanitized with
704              // filter_xss_admin on the server. otherwise text() should be used
705              // to avoid an XSS vulnerability. text() however would preclude
706              // the use of tags like <strong> or <a>.
707              $markups.html(action['argument']);
708            }
709            else {
710              $selects.not('.webform-disabled-flag')
711                .webformProp('disabled', false);
712              $texts.not('.webform-disabled-flag')
713                .webformProp('readonly', false);
714              // Markup not set? Then restore original markup as provided in
715              // the attribute data-webform-markup.
716              $markups.each(function () {
717                var $this = $(this);
718                var original = $this.data('webform-markup');
719                if (original !== undefined) {
720                  $this.html(original);
721                }
722              });
723            }
724            break;
725        }
726      }); // End look on each action for one conditional.
727    }); // End loop on each conditional.
728
729    $form.find('.webform-disabled-flag').removeClass('webform-disabled-flag');
730  };
731
732  /**
733   * Event handler to prevent propagation of events.
734   *
735   * Typically click for disabling radio and checkboxes.
736   */
737  Drupal.webform.stopEvent = function () {
738    return false;
739  };
740
741  Drupal.webform.conditionalOperatorStringEqual = function (element, existingValue, ruleValue) {
742    var returnValue = false;
743    var currentValue = Drupal.webform.stringValue(element, existingValue);
744    $.each(currentValue, function (n, value) {
745      if (value.toLowerCase() === ruleValue.toLowerCase()) {
746        returnValue = true;
747        return false; // break.
748      }
749    });
750    return returnValue;
751  };
752
753  Drupal.webform.conditionalOperatorStringNotEqual = function (element, existingValue, ruleValue) {
754    var found = false;
755    var currentValue = Drupal.webform.stringValue(element, existingValue);
756    $.each(currentValue, function (n, value) {
757      if (value.toLowerCase() === ruleValue.toLowerCase()) {
758        found = true;
759      }
760    });
761    return !found;
762  };
763
764  Drupal.webform.conditionalOperatorStringContains = function (element, existingValue, ruleValue) {
765    var returnValue = false;
766    var currentValue = Drupal.webform.stringValue(element, existingValue);
767    $.each(currentValue, function (n, value) {
768      if (value.toLowerCase().indexOf(ruleValue.toLowerCase()) > -1) {
769        returnValue = true;
770        return false; // break.
771      }
772    });
773    return returnValue;
774  };
775
776  Drupal.webform.conditionalOperatorStringDoesNotContain = function (element, existingValue, ruleValue) {
777    var found = false;
778    var currentValue = Drupal.webform.stringValue(element, existingValue);
779    $.each(currentValue, function (n, value) {
780      if (value.toLowerCase().indexOf(ruleValue.toLowerCase()) > -1) {
781        found = true;
782      }
783    });
784    return !found;
785  };
786
787  Drupal.webform.conditionalOperatorStringBeginsWith = function (element, existingValue, ruleValue) {
788    var returnValue = false;
789    var currentValue = Drupal.webform.stringValue(element, existingValue);
790    $.each(currentValue, function (n, value) {
791      if (value.toLowerCase().indexOf(ruleValue.toLowerCase()) === 0) {
792        returnValue = true;
793        return false; // break.
794      }
795    });
796    return returnValue;
797  };
798
799  Drupal.webform.conditionalOperatorStringEndsWith = function (element, existingValue, ruleValue) {
800    var returnValue = false;
801    var currentValue = Drupal.webform.stringValue(element, existingValue);
802    $.each(currentValue, function (n, value) {
803      if (value.toLowerCase().lastIndexOf(ruleValue.toLowerCase()) === value.length - ruleValue.length) {
804        returnValue = true;
805        return false; // break.
806      }
807    });
808    return returnValue;
809  };
810
811  Drupal.webform.conditionalOperatorStringEmpty = function (element, existingValue, ruleValue) {
812    var currentValue = Drupal.webform.stringValue(element, existingValue);
813    var returnValue = true;
814    $.each(currentValue, function (n, value) {
815      if (value !== '') {
816        returnValue = false;
817        return false; // break.
818      }
819    });
820    return returnValue;
821  };
822
823  Drupal.webform.conditionalOperatorStringNotEmpty = function (element, existingValue, ruleValue) {
824    return !Drupal.webform.conditionalOperatorStringEmpty(element, existingValue, ruleValue);
825  };
826
827  Drupal.webform.conditionalOperatorSelectGreaterThan = function (element, existingValue, ruleValue) {
828    var currentValue = Drupal.webform.stringValue(element, existingValue);
829    return Drupal.webform.compare_select(currentValue[0], ruleValue, element) > 0;
830  };
831
832  Drupal.webform.conditionalOperatorSelectGreaterThanEqual = function (element, existingValue, ruleValue) {
833    var currentValue = Drupal.webform.stringValue(element, existingValue);
834    var comparison = Drupal.webform.compare_select(currentValue[0], ruleValue, element);
835    return comparison > 0 || comparison === 0;
836  };
837
838  Drupal.webform.conditionalOperatorSelectLessThan = function (element, existingValue, ruleValue) {
839    var currentValue = Drupal.webform.stringValue(element, existingValue);
840    return Drupal.webform.compare_select(currentValue[0], ruleValue, element) < 0;
841  };
842
843  Drupal.webform.conditionalOperatorSelectLessThanEqual = function (element, existingValue, ruleValue) {
844    var currentValue = Drupal.webform.stringValue(element, existingV
844alue);
845    var comparison = Drupal.webform.compare_select(currentValue[0], ruleValue, element);
846    return comparison < 0 || comparison === 0;
847  };
848
849  Drupal.webform.conditionalOperatorNumericEqual = function (element, existingValue, ruleValue) {
850    // See float comparison: http://php.net/manual/en/language.types.float.php
851    var currentValue = Drupal.webform.stringValue(element, existingValue);
852    var epsilon = 0.000001;
853    // An empty string does not match any number.
854    return currentValue[0] === '' ? false : (Math.abs(parseFloat(currentValue[0]) - parseFloat(ruleValue)) < epsilon);
855  };
856
857  Drupal.webform.conditionalOperatorNumericNotEqual = function (element, existingValue, ruleValue) {
858    // See float comparison: http://php.net/manual/en/language.types.float.php
859    var currentValue = Drupal.webform.stringValue(element, existingValue);
860    var epsilon = 0.000001;
861    // An empty string does not match any number.
862    return currentValue[0] === '' ? true : (Math.abs(parseFloat(currentValue[0]) - parseFloat(ruleValue)) >= epsilon);
863  };
864
865  Drupal.webform.conditionalOperatorNumericGreaterThan = function (element, existingValue, ruleValue) {
866    var currentValue = Drupal.webform.stringValue(element, existingValue);
867    return parseFloat(currentValue[0]) > parseFloat(ruleValue);
868  };
869
870  Drupal.webform.conditionalOperatorNumericGreaterThanEqual = function (element, existingValue, ruleValue) {
871    return Drupal.webform.conditionalOperatorNumericGreaterThan(element, existingValue, ruleValue) ||
872           Drupal.webform.conditionalOperatorNumericEqual(element, existingValue, ruleValue);
873  };
874
875  Drupal.webform.conditionalOperatorNumericLessThan = function (element, existingValue, ruleValue) {
876    var currentValue = Drupal.webform.stringValue(element, existingValue);
877    return parseFloat(currentValue[0]) < parseFloat(ruleValue);
878  };
879
880  Drupal.webform.conditionalOperatorNumericLessThanEqual = function (element, existingValue, ruleValue) {
881    return Drupal.webform.conditionalOperatorNumericLessThan(element, existingValue, ruleValue) ||
882           Drupal.webform.conditionalOperatorNumericEqual(element, existingValue, ruleValue);
883  };
884
885  Drupal.webform.conditionalOperatorDateEqual = function (element, existingValue, ruleValue) {
886    var currentValue = Drupal.webform.dateValue(element, existingValue);
887    return currentValue === ruleValue;
888  };
889
890  Drupal.webform.conditionalOperatorDateNotEqual = function (element, existingValue, ruleValue) {
891    return !Drupal.webform.conditionalOperatorDateEqual(element, existingValue, ruleValue);
892  };
893
894  Drupal.webform.conditionalOperatorDateBefore = function (element, existingValue, ruleValue) {
895    var currentValue = Drupal.webform.dateValue(element, existingValue);
896    return (currentValue !== false) && currentValue < ruleValue;
897  };
898
899  Drupal.webform.conditionalOperatorDateBeforeEqual = function (element, existingValue, ruleValue) {
900    var currentValue = Drupal.webform.dateValue(element, existingValue);
901    return (currentValue !== false) && (currentValue < ruleValue || currentValue === ruleValue);
902  };
903
904  Drupal.webform.conditionalOperatorDateAfter = function (element, existingValue, ruleValue) {
905    var currentValue = Drupal.webform.dateValue(element, existingValue);
906    return (currentValue !== false) && currentValue > ruleValue;
907  };
908
909  Drupal.webform.conditionalOperatorDateAfterEqual = function (element, existingValue, ruleValue) {
910    var currentValue = Drupal.webform.dateValue(element, existingValue);
911    return (currentValue !== false) && (currentValue > ruleValue || currentValue === ruleValue);
912  };
913
914  Drupal.webform.conditionalOperatorTimeEqual = function (element, existingValue, ruleValue) {
915    var currentValue = Drupal.webform.timeValue(element, existingValue);
916    return currentValue === ruleValue;
917  };
918
919  Drupal.webform.conditionalOperatorTimeNotEqual = function (element, existingValue, ruleValue) {
920    return !Drupal.webform.conditionalOperatorTimeEqual(element, existingValue, ruleValue);
921  };
922
923  Drupal.webform.conditionalOperatorTimeBefore = function (element, existingV
923alue, ruleValue) {
924    // Date and time operators intentionally exclusive for "before".
925    var currentValue = Drupal.webform.timeValue(element, existingValue);
926    return (currentValue !== false) && (currentValue < ruleValue);
927  };
928
929  Drupal.webform.conditionalOperatorTimeBeforeEqual = function (element, existingValue, ruleValue) {
930    // Date and time operators intentionally exclusive for "before".
931    var currentValue = Drupal.webform.timeValue(element, existingValue);
932    return (currentValue !== false) && (currentValue < ruleValue || currentValue === ruleValue);
933  };
934
935  Drupal.webform.conditionalOperatorTimeAfter = function (element, existingValue, ruleValue) {
936    // Date and time operators intentionally inclusive for "after".
937    var currentValue = Drupal.webform.timeValue(element, existingValue);
938    return (currentValue !== false) && (currentValue > ruleValue);
939  };
940
941  Drupal.webform.conditionalOperatorTimeAfterEqual = function (element, existingValue, ruleValue) {
942    // Date and time operators intentionally inclusive for "after".
943    var currentValue = Drupal.webform.timeValue(element, existingValue);
944    return (currentValue !== false) && (currentValue > ruleValue || currentValue === ruleValue);
945  };
946
947  /**
948   * Utility function to compare values of a select component.
949   *
950   * @param string a
951   *   First select option key to compare
952   * @param string b
953   *   Second select option key to compare
954   * @param array options
955   *   Associative array where the a and b are within the keys
956   *
957   * @return integer based upon position of $a and $b in $options
958   *   -N if $a above (<) $b
959   *   0 if $a = $b
960   *   +N if $a is below (>) $b
961   */
962  Drupal.webform.compare_select = function (a, b, element) {
963    var optionList = [];
964    $('option,input:radio,input:checkbox', element).each(function () {
965      optionList.push($(this).val());
966    });
967    var a_position = optionList.indexOf(a);
968    var b_position = optionList.indexOf(b);
969    return (a_position < 0 || b_position < 0) ? null : a_position - b_position;
970  };
971
972  /**
973   * Utility to return current visibility.
974   *
975   * Uses actual visibility, except for hidden components which use the applied
976   * disabled class.
977   */
978  Drupal.webform.isVisible = function ($element) {
979    return $element.hasClass('webform-component-hidden')
980              ? !$element.find('input').first().hasClass('webform-conditional-disabled')
981              : $element.closest('.webform-conditional-hidden').length == 0;
982  };
983
984  /**
985   * Function to get a string value from a select/radios/text/etc. field.
986   */
987  Drupal.webform.stringValue = function (element, existingValue) {
988    var value = [];
989    if (element) {
990      var $element = $(element);
991      if (Drupal.webform.isVisible($element)) {
992        // Checkboxes and radios.
993        $element.find('input[type=checkbox]:checked,input[type=radio]:checked').each(function () {
994          value.push(this.value);
995        });
996        // Select lists.
997        if (!value.length) {
998          var selectValue = $element.find('select').val();
999          if (selectValue) {
1000            if ($.isArray(selectValue)) {
1001              value = selectValue;
1002            }
1003            else {
1004              value.push(selectValue);
1005            }
1006          }
1007        }
1008        // Simple text fields. This check is done last so that the select list
1009        // in select-or-other fields comes before the "other" text field.
1010        if (!value.length) {
1011          $element.find('input:not([type=checkbox],[type=radio]),textarea').each(function () {
1012            value.push(this.value);
1013          });
1014        }
1015      }
1016    }
1017    else {
1018      switch ($.type(existingValue)) {
1019        case 'array':
1020          value = existingValue;
1021          break;
1022
1023        case 'string':
1024          value.push(existingValue);
1025          break;
1026      }
1027    }
1028    return value;
1029  };
1030
1031  /**
1032   * Utility function to calculate a second-based timestamp from a time field.
1033   */
1034  Drupal.webform.dateValue = function (element, existingValue) {
1035    var value = false;
1036    if (element) {
1037      var $element = $(element);
1038      if (Drupal.webform.isVisible($element)) {
1039        var day = $element.find('[name*=day]').val();
1040        var month = $element.find('[name*=month]').val();
1041        var year = $element.find('[name*=year]').val();
1042        // Months are 0 indexed in JavaScript.
1043        if (month) {
1044          month--;
1045        }
1046        if (year !== '' && month !== '' && day !== '') {
1047          value = Date.UTC(year, month, day) / 1000;
1048        }
1049      }
1050    }
1051    else {
1052      if ($.type(existingValue) === 'array' && existingValue.length) {
1053        existingValue = existingValue[0];
1054      }
1055      if ($.type(existingValue) === 'string') {
1056        existingValue = existingV
1056alue.split('-');
1057      }
1058      if (existingValue.length === 3) {
1059        value = Date.UTC(existingValue[0], existingValue[1], existingValue[2]) / 1000;
1060      }
1061    }
1062    return value;
1063  };
1064
1065  /**
1066   * Utility function to calculate a millisecond timestamp from a time field.
1067   */
1068  Drupal.webform.timeValue = function (element, existingValue) {
1069    var value = false;
1070    if (element) {
1071      var $element = $(element);
1072      if (Drupal.webform.isVisible($element)) {
1073        var hour = $element.find('[name*=hour]').val();
1074        var minute = $element.find('[name*=minute]').val();
1075        var ampm = $element.find('[name*=ampm]:checked').val();
1076
1077        // Convert to integers if set.
1078        hour = (hour === '') ? hour : parseInt(hour);
1079        minute = (minute === '') ? minute : parseInt(minute);
1080
1081        if (hour !== '') {
1082          hour = (hour < 12 && ampm == 'pm') ? hour + 12 : hour;
1083          hour = (hour === 12 && ampm == 'am') ? 0 : hour;
1084        }
1085        if (hour !== '' && minute !== '') {
1086          value = Date.UTC(1970, 0, 1, hour, minute) / 1000;
1087        }
1088      }
1089    }
1090    else {
1091      if ($.type(existingValue) === 'array' && existingValue.length) {
1092        existingValue = existingValue[0];
1093      }
1094      if ($.type(existingValue) === 'string') {
1095        existingValue = existingValue.split(':');
1096      }
1097      if (existingValue.length >= 2) {
1098        value = Date.UTC(1970, 0, 1, existingValue[0], existingValue[1]) / 1000;
1099      }
1100    }
1101    return value;
1102  };
1103
1104  /**
1105   * Make a prop shim for jQuery < 1.9.
1106   */
1107  $.fn.webformProp = $.fn.webformProp || function (name, value) {
1108    if (value) {
1109      return $.fn.prop ? this.prop(name, true) : this.attr(name, true);
1110    }
1111    else {
1112      return $.fn.prop ? this.prop(name, false) : this.removeAttr(name);
1113    }
1114  };
1115
1116  /**
1117   * Make a multi-valued val() function.
1118   *
1119   * This is for setting checkboxes, radios, and select elements.
1120   */
1121  $.fn.webformVal = function (values) {
1122    this.each(function () {
1123      var $this = $(this);
1124      var value = $this.val();
1125      var on = $.inArray($this.val(), values) != -1;
1126      if (this.nodeName == 'OPTION') {
1127        $this.webformProp('selected', on ? value : false);
1128      }
1129      else {
1130        $this.val(on ? [value] : false);
1131      }
1132    });
1133    return this;
1134  };
1135
1136  /**
1137   * Given a table's DOM element, restripe the odd/even classes.
1138   */
1139  Drupal.webform.restripeTable = function (table) {
1140    // :even and :odd are reversed because jQuery counts from 0 and
1141    // we count from 1, so we're out of sync.
1142    // Match immediate children of the parent element to allow nesting.
1143    $('> tbody > tr, > tr', table)
1144      .filter(':visible:odd').filter('.odd')
1145        .removeClass('odd').addClass('even')
1146      .end().end()
1147      .filter(':visible:even').filter('.even')
1148        .removeClass('even').addClass('odd');
1149  };
1150
1151})(jQuery);
1152;

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.