1/*! 2 * Monday Webforms for FirstSpirit v1.8.12.FS5, (c) 2018 Monday Consulting GmbH 3 * 4 * @see https://monday-webforms.com/ 5 */ 6 7;(function(factory) { 8 "use strict"; 9 if (typeof define === 'function' && define.amd) { 10 // AMD. Register as an anonymous module. 11 define(['jquery'], factory); 12 } else if (typeof exports === 'object' && typeof require === 'function') { 13 // Node/CommonJS 14 factory(require('jquery')); 15 } else { 16 // Browser globals 17 factory(jQuery); 18 } 19}(function($) { 20 "use strict"; 21 22 // polyfill for customevent for IE10 23 (function() { 24 if (typeof window.CustomEvent === "function") { 25 return false; 26 } 27 function CustomEvent(event, params) { 28 params = params || {bubbles: false, cancelable: false, detail: undefined}; 29 var evt = document.createEvent('CustomEvent'); 30 evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); 31 return evt; 32 } 33 34 CustomEvent.prototype = window.Event.prototype; 35 36 window.CustomEvent = CustomEvent; 37 })(); 38 39 var EVENTS = { 40 AJAX_FINISHED: "mwf-ajax-finished", 41 AJAX_ERROR: "mwf-ajax-error", 42 FILL_DROPDOWN: "mwf-fill-dropdown", 43 FILL_SELECTION: "mwf-fill-selection", 44 FILL_HIDDEN: "mwf-fill-hidden", 45 SUGGESTION_SELECTED: "mwf-suggestion-selected", 46 VALUE_CHANGED: "mwf-value-changed" 47 }, 48 49 globalSettings = {}, 50 initialXhrRequest; 51 52 function triggerEvent(el, eventName, options) { 53 var event; 54 if (window.CustomEvent) { 55 event = new CustomEvent(eventName, options); 56 } else { 57 event = document.createEvent('CustomEvent'); 58 event.initCustomEvent(eventName, true, true, options); 59 } 60 el.dispatchEvent(event); 61 } 62 63 function globalSettingsWithVariant(variant) { 64 return variant === undefined ? 65 globalSettings.def : $.extend(true, {}, globalSettings.def, globalSettings[variant]); 66 } 67 68 /** 69 * Monday Webforms jQuery-Plugin 70 * @constructor 71 */ 72 function Webforms(elem, settings) { 73 var 74 plugin = this, 75 $elem = $(elem), 76 operators = {}, 77 filenames = {}, 78 79 uiState = { 80 visible: {}, 81 hidden: {}, 82 writable: {}, 83 readonly: {}, 84 optional: {}, 85 mandatory: {}, 86 disabled: {}, 87 enabled: {} 88 }, 89 90 stateMapping = { 91 visible: 'hidden', 92 hidden: 'visible', 93 writable: 'readonly', 94 readonly: 'writable', 95 optional: 'mandatory', 96 mandatory: 'optional', 97 disabled: 'enabled', 98 enabled: 'disabled' 99 }, 100 101 $form = $elem.is('form') ? $elem : $elem.find("form"), 102 formId = $form.dataWithDefault('mwf-id', $form.data('mwf-form')), 103 targetUrl = $form.dataWithDefault('mwf-target', settings.url), 104 statisticsUrl = settings.statisticsUrl, 105 formdata = settings.formdata !== undefined ? settings.formdata : {}, 106 trimSpaces = settings.trimSpaces !== undefined ? settings.trimSpaces : true; 107 108 if (!statisticsUrl || 0 === statisticsUrl.length) { 109 statisticsUrl = null; 110 } 111 112 plugin.settings = settings; 113 114 /* internal utility functions 115 ----------------------------------------------------------------------------------------------------------- */ 116 117 function updateUI(fields, conditionId, cond) { 118 var s, i, inverseState, isTrue, isFalse, state, input, 119 120 conditionalFieldsState = { 121 'visible': [], 'hidden': [], 122 'writable': [], 'readonly': [], 123 'optional': [], 'mandatory': [], 124 'enabled': [], 'disabled': [] 125 }; 126 127 // clear UI state of this condition 128 for (s in uiState) { 129 if (uiState.hasOwnProperty(s)) { 130 delete uiState[s][conditionId]; 131 } 132 } 133 134 for (i = 0; i < fields.length; i++) { 135 input = fields[i].input; 136 state = fields[i].state; 137 138 if (cond) { 139 conditionalFieldsState[state].push(input); 140 } 141 142 uiState[state][conditionId] = conditionalFieldsState[state]; 143 144 inverseState = stateMapping[state]; 145 146 isTrue = containsState(state, input); 147 isFalse = containsState(inverseState, input); 148 149 if (isTrue) { 150 plugin.settings.operations[state]($form, fields[i]); 151 if (plugin.settings.onConditionTrue !== undefined) { 152 plugin.settings.onConditionTrue($form, fields[i], state); 153 } 154 } else if (isFalse || !isTrue) { 155 plugin.settings.operations[inverseState]($form, fields[i]); 156 if (plugin.settings.onConditionFalse !== undefined) { 157 plugin.settings.onConditionFalse($form, fields[i], inverseState); 158 } 159 } 160 } 161 } 162 163 function containsState(type, input) { 164 var state = uiState[type], cond; 165 for (cond in state) { 166 if (state.hasOwnProperty(cond) && $.inArray(input, state[cond]) > -1) { 167 return true; 168 } 169 } 170 return false;
171 } 172 173 function valueChanged($elem) { 174 if (!$elem.is(':file')) { 175 formdata = serializeForm($form); 176 $form.trigger("mwf-valuechange", $elem); 177 } 178 } 179 180 function startsWith(formValue, value) { 181 if (formValue == null || value == null) { 182 return false; 183 } 184 185 return RegExp("^" + value).test(formValue); 186 } 187 188 function serializeForm($form) { 189 var o = {}, a = $form.serializeArray(), form = $form.get(0); 190 191 $.each(a, function() { 192 var input = form.querySelector('[name="' + this.name + '"]'), 193 value = this.value || '', 194 type = input.getAttribute('type'), 195 key; 196 197 if (type === 'radio' || type === 'checkbox' || input.nodeName.toLowerCase() === 'select') { 198 199 if (!o.hasOwnProperty(this.name)) { 200 o[this.name] = []; 201 } 202 203 if (startsWith(value, '{')) { 204 try { 205 key = JSON.parse(value).k; 206 } catch (ex) { 207 // do nothing 208 } 209 } else if (value === 'EMPTY_VALUE') { 210 value = ''; 211 } 212 213 o[this.name].push((key !== undefined) ? key : value); 214 215 } else if (type === 'hidden') { 216 217 if (startsWith(value, '{')) { 218 try { 219 key = JSON.parse(value).v; 220 } catch (ex) { 221 // do nothing 222 } 223 } 224 225 o[this.name] = (key !== undefined) ? key : value; 226 } else { 227 o[this.name] = trimSpaces ? value.trim() : value; 228 } 229 }); 230 231 $.each(form.querySelectorAll('input[type="checkbox"]:not(:checked),input[type="radio"]:not(:checked)'), function() { 232 var name = this.getAttribute('name'); 233 if (!o.hasOwnProperty(name)) { 234 o[name] = ''; 235 } 236 }); 237 238 return o; 239 } 240 241 function valueLabel(name, v) { 242 var l = []; 243 244 $.each($form.find('[name="' + name + '"]'), function() { 245 var $input = $(this); 246 247 if ($input.is(':radio') || $input.is(':checkbox')) { 248 if ($.inArray($input.attr('data-mwf-value'), v) !== -1) { 249 l.push($input.attr('data-mwf-label')); 250 } 251 } else if ($input.is('select')) { 252 $.each($input.find('option'), function() { 253 var $option = $(this); 254 255 if ($.inArray($option.attr('data-mwf-value'), v) !== -1) { 256 l.push($option.attr('data-mwf-label')); 257 } 258 }); 259 } else if ($input.is(':file')) { 260 $.merge(l, filenames[name]); 261 } else { 262 l.push(v); 263 } 264 }); 265 266 return l; 267 } 268 269 /* API functions 270 ----------------------------------------------------------------------------------------------------------- */ 271 272 function maxSelected(array, max) { 273 var m = Number(max), l = (array !== null) ? array.length : 0; 274 return (l < m); 275 } 276 277 function minSelected(array, min) { 278 var m = Number(min), l = (array !== null) ? array.length : 0; 279 return (l > m); 280 } 281 282 function isSelected(array, s) { 283 return array != null && $.inArray(s, array) > -1; 284 } 285 286 function parseAge(format, str) { 287 if (str == null) { 288 return null; 289 } 290 var date = parseDate(format, str), today = new Date(); 291 return Math.floor((today - date) / (365.25 * 24 * 60 * 60 * 1000)); 292 } 293 294 function parseDate(format, date) { 295 if (date == null) { 296 return null; 297 } 298 return $.format.date(date, format); 299 } 300 301 function isEmptyList(array) { 302 var i, s; 303 if (array != null) { 304 for (i = 0; i < array.length; i++) { 305 s = String(array[i]); 306 if (s != null && s !== '' && s !== 'EMPTY_VALUE') { 307 return false;
308 } 309 } 310 } 311 return true; 312 } 313 314 function ajaxFillSelection($elem, attr) { 315 var data = $.extend(formdata, attr.data); 316 317 if ((attr.createEntry === undefined)) { 318 attr.createEntry = (attr.type === 'checkbox') ? plugin.settings.createCheckBox : plugin.settings.createRadio; 319 } 320 321 if ((attr.onFillSelection === undefined)) { 322 attr.onFillSelection = plugin.settings.onFillSelection; 323 } 324 325 $.ajax({ 326 url: attr.url, 327 type: 'POST', 328 data: data, 329 traditional: true, 330 cache: false, 331 xhrFields: { 332 withCredentials: true 333 } 334 }) 335 .done(function(json) { 336 var pre = attr.preselected.split(','), i, entry; 337 338 $elem.find('[data-mwf-mutable]').remove(); 339 340 for (i in json) { 341 if (json.hasOwnProperty(i)) { 342 entry = json[i];
343 $elem.append(attr.createEntry($form, attr.name, entry, $.inArray(entry.k, pre) !== -1)); 344 } 345 } 346 347 attr.onFillSelection($form, $elem); 348 triggerEvent(document, EVENTS.FILL_SELECTION, {detail: {$form: $form, $elem: $elem}}); 349 }) 350 .fail(function(jqXHR, textStatus, errorThrown) { 351 plugin.settings.onAjaxError(jqXHR, textStatus, errorThrown); 352 }); 353 } 354 355 function ajaxFillHidden($elem, attr) { 356 var data = $.extend(formdata, attr.data); 357 358 $.ajax({ 359 url: attr.url, 360 type: 'POST', 361 data: data, 362 traditional: true, 363 cache: false, 364 xhrFields: { 365 withCredentials: true 366 } 367 }) 368 .done(function(json) { 369 $elem.val(JSON.stringify(json)); 370 $elem.attr('data-mwf-value', json.v); 371 $elem.trigger('change'); 372 373 triggerEvent(document, EVENTS.FILL_HIDDEN, {detail: {$form: $form, $elem: $elem}}); 374 }) 375 .fail(function(jqXHR, textStatus, errorThrown) { 376 plugin.settings.onAjaxError(jqXHR, textStatus, errorThrown); 377 }); 378 } 379 380 function ajaxFillDropdown($elem, attr) { 381 var data = $.extend(formdata, attr.data); 382 383 if ((attr.createOption === undefined)) { 384 attr.createOption = plugin.settings.createOption; 385 } 386 387 if ((attr.onFillDropdown === undefined)) { 388 attr.onFillDropdown = plugin.settings.onFillDropdown; 389 } 390 391 $.ajax({ 392 url: attr.url, 393 type: 'POST', 394 data: data, 395 traditional: true, 396 cache: false, 397 xhrFields: { 398 withCredentials: true 399 } 400 }) 401 .done(function(json) { 402 var $option, i, entry, pre = attr.preselected.split(','); 403 404 $elem.find('[data-mwf-mutable]').remove(); 405 406 for (i in json) { 407 if (json.hasOwnProperty(i)) { 408 entry = json[i]; 409 $option = attr.createOption($form, entry, $.inArray(entry.k, pre) !== -1);
410 $elem.append($option); 411 } 412 } 413 414 attr.onFillDropdown($form, $elem); 415 416 triggerEvent(document, EVENTS.FILL_DROPDOWN, {detail: {$form: $form, $elem: $elem}}); 417 }) 418 .fail(function(jqXHR, textStatus, errorThrown) { 419 plugin.settings.onAjaxError(jqXHR, textStatus, errorThrown); 420 }); 421 } 422 423 function ajaxAutocomplete($elem, attr) { 424 var chars = 1; 425 426 if (attr.params.chars !== undefined) { 427 chars = attr.params.chars; 428 } 429 430 var onSelect = function(selection) { 431 valueChanged($elem); 432 triggerEvent(document, EVENTS.SUGGESTION_SELECTED, { 433 detail: { 434 $form: $form, 435 $elem: $elem, 436 id: formId, 437 selection: selection, 438 params: attr.params 439 } 440 }); 441 if ($.isFunction(attr.onSelect)) { 442 attr.onSelect(arguments); 443 } 444 }; 445 446 $elem.autocomplete({ 447 paramName: 'query', 448 params: attr.data, 449 serviceUrl: attr.url, 450 maxHeight: 150, 451 noCache: true, 452 minChars: chars, 453 type: 'POST', 454 onSelect: onSelect, 455 autoSelectFirst: true, 456 sendFormData: true, 457 458 transformResult: function(response) { 459 response = JSON.parse(response); 460 return { 461 suggestions: $.map(response, function(entry, key) { 462 return {value: entry.v, data: entry.k}; 463 }) 464 }; 465 } 466 }); 467 } 468 469 function ajaxSubmit(opt) { 470 var $buttons = $form.find(':button').filter(':not(:disabled)'), 471 data = {_parentUrl: window.location.href, _timezone: $.timezone()}; 472 473 if (plugin.settings.appendUrlVars) { 474 $.extend(data, $.getUrlVars(window.location.search)); 475 } 476 477 $.extend(data, $.getUrlVars(opt.query), opt.data, $form.serializeObject()); 478 479 if (opt.onSubmit !== undefined) { 480 if (!opt.onSubmit($form, opt.url, opt.query)) { 481 return; 482 } 483 } 484 485 $buttons.prop('disabled', true); 486 487 $.ajax({ 488 url: opt.url, 489 type: 'POST', 490 data: data, 491 traditional: true, 492 cache: false, 493 xhrFields: { 494 withCredentials: true 495 } 496 }) 497 .done(function(data, textStatus, jqXHR) { 498 499 if (jqXHR && jqXHR.getResponseHeader("X-Redirect-Location")) { 500 if (opt.onRedirect !== undefined) { 501 opt.onRedirect($form, data, textStatus, jqXHR); 502 } 503 var timeout = (jqXHR.getResponseHeader('X-Redirect-Delay') || 0) * 1000; 504 setTimeout(function() { 505 location.assign(jqXHR.getResponseHeader('X-Redirect-Location')); 506 }, timeout); 507 508 if (!timeout) { 509 return; 510 } 511 } 512 513 $elem = $elem.replaceWithPush(data); 514 $form = $elem.is('form') ? $elem : $elem.find("form"); 515 516 if (opt.onSuccess !== undefined) { 517 opt.onSuccess($form, data, textStatus, jqXHR); 518 } 519 520 triggerEvent(document, EVENTS.AJAX_FINISHED, {detail: {$dest: $elem}}); 521 }) 522 .fail(function(jqXHR, textStatus, errorThrown) { 523 if (opt.onError !== undefined) { 524 opt.onError($form, jqXHR, textStatus, errorThrown); 525 } 526 527 $buttons.prop('disabled', false); 528 triggerEvent(document, EVENTS.AJAX_ERROR, { 529 detail: { 530 $dest: $elem, 531 jqXHR: jqXHR, 532 textStatus: textStatus, 533 errorThrown: errorThrown 534 } 535 }) 536 }); 537 } 538 539 function createCondition(conditionId, conjunction, conditions, fields) { 540 var checkCondition = function() { 541 var all = true, any = false, condTrue, i, formValue, cond; 542 543 for (i = 0; i < conditions.length; i++) { 544 cond = conditions[i]; 545 546 if (!cond) { 547 continue; 548 } 549 550 formValue = formdata[cond[1]]; 551 552 if (formValue === undefined) { 553 formValue = cond[4]; 554 } 555 condTrue = operators[cond[2]](formValue, cond[3]); 556 557 if (condTrue) { 558 any = true; 559 } else { 560 all = false;
561 } 562 563 if (!conjunction && any) { 564 break; 565 } 566 } 567 568 updateUI(fields, conditionId, (all || (!conjunction && any))); 569 }; 570 571 // register event listener 572 $form.on('mwf-valuechange', function(e, input) { 573 var cond, i; 574 575 for (i = 0; i < conditions.length; i++) { 576 cond = conditions[i]; 577 578 if (!cond) { 579 continue; 580 } 581 582 if ($(input).attr("name") === conditions[i][1]) { 583 checkCondition(); 584 } 585 } 586 }); 587 588 // check conditions initially 589 checkCondition(); 590 591 if (plugin.settings.onConditionCreated !== undefined) { 592 plugin.settings.onConditionCreated($form, conditionId, conjunction, conditions, fields); 593 } 594 } 595 596 function createCalculatedValue(calcValueId, js, fields, formVariables, updateV
596alue) { 597 updateValue = (updateValue === undefined) ? plugin.settings.updateCalculatedValue : updateValue; 598 599 var name, 600 id = calcValueId, 601 vars = formVariables, 602 fct, 603 calculate = function() { 604 var state = $.extend({}, fields, formdata, vars), 605 result = fct(state), 606 $field = $form.find('[data-mwf-id="' + id + '"]'); 607 608 updateValue($form, id, result); 609 $field.val(result).trigger('change'); 610 }; 611 612 try { 613 eval('fct = function(s) {' + js + '}'); 614 } catch (ex) { 615 $.logError(ex.message); 616 } 617 618 // register event listener 619 $form.on('mwf-valuechange', function(e, input) { 620 for (name in fields) { 621 if (fields.hasOwnProperty(name) && $(input).attr('name') === name) { 622 calculate(); 623 break; 624 } 625 } 626 }); 627 } 628 629 /* condition operators 630 ----------------------------------------------------------------------------------------------------------- */ 631 632 operators.contains = function(formValue, value) { 633 if (formValue == null || value == null) { 634 return false; 635 } 636 return formValue.indexOf(value) !== -1; 637 }; 638 639 operators.containsnot = function(formValue, value) { 640 if (formValue == null || value == null) { 641 return false; 642 } 643 return formValue.indexOf(value) === -1; 644 }; 645 646 operators.startswith = function(formValue, value) { 647 return startsWith(formValue, value); 648 }; 649 650 operators.endswith = function(formValue, value) { 651 if (formValue == null || value == null) { 652 return false; 653 } 654 return RegExp(value + "$").test(formValue); 655 }; 656 657 operators.equal = function(formValue, value) { 658 if (formValue == null || value == null) { 659 return formValue === value; 660 } 661 var f1 = parseFloat(formValue.replace(',', '.')), 662 f2 = parseFloat(value.replace(',', '.')); 663 664 return (!isNaN(f1) && !isNaN(f2) && f1 === f2) || (formValue === value); 665 }; 666 667 operators.notequal = function(formValue, value) { 668 if (formValue == null || value == null) { 669 return formValue !== value; 670 } 671 var f1 = parseFloat(formValue.replace(',', '.')), 672 f2 = parseFloat(value.replace(',', '.')); 673 674 return (!isNaN(f1) && !isNaN(f2) && f1 !== f2) || (formValue !== value); 675 }; 676 677 operators.empty = function(formValue, value) { 678 return formValue == null || formValue === ''; 679 }; 680 681 operators.notempty = function(formValue, value) { 682 return formValue != null && formValue !== ''; 683 }; 684 685 operators.emptylist = function(formValue, value) { 686 return isEmptyList(formValue); 687 }; 688 689 operators.notemptylist = function(formValue, value) { 690 return !isEmptyList(formValue); 691 }; 692 693 operators.selected = function(formValue, value) { 694 if (formValue == null || value == null) { 695 return false; 696 } 697 return $.inArray(value, formValue) !== -1; 698 }; 699 700 operators.notselected = function(formValue, value) { 701 if (formValue == null || value == null) { 702 return false; 703 } 704 return $.inArray(value, formValue) === -1; 705 }; 706 707 operators.minselected = function(formValue, value) { 708 var l = (formValue == null) ? 0 : formValue.length; 709 return l > Number(value); 710 }; 711 712 operators.maxselected = function(formValue, value) { 713 var l = (formValue == null) ? 0 : formValue.length; 714 return l < Number(value); 715 }; 716 717 operators.lessthan = function(formValue, value) { 718 if (formValue == null || value == null) { 719 return false;
720 } 721 var f1 = parseFloat(formValue.replace(',', '.')), 722 f2 = parseFloat(value.replace(',', '.')); 723 724 return (!isNaN(f1) && !isNaN(f2) && f1 < f2); 725 }; 726 727 operators.greaterthan = function(formValue, value) { 728 if (formValue == null || value == null) { 729 return false; 730 } 731 var f1 = parseFloat(formValue.replace(',', '.')), 732 f2 = parseFloat(value.replace(',', '.')); 733 734 return (!isNaN(f1) && !isNaN(f2) && f1 > f2); 735 }; 736 737 /* public methods 738 ----------------------------------------------------------------------------------------------------------- */ 739 740 plugin.formSubmit = function(opt) { 741 ajaxSubmit({ 742 url: targetUrl, 743 id: formId, 744 query: (opt.query !== undefined) ? opt.query : '', 745 onSubmit: (opt.submit !== undefined) ? opt.submit : plugin.settings.onSubmit, 746 onSuccess: (opt.success !== undefined) ? opt.success : plugin.settings.onSuccess, 747 onError: (opt.error !== undefined) ? opt.error : plugin.settings.onAjaxError, 748 onRedirect: (opt.redirect !== undefined) ? opt.redirect : plugin.settings.onRedirect 749 }); 750 }; 751 752 plugin.gotoPage = function(opt) { 753 ajaxSubmit({ 754 url: targetUrl, 755 id: formId, 756 query: opt.query.concat('&_target', opt.page, '=', opt.page), 757 onSubmit: (opt.submit !== undefined) ? opt.submit : plugin.settings.onSubmit, 758 onSuccess: (opt.success !== undefined) ? opt.success : plugin.settings.onSuccess, 759 onError: (opt.error !== undefined) ? opt.error : plugin.settings.onAjaxError, 760 onRedirect: (opt.redirect !== undefined) ? opt.redirect : plugin.settings.onRedirect 761 }); 762 }; 763 764 plugin.init = function() { 765 $form.find('input').keydown(function(e) { 766 if (e.keyCode === 13) { 767 e.preventDefault(); 768 return false; 769 } 770 }); 771 772 $form.on('change', function(event) { 773 valueChanged($(event.target)); 774 775 if (statisticsUrl !== null) { 776 $.ajax({ 777 url: statisticsUrl, 778 xhrFields: { 779 withCredentials: true 780 } 781 }); 782 statisticsUrl = null; 783 } 784 }); 785 786 if (targetUrl === undefined) { 787 $.logError('No target URL specified.') 788 } 789 790 $.each($form.find('[data-mwf-submit]'), function() { 791 var attr = $(this).data('mwf-submit'), 792 query = (attr.query !== undefined) ? attr.query : '', 793 onSuccess = (attr.success !== undefined) ? attr.success : plugin.settings.onSuccess, 794 onRedirect = (attr.redirect !== undefined) ? attr.redirect : plugin.settings.onRedirect, 795 onError = (attr.error !== undefined) ? attr.error : plugin.settings.onAjaxError, 796 onSubmit = (attr.submit !== undefined) ? attr.submit : plugin.settings.onSubmit; 797 798 switch (attr.type) { 799 case 'next': 800 case 'back': 801 case 'goto': 802 query = query.concat('&_target', attr.page, '=', attr.page); 803 break; 804 805 case 'cancel': 806 case 'exit': 807 case 'finish': 808 query = query.concat('&_', attr.type, '=1'); 809 break; 810 } 811 812 $(this).on('click', function() { 813 ajaxSubmit({ 814 url: targetUrl, 815 id: formId, 816 query: query, 817 onSubmit: onSubmit, 818 onSuccess: onSuccess, 819 onError: onError, 820 onRedirect: onRedirect 821 }); 822 }); 823 }); 824 825 $.each($form.find('[data-mwf-bind]'), function() { 826 var name = $(this).data('mwf-bind'), 827 $elem = $(this); 828 829 $form.on('mwf-valuechange', function(e, input) { 830 var v, l; 831 832 if ($(input).attr('name') === name) { 833 v = formdata[name]; 834 l = valueLabel(name, v); 835 836 plugin.settings.updateFormValue($form, $elem, name, l); 837 triggerEvent(document, EVENTS.VALUE_CHANGED, { 838 detail: { 839 $form: $form, 840 $elem: $elem, 841 name: name, 842 value: l 843 } 844 }); 845 return false;
846 } 847 }); 848 }); 849 850 $.each($form.find('[data-mwf-fileupload]'), function() { 851 var $upload = $(this), 852 attr = $(this).data('mwf-fileupload'), 853 $dropzone = $upload.find('[data-mwf-dropzone]'), 854 $files = $upload.find('[data-mwf-files]'), 855 $fileInput = $upload.find('input:file'), 856 multiple = $fileInput.attr('multiple') !== undefined, 857 useXhr = (!multiple && $.support.xhrFileUpload) || $.support.xhrFormDataFileUpload, 858 count = 0, 859 pendingList = [], 860 errorRows = [], 861 enabled = true, 862 $buttons = null; 863 864 $upload.find('[data-mwf-file-upload-all]').on('click', function() { 865 pendingList.forEach(function(data) { 866 data.submit(); 867 }); 868 pendingList = []; 869 }); 870 871 $upload.find('[data-mwf-file-delete-all]').on('click', function() { 872 $files.find('[data-mwf-file-delete]').trigger('click'); 873 pendingList = []; 874 }); 875 876 $upload.on('disable', function() { 877 enabled = false; 878 $upload.fileupload('disable'); 879 $upload.addClass('mwf-upload-disabled'); 880 $upload.find(':button').prop('disabled', true); 881 $fileInput.prop('disabled', true); 882 }); 883 884 $upload.on('enable', function() { 885 enabled = true; 886 $upload.fileupload('enable'); 887 $upload.removeClass('mwf-upload-disabled'); 888 $upload.find(':button').prop('disabled', false); 889 $fileInput.prop('disabled', false); 890 }); 891 892 $dropzone.on('dragover', function() { 893 if (enabled) { 894 $(this).addClass('mwf-upload-dragover'); 895 } 896 }); 897 898 $dropzone.on('dragleave drop', function() { 899 $(this).removeClass('mwf-upload-dragover'); 900 }); 901 902 $upload.fileupload({ 903 url: attr.url, 904 paramName: attr.name, 905 dataType: 'json', 906 dropZone: $dropzone, 907 fileInput: $fileInput, 908 previewMaxWidth: attr.previewMaxWidth, 909 previewMaxHeight: attr.previewMaxHeight, 910 previewCrop: true, 911 maxNumberOfFiles: 1, 912 formData: {xhr: useXhr}, 913 xhrFields: { 914 withCredentials: true 915 }, 916 917 add: function(e, data) { 918 var $this = $upload; 919 920 if (!enabled) { 921 return false; 922 } 923 924 $.each(errorRows, function(index, $row) { 925 $row.remove(); 926 }); 927 928 if (multiple || count === 0) { 929 count++; 930 } else { 931 return false; 932 } 933 934 pendingList.push(data); 935 936 data.process(function() { 937 return $this.fileupload('process', data); 938 }).always(function() { 939 $.each(data.files, function(index, file) { 940 var $row = plugin.settings.createUploadFileRow($form, attr, file); 941 data.context = $row; 942 943 $row.find('[data-mwf-file-upload]').data(data).on('click', function() { 944 pendingList.splice($.inArray(data, pendingList), 1); 945 data.submit(); 946 }); 947 948 $row.find('[data-mwf-file-delete]').data(data).on('click', function() { 949 $row.remove(); 950 pendingList.splice($.inArray(data, pendingList), 1); 951 count--; 952 }); 953 954 $row.find('[data-mwf-file-preview]').append(file.preview); 955 956 $files.append($row); 957 }); 958 959 if (attr.autoUpload === true) { 960 data.submit(); 961 } 962 }); 963 }, 964 965 submit: function(e, data) { 966 if ($buttons === null) { 967 $buttons = $form.find(':button').filter(':not(:disabled)'); 968 $buttons.prop('disabled', true); 969 } 970 }, 971 972 progress: function(e, data) { 973 var progress = parseInt(data.loaded / data.total * 100, 10); 974 if (data.context) { 975 data.context.each(function() { 976 data.context.find('[data-mwf-file-progress]').attr('aria-valuenow', progress).css('display', 'block').children().first().css('width', progress + '%').text(progress + '%'); 977 }); 978 } 979 }, 980 981 done: function(e, data) { 982 var files = (typeof data.result === 'string') ? JSON.parse(data.result).files : data.result.files; 983 984 $.each(files, function(index, file) { 985 var $row = plugin.settings.createDownloadFileRow($form, attr, file); 986 987 if (data.context !== undefined) { 988 data.context.replaceWith($row) 989 } else { 990 $files.append($row); 991 } 992 993 if (file.error === undefined) { 994 $row.find('[data-mwf-file-delete]').on('click', function() { 995 if (file.delete_url) { 996 $.ajax({ 997 url: file.delete_url, 998 xhrFields: { 999 withCredentials: true 1000 } 1001 }); 1002 } 1003 $row.remove(); 1004 pendingList.splice($.inArray(data, pendingList), 1); 1005 1006 // update filenames 1007 if (filenames.hasOwnProperty(attr.name)) { 1008 filenames[attr.name].splice($.inArray(file.name, filenames[attr.name]), 1
1008); 1009 $form.trigger("mwf-valuechange", data.fileInput); 1010 } 1011 1012 count--; 1013 }); 1014 1015 // update filenames 1016 if (!filenames.hasOwnProperty(attr.name)) { 1017 filenames[attr.name] = []; 1018 } 1019 1020 filenames[attr.name].push(file.name); 1021 $form.trigger("mwf-valuechange", data.fileInput); 1022 1023 } else { 1024 $row.find('[data-mwf-file-delete]').on('click', function() { 1025 $row.remove(); 1026 pendingList.splice($.inArray(data, pendingList), 1); 1027 }); 1028 1029 errorRows.push($row); 1030 count--; 1031 } 1032 }); 1033 }, 1034 1035 fail: function(e, data) { 1036 $.each(data.files, function(index, file) { 1037 var $row = plugin.settings.createDownloadFileRow($form, attr, { 1038 name: file.name, 1039 size: file.size, 1040 error: attr.labels.error 1041 }); 1042 1043 $row.find('[data-mwf-file-delete]').data(data).on('click', function() { 1044 $row.remove(); 1045 pendingList.splice($.inArray(data, pendingList), 1); 1046 }); 1047 1048 errorRows.push($row); 1049 count--; 1050 1051 if (data.context !== undefined) { 1052 data.context.replaceWith($row) 1053 } else { 1054 $files.append($row); 1055 } 1056 }); 1057 }, 1058 1059 always: function(e, data) { 1060 if ($buttons !== null && $upload.fileupload('active') === 1) { 1061 $buttons.prop('disabled', false); 1062 $buttons = null; 1063 } 1064 } 1065 }); 1066 1067 // preload existing files 1068 $.ajax({ 1069 url: attr.url, 1070 dataType: "json", 1071 data: {_name: attr.name, _do: 'files'}, 1072 xhrFields: { 1073 withCredentials: true 1074 } 1075 }).done(function(result) { 1076 $upload.fileupload('option', 'done').call($upload, $.Event('done'), {result: result}); 1077 count = result.files.length; 1078 }); 1079 }); 1080 1081 $.each($form.find('[data-mwf-datasource]'), function() { 1082 var def = { 1083 params: {}, 1084 data: {} 1085 }, 1086 attr = $.extend(true, {}, def, $(this).data('mwf-datasource')), 1087 $elem = $(this); 1088 1089 switch (attr.type) { 1090 case 'checkbox': 1091 case 'radio': 1092 ajaxFillSelection($elem, attr); 1093 1094 $form.on('mwf-valuechange', function(e, input) { 1095 if ($.trim(attr.params.dependsOn)) { 1096 $.each(attr.params.dependsOn.split(','), function(i, v) { 1097 if ($(input).attr('name') === v) { 1098 ajaxFillSelection($elem, attr); 1099 return false; 1100 } 1101 }); 1102 } 1103 }); 1104 break; 1105 case 'selection': 1106 ajaxFillDropdown($elem, attr); 1107 1108 $form.on('mwf-valuechange', function(e, input) { 1109 if ($.trim(attr.params.dependsOn)) { 1110 $.each(attr.params.dependsOn.split(','), function(i, v) { 1111 if ($(input).attr('name') === v) { 1112 ajaxFillDropdown($elem, attr); 1113 return false;
1114 } 1115 }); 1116 } 1117 }); 1118 break; 1119 case 'suggestion': 1120 ajaxAutocomplete($elem, attr); 1121 break; 1122 case 'hidden': 1123 ajaxFillHidden($elem, attr); 1124 1125 $form.on('mwf-valuechange', function(e, input) { 1126 if ($.trim(attr.params.dependsOn)) { 1127 $.each(attr.params.dependsOn.split(','), function(i, v) { 1128 if ($(input).attr('name') === v) { 1129 ajaxFillHidden($elem, attr); 1130 return false; 1131 } 1132 }); 1133 } 1134 }); 1135 break; 1136 default: 1137 $.logError(attr.type === undefined ? 1138 'Please specifiy the datasource type (checkbox, radio, selection or suggestion).' : 1139 'Unknown datasource type "'.concat(attr.type, '".')); 1140 } 1141 }); 1142 1143 $.each(plugin.settings.conditions, function() { 1144 createCondition($(this).attr('id'), $(this).attr('conjunction'), $(this).attr('conditions'), $(this).attr('fields')); 1145 }); 1146 1147 $.each(plugin.settings.calculatedValues, function() { 1148 createCalculatedValue($(this).attr('id'), $(this).attr('js'), $(this).attr('fields'), $(this).attr('vars')); 1149 }); 1150 1151 plugin.settings.onInit($form); 1152 }; 1153 1154 plugin.init(); 1155 } 1156 1157 /* default plugin settings 1158 ----------------------------------------------------------------------------------------------------------- */ 1159 1160 globalSettings.def = { 1161 appendUrlVars: false, 1162 operations: {}, 1163 conditions: [], 1164 calculatedValues: [], 1165 fileuploadOptions: {}, 1166 onConditionTrue: undefined, 1167 onConditionFalse: undefined, 1168 statisticsUrl: null 1169 }; 1170 1171 globalSettings.def.operations['visible'] = function($form, field) { 1172 var $field = $form.find('[data-mwf-container="' + field.input + '"]'); 1173 $field.removeAttr('disabled'); 1174 $field.removeClass('mwf-hidden'); 1175 }; 1176 1177 globalSettings.def.operations['hidden'] = function($form, field) { 1178 var $field = $form.find('[data-mwf-container="' + field.input + '"]'); 1179 $field.attr("disabled", "true"); 1180 $field.addClass('mwf-hidden'); 1181 }; 1182 1183 globalSettings.def.operations['writable'] = function($form, field) { 1184 var $field = $form.find('[data-mwf-id="' + field.input + '"]'); 1185 $field.removeAttr('readonly'); 1186 }; 1187 1188 globalSettings.def.operations['readonly'] = function($form, field) { 1189 var $field = $form.find('[data-mwf-id="' + field.input + '"]'); 1190 $field.val(field.value); 1191 $field.attr("readonly", "true"); 1192 }; 1193
1194 globalSettings.def.operations['enabled'] = function($form, field) { 1195 var $field = $form.find('[data-mwf-id="' + field.input + '"]'); 1196 $field.removeAttr('disabled'); 1197 $field.trigger('enable'); 1198 }; 1199 1200 globalSettings.def.operations['disabled'] = function($form, field) { 1201 var $field = $form.find('[data-mwf-id="' + field.input + '"]'); 1202 $field.attr("disabled", "true"); 1203 $field.trigger('disable'); 1204 }; 1205 1206 globalSettings.def.operations['optional'] = function($form, field) { 1207 var $label = $form.find('label[for="' + field.input + '"]'); 1208 $label.children('span.mwf-required').remove(); 1209 }; 1210 1211 globalSettings.def.operations['mandatory'] = function($form, field) { 1212 var $label = $form.find('label[for="' + field.input + '"]'), 1213 $span = $('<span></span>').attr('class', 'mwf-required').text('*'); 1214 $label.children('span.mwf-required').remove(); 1215 $label.append($span); 1216 }; 1217 1218 globalSettings.def.createOption = function($form, entry, selected) { 1219 var $option = $('<option></option>') 1220 .attr('data-mwf-value', entry.k) 1221 .attr('data-mwf-label', entry.v) 1222 .attr('data-mwf-mutable', '') 1223 .attr('value', JSON.stringify(entry)) 1224 .append(entry.v); 1225 1226 if (selected) { 1227 $option.attr('selected', true); 1228 } 1229 return $option; 1230 }; 1231 1232 globalSettings.def.createRadio = function($form, name, entry, checked) { 1233 var $span, $input, $label; 1234 1235 $span = $('<span></span>') 1236 .attr('class', 'mwf-option') 1237 .attr('data-mwf-mutable', ''); 1238 1239 $input = $('<input/>') 1240 .attr('type', 'radio') 1241 .attr('id', entry.i) 1242 .attr('data-mwf-id', entry.i) 1243 .attr('data-mwf-value', entry.k) 1244 .attr('data-mwf-label', entry.v) 1245 .attr('value', JSON.stringify(entry)) 1246 .attr('name', name) 1247 .attr('class', 'mwf-radio'); 1248 1249 if (checked) { 1250 $input.attr('checked', 'checked'); 1251 } 1252 1253 $label = $('<label></label>') 1254 .attr('for', entry.i).append(entry.v); 1255 1256 $span.append($input); 1257 $span.append(' '); 1258 $span.append($label); 1259 1260 return $span; 1261 }; 1262 1263 globalSettings.def.createCheckBox = function($form, name, entry, checked) { 1264 var $span, $input, $label; 1265 1266 $span = $('<span></span>') 1267 .attr('class', 'mwf-option') 1268 .attr('data-mwf-mutable', ''); 1269 1270 $input = $('<input/>') 1271 .attr('type', 'checkbox') 1272 .attr('id', entry.i) 1273 .attr('data-mwf-id', entry.i) 1274 .attr('data-mwf-value', entry.k) 1275 .attr('data-mwf-label', entry.v) 1276 .attr('value', JSON.stringify(entry)) 1277 .attr('name', name) 1278 .attr('class', 'mwf-checkbox'); 1279 1280 if (checked) { 1281 $input.attr('checked', 'checked'); 1282 } 1283 1284 $label = $('<label></label>') 1285 .attr('for', entry.i).append(entry.v); 1286 1287 $span.append($input); 1288 $span.append(' '); 1289 $span.append($label); 1290 1291 return $span; 1292 }; 1293 1294 globalSettings.def.updateFormValue = function($form, $elem, name, v) { 1295 $elem.html($.isArray(v) ? v.join(', ') : v); 1296 }; 1297 1298 globalSettings.def.createUploadFileRow = function($form, attr, file) { 1299 1300 var $row, $fileinfo, $meta, $preview, $ul, $name, $size, $buttons, $upload, $delete, $span, $progress, $error; 1301 1302 $row = $('<div/>').attr('data-mwf-file', '').attr('class', 'mwf-upload-row'); 1303 1304 $fileinfo = $('<div/>').attr('class', 'mwf-upload-fileinfo'); 1305 1306 $preview = $('<div/>').attr('data-mwf-file-preview', '').attr('class', 'mwf-upload-preview'); 1307 1308 $meta = $('<div/>').attr('class', 'mwf-upload-metadata'); 1309 1310 $ul = $('<ul/>'); 1311 1312 $name = $('<li>').text(attr.labels.name + ': ' + file.name); 1313 1314 $size = $('<li>').text(attr.labels.size + ': ' + $.formatSize(file.size)); 1315 1316 $buttons = $('<div/>').attr('class', ' mwf-upload-actions'); 1317 1318 $upload = $('<button>').attr('data-mwf-file-upload', '').attr('class', 'mwf-upload-upload').text(attr.labels.upload); 1319 1320 $delete = $('<button>').attr('data-mwf-file-delete', '').attr('class', 'mwf-upload-delete').text(attr.labels.del); 1321 1322 $span = $('<span>').css('width', '0%'); 1323 1324 $progress = $('<div/>').attr('data-mwf-file-progress', '').attr('class', 'mwf-upload-progressbar'); 1325 1326 $error = $('<div/>').attr('data-mwf-file-error', '').attr('class', 'mwf-upload-error'); 1327 1328 $buttons.append($delete); 1329 1330 if (attr.autoUpload === false) { 1331 $buttons.append($upload); 1332 } 1333 1334 $ul.append($name); 1335 $ul.append($size); 1336 $meta.append($ul); 1337 $fileinfo.append($preview); 1338 $fileinfo.append($meta); 1339 $progress.append($span); 1340 $row.append($fileinfo); 1341 $row.append($buttons); 1342 $row.append($error); 1343 $row.append($progress); 1344 1345 return $row; 1346 }; 1347 1348 globalSettings.def.createDownloadFileRow = function($form, attr, file) { 1349 1350 var $row, $fileinfo, $meta, $preview, $image, $ul, $name, $size, $buttons, $delete, $span, $error; 1351 1352 $row = $('<div/>').attr('data-mwf-file', '').attr('class', 'mwf-upload-row'); 1353 1354 $fileinfo = $('<div/>').attr('class', 'mwf-upload-fileinfo'); 1355 1356 $preview = $('<div/>').attr('data-mwf-preview', '').attr('class', 'mwf-upload-preview'); 1357 1358 $meta = $('<div/>').attr('class', 'mwf-upload-metadata'); 1359 1360 $ul = $('<ul/>'); 1361 1362 $name = $('<li>').text(attr.labels.name + ': ' + file.name); 1363 1364 $size = $('<li>').text(attr.labels.size + ': ' + $.formatSize(file.size)); 1365 1366 $buttons = $('<div/>').attr('class', ' mwf-upload-actions'); 1367 1368 $delete = $('<button>').attr('data-mwf-file-delete', '').attr('class', 'mwf-upload-delete').text(attr.labels.del); 1369 1370 $buttons.append($delete); 1371 $ul.append($name); 1372 $ul.append($size); 1373 $meta.append($ul); 1374 1375 if (file.thumbnail_url) { 1376 $image = $('<img/>').attr('src', file.thumbnail_url); 1377 $preview.append($image); 1378 } 1379 1380 $fileinfo.append($preview); 1381 $fileinfo.append($meta); 1382 $row.append($fileinfo); 1383 $row.append($buttons); 1384 1385 if (file.error) { 1386 $error = $('<div/>').attr('data-mwf-file-error', '').attr('class', 'mwf-upload-error'); 1387 $span = $('<span>').text(file.error); 1388 $error.append($span); 1389 $row.append($error); 1390 } 1391 1392 return $row; 1393 }; 1394 1395 globalSettings.def.updateCalculatedValue = function($form, id, value) { 1396 $form.find('[data-mwf-value="' + id + '"]').text(value).html(); 1397 }; 1398 1399 globalSettings.def.onAjaxError = function(jqXHR, status, error) { 1400 $.logError(jqXHR.responseText); 1401 }; 1402 1403 globalSettings.def.onSubmit = function($form, url, query) { 1404 return true; 1405 }; 1406 1407 globalSettings.def.onConditionCreated = function($form, conditionId, conjunction, conditions, fields) { 1408 // do nothing 1409 }; 1410 1411 globalSettings.def.onFillDropdown = function($form, $elem) { 1412 // do nothing 1413 }; 1414 1415 globalSettings.def.onFillSelection = function($form, $elem) { 1416 // do nothing 1417 }; 1418 1419 globalSettings.def.onInit = function($form) { 1420 // do nothing 1421 }; 1422 1423 1424 /* plugin related jQuery functions 1425 --------------------------------------------------------------------------------------------------------------- */ 1426 1427 $.fn.webforms = function(opt) {
1428 var dataKey = 'webforms', $this = $(this), s; 1429 1430 s = { 1431 id: $this.data('mwf-id'), 1432 type: 'GET', 1433 appendUrlVars: false 1434 }; 1435 1436 $.extend(true, s, globalSettingsWithVariant(opt.variant), opt); 1437 1438 if ($this.is('form') || $this.find('form').length > 0) { 1439 return $this.each(function() { 1440 var instance = $this.data(dataKey); 1441 1442 if (instance && instance.dispose) { 1443 instance.dispose(); 1444 } 1445 1446 instance = new Webforms($this, s); 1447 $this.data(dataKey, instance); 1448 }); 1449 } else { 1450 s.selector = $this; 1451 $.mwfAjaxReplace(s); 1452 } 1453 }; 1454 1455 $.fn.webforms.settings = function(variant) { 1456 if (variant === undefined) { 1457 return globalSettings.def; 1458 } else { 1459 if (globalSettings[variant] === undefined) { 1460 globalSettings[variant] = {}; 1461 } 1462 return globalSettings[variant]; 1463 } 1464 }; 1465 1466 /* deprecated: Use $.fn.webforms.settings instead. */ 1467 $.fn.webforms.defaults = $.fn.webforms.settings; 1468 1469 /* general jQuery utility functions 1470 --------------------------------------------------------------------------------------------------------------- */ 1471 1472 $.fn.replaceWithPush = function(elem) { 1473 var $elem = $(elem); 1474 this.replaceWith($elem); 1475 return $elem; 1476 }; 1477 1478 $.fn.dataWithDefault = function(key, def) { 1479 var value = this.data(key); 1480 return (value !== undefined) ? value : def; 1481 }; 1482 1483 if (typeof $.fn.serializeObject === 'undefined') { 1484 $.fn.serializeObject = function() { 1485 var o = {}, a = this.serializeArray(); 1486 $.each(a, function() { 1487 if (o[this.name] !== undefined) { 1488 if (!o[this.name].push) { 1489 o[this.name] = [o[this.name]]; 1490 } 1491 o[this.name].push(this.value || ''); 1492 } else { 1493 o[this.name] = this.value || ''; 1494 } 1495 }); 1496 return o; 1497 }; 1498 } 1499 1500 if (typeof $.logError === 'undefined') { 1501 $.extend({ 1502 logError: function(msg) { 1503 try { 1504 if (msg !== undefined && typeof window.console !== 'undefined') { 1505 console.error(msg); 1506 } 1507 } catch (ex) { 1508 } 1509 } 1510 }); 1511 } 1512 1513 $.extend({ 1514 mwfAjaxReplace: function(opt) { 1515 var $dest = $(opt.selector), optinId, s, performAjaxRequest, 1516 data = {_parentUrl: window.location.href, _timezone: $.timezone()}; 1517 1518 if ($dest.length > 0) { 1519 optinId = $.getOptinIdFromHash(opt.uid); 1520 1521 if (optinId !== null) { 1522 data._optinId = optinId; 1523 1524 if (typeof history.replaceState !== 'undefined') { 1525 history.replaceState({}, document.title, window.location.pathname); 1526 } else { 1527 window.location.hash = ''; 1528 } 1529 1530 $('html, body').animate({ 1531 scrollTop: $dest.offset().top 1532 }); 1533 } 1534 1535 s = { 1536 url: null, 1537 type: 'POST', 1538 appendUrlVars: false 1539 }; 1540 1541 // Create the final settings object 1542 $.extend(s, opt); 1543 1544 if (s.appendUrlVars) { 1545 $.extend(data, $.getUrlVars(window.location.search)); 1546 } 1547 1548 $.extend(data, $.getUrlVars(s.query), opt.data); 1549 1550 performAjaxRequest = function() { 1551 return $.ajax({ 1552 url: s.url, 1553 type: s.type, 1554 data: data, 1555 traditional: true, 1556 cache: false, 1557 xhrFields: { 1558 withCredentials: true 1559 } 1560 }) 1561 .done(function(innerData, textStatus, jqXHR) { 1562 if (jqXHR && jqXHR.getResponseHeader("X-Redirect-Location")) { 1563 location.assign(jqXHR.getResponseHeader("X-Redirect-Location")); 1564 return; 1565 } 1566 1567 $dest = $dest.replaceWithPush(innerData); 1568 if (s.onSuccess !== undefined) { 1569 s.onSuccess(innerData, textStatus, jqXHR); 1570 } 1571 triggerEvent(document, EVENTS.AJAX_FINISHED, {detail: {$dest: $dest}}); 1572 }) 1573 .fail(function(jqXHR, textStatus, errorThrown) { 1574 if (s.onError !== undefined) { 1575 s.onError(jqXHR, textStatus, errorThrown); 1576 } else { 1577 $.logError(jqXHR.responseText); 1578 } 1579 1580 triggerEvent(document, EVENTS.AJAX_ERROR, { 1581 detail: { 1582 $dest: $dest, 1583 jqXHR: jqXHR, 1584 textStatus: textStatus, 1585 errorThrown: errorThrown 1586 } 1587 }); 1588 }) 1589 }; 1590 1591 if (initialXhrRequest === undefined) { 1592 // The first request may be performed instantaneously 1593 initialXhrRequest = performAjaxRequest(); 1594 } else { 1595 // Following requests have to wait for the termination of the first request. 1596 // This prevents the creation of multiple sessions on pages with more than one form. 1597 $.when(initialXhrRequest).always(performAjaxRequest); 1598 } 1599 } 1600 }, 1601 1602 getUrlVars: function(url) { 1603 var params = {}, i, param, pos, key, value, length; 1604 1605 if (typeof url === "string" && url.length > 0) { 1606 if (url[0] === '?') { 1607 url = url.substring(1); 1608 } 1609 1610 url = url.split('&'); 1611 1612 for (i = 0, length = url.length; i < length; i++) { 1613 if (!url[i] || 0 === url[i].length) { 1614 continue; 1615 } 1616 1617 param = url[i]; 1618 pos = param.indexOf('='); 1619 1620 if (pos >= 0) { 1621 key = param.substr(0, pos); 1622 value = param.substr(pos + 1); 1623 } else { 1624 key = param; 1625 value = ''; 1626 } 1627 1628 value = decodeURIComponent(value); 1629 1630 if (params[key] === undefined) { 1631 params[key] = value; 1632 } else if (params[key] instanceof Array) { 1633 params[key].push(value); 1634 } else { 1635 params[key] = [params[key], value]; 1636 } 1637 } 1638 } 1639 1640 return params; 1641 }, 1642 1643 getUrlVar: function(url, name) { 1644 return $.getUrlVars(url)[name]; 1645 }, 1646 1647 getOptinIdFromHash: function(id) { 1648 // legacy hash = mwf:uuid 1649 // new hash = mwf:formId:uuid 1650 var hash = location.hash.replace('#', ''), 1651 idx = hash.indexOf("mwf:"); 1652 1653 if (idx !== -1) { 1654 var elements = hash.split(":"); 1655 if (elements.length === 2 || elements[1] === String(id)) { 1656 return hash.substring(idx + 4, hash.length); 1657 } 1658 } 1659 return null; 1660 }, 1661 1662 formatSize: function(bytes) { 1663 if (typeof bytes !== 'number') { 1664 return ''; 1665 } 1666 if (bytes >= 1000000000) { 1667 return (bytes / 1000000000).toFixed(2) + ' GB'; 1668 } 1669 if (bytes >= 1000000) { 1670 return (bytes / 1000000).toFixed(2) + ' MB'; 1671 } 1672 return (bytes / 1000).toFixed(2) + ' KB'; 1673 }, 1674 1675 timezone: function() { 1676 try { 1677 return Intl.DateTimeFormat().resolvedOptions().timeZone; 1678 } catch (ex) { 1679 return "UTC"; 1680 } 1681 } 1682 }); 1683 1684}));
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.