1(function ($) { 2 var Quickfit, QuickfitHelper, defaults, pluginName; 3 4 pluginName = 'quickfit'; 5 6 defaults = { 7 min: 8, 8 max: 12, 9 tolerance: 0.02, 10 truncate: false, 11 width: null, 12 sampleNumberOfLetters: 10, 13 sampleFontSize: 12 14 }; 15 QuickfitHelper = (function () { 16 17 var sharedInstance = null; 18 19 QuickfitHelper.instance = function (options) { 20 if (!sharedInstance) { 21 sharedInstance = new QuickfitHelper(options); 22 } 23 return sharedInstance; 24 }; 25 26 function QuickfitHelper(options) { 27 this.options = options; 28 29 this.item = $('<span id="meassure"></span>'); 30 this.item.css({ 31 position: 'absolute', 32 left: '-1000px', 33 top: '-1000px', 34 'font-size': "" + this.options.sampleFontSize + "px" 35 }); 36 $('body').append(this.item); 37 38 this.meassures = {}; 39 } 40 41 QuickfitHelper.prototype.getMeassure = function (letter) { 42 var currentMeassure; 43 currentMeassure = this.meassures[letter]; 44 if (!currentMeassure) { 45 currentMeassure = this.setMeassure(letter); 46 } 47 return currentMeassure; 48 }; 49 50 QuickfitHelper.prototype.setMeassure = function (letter) { 51 var currentMeassure, index, sampleLetter, text, _ref; 52 53 text = ''; 54 sampleLetter = letter === ' ' ? ' ' : letter; 55 56 for (index = 0, _ref = this.options.sampleNumberOfLetters - 1; 0 <= _ref ? index <= _ref : index >= _ref; 0 <= _ref ? index++ : index--) { 57 text += sampleLetter; 58 } 59 60 this.item.html(text); 61 currentMeassure = this.item.width() / this.options.sampleNumberOfLetters / this.options.sampleFontSize; 62 this.meassures[letter] = currentMeassure; 63 64 return currentMeassure; 65 }; 66 67 return QuickfitHelper; 68 69 })(); 70 71 Quickfit = (function () { 72 73 function Quickfit(element, options) { 74 this.$element = element; 75 this.options = $.extend({}, defaults, options); 76 this.$element = $(this.$element); 77 this._defaults = defaults; 78 this._name = pluginName; 79 this.quickfitHelper = QuickfitHelper.instance(this.options); 80 } 81 82 Quickfit.prototype.fit = function () { 83 var elementWidth; 84 if (!this.options.width) { 85 elementWidth = this.$element.width(); 86 this.options.width = elementWidth - this.options.tolerance * elementWidth; 87 } 88 if (this.text = this.$element.attr('data-quickfit')) { 89 this.previouslyTruncated = true; 90 } else { 91 this.text = this.$element.text(); 92 } 93 this.calculateFontSize(); 94 95 if (this.options.truncate) this.truncate(); 96 97 return { 98 $element: this.$element, 99 size: this.fontSize 100 }; 101 }; 102 103 Quickfit.prototype.calculateFontSize = function () { 104 var letter, textWidth, i; 105 106 textWidth = 0; 107 for (i = 0; i < this.text.length; ++i) { 108 letter = this.text.charAt(i); 109 textWidth += this.quickfitHelper.getMeassure(letter); 110 } 111 112 this.targetFontSize = parseInt(this.options.width / textWidth); 113 return this.fontSize = Math.max(this.options.min, Math.min(this.options.max, this.targetFontSize)); 114 }; 115 116 Quickfit.prototype.truncate = function () { 117 var index, lastLetter, letter, textToAdd, textWidth; 118 119 if (this.fontSize > this.targetFontSize) { 120 textToAdd = ''; 121 textWidth = 3 * this.quickfitHelper.getMeassure('.') * this.fontSize; 122 123 index = 0; 124 while (textWidth < this.options.width && index < this.text.length) { 125 letter = this.text[index++]; 126 if (lastLetter) textToAdd += lastLetter; 127 textWidth += this.fontSize * this.quickfitHelper.getMeassure(letter); 128 lastLetter = letter; 129 } 130 131 if (textToAdd.length + 1 === this.text.length) { 132 textToAdd = this.text; 133 } else { 134 textToAdd += '...'; 135 } 136 this.textWasTruncated = true; 137 138 return this.$element.attr('data-quickfit', this.text).html(textToAdd); 139 140 } else { 141 if (this.previouslyTruncated) { 142 return this.$element.html(this.text); 143 } 144 } 145 }; 146 147 return Quickfit; 148 149 })();
150 151 return $.fn.quickfit = function (options) { 152 var measurements = []; 153 154 // Separate measurements from repaints 155 // First calculate all measurements... 156 var $elements = this.each(function () { 157 var measurement = new Quickfit(this, options).fit(); 158 measurements.push(measurement); 159 return measurement.$element; 160 }); 161 162 // ... then apply the measurements. 163 for (var i = 0; i < measurements.length; i++) { 164 var measurement = measurements[i]; 165 166 measurement.$element.css({ fontSize: measurement.size + 'px' }); 167 } 168 169 return $elements; 170 }; 171 172})(jQuery, window); 173; 174(function ($) { 175 176Drupal.behaviors.textarea = { 177 attach: function (context, settings) { 178 $('.form-textarea-wrapper.resizable', context).once('textarea', function () { 179 var staticOffset = null; 180 var textarea = $(this).addClass('resizable-textarea').find('textarea'); 181 var grippie = $('<div class="grippie"></div>').mousedown(startDrag); 182 183 grippie.insertAfter(textarea); 184 185 function startDrag(e) { 186 staticOffset = textarea.height() - e.pageY; 187 textarea.css('opacity', 0.25); 188 $(document).mousemove(performDrag).mouseup(endDrag); 189 return false; 190 } 191 192 function performDrag(e) { 193 textarea.height(Math.max(32, staticOffset + e.pageY) + 'px'); 194 return false; 195 } 196 197 function endDrag(e) { 198 $(document).unbind('mousemove', performDrag).unbind('mouseup', endDrag); 199 textarea.css('opacity', 1); 200 } 201 }); 202 } 203}; 204 205})(jQuery); 206; 207/** 208 * @file 209 * Unlock protected forms by resetting the form action to the path that 210 * it should be, only if the current user is verified to be human. 211 */ 212(function ($) { 213 Drupal.antibot = {}; 214 215 Drupal.behaviors.antibot = { 216 attach: function (context) { 217 // Assume the user is not human, despite JS being enabled. 218 Drupal.settings.antibot.human = false; 219 220 // Wait for a mouse to move, indicating they are human. 221 $('body').mousemove(function() { 222 // Unlock the forms. 223 Drupal.antibot.unlockForms(); 224 }); 225 226 // Wait for a touch move event, indicating that they are human. 227 $('body').bind('touchmove', function() { 228 // Unlock the forms. 229 Drupal.antibot.unlockForms(); 230 }); 231 232 // A tab or enter key pressed can also indicate they are human. 233 $('body').keydown(function(e) { 234 if ((e.keyCode == 9) || (e.keyCode == 13)) { 235 // Unlock the forms. 236 Drupal.antibot.unlockForms(); 237 } 238 }); 239 } 240 }; 241 242 /** 243 * Revert the action on the protected forms to what it was originally 244 * set to. 245 */ 246 Drupal.antibot.unlockForms = function() { 247 // Act only if we haven't yet verified this user as being human. 248 if (!Drupal.settings.antibot.human) { 249 // Iterate all antibot forms that we need to unlock. 250 for (var id in Drupal.settings.antibot.forms) { 251 // Switch the action to the original value. 252 $('form#' + id).attr('action', Drupal.settings.antibot.forms[id].action); 253 254 // Check if a key is required. 255 if (Drupal.settings.antibot.forms[id].key) { 256 // Inject the key value. 257 $('form#' + id).find('input[name="antibot_key"]').val(Drupal.settings.antibot.forms[id].key); 258 } 259 } 260 // Mark this user as being human. 261 Drupal.settings.antibot.human = true; 262 } 263 }; 264 265})(jQuery); 266; 267/** 268 * @file 269 * JavaScript behaviors for the front-end display of webforms. 270 */ 271 272(function ($) { 273 274 "use strict"; 275 276 Drupal.behaviors.webform = Drupal.behaviors.webform || {}; 277 278 Drupal.behaviors.webform.attach = function (context) { 279 // Calendar datepicker behavior. 280 Drupal.webform.datepicker(context); 281 282 // Conditional logic. 283 if (Drupal.settings.webform && Drupal.settings.webform.conditionals) { 284 Drupal.webform.conditional(context); 285 } 286 }; 287 288 Drupal.webform = Drupal.webform || {}; 289 290 Drupal.webform.datepicker = function (context) { 291 $('div.webform-datepicker').each(function () { 292 var $webformDatepicker = $(this); 293 var $calendar = $webformDatepicker.find('input.webform-calendar'); 294 295 // Ensure the page we're on actually contains a datepicker. 296 if ($calendar.length == 0) { 297 return; 298 } 299 300 var startDate = $calendar[0].className.replace(/.*webform-calendar-start-(\d{4}-\d{2}-\d{2}).*/, '$1').split('-'); 301 var endDate = $calendar[0].className.replace(/.*webform-calendar-end-(\d{4}-\d{2}-\d{2}).*/, '$1').split('-'); 302 var firstDay = $calendar[0].className.replace(/.*webform-calendar-day-(\d).*/, '$1'); 303 // Convert date strings into actual Date objects. 304 startDate = new Date(startDate[0], startDate[1] - 1, startDate[2]); 305 endDate = new Date(endDate[0], endDate[1] - 1, endDate[2]); 306 307 // Ensure that start comes before end for datepicker. 308 if (startDate >
308 endDate) { 309 var laterDate = startDate; 310 startDate = endDate; 311 endDate = laterDate; 312 } 313 314 var startYear = startDate.getFullYear(); 315 var endYear = endDate.getFullYear(); 316 317 // Set up the jQuery datepicker element. 318 $calendar.datepicker({ 319 dateFormat: 'yy-mm-dd', 320 yearRange: startYear + ':' + endYear, 321 firstDay: parseInt(firstDay), 322 minDate: startDate, 323 maxDate: endDate, 324 onSelect: function (dateText, inst) { 325 var date = dateText.split('-'); 326 $webformDatepicker.find('select.year, input.year').val(+date[0]).trigger('change'); 327 $webformDatepicker.find('select.month').val(+date[1]).trigger('change'); 328 $webformDatepicker.find('select.day').val(+date[2]).trigger('change'); 329 }, 330 beforeShow: function (input, inst) { 331 // Get the select list values. 332 var year = $webformDatepicker.find('select.year, input.year').val(); 333 var month = $webformDatepicker.find('select.month').val(); 334 var day = $webformDatepicker.find('select.day').val(); 335 336 // If empty, default to the current year/month/day in the popup. 337 var today = new Date(); 338 year = year ? year : today.getFullYear(); 339 month = month ? month : today.getMonth() + 1; 340 day = day ? day : today.getDate(); 341 342 // Make sure that the default year fits in the available options. 343 year = (year < startYear || year > endYear) ? startYear : year; 344 345 // jQuery UI Datepicker will read the input field and base its date 346 // off of that, even though in our case the input field is a button. 347 $(input).val(year + '-' + month + '-' + day); 348 } 349 }); 350 351 // Prevent the calendar button from submitting the form. 352 $calendar.click(function (event) { 353 // This event is triggered also when pressing enter when the focus is on 354 // previous webform components, but we only want to do something when 355 // we are on the calendar component. By checking the event client x/y 356 // position we known if it was the user clicking. For keyboard navigators 357 // simply the focus handles the date picker so we don't have to do 358 // anything special for them. 359 if (event.clientX !== 0 && event.clientY !== 0) { 360 // Focus is only necessary for Safari. But it has no impact on other 361 // browsers. 362 $(this).focus(); 363 event.preventDefault(); 364 } 365 }); 366 367 // Clear date on backspace or delete. 368 $calendar.keyup(function (e) { 369 if (e.keyCode == 8 || e.keyCode == 46) { 370 $.datepicker._clearDate(this); 371 } 372 }); 373 }); 374 }; 375 376 Drupal.webform.conditional = function (context) { 377 // Add the bindings to each webform on the page. 378 $.each(Drupal.settings.webform.conditionals, function (formKey, settings) { 379 var $form = $('.' + formKey + ':not(.webform-conditional-processed)'); 380 $form.each(function (index, currentForm) { 381 var $currentForm = $(currentForm); 382 $currentForm.addClass('webform-conditional-processed'); 383 $currentForm.bind('change', {'settings': settings}, Drupal.webform.conditionalCheck); 384 385 // Trigger all the elements that cause conditionals on this form. 386 Drupal.webform.doConditions($currentForm, settings); 387 }); 388 }); 389 }; 390 391 /** 392 * Event handler to respond to field changes in a form. 393 * 394 * This event is bound to the entire form, not individual fields. 395 */ 396 Drupal.webform.conditionalCheck = function (e) { 397 var $triggerElement = $(e.target).closest('.webform-component'); 398 if (!$triggerElement.length) { 399 return; 400 } 401 var $form = $triggerElement.closest('form'); 402 var triggerElementKey = $triggerElement.attr('class').match(/webform-component--[^ ]+/)[0]; 403 var settings = e.data.settings; 404 if (settings.sourceMap[triggerElementKey]) { 405 Drupal.webform.doConditions($form, settings); 406 } 407 }; 408 409 /** 410 * Processes all conditional. 411 */ 412 Drupal.webform.doConditions = function ($form, settings) { 413 414 var stackPointer; 415 var resultStack; 416 417 /** 418 * Initializes an execution stack for a conditional group's rules. 419 * 420 * Also initializes sub-conditional rules. 421 */ 422 function executionStackInitialize(andor) { 423 stackPointer = -1; 424 resultStack = []; 425 executionStackPush(andor); 426 } 427 428 /** 429 * Starts a new subconditional for the given and/or operator. 430 */ 431 function executionStackPush(andor) { 432 resultStack[++stackPointer] = { 433 results: [], 434 andor: andor, 435 }; 436 } 437 438 /** 439 * Adds a rule's result to the current sub-conditional. 440 */ 441 function executionStackAccumulate(result) { 442 resultStack[stackPointer]['results'].push(result); 443 } 444 445 /** 446 * Finishes a sub-conditional and adds the result to the parent stack frame. 447 */ 448 function executionStackPop() { 449 // Calculate the and/or result. 450 var stackFrame = resultStack[stackPointer]; 451 // Pop stack and protect against stack underflow. 452 stackPointer = Math.max(0, stackPointer - 1); 453 var $conditionalResults = stackFrame['results']; 454 var filteredResults = $.map($conditionalResults, function (val) { 455 return val ? val : null; 456 }); 457 return stackFrame['andor'] === 'or' 458 ? filteredResults.length > 0 459 : filteredResults.length === $conditionalResults.length; 460 } 461 462 // Track what has been set/hidden for each target component's elements. 463 // Hidden elements must be disabled because if they are required and don't 464 // have a value, they will prevent submission due to html5 validation. 465 // Each execution of the conditionals adds a temporary class 466 // webform-disabled-flag so that elements hidden or set can be disabled and 467 // also be prevented from being re-enabled by another conditional (such as a 468 // parent fieldset). After processing conditionals, this temporary class 469 // must be removed in preparation for the next execution of the 470 // conditionals. 471 $.each(settings.ruleGroups, function (rgid_key, rule_group) { 472 var ruleGroup = settings.ruleGroups[rgid_key]; 473 474 // Perform the comparison callback and build the results for this group. 475 executionStackInitialize(ruleGroup['andor']); 476 $.each(ruleGroup['rules'], function (m, rule) { 477 switch (rule['source_type']) { 478 case 'component':
479 var elementKey = rule['source']; 480 var element = $form.find('.' + elementKey)[0]; 481 var existingValue = settings.values[elementKey] ? settings.values[elementKey] : null; 482 executionStackAccumulate(window['Drupal']['webform'][rule.callback](element, existingValue, rule['value'])); 483 break; 484 485 case 'conditional_start': 486 executionStackPush(rule['andor']); 487 break; 488 489 case 'conditional_end': 490 executionStackAccumulate(executionStackPop()); 491 break; 492 } 493 }); 494 var conditionalResult = executionStackPop(); 495 496 $.each(ruleGroup['actions'], function (aid, action) { 497 var $target = $form.find('.' + action['target']); 498 var actionResult = action['invert'] ? !conditionalResult : conditionalResult; 499 switch (action['action']) { 500 case 'show': 501 var changed = actionResult != Drupal.webform.isVisible($target); 502 if (actionResult) { 503 $target.find('.webform-conditional-disabled:not(.webform-disabled-flag)') 504 .removeClass('webform-conditional-disabled') 505 .webformProp('disabled', false); 506 $target 507 .removeClass('webform-conditional-hidden') 508 .show(); 509 $form.find('.chosen-disabled').prev().trigger('chosen:updated.chosen'); 510 } 511 else { 512 $target 513 .hide() 514 .addClass('webform-conditional-hidden') 515 .find(':input') 516 .addClass('webform-conditional-disabled webform-disabled-flag') 517 .webformProp('disabled', true); 518 } 519 if (changed && $target.is('tr')) { 520 Drupal.webform.restripeTable($target.closest('table').first()); 521 } 522 break; 523 524 case 'require': 525 var $requiredSpan = $target.find('.form-required, .form-optional').first(); 526 if (actionResult != $requiredSpan.hasClass('form-required')) { 527 var $targetInputElements = $target.find("input:text,textarea,input[type='email'],select,input:radio,input:checkbox,input:file"); 528 // Rather than hide the required tag, remove it so that other 529 // jQuery can respond via Drupal behaviors. 530 Drupal.detachBehaviors($requiredSpan); 531 $targetInputElements 532 .webformProp('required', actionResult) 533 .toggleClass('required', actionResult); 534 if (actionResult) { 535 $requiredSpan.replaceWith('<span class="form-required" title="' + Drupal.t('This field is required.') + '">*</span>'); 536 } 537 else { 538 $requiredSpan.replaceWith('<span class="form-optional"></span>'); 539 } 540 Drupal.attachBehaviors($requiredSpan); 541 } 542 break; 543 544 case 'set': 545 var $texts = $target.find("input:text,textarea,input[type='email']"); 546 var $selects = $target.find('select,select option,input:radio,input:checkbox'); 547 var $markups = $target.filter('.webform-component-markup'); 548 if (actionResult) { 549 var multiple = $.map(action['argument'].split(','), $.trim); 550 $selects 551 .webformVal(multiple) 552 .webformProp('disabled', true) 553 .addClass('webform-disabled-flag'); 554 $texts 555 .val([action['argument']]) 556 .webformProp('readonly', true) 557 .addClass('webform-disabled-flag'); 558 // A special case is made for markup. It is sanitized with 559 // filter_xss_admin on the server. otherwise text() should be used 560 // to avoid an XSS vulnerability. text() however would preclude 561 // the use of tags like <strong> or <a>. 562 $markups.html(action['argument']); 563 } 564 else { 565 $selects.not('.webform-disabled-flag') 566 .webformProp('disabled', false); 567 $texts.not('.webform-disabled-flag') 568 .webformProp('readonly', false); 569 // Markup not set? Then restore original markup as provided in 570 // the attribute data-webform-markup. 571 $markups.each(function () { 572 var $this = $(this); 573 var original = $this.data('webform-markup'); 574 if (original !== undefined) { 575 $this.html(original); 576 } 577 }); 578 } 579 break; 580 } 581 }); // End look on each action for one conditional. 582 }); // End loop on each conditional. 583 584 $form.find('.webform-disabled-flag').removeClass('webform-disabled-flag'); 585 }; 586 587 /** 588 * Event handler to prevent propagation of events. 589 * 590 * Typically click for disabling radio and checkboxes. 591 */ 592 Drupal.webform.stopEvent = function () { 593 return false;
594 }; 595 596 Drupal.webform.conditionalOperatorStringEqual = function (element, existingValue, ruleValue) { 597 var returnValue = false; 598 var currentValue = Drupal.webform.stringValue(element, existingValue); 599 $.each(currentValue, function (n, value) { 600 if (value.toLowerCase() === ruleValue.toLowerCase()) { 601 returnValue = true; 602 return false; // break. 603 } 604 }); 605 return returnValue; 606 }; 607 608 Drupal.webform.conditionalOperatorStringNotEqual = function (element, existingValue, ruleValue) { 609 var found = false; 610 var currentValue = Drupal.webform.stringValue(element, existingValue); 611 $.each(currentValue, function (n, value) { 612 if (value.toLowerCase() === ruleValue.toLowerCase()) { 613 found = true; 614 } 615 }); 616 return !found; 617 }; 618 619 Drupal.webform.conditionalOperatorStringContains = function (element, existingValue, ruleValue) { 620 var returnValue = false; 621 var currentValue = Drupal.webform.stringValue(element, existingValue); 622 $.each(currentValue, function (n, value) { 623 if (value.toLowerCase().indexOf(ruleValue.toLowerCase()) > -1) { 624 returnValue = true; 625 return false; // break. 626 } 627 }); 628 return returnValue; 629 }; 630 631 Drupal.webform.conditionalOperatorStringDoesNotContain = function (element, existingValue, ruleValue) { 632 var found = false; 633 var currentValue = Drupal.webform.stringValue(element, existingValue); 634 $.each(currentValue, function (n, value) { 635 if (value.toLowerCase().indexOf(ruleValue.toLowerCase()) > -1) { 636 found = true; 637 } 638 }); 639 return !found; 640 }; 641 642 Drupal.webform.conditionalOperatorStringBeginsWith = function (element, existingValue, ruleValue) { 643 var returnValue = false; 644 var currentValue = Drupal.webform.stringValue(element, existingValue); 645 $.each(currentValue, function (n, value) { 646 if (value.toLowerCase().indexOf(ruleValue.toLowerCase()) === 0) { 647 returnValue = true; 648 return false; // break. 649 } 650 }); 651 return returnValue; 652 }; 653 654 Drupal.webform.conditionalOperatorStringEndsWith = function (element, existingValue, ruleValue) { 655 var returnValue = false; 656 var currentValue = Drupal.webform.stringValue(element, existingValue); 657 $.each(currentValue, function (n, value) { 658 if (value.toLowerCase().lastIndexOf(ruleValue.toLowerCase()) === value.length - ruleValue.length) { 659 returnValue = true; 660 return false; // break. 661 } 662 }); 663 return returnValue; 664 }; 665 666 Drupal.webform.conditionalOperatorStringEmpty = function (element, existingValue, ruleValue) { 667 var currentValue = Drupal.webform.stringValue(element, existingValue); 668 var returnValue = true; 669 $.each(currentValue, function (n, value) { 670 if (value !== '') { 671 returnValue = false; 672 return false; // break. 673 } 674 }); 675 return returnValue; 676 }; 677 678 Drupal.webform.conditionalOperatorStringNotEmpty = function (element, existingValue, ruleValue) { 679 return !Drupal.webform.conditionalOperatorStringEmpty(element, existingValue, ruleValue); 680 }; 681 682 Drupal.webform.conditionalOperatorSelectGreaterThan = function (element, existingValue, ruleValue) { 683 var currentValue = Drupal.webform.stringValue(element, existingValue); 684 return Drupal.webform.compare_select(currentValue[0], ruleValue, element) > 0; 685 }; 686 687 Drupal.webform.conditionalOperatorSelectGreaterThanEqual = function (element, existingValue, ruleValue) { 688 var currentValue = Drupal.webform.stringValue(element, existingValue); 689 var comparison = Drupal.webform.compare_select(currentValue[0], ruleValue, element); 690 return comparison > 0 || comparison === 0; 691 }; 692 693 Drupal.webform.conditionalOperatorSelectLessThan = function (element, existingValue, ruleValue) { 694 var currentValue = Drupal.webform.stringValue(element, existingValue); 695 return Drupal.webform.compare_select(currentValue[0], ruleValue, element) < 0; 696 }; 697 698 Drupal.webform.conditionalOperatorSelectLessThanEqual = function (element, existingValue, ruleValue) { 699 var currentValue = Drupal.webform.stringValue(element, existingV
699alue); 700 var comparison = Drupal.webform.compare_select(currentValue[0], ruleValue, element); 701 return comparison < 0 || comparison === 0; 702 }; 703 704 Drupal.webform.conditionalOperatorNumericEqual = function (element, existingValue, ruleValue) { 705 // See float comparison: http://php.net/manual/en/language.types.float.php 706 var currentValue = Drupal.webform.stringValue(element, existingValue); 707 var epsilon = 0.000001; 708 // An empty string does not match any number. 709 return currentValue[0] === '' ? false : (Math.abs(parseFloat(currentValue[0]) - parseFloat(ruleValue)) < epsilon); 710 }; 711 712 Drupal.webform.conditionalOperatorNumericNotEqual = function (element, existingValue, ruleValue) { 713 // See float comparison: http://php.net/manual/en/language.types.float.php 714 var currentValue = Drupal.webform.stringValue(element, existingValue); 715 var epsilon = 0.000001; 716 // An empty string does not match any number. 717 return currentValue[0] === '' ? true : (Math.abs(parseFloat(currentValue[0]) - parseFloat(ruleValue)) >= epsilon); 718 }; 719 720 Drupal.webform.conditionalOperatorNumericGreaterThan = function (element, existingValue, ruleValue) { 721 var currentValue = Drupal.webform.stringValue(element, existingValue); 722 return parseFloat(currentValue[0]) > parseFloat(ruleValue); 723 }; 724 725 Drupal.webform.conditionalOperatorNumericGreaterThanEqual = function (element, existingValue, ruleValue) { 726 return Drupal.webform.conditionalOperatorNumericGreaterThan(element, existingValue, ruleValue) || 727 Drupal.webform.conditionalOperatorNumericEqual(element, existingValue, ruleValue); 728 }; 729 730 Drupal.webform.conditionalOperatorNumericLessThan = function (element, existingValue, ruleValue) { 731 var currentValue = Drupal.webform.stringValue(element, existingValue); 732 return parseFloat(currentValue[0]) < parseFloat(ruleValue); 733 }; 734 735 Drupal.webform.conditionalOperatorNumericLessThanEqual = function (element, existingValue, ruleValue) { 736 return Drupal.webform.conditionalOperatorNumericLessThan(element, existingValue, ruleValue) || 737 Drupal.webform.conditionalOperatorNumericEqual(element, existingValue, ruleValue); 738 }; 739 740 Drupal.webform.conditionalOperatorDateEqual = function (element, existingValue, ruleValue) { 741 var currentValue = Drupal.webform.dateValue(element, existingValue); 742 return currentValue === ruleValue; 743 }; 744 745 Drupal.webform.conditionalOperatorDateNotEqual = function (element, existingValue, ruleValue) { 746 return !Drupal.webform.conditionalOperatorDateEqual(element, existingValue, ruleValue); 747 }; 748 749 Drupal.webform.conditionalOperatorDateBefore = function (element, existingValue, ruleValue) { 750 var currentValue = Drupal.webform.dateValue(element, existingValue); 751 return (currentValue !== false) && currentValue < ruleValue; 752 }; 753 754 Drupal.webform.conditionalOperatorDateBeforeEqual = function (element, existingValue, ruleValue) { 755 var currentValue = Drupal.webform.dateValue(element, existingValue); 756 return (currentValue !== false) && (currentValue < ruleValue || currentValue === ruleValue); 757 }; 758 759 Drupal.webform.conditionalOperatorDateAfter = function (element, existingValue, ruleValue) { 760 var currentValue = Drupal.webform.dateValue(element, existingValue); 761 return (currentValue !== false) && currentValue > ruleValue; 762 }; 763 764 Drupal.webform.conditionalOperatorDateAfterEqual = function (element, existingValue, ruleValue) { 765 var currentValue = Drupal.webform.dateValue(element, existingValue); 766 return (currentValue !== false) && (currentValue > ruleValue || currentValue === ruleValue); 767 }; 768 769 Drupal.webform.conditionalOperatorTimeEqual = function (element, existingValue, ruleValue) { 770 var currentValue = Drupal.webform.timeValue(element, existingValue); 771 return currentValue === ruleValue; 772 }; 773 774 Drupal.webform.conditionalOperatorTimeNotEqual = function (element, existingValue, ruleValue) { 775 return !Drupal.webform.conditionalOperatorTimeEqual(element, existingValue, ruleValue); 776 }; 777 778 Drupal.webform.conditionalOperatorTimeBefore = function (element, existingV
778alue, ruleValue) { 779 // Date and time operators intentionally exclusive for "before". 780 var currentValue = Drupal.webform.timeValue(element, existingValue); 781 return (currentValue !== false) && (currentValue < ruleValue); 782 }; 783 784 Drupal.webform.conditionalOperatorTimeBeforeEqual = function (element, existingValue, ruleValue) { 785 // Date and time operators intentionally exclusive for "before". 786 var currentValue = Drupal.webform.timeValue(element, existingValue); 787 return (currentValue !== false) && (currentValue < ruleValue || currentValue === ruleValue); 788 }; 789 790 Drupal.webform.conditionalOperatorTimeAfter = function (element, existingValue, ruleValue) { 791 // Date and time operators intentionally inclusive for "after". 792 var currentValue = Drupal.webform.timeValue(element, existingValue); 793 return (currentValue !== false) && (currentValue > ruleValue); 794 }; 795 796 Drupal.webform.conditionalOperatorTimeAfterEqual = function (element, existingValue, ruleValue) { 797 // Date and time operators intentionally inclusive for "after". 798 var currentValue = Drupal.webform.timeValue(element, existingValue); 799 return (currentValue !== false) && (currentValue > ruleValue || currentValue === ruleValue); 800 }; 801 802 /** 803 * Utility function to compare values of a select component. 804 * 805 * @param string a 806 * First select option key to compare 807 * @param string b 808 * Second select option key to compare 809 * @param array options 810 * Associative array where the a and b are within the keys 811 * 812 * @return integer based upon position of $a and $b in $options 813 * -N if $a above (<) $b 814 * 0 if $a = $b 815 * +N if $a is below (>) $b 816 */ 817 Drupal.webform.compare_select = function (a, b, element) { 818 var optionList = []; 819 $('option,input:radio,input:checkbox', element).each(function () { 820 optionList.push($(this).val()); 821 }); 822 var a_position = optionList.indexOf(a); 823 var b_position = optionList.indexOf(b); 824 return (a_position < 0 || b_position < 0) ? null : a_position - b_position; 825 }; 826 827 /** 828 * Utility to return current visibility. 829 * 830 * Uses actual visibility, except for hidden components which use the applied 831 * disabled class. 832 */ 833 Drupal.webform.isVisible = function ($element) { 834 return $element.hasClass('webform-component-hidden') 835 ? !$element.find('input').first().hasClass('webform-conditional-disabled') 836 : $element.closest('.webform-conditional-hidden').length == 0; 837 }; 838 839 /** 840 * Function to get a string value from a select/radios/text/etc. field. 841 */ 842 Drupal.webform.stringValue = function (element, existingValue) { 843 var value = []; 844 if (element) { 845 var $element = $(element); 846 if (Drupal.webform.isVisible($element)) { 847 // Checkboxes and radios. 848 $element.find('input[type=checkbox]:checked,input[type=radio]:checked').each(function () { 849 value.push(this.value); 850 }); 851 // Select lists. 852 if (!value.length) { 853 var selectValue = $element.find('select').val(); 854 if (selectValue) { 855 if ($.isArray(selectValue)) { 856 value = selectValue; 857 } 858 else { 859 value.push(selectValue); 860 } 861 } 862 } 863 // Simple text fields. This check is done last so that the select list 864 // in select-or-other fields comes before the "other" text field. 865 if (!value.length) { 866 $element.find('input:not([type=checkbox],[type=radio]),textarea').each(function () { 867 value.push(this.value); 868 }); 869 } 870 } 871 } 872 else { 873 switch ($.type(existingValue)) { 874 case 'array':
875 value = existingValue; 876 break; 877 878 case 'string': 879 value.push(existingValue); 880 break; 881 } 882 } 883 return value; 884 }; 885 886 /** 887 * Utility function to calculate a second-based timestamp from a time field. 888 */ 889 Drupal.webform.dateValue = function (element, existingValue) { 890 var value = false; 891 if (element) { 892 var $element = $(element); 893 if (Drupal.webform.isVisible($element)) { 894 var day = $element.find('[name*=day]').val(); 895 var month = $element.find('[name*=month]').val(); 896 var year = $element.find('[name*=year]').val(); 897 // Months are 0 indexed in JavaScript. 898 if (month) { 899 month--; 900 } 901 if (year !== '' && month !== '' && day !== '') { 902 value = Date.UTC(year, month, day) / 1000; 903 } 904 } 905 } 906 else { 907 if ($.type(existingValue) === 'array' && existingValue.length) { 908 existingValue = existingValue[0]; 909 } 910 if ($.type(existingValue) === 'string') { 911 existingValue = existingV
911alue.split('-'); 912 } 913 if (existingValue.length === 3) { 914 value = Date.UTC(existingValue[0], existingValue[1], existingValue[2]) / 1000; 915 } 916 } 917 return value; 918 }; 919 920 /** 921 * Utility function to calculate a millisecond timestamp from a time field. 922 */ 923 Drupal.webform.timeValue = function (element, existingValue) { 924 var value = false; 925 if (element) { 926 var $element = $(element); 927 if (Drupal.webform.isVisible($element)) { 928 var hour = $element.find('[name*=hour]').val(); 929 var minute = $element.find('[name*=minute]').val(); 930 var ampm = $element.find('[name*=ampm]:checked').val(); 931 932 // Convert to integers if set. 933 hour = (hour === '') ? hour : parseInt(hour); 934 minute = (minute === '') ? minute : parseInt(minute); 935 936 if (hour !== '') { 937 hour = (hour < 12 && ampm == 'pm') ? hour + 12 : hour; 938 hour = (hour === 12 && ampm == 'am') ? 0 : hour; 939 } 940 if (hour !== '' && minute !== '') { 941 value = Date.UTC(1970, 0, 1, hour, minute) / 1000; 942 } 943 } 944 } 945 else { 946 if ($.type(existingValue) === 'array' && existingValue.length) {
947 existingValue = existingValue[0]; 948 } 949 if ($.type(existingValue) === 'string') { 950 existingValue = existingValue.split(':'); 951 } 952 if (existingValue.length >= 2) { 953 value = Date.UTC(1970, 0, 1, existingValue[0], existingValue[1]) / 1000; 954 } 955 } 956 return value; 957 }; 958 959 /** 960 * Make a prop shim for jQuery < 1.9. 961 */ 962 $.fn.webformProp = $.fn.webformProp || function (name, value) { 963 if (value) { 964 return $.fn.prop ? this.prop(name, true) : this.attr(name, true); 965 } 966 else { 967 return $.fn.prop ? this.prop(name, false) : this.removeAttr(name); 968 } 969 }; 970 971 /** 972 * Make a multi-valued val() function. 973 * 974 * This is for setting checkboxes, radios, and select elements. 975 */ 976 $.fn.webformVal = function (values) { 977 this.each(function () { 978 var $this = $(this); 979 var value = $this.val(); 980 var on = $.inArray($this.val(), values) != -1; 981 if (this.nodeName == 'OPTION') { 982 $this.webformProp('selected', on ? value : false); 983 } 984 else { 985 $this.val(on ? [value] : false); 986 } 987 }); 988 return this; 989 }; 990 991 /** 992 * Given a table's DOM element, restripe the odd/even classes. 993 */ 994 Drupal.webform.restripeTable = function (table) { 995 // :even and :odd are reversed because jQuery counts from 0 and 996 // we count from 1, so we're out of sync. 997 // Match immediate children of the parent element to allow nesting. 998 $('> tbody > tr, > tr', table) 999 .filter(':visible:odd').filter('.odd') 1000 .removeClass('odd').addClass('even') 1001 .end().end() 1002 .filter(':visible:even').filter('.even') 1003 .removeClass('even').addClass('odd'); 1004 }; 1005 1006})(jQuery); 1007;
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.