1(function () 2{ 3 "use strict"; 4 5 $.require(['touch'], function (touch) 6 { 7 var FIELDS_API = new FieldsAPI(); 8 $.register('fields', FIELDS_API); 9 10 function getRandomNumber(fMax) 11 { 12 return Math.floor(Math.random() * (fMax + 1)); 13 } 14 15 function FieldsAPI() 16 { 17 var THIS = this; 18 19 var FIELD_TYPE_MAP = { 20 text: TextField, 21 select: SelectField, 22 textarea: TextAreaField, 23 date: DateField, 24 datetime: DateTimeField, 25 checkbox: CheckBoxField, 26 hidden: HiddenField, 27 radio: SelectField, 28 password: PasswordField, 29 upload: UploadField, 30 label: LabelField, 31 phone: PhoneField, 32 selectmultiple: SelectMultipleField, 33 toggle: ToggleField, 34 //search: SearchField, 35 button: ButtonField, 36 //autocomplete: AutoCompleteField, 37 number: NumberField, 38 tinymce: TinyMceField, 39 radiolist: RadioListField, 40 checkboxlist: CheckBoxListField, 41 radiorow: RadioRowField, 42 checkboxrow: CheckBoxRowField, 43 color: ColorField, 44 confirmation: ConfirmationField, 45 signature: SignatureField, 46 range: RangeField, 47 textarray: TextArrayField, 48 email: EmailField, 49 url: UrlField 50 }; 51 52 this.all = FIELD_TYPE_MAP; 53 54 this.get = get; 55 function get(fieldData) 56 { 57 if (typeof (FIELD_TYPE_MAP[fieldData.type]) === 'function') 58 { 59 return new FIELD_TYPE_MAP[fieldData.type](fieldData, THIS); 60 } 61 62 return new TextField(fieldData, THIS); 63 } 64 65 this.add = add; 66 function add(name, fieldDef) 67 { 68 if (typeof (FIELD_TYPE_MAP[name]) !== 'undefined') 69 { 70 console.warn('FieldsAPI', 'A definition with the name ' + name + ' has already been added.'); 71 return; 72 } 73 74 FIELD_TYPE_MAP[name] = fieldDef; 75 } 76 77 this.override = override; 78 function override(name, fieldDef) 79 { 80 //console.log('FieldsAPI - field type override added', name); 81 FIELD_TYPE_MAP[name] = fieldDef; 82 } 83 84 this.getForm = getForm; 85 function getForm(data, onSubmit) 86 { 87 if (typeof (data.tabs) === 'object' && data.tabs.length > 0) 88 { 89 return new TabbedForm(data, onSubmit); 90 } 91 else 92 { 93 return new Form(data, onSubmit); 94 } 95 96 } 97 98 this.getTabbedForm = getTabbedForm; 99 function getTabbedForm(data, onSubmit) 100 { 101 return new TabbedForm(data, onSubmit); 102 } 103 104 var pluginsManager = new PluginsManager(); 105 this.plugins = pluginsManager; 106 107 this.abstracts = { 108 field: TextField, 109 upload: UploadField 110 }; 111 } 112 113 function PluginsManager() 114 { 115 var all = {}; 116 117 this.add = add; 118 function add(name, plugin) 119 { 120 if (typeof (all[name]) === 'undefined') 121 { 122 all[name] = plugin; 123 } 124 else 125 { 126 console.warn('fields.pluginsManager', name, 'already exists'); 127 } 128 } 129 130 this.get = get; 131 function get(name) 132 { 133 if (typeof (all[name]) === 'undefined') 134 { 135 console.warn('fields.pluginsManager', name, 'does not exist'); 136 return null; 137 } 138 139 return all[name]; 140 } 141 142 143 function start() 144 { 145 146 } 147 148 start(); 149 } 150 151 152 function TextField(data) 153 { 154 var THIS = this; 155 156 this.variable = data.variable; 157 158 //overridable 159 this.generateLabel = function () 160 { 161 var $div = $('<div class="question" />').html(data.question); 162 if (typeof (data.description) !== 'undefined' && data.description !== null && data.description !== '') 163 { 164 var $description = $('<div class="description" />').html(data.description).appendTo($div); 165 $description.on('click', function () 166 { 167 $(this).toggleClass('minimized'); 168 }); 169 } 170 171 return $div; 172 }; 173 174 175 //overridable 176 this.generateInput = function () 177 { 178 return $('<input type="text" autocomplete="off" class="input-text" />').attr({ 179 value: data.value, 180 placeholder: data.placeholder 181 }); 182 }; 183 184 this.createInput = createInput; 185 function createInput() 186 { 187 var input = THIS.generateInput().attr({ 188 'data-variable': data.variable, 189 'data-index': data.index, 190 'data-group-index': data.groupIndex, 191 'data-type': data.type, 192 'data-value': data.value 193 }).addClass('do-input').addClass('input-' + data.type); 194 195 if (typeof (data.css) === 'object') 196 { 197 input.css(data.css); 198 } 199 200 if (typeof (data.style) === 'string') 201 { 202 input.attr('style', data.style); 203 } 204 205 if (typeof (data.index) === 'number') 206 { 207 input.attr('tabindex', data.index); 208 } 209 210 if (typeof (data.selectOnFocus) === 'boolean') 211 { 212 input.on('focus', function () 213 { 214 input.select(); 215 });
216 } 217 addFollowUpFieldsToReveal(); 218 return input; 219 } 220 221 222 this.$label = null; 223 this.$input = null; 224 this.$container = null; 225 226 this.addTo = function ($modal) 227 { 228 THIS.$container = $('<div class="do-input-container" />').addClass('do-input-container-' + data.type).attr({ 229 'data-variable': data.variable, 230 'data-columns': data.columns, 231 'data-hidden': isHiddenByDefault, 232 'data-required': data.required 233 }).appendTo($modal); 234 235 236 THIS.$label = THIS.generateLabel(); 237 THIS.$input = THIS.createInput(); 238 239 THIS.$label.appendTo(THIS.$container); 240 if (THIS.placeInputWithinLabel) 241 { 242 THIS.$input.appendTo(THIS.$label); 243 } 244 else 245 { 246 THIS.$input.appendTo(THIS.$container); 247 } 248 249 250 THIS.addListenersTo(THIS.$input); 251 THIS.onDisplay(THIS.$input, THIS.$label, THIS.$container); 252 return THIS.$container; 253 }; 254 255 this.placeInputWithinLabel = false; 256 257 258 this.addListenersTo = function ($i) 259 { 260 261 //set your default listeners here 262 $i.on('keyup', function () 263 { 264 THIS.onChange(); 265 }); 266 267 $i.on('paste', function () 268 { 269 THIS.onChange(); 270 }); 271 272 $i.on('change', function () 273 { 274 THIS.onChange(); 275 }); 276 277 $i.on('focus', function () 278 { 279 THIS.onFocus(); 280 }); 281 282 $i.on('blur', function () 283 { 284 THIS.onBlur(); 285 }); 286 }; 287 288 this.triggerChanged = triggerChanged; 289 function triggerChanged() 290 { 291 THIS.$input.trigger($.Event('fieldValueChanged'), [THIS]); 292 } 293 294 this.getValue = function () 295 { 296 return THIS.$input.val(); 297 } 298 299 300 this.onChange = function () 301 { 302 THIS.triggerChanged(); 303 }; 304 305 this.onFocus = function () 306 { 307 308 }; 309 310 this.onBlur = function () 311 { 312 313 }; 314 315 this.validate = function () 316 { 317 if (!data.required) 318 { 319 return true; 320 } 321 322 if (isHiddenByDefault && !THIS.isRevealed) 323 { 324 return true; 325 } 326 327 if (THIS.isHidden === true) 328 { 329 return true; 330 } 331 332 return THIS.getValue() !== ''; 333 }; 334 335 this.onDisplay = function ($i, $label, $container) 336 { 337 338 }; 339 340 this.onTabFocus = function () { }; 341 342 this.addWarning = addWarning; 343 function addWarning() 344 { 345 //console.log(data.variable, 'addWarning'); 346 THIS.$container.addClass('warning'); 347 } 348 349 this.removeWarning = removeWarning; 350 function removeWarning() 351 { 352 //console.log(data.variable, 'removeWarning'); 353 THIS.$container.removeClass('warning'); 354 } 355 356 this.isRevealed = true; 357 var isHiddenByDefault = false; 358 if (typeof (data.ishidden) === 'boolean') 359 { 360 isHiddenByDefault = data.ishidden; 361 this.isRevealed = false; 362 } 363 364 this.reveal = reveal; 365 function reveal() 366 { 367 if (isHiddenByDefault === true) 368 { 369 THIS.$container.attr('data-revealed', true); 370 THIS.isRevealed = true; 371 } 372 373 } 374 375 this.unReveal = unReveal; 376 function unReveal() 377 { 378 //console.log(data.variable, 'f.unReveal, isHiddenByDefault', isHiddenByDefault); 379 if (isHiddenByDefault === true) 380 { 381 THIS.$container.attr('data-revealed', false); 382 THIS.isRevealed = false; 383 384 } 385 } 386 387 this.getFieldsToHide = getFieldsToHide; 388 function getFieldsToHide() 389 { 390 return []; 391 } 392 393 this.isHidden = false; 394 this.hide = hide; 395 function hide() 396 { 397 THIS.$container.attr('data-hide', true); 398 THIS.isHidden = true; 399 } 400 401 this.unHide = unHide; 402 function unHide() 403 { 404 THIS.$container.attr('data-hide', false); 405 THIS.isHidden = false; 406 } 407 408 this.receiveExpectedValue = receiveExpectedValue; 409 function receiveExpectedValue(key, value) 410 { 411 } 412 413 this.getExpectedValues = getExpectedValues; 414 function getExpectedValues() 415 { 416 if (typeof (data.expectedValues) === 'undefined') 417 { 418 return null; 419 } 420 421 return data.expectedValues; 422 } 423 424 this.getFollowUpInput = function () 425 { 426 return null; 427 } 428 429 430 var followUps = new FollowUpFields(this); 431 this.followUps = followUps; 432 433 this.getExtraValues = function () 434 { 435 return {}; 436 }; 437 438 this.setRequired = function (isRequired) 439 { 440 data.required = isRequired; 441 if (THIS.$container !== null) 442 { 443 THIS.$container.attr('data-required', isRequired); 444 } 445 446 }; 447 448 function addFollowUpFieldsToReveal() 449 { 450 if (typeof (data.options) === 'undefined') 451 { 452 return; 453 } 454 455 if (data.options === null) 456 { 457 return; 458 } 459 460 data.options.forEach(function (option) 461 { 462 if (typeof (option.fieldsToReveal) !== 'undefined' && option.fieldsToReveal !== null) 463 { 464 option.fieldsToReveal.forEach(function (fieldVariable) 465 { 466 THIS.followUps.addFieldToReveal(option.value, fieldVariable); 467 //console.log('checkbox', 'reveal: ' + fieldVariable); 468 });
469 } 470 }); 471 } 472 473 } 474 475 function FollowUpFields(field) 476 { 477 var THIS = this; 478 /* 479 toReveal = { 480 fieldValue1: ['fieldVariable1', 'fieldVariable2', 'fieldVariable3'], 481 fieldValue2: ['fieldVariable4', 'fieldVariable5', 'fieldVariable6'] 482 } 483 */ 484 var toReveal = {}; 485 //this.toReveal = toReveal; 486 487 this.getFieldsToReveal = getFieldsToReveal; 488 function getFieldsToReveal(currentValue) 489 { 490 //console.log('getFieldsToReveal', toReveal); 491 if (typeof (toReveal[currentValue]) === 'undefined') 492 { 493 //console.log('getFieldsToReveal.' + currentValue, []); 494 return []; 495 } 496 497 //console.log('getFieldsToReveal.' + currentValue, toReveal[currentValue]); 498 return toReveal[currentValue]; 499 } 500 501 this.addFieldToReveal = addFieldToReveal; 502 function addFieldToReveal(optionValue, fieldVariable) 503 { 504 if (typeof (toReveal[optionValue]) === 'undefined') 505 { 506 toReveal[optionValue] = []; 507 } 508 509 toReveal[optionValue].push(fieldVariable); 510 //console.log('addFieldToReveal', optionValue, fieldVariable); 511 } 512 513 var toInsert = {}; 514 this.getFieldsToInsert = getFieldsToInsert; 515 function getFieldsToInsert() 516 { 517 var currentValue = field.getValue(); 518 //console.log(field.variable, 'currentValue', currentValue); 519 520 if (typeof (toInsert[currentValue]) === 'undefined') 521 { 522 //console.log(field.variable, 'getFieldsToInsert', toInsert); 523 return []; 524 } 525 526 return toInsert[currentValue]; 527 528 } 529 530 this.addFieldToInsert = addFieldToInsert; 531 function addFieldToInsert(optionValue, fieldData) 532 { 533 if (typeof (toInsert[optionValue]) === 'undefined') 534 { 535 toInsert[optionValue] = []; 536 } 537 538 toInsert[optionValue].push(fieldData); 539 } 540 541 this.insertFieldsToInsert = insertFieldsToInsert; 542 function insertFieldsToInsert($fieldContainer) 543 { 544 removeInsertedFields($fieldContainer); 545 var currentValue = field.getValue(); 546 var fieldsToInsert = getFieldsToInsert(currentValue); 547 if (fieldsToInsert.length === 0) 548 { 549 return; 550 } 551 552 553 } 554 555 function removeInsertedFields($fieldContainer) 556 { 557 $fieldContainer.parent().find('[data-inserted-by="' + field.variable + '"]').remove(); 558 559 } 560 561 562 function start() 563 { 564 565 } 566 567 start(); 568 569 } 570 571 function TextAreaField(data) 572 { 573 //lets override TextField so we don't need to repeat any code 574 TextField.call(this, data); 575 var THIS = this; 576 577 //override the base TextField.generateInput method 578 this.generateInput = function () 579 { 580 var $item = $('<textarea autocomplete="off" />').attr({ 581 placeholder: data.placeholder 582 }).val(data.value); 583 584 if (typeof (data.height) === 'number' && data.height > 0) 585 { 586 $item.css('height', data.height); 587 } 588 589 return $item; 590 } 591 } 592 593 function SelectField(data) 594 { 595 TextField.call(this, data); 596 var THIS = this; 597 598 this.generateInput = function () 599 { 600 var $select = $('<select />').attr({ 601 placeholder: data.placeholder, 602 'data-variable': data.variable, 603 }); 604 605 if (data.type === 'selectmultiple') 606 { 607 $select.attr('multiple', true).addClass('input-select-multiple'); 608 } 609 getOption({ 610 value: '', 611 label: '-- Select One --' 612 }).appendTo($select); 613 614 data.options.forEach(function (option) 615 { 616 getOption(option).appendTo($select); 617 //addFieldsToReveal(option); 618 }); 619 620 return $select; 621 } 622 623 this.addListenersTo = function ($input) 624 { 625 $input.on('change', function () 626 { 627 THIS.onChange(); 628 }); 629 }; 630 631 632 function getOption(optionData) 633 { 634 var $option = $('<option />').attr({ 635 value: optionData.value 636 }).html(optionData.label); 637 638 if (optionData.value === data.value) 639 { 640 $option.attr('selected', true); 641 } 642 643 return $option; 644 } 645 646 this.addOption = addOption; 647 function addOption(label, value) 648 { 649 return $('<option />').attr('value', value).html(label).appendTo(THIS.$input); 650 } 651 652 653 function addFieldsToReveal(option) 654 { 655 if (typeof (option.fieldsToReveal) === 'undefined') 656 { 657 return; 658 } 659 660 if (option.fieldsToReveal === null) 661 { 662 return; 663 } 664 665 option.fieldsToReveal.forEach(function (fieldVariable) 666 { 667 //console.log('addFieldsToReveal', fieldVariable); 668 THIS.followUps.addFieldToReveal(option.value, fieldVariable); 669 }); 670 } 671 672 this.getFieldsToHide = function () 673 { 674 if (typeof (data.fieldsToHideOnSelect) === 'undefined') 675 { 676 return []; 677 } 678 679 if (data.fieldsToHideOnSelect === null) 680 { 681 return []; 682 } 683 684 var currentValue = THIS.getValue(); 685 if (currentValue === '') 686 { 687 return []; 688 } 689 690 return data.fieldsToHideOnSelect; 691 }; 692 693 this.setOptions = setOptions; 694 function setOptions(options) 695 { 696 data.options = options; 697 THIS.$input.html(''); 698 data.options.forEach(function (option) 699 { 700 getOption(option).appendTo(THIS.$input); 701 addFieldsToReveal(option); 702 }); 703 704 } 705 706 function onChange() 707 { 708 THIS.onChange(); 709 setSubFields(); 710 } 711 712 function setSubFields() 713 { 714 var option = findOption(THIS.getValue()); 715 if (option === null) 716 { 717 return; 718 } 719 720 if (typeof (option.subFields) === 'undefined') 721 { 722 return; 723 } 724 725 if (option.subFields === 'null') 726 { 727 return; 728 } 729 730 731 } 732 733 function findOption(value) 734 { 735 var result = null; 736 data.options.forEach(function (option) 737 { 738 if (result === null && option.value === value) 739 { 740 result = option; 741 } 742 }); 743 return result; 744 } 745 746 this.setValue = setValue; 747 function setValue(value) 748 { 749 THIS.$input.val(value); 750 } 751 } 752 753 function DateField(data) 754 { 755 TextField.call(this, data); 756 var THIS = this; 757 758 this.generateInput = function () 759 { 760 if (isValidDateValue()) 761 { 762 return $('<input type="date" autocomplete="off" class="input-text" />').attr({ 763 value: data.value, 764 placeholder: data.placeholder 765 });
766 } 767 else 768 { 769 return generateLegacyDateInput(); 770 771 } 772 } 773 774 function isValidDateValue() 775 { 776 if (data.value === null || data.value === '') 777 { 778 return true; 779 } 780 781 return data.value.indexOf('-') > -1; 782 } 783 784 var isLegacy = false; 785 function generateLegacyDateInput() 786 { 787 isLegacy = true; 788 return $('<input type="text" class="input-text input-date" />').attr({ 789 placeholder: data.placeholder, 790 value: data.value 791 }); 792 } 793 794 this.onDisplay = function ($input) 795 { 796 if (!isLegacy) 797 { 798 return; 799 } 800 801 if (typeof ($.datepicker) === 'object') 802 { 803 $input.datepicker(); 804 } 805 806 }; 807 } 808 809 function DateTimeField(data) 810 { 811 TextField.call(this, data); 812 var THIS = this; 813 814 this.generateInput = function () 815 { 816 if (isValidDateValue()) 817 { 818 return $('<input type="datetime-local" autocomplete="off" />').attr({ 819 value: data.value, 820 placeholder: data.placeholder 821 }); 822 } 823 else 824 { 825 return generateLegacyDateInput(); 826 827 } 828 829 } 830 831 var isLegacy = false; 832 function generateLegacyDateInput() 833 { 834 isLegacy = true; 835 return $('<input type="text" autocomplete="off" class="input-text input-datetime" />').attr({ 836 placeholder: data.placeholder, 837 value: data.value 838 }); 839 } 840 841 function isValidDateValue() 842 { 843 if (data.value === null || data.value === '') 844 { 845 return true; 846 } 847 848 return data.value.indexOf('-') > -1; 849 } 850 851 this.onDisplay = function ($input) 852 { 853 if (!isLegacy) 854 { 855 return; 856 } 857 858 if (typeof ($.fn.datetimepicker) !== 'function') 859 { 860 console.warn('do.DateTimeField', 'jquery.datetimepicker is not installed'); 861 return; 862 } 863 864 $input.datetimepicker({ 865 controlType: 'select', 866 oneLine: true, 867 onClose: function () 868 { 869 $(this).trigger('change'); 870 }, 871 timeFormat: 'h:mm tt', 872 ampm: true 873 }); 874 875 $input.attr('autocomplete', 'off'); 876 }; 877 } 878 879 880 function CheckBoxField(data) 881 { 882 TextField.call(this, data); 883 var THIS = this; 884 var label = getCheckboxLabel(); 885 var hasLabel = label !== null; 886 this.hasLabel = hasLabel; 887 888 if (!hasLabel) 889 { 890 this.placeInputWithinLabel = true; 891 } 892 893 function getCheckboxLabel() 894 { 895 if (typeof (data.checkboxLabel) === 'undefined' || data.checkboxLabel === null) 896 { 897 return null; 898 } 899 900 if (data.checkboxLabel === '') 901 { 902 return null; 903 } 904 905 return data.checkboxLabel; 906 } 907 908 this.generateLabel = function () 909 { 910 var $div = $('<div class="question" />').attr('data-has-label', hasLabel); 911 $('<div class="question-inner" />').html(data.question).appendTo($div); 912 return $div; 913 }; 914 915 this.generateInput = function () 916 { 917 if (hasLabel) 918 { 919 return generateInputWithLabel(); 920 } 921 else 922 { 923 return getCheckbox(); 924 } 925 } 926 927 function getCheckbox() 928 { 929 var $input = $('<input type="checkbox" />'); 930 if (data.value === '1') 931 { 932 $input.attr('checked', true); 933 $input.prop('checked', true); 934 } 935 return $input; 936 } 937 938 function generateInputWithLabel() 939 { 940 var $div = $('<div class="checkbox-container" />'); 941 getCheckbox().appendTo($div); 942 $('<div class="checkbox-label" />').html(label).appendTo($div); 943 return $div; 944 } 945 this.onDisplay = function ($input, $label) 946 { 947 if (hasLabel) 948 { 949 $input.on('click', 'input', function (e) 950 { 951 THIS.onCheckboxClick(); 952 e.stopPropagation(); 953 }); 954 955 $input.on('click', function (e) 956 { 957 $input.find('input').trigger('click'); 958 }); 959 960 $label.on('click', function (e) 961 { 962 $input.find('input').trigger('click'); 963 }); 964 } 965 else 966 { 967 $input.on('click', function (e) 968 { 969 THIS.onCheckboxClick(); 970 e.stopPropagation(); 971 }); 972 973 $label.on('click', function (e) 974 { 975 $input.trigger('click'); 976 });
977 } 978 979 980 }; 981 982 this.onCheckboxClick = function () 983 { 984 }; 985 986 this.validate = function () 987 { 988 return true; 989 }; 990 991 this.getValue = function () 992 { 993 if (hasLabel) 994 { 995 if (THIS.$input.find('input').prop('checked') === true) 996 { 997 return '1'; 998 } 999 else 1000 { 1001 return '0'; 1002 } 1003 1004 } 1005 else 1006 { 1007 if (THIS.$input.prop('checked') === true) 1008 { 1009 return '1'; 1010 } 1011 else 1012 { 1013 return '0'; 1014 } 1015 } 1016 } 1017 1018 1019 } 1020 1021 function HiddenField(data) 1022 { 1023 TextField.call(this, data); 1024 var THIS = this; 1025 this.generateInput = function () 1026 { 1027 return $('<input type="hidden" />').attr('value', data.value); 1028 } 1029 1030 this.validate = function () 1031 { 1032 return true; 1033 }; 1034 1035 this.onDisplay = function ($input, $label, $container) 1036 { 1037 $container.hide(); 1038 }; 1039 1040 this.getValue = function () 1041 { 1042 if (data.value !== null) 1043 { 1044 return data.value; 1045 } 1046 1047 return ''; 1048 } 1049 } 1050 1051 function PasswordField(data) 1052 { 1053 TextField.call(this, data); 1054 var THIS = this; 1055 this.generateInput = function () 1056 { 1057 return $('<input type="password" autocomplete="new-password" />').attr({ 1058 placeholder: data.placeholder, 1059 value: data.value 1060 }); 1061 } 1062 1063 } 1064 function EmailField(data) 1065 { 1066 TextField.call(this, data); 1067 var THIS = this; 1068 this.generateInput = function () 1069 { 1070 return $('<input type="email" autocomplete="off" />').attr({ 1071 placeholder: data.placeholder, 1072 value: data.value 1073 }); 1074 } 1075 1076 var _$input = null; 1077 this.onDisplay = function ($input, $question, $container) 1078 { 1079 _$input = $input; 1080 }; 1081 1082 this.validate = function () 1083 { 1084 var v = THIS.getValue(); 1085 1086 if (v === '') 1087 { 1088 if (data.required) 1089 { 1090 return false; 1091 } 1092 else 1093 { 1094 return true; 1095 } 1096 1097 } 1098 1099 if (THIS.isHidden === true) 1100 { 1101 return true; 1102 } 1103 1104 return _$input[0].validity.valid; 1105 }; 1106 1107 1108 } 1109 1110 function UrlField(data) 1111 { 1112 TextField.call(this, data); 1113 var THIS = this; 1114 this.generateInput = function () 1115 { 1116 return $('<input type="url" autocomplete="off" />').attr({ 1117 placeholder: data.placeholder, 1118 value: data.value 1119 }); 1120 } 1121 1122 } 1123 1124 function RangeField(data) 1125 { 1126 TextField.call(this, data); 1127 1128 var $input = null; 1129 this.generateInput = function () 1130 { 1131 $input = $('<input type="range" />').attr({ 1132 value: data.value 1133 }); 1134 1135 if (typeof (data.min) !== 'undefined') 1136 { 1137 $input.attr('min', data.min); 1138 } 1139 1140 if (typeof (data.max) !== 'undefined') 1141 { 1142 $input.attr('max', data.max); 1143 } 1144 1145 if (typeof (data.step) !== 'undefined') 1146 { 1147 $input.attr('step', data.step); 1148 } 1149 1150 return $input; 1151 } 1152 1153 var $valueDisplay = null; 1154 this.onDisplay = function ($i, $label, $container) 1155 { 1156 $valueDisplay = $('<div class="value-display" />').appendTo($container); 1157 1158 $valueDisplay.html($i.val()); 1159 $i.on('input', function () 1160 { 1161 $valueDisplay.html($i.val()); 1162 }); 1163 1164 }; 1165 1166 this.setValue = function (v) 1167 { 1168 $input.val(v); 1169 $valueDisplay.html(v); 1170 }; 1171 } 1172 1173 function UploadField(options) 1174 { 1175 TextField.call(this, options); 1176 var THIS = this; 1177 1178 var uploadResult = null; 1179 1180 this.generateInput = function () 1181 { 1182 /* 1183 if (typeof ($.fn.fileupload) !== 'function') 1184 { 1185 return getUploadUnavailable('FileUpload plugin is not present'); 1186 } 1187 */ 1188 if (typeof (options.action) === 'undefined' || options.action === '') 1189 { 1190 options.action = 'do-upload'; 1191 } 1192 1193 var div = $('<div class="input-file" style="border: 0 none transparent; padding: 15px 0;" />'); 1194 var progressOuter = $('<div class="progress" />').appendTo(div); 1195 //var progressBar = $('<div class="progress-bar" style="display: none; border-radius: 2px; background-color: #00FF00; width: 0%; min-height: 20px; text-align: center; color: #FFF; pointer-events: none;" />').appendTo(progressOuter); 1196 var progressBar = $('<div class="progress-bar" />').appendTo(progressOuter); 1197 var progressBarLabel = $('<div class="progress-bar-label" />').appendTo(progressOuter); 1198 var $field = $('<input type="file" />').appendTo(div); 1199 if (options.isMultiple) 1200 { 1201 $field.attr('multiple', true); 1202 } 1203 1204 return div; 1205 } 1206 1207 function getUploadUnavailable(reason) 1208 { 1209 return $('<div />').html('<em>ERROR: Uploader is unavailable because ' + reason + '</em>'); 1210 } 1211 1212 this.url = function () 1213 { 1214 console.warn('This upload field [url] must be overridden.'); 1215 return ''; 1216 }; 1217 /*
1218 function _getUploadUrl() 1219 { 1220 return req.url + options.action + '&variable=' + options.variable + req.varsWithInputs(); 1221 } 1222 */ 1223 this.onFinished = function (data) 1224 { 1225 //console.warn('This upload field [onFinished] must be overridden.'); 1226 }; 1227 1228 this.onDisplay = function (div, $label) 1229 { 1230 var $field = div.find('input'); 1231 var progressOuter = div.find('.progress').attr('data-status', 'none'); 1232 1233 var progressBar = div.find('.progress-bar'); 1234 var progressBarLabel = div.find('.progress-bar-label'); 1235 1236 ensureInstalled(function () 1237 { 1238 $field.fileupload({ 1239 //returns the function serialized :( url: _getUploadUrl, 1240 1241 url: THIS.url() + options.action + '&variable=' + options.variable, 1242 dataType: 'json', 1243 progressInterval: 1, 1244 bitrateInterval: 10, 1245 dropZone: null, 1246 done: function (e, data) 1247 { 1248 1249 if (typeof (data.result.value) === 'string') 1250 { 1251 uploadResult = data.result.value; 1252 } 1253 else 1254 { 1255 uploadResult = ''; 1256 } 1257 1258 div.find('input').css('display', 'none'); 1259 if (data.result.status === 'OK' || data.result.status === 'MESSAGE') 1260 { 1261 progressOuter.attr('data-status', 'completed'); 1262 progressBarLabel.html('<i class="fa fa-check-circle-o" /><span>File Uploaded</span>'); 1263 1264 /* 1265 progressBar.html('<i class="fa fa-check-circle-o" /><span>File Uploaded</span>').css({ 1266 'background-color': 'transparent', 1267 'color': '#000000' 1268 });
1269 */ 1270 1271 THIS.onFinished(data); 1272 } 1273 else 1274 { 1275 progressOuter.attr('data-status', 'error'); 1276 progressBarLabel.html('<i class="fa fa-times-circle-o" /><span>' + data.result.message + '</span>'); 1277 1278 /* 1279 progressBar.html('<i class="fa fa-times-circle-o" /><span>' + data.result.message + '</span>').css({ 1280 'background-color': '#FF0000', 1281 'color': '#FFFFFF', 1282 'height': 'auto' 1283 }); 1284 */ 1285 1286 div.find('input').css('display', 'block'); 1287 1288 } 1289 }, 1290 progressall: function (e, data) 1291 { 1292 div.find('input').css('display', 'none'); 1293 1294 var progress = parseInt(data.loaded / data.total * 100, 10); 1295 //div.data('progress', progress); 1296 1297 progressOuter.attr('data-progress', progress); 1298 1299 if (progress === 100) 1300 { 1301 progressBarLabel.html(progress + '% Processing...'); 1302 progressOuter.attr('data-status', 'processing'); 1303 1304 /* 1305 1306 progressBar.css({ 1307 'display': 'block', 1308 'width': progress + '%', 1309 'background-color': '#00FF00' 1310 }).html('Processing... Please Wait...'); 1311 */ 1312 1313 } 1314 else 1315 { 1316 progressBarLabel.html(progress + '% Uploading File...'); 1317 progressOuter.attr('data-status', 'uploading'); 1318 /* 1319 progressBar.css({ 1320 'display': 'block', 1321 'width': progress + '%', 1322 'background-color': '#00FF00' 1323 }).html(progress + '% Uploading File...'); 1324 */ 1325 1326 } 1327 }, 1328 add: function (e, data) 1329 { 1330 //console.log('upload', 'add'); 1331 data.url = THIS.url() + options.action + '&variable=' + options.variable;//_getUploadUrl(); 1332 //console.log('upload', data.url); 1333 data.submit(); 1334 } 1335 }); 1336 }); 1337 1338 1339 } 1340 1341 var isInstalled = typeof ($.fn.fileupload) !== 'undefined'; 1342 1343 function ensureInstalled(callback) 1344 { 1345 if (isInstalled) 1346 { 1347 callback(); 1348 return; 1349 } 1350 1351 if (options.javascriptResources === null) 1352 { 1353 options.javascriptResources = ['/remote/?action=resource-js&url=/functions/modules/pages3/js/jquery.fileupload.js']; 1354 } 1355 //console.log('options', options); 1356 $.require(['scriptInstaller'], function (scriptInstaller) 1357 { 1358 scriptInstaller.install(options.javascriptResources, function () 1359 { 1360 isInstalled = true; 1361 callback(); 1362 }); 1363 }); 1364 1365 } 1366 this.getValue = function () 1367 { 1368 return uploadResult; 1369 } 1370 1371 this.validate = function () 1372 { 1373 if (!options.required) 1374 { 1375 return true; 1376 } 1377 1378 if (!THIS.isRevealed) 1379 { 1380 return true; 1381 } 1382 1383 if (THIS.isHidden) 1384 { 1385 return true; 1386 } 1387 1388 return uploadResult !== null; 1389 } 1390 1391 1392 } 1393 1394 1395 function LabelField(data) 1396 { 1397 TextField.call(this, data); 1398 var THIS = this; 1399 1400 this.generateInput = function () 1401 { 1402 return $('<div />'); 1403 }; 1404 1405 this.validate = function () 1406 { 1407 return true; 1408 }; 1409 1410 this.getValue = function () 1411 { 1412 if (data.value !== null) 1413 { 1414 return data.value; 1415 } 1416 1417 return ''; 1418 }; 1419 } 1420 1421 function PhoneField(data) 1422 { 1423 TextField.call(this, data); 1424 var THIS = this; 1425 this.generateInput = function () 1426 { 1427 return $('<input type="tel" autocomplete="off" class="input-text input-phone" />').attr({ 1428 placeholder: data.placeholder, 1429 value: data.value 1430 }); 1431 } 1432 } 1433 function SelectMultipleField(data) 1434 { 1435 SelectField.call(this, data); 1436 var THIS = this; 1437 } 1438 function ToggleField(data) 1439 { 1440 CheckBoxField.call(this, data); 1441 var THIS = this; 1442 } 1443 1444 function ConfirmationField(data) 1445 { 1446 CheckBoxField.call(this, data); 1447 var THIS = this; 1448 1449 this.onCheckboxClick = function () 1450 { 1451 //THIS.$input.trigger($.Event('change')); 1452 1453 THIS.triggerChanged(); 1454 }; 1455 1456 this.validate = function () 1457 { 1458 if (THIS.hasLabel) 1459 { 1460 return THIS.$input.find('input').prop('checked') === true; 1461 } 1462 else 1463 { 1464 return THIS.$input.prop('checked') === true; 1465 } 1466 }; 1467 } 1468 1469 1470 function SearchField(data) 1471 { 1472 TextField.call(this, data); 1473 var THIS = this; 1474 } 1475 1476 function ButtonField(data) 1477 { 1478 TextField.call(this, data); 1479 var THIS = this; 1480 1481 this.generateInput = function () 1482 { 1483 var button = $('<a class="button" />'); 1484 1485 if (data.icon !== '') 1486 { 1487 $('<i class="fa fa-' + data.icon + '" />').appendTo(button); 1488 } 1489 $('<span />').html(data.question).appendTo(button); 1490 1491 1492 return button; 1493 }; 1494 1495 this.onDisplay = function ($input, $label, $container) 1496 { 1497 $input.on('click', function () 1498 { 1499 onClick($(this)); 1500 }); 1501 }; 1502 1503 function onClick($button) 1504 { 1505 if (typeof (data.onClick) === 'function') 1506 { 1507 //req.close(); 1508 data.onClick($button); 1509 return; 1510 } 1511 var o = { 1512 action: data.action 1513 }; 1514 1515 if (typeof (data.id) === 'number') 1516 { 1517 o.id = data.id; 1518 } 1519 1520 if (typeof (data.vars) === 'object') 1521 { 1522 o.vars = data.vars; 1523 } 1524 1525 if (typeof (data.post) === 'object') 1526 { 1527 o.post = data.post; 1528 } 1529 var r = $.extend(true, req.options, o); 1530 //req.close(); 1531 //req.doPlugin.run(r); 1532 } 1533 1534 this.getValue = function () 1535 { 1536 return ''; 1537 } 1538 1539 this.validate = function () 1540 { 1541 return true; 1542 }; 1543 1544 } 1545 1546 function AutoCompleteField(data) 1547 { 1548 TextField.call(this, data); 1549 var THIS = this; 1550 1551 this.generateInput = function () 1552 { 1553 var field = $('<input type="text" autocomplete="off" class="input-text input-autocomplete" />'); 1554 var v = ''; 1555 data.options.forEach(function (option) 1556 { 1557 if (option.value == data.value) 1558 { 1559 v = option.label; 1560 } 1561 }); 1562 1563 field.attr('value', v).attr('data-selected-value', data.value); 1564 return field; 1565 1566 }; 1567 1568 this.onDisplay = function ($input, $label, $container) 1569 { 1570 $container.addClass('ui-front'); 1571 $input.autocomplete({ 1572 source: data.options, 1573 open: function (e, ui) 1574 { 1575 $container.addClass('focused'); 1576 }, 1577 close: function (e, ui) 1578 { 1579 $container.removeClass('focused'); 1580 }, 1581 select: function (e, ui) 1582 { 1583 $input.attr('data-selected-value', ui.item.value); 1584 $input.val(ui.item.label); 1585 return false; 1586 }, 1587 autoFocus: true 1588 }); 1589 $input.attr('data-selected-value', data.value); 1590 1591 }; 1592 1593 this.getValue = function () 1594 { 1595 return THIS.$input.attr('data-selected-value'); 1596 }; 1597 1598 this.validate = function () 1599 { 1600 return true; 1601 }; 1602 } 1603 1604 function NumberField(data) 1605 { 1606 TextField.call(this, data); 1607 var THIS = this; 1608 this.generateInput = function () 1609 { 1610 var $input = $('<input type="number" autocomplete="off" class="input-text" />').attr({ 1611 value: data.value, 1612 placeholder: data.placeholder 1613 }); 1614 1615 if (typeof (data.step) === 'number') 1616 { 1617 $input.attr('step', data.step); 1618 } 1619 1620 if (typeof (data.min) === 'number') 1621 { 1622 $input.attr('min', data.min); 1623 } 1624 1625 if (typeof (data.max) === 'number') 1626 { 1627 $input.attr('max', data.max); 1628 } 1629 1630 return $input; 1631 }; 1632 } 1633 1634 1635 var TINYMCE_INSTALLED = false; 1636 function TinyMceField(data) 1637 { 1638 TextField.call(this, data); 1639 var THIS = this; 1640 1641 var id = 'do_tinymce_' + getRandomNumber(999999); 1642 1643 this.generateInput = function () 1644 { 1645 var $item = $('<textarea autocomplete="off" />').attr({ 1646 placeholder: data.placeholder, 1647 id: id 1648 }).val(data.value); 1649 1650 if (typeof (data.height) === 'number') 1651 { 1652 $item.css('height', data.height); 1653 } 1654 1655 return $item; 1656 } 1657 1658 this.onDisplay = function ($input, $label, $container) 1659 { 1660 ensureInstalled(function () 1661 { 1662 var options = $.extend(true, data.tinymceOptions, { 1663 selector: '#' + $input.attr('id'), 1664 content_css: '/remote/?action=do-tinymce-css', 1665 });
1666 1667 if (!touch.isTouch() && typeof (data.sendKeyUpEvents) === 'boolean' && data.sendKeyUpEvents === true) 1668 { 1669 options.init_instance_callback = function (ed) 1670 { 1671 ed.on('keyup', function (e) 1672 { 1673 $input.trigger($.Event('change')); 1674 $input.trigger($.Event('htmlchanged')); 1675 }); 1676 }; 1677 } 1678 1679 //hack to get it to initialize in AF 1680 setTimeout(function () 1681 { 1682 tinyMCE.init(options); 1683 }, 30); 1684 }); 1685 }; 1686 1687 this.getValue = function () 1688 { 1689 if (typeof (tinyMCE) === 'undefined') 1690 { 1691 return data.value; 1692 } 1693 1694 var f = tinyMCE.get(id); 1695 if (f === null) 1696 { 1697 return data.value; 1698 } 1699 1700 return f.getContent(); 1701 }; 1702 1703 function ensureInstalled(callback) 1704 { 1705 if (TINYMCE_INSTALLED === true) 1706 { 1707 callback(); 1708 return; 1709 } 1710 1711 if (typeof (window.tinyMCE) === 'object') 1712 { 1713 TINYMCE_INSTALLED = true; 1714 callback(); 1715 return; 1716 } 1717 1718 $.require(['scriptInstaller'], function (scriptInstaller) 1719 { 1720 scriptInstaller.install(data.javascriptResources, function () 1721 { 1722 TINYMCE_INSTALLED = true; 1723 callback(); 1724 }); 1725 }); 1726 1727 } 1728 } 1729 1730 1731 1732 function RadioListField(data) 1733 { 1734 TextField.call(this, data); 1735 var THIS = this; 1736 1737 var id = 'do_radiolist_' + getRandomNumber(999999); 1738 this.getLayout = function () 1739 { 1740 return 'column'; 1741 }; 1742 1743 this.generateInput = function () 1744 { 1745 var $select = $('<div class="input-list" />').attr({ 1746 placeholder: data.placeholder, 1747 'data-variable': data.variable, 1748 'data-layout': THIS.getLayout(), 1749 'data-option-columns': data.optionColumns 1750 }); 1751 1752 data.options.forEach(function (option) 1753 { 1754 getOption(option).appendTo($select); 1755 }); 1756 1757 return $select; 1758 } 1759 1760 1761 function getOption(optionData) 1762 { 1763 var $option = $('<div class="option" />').attr({ 1764 'data-value': optionData.value 1765 }); 1766 1767 var cbid = id + '_' + getRandomNumber(999999); 1768 1769 var $input = $('<input type="radio" />').attr({ 1770 name: id, 1771 id: cbid, 1772 value: optionData.value 1773 }).appendTo($option); 1774 1775 if (optionData.value === data.value) 1776 { 1777 $input.prop('checked', true); 1778 } 1779 1780 var $label = $('<label />').attr({ 1781 for: cbid 1782 }).html(optionData.label).appendTo($option); 1783 1784 1785 return $option; 1786 1787 } 1788 1789 //override the base TextField.addListenersTo method 1790 this.addListenersTo = function ($input) 1791 { 1792 $input.on('click', 'input', function () 1793 { 1794 data.value = $(this).attr('value'); 1795 //console.log('value set to ', data.value); 1796 THIS.onChange(); 1797 }); 1798 }; 1799 1800 this.getValue = function () 1801 { 1802 return data.value; 1803 }; 1804 1805 1806 } 1807 1808 function RadioRowField(data) 1809 { 1810 RadioListField.call(this, data); 1811 this.getLayout = function () 1812 { 1813 return 'row'; 1814 }; 1815 } 1816 1817 1818 function CheckBoxListField(data) 1819 { 1820 TextField.call(this, data); 1821 var THIS = this; 1822 1823 var id = 'do_checkboxlist_' + getRandomNumber(999999); 1824 1825 this.getLayout = function () 1826 { 1827 return 'column'; 1828 }; 1829 1830 this.generateInput = function () 1831 { 1832 var $select = $('<div class="input-list" />').attr({ 1833 placeholder: data.placeholder, 1834 'data-variable': data.variable, 1835 'data-layout': THIS.getLayout(), 1836 'data-option-columns': data.optionColumns 1837 }); 1838 1839 data.options.forEach(function (option) 1840 { 1841 getOption(option).appendTo($select); 1842 }); 1843 1844 return $select; 1845 } 1846 1847 function getOption(optionData) 1848 { 1849 var $option = $('<div class="option" />').attr({ 1850 'data-value': optionData.value 1851 }); 1852 1853 var cbid = id + '_' + getRandomNumber(999999); 1854 1855 var $input = $('<input type="checkbox" />').attr({ 1856 name: id, 1857 id: cbid, 1858 value: optionData.value 1859 }).appendTo($option); 1860 1861 if (optionData.value === data.value) 1862 { 1863 $input.prop('checked', true); 1864 } 1865 1866 var $label = $('<label />').attr({ 1867 for: cbid 1868 }).html(optionData.label).appendTo($option); 1869 1870 1871 return $option; 1872 1873 } 1874 1875 //override the base TextField.addListenersTo method 1876 this.addListenersTo = function ($input) 1877 { 1878 $input.on('click', 'input', function () 1879 { 1880 THIS.onChange(); 1881 }); 1882 }; 1883 1884 1885 this.getValue = function () 1886 { 1887 var values = []; 1888 this.$input.find('input').each(function () 1889 { 1890 var cb = $(this); 1891 if (cb.prop('checked') === true) 1892 { 1893 values.push(cb.attr('value')); 1894 } 1895 }); 1896 return JSON.stringify(values); 1897 }; 1898 1899 1900 this.validate = function () 1901 { 1902 return true; 1903 }; 1904 1905 1906 } 1907 1908 function CheckBoxRowField(data) 1909 { 1910 CheckBoxListField.call(this, data); 1911 this.getLayout = function () 1912 { 1913 return 'row'; 1914 }; 1915 } 1916 1917 function ColorField(data) 1918 { 1919 TextField.call(this, data); 1920 1921 this.generateInput = function () 1922 { 1923 return $('<input type="color" class="input-text" />').attr({ 1924 value: data.value, 1925 //colorpicker: 'hex', 1926 placeholder: data.placeholder 1927 }); 1928 }; 1929 1930 } 1931 1932 function SignatureField(data) 1933 { 1934 var THIS = this; 1935 var canvas = null; 1936 var ctx = null; 1937 1938 TextField.call(this, data); 1939 1940 1941 this.generateInput = function () 1942 {
1943 var $div = $('<div class="signature-container" />'); 1944 $('<canvas width="400" height="200" style="border: 1px dashed #CCC; cursor: pointer;" />').appendTo($div); 1945 getResetButton().appendTo($div); 1946 1947 return $div; 1948 }; 1949 1950 this.onDisplay = function ($input, $label, $container) 1951 { 1952 $container.on('click', '[data-reset-signature-button]', function () 1953 { 1954 reset(); 1955 }); 1956 1957 canvas = getCanvas()[0]; 1958 ctx = canvas.getContext("2d"); 1959 1960 canvas.addEventListener("mousemove", function (e) 1961 { 1962 if (isDrawing) 1963 { 1964 findxy('move', e); 1965 } 1966 }, false); 1967 1968 canvas.addEventListener("mousedown", function (e) 1969 { 1970 isDrawing = true; 1971 findxy('down', e); 1972 }, false); 1973 1974 canvas.addEventListener("mouseup", function (e) 1975 { 1976 if (isDrawing) 1977 { 1978 isDrawing = false; 1979 isDrawed = true; 1980 findxy('up', e); 1981 } 1982 1983 }, false); 1984 1985 canvas.addEventListener("mouseleave", function (e) 1986 { 1987 if (isDrawing) 1988 { 1989 findxy('out', e); 1990 } 1991 }, false); 1992 1993 }; 1994 1995 1996 function getCanvas() 1997 { 1998 return THIS.$input.find('canvas'); 1999 } 2000 2001 2002 var flag = false, 2003 prevX = 0, 2004 currX = 0, 2005 prevY = 0, 2006 currY = 0, 2007 dot_flag = false; 2008 2009 var x = "black", 2010 y = 2; 2011 2012 2013 var isDrawing = false; 2014 var isDrawed = false; 2015 2016 2017 function getResetButton() 2018 { 2019 var div = $('<div />'); 2020 $('<a class="button" data-reset-signature-button />').html('Clear').appendTo(div); 2021 return div; 2022 } 2023 2024 function reset() 2025 { 2026 isDrawed = false; 2027 isDrawing = false; 2028 THIS.$input.find('canvas').remove(); 2029 $('<canvas width="400" height="200" style="border: 1px dashed #CCC; cursor: pointer;" />').prependTo(THIS.$input); 2030 canvas = getCanvas()[0]; 2031 ctx = canvas.getContext("2d"); 2032 2033 canvas.addEventListener("mousemove", function (e) 2034 { 2035 if (isDrawing) 2036 { 2037 findxy('move', e); 2038 } 2039 }, false); 2040 2041 canvas.addEventListener("mousedown", function (e) 2042 { 2043 isDrawing = true; 2044 findxy('down', e); 2045 }, false); 2046 2047 canvas.addEventListener("mouseup", function (e) 2048 { 2049 if (isDrawing) 2050 { 2051 isDrawing = false; 2052 isDrawed = true; 2053 findxy('up', e); 2054 } 2055 2056 }, false); 2057 2058 canvas.addEventListener("mouseleave", function (e) 2059 { 2060 if (isDrawing) 2061 { 2062 findxy('out', e); 2063 } 2064 }, false); 2065 } 2066 2067 function draw() 2068 { 2069 ctx.beginPath(); 2070 ctx.moveTo(prevX, prevY); 2071 ctx.lineTo(currX, currY); 2072 ctx.strokeStyle = x; 2073 ctx.lineWidth = y; 2074 ctx.stroke(); 2075 ctx.closePath(); 2076 } 2077 2078 function erase() 2079 { 2080 ctx.clearRect(0, 0, w, h); 2081 } 2082 2083 2084 function findxy(res, e) 2085 { 2086 var $canvas = getCanvas(); 2087 var offset = $canvas.offset(); 2088 2089 if (res == 'down') 2090 { 2091 prevX = currX; 2092 prevY = currY; 2093 currX = e.pageX - offset.left; 2094 currY = e.pageY - offset.top; 2095 2096 flag = true; 2097 dot_flag = true; 2098 if (dot_flag) 2099 { 2100 ctx.beginPath(); 2101 ctx.fillStyle = x; 2102 ctx.fillRect(currX, currY, 2, 2); 2103 ctx.closePath(); 2104 dot_flag = false; 2105 } 2106 } 2107 if (res == 'up' || res == "out") 2108 { 2109 flag = false; 2110 } 2111 if (res == 'move') 2112 { 2113 if (flag) 2114 { 2115 prevX = currX; 2116 prevY = currY; 2117 currX = e.pageX - offset.left;// - canvas.offsetLeft; 2118 currY = e.pageY - offset.top;// - canvas.offsetTop; 2119 draw(); 2120 } 2121 } 2122 } 2123 2124 this.getValue = function () 2125 { 2126 return canvas.toDataURL(); 2127 } 2128 2129 this.validate = validate; 2130 function validate() 2131 { 2132 if (data.required) 2133 { 2134 return isDrawed; 2135 } 2136 else 2137 { 2138 return true; 2139 } 2140 2141 } 2142 2143 2144 2145 } 2146 2147 function TextArrayField(data) 2148 { 2149 TextField.call(this, data); 2150 var THIS = this; 2151 /* 2152 if (data.value !== null && data.value !== '') 2153 { 2154 try 2155 { 2156 _currentValue = JSON.parse(data.value); 2157 } 2158 catch (e) 2159 { 2160 _currentValue = []; 2161 } 2162 } 2163 */ 2164 var selectionFields = []; 2165 var currentIndex = 0; 2166 var $items = null; 2167 this.generateInput = function () 2168 {
2169 var $container = $('<div class="text-array-field" />'); 2170 $items = $('<div class="items" />').appendTo($container); 2171 addButtonFactory().appendTo($container); 2172 return $container; 2173 }; 2174 2175 2176 this.onDisplay = function ($input, $label, $container) 2177 { 2178 $container.on('click', '[data-text-array-add-button]', addAnotherField); 2179 }; 2180 2181 function addButtonFactory() 2182 { 2183 var $buttonsContainer = $('<div class="buttons" />'); 2184 var $addButton = $('<a class="button" data-text-array-add-button />').appendTo($buttonsContainer); 2185 $('<i class="fa fa-plus" />').appendTo($addButton); 2186 return $buttonsContainer; 2187 2188 } 2189 function addAnotherField() 2190 { 2191 currentIndex++; 2192 2193 var d = $.extend(true, {}, data); 2194 d.name = d.name += '___' + currentIndex; 2195 d.question = data.ItemLabel; 2196 d.value = ''; 2197 d.required = false; 2198 2199 var f = new TextField(d); 2200 2201 var $field = $('<div class="item" />').appendTo($items); 2202 f.addTo($field); 2203 selectionFields.push(f); 2204 } 2205 2206 this.getValue = function () 2207 { 2208 var v = []; 2209 selectionFields.forEach(function (f) 2210 { 2211 var fieldValue = f.getValue(); 2212 if (fieldValue !== '') 2213 { 2214 v.push(fieldValue); 2215 } 2216 2217 }); 2218 2219 return JSON.stringify(v); 2220 }; 2221 } 2222 2223 2224 $.require(['pageController', 'fields'], function (pageController, fieldsApi) 2225 { 2226 fieldsApi.add('autocomplete', AutoCompleteField); 2227 2228 function AutoCompleteField(data) 2229 { 2230 fieldsApi.all.text.call(this, data); 2231 var THIS = this;
2232 var ajax = pageController.ajax.run; 2233 2234 if (data.queryString === null) 2235 { 2236 data.queryString = {}; 2237 } 2238 2239 if (data.appName !== null && data.appName !== '') 2240 { 2241 $.require(['accounts'], function (accounts) 2242 { 2243 var account = accounts.get(data.appName); 2244 if (account !== null) 2245 { 2246 ajax = account.$do; 2247 } 2248 }); 2249 } 2250 2251 this.generateInput = function () 2252 { 2253 var field = $('<input type="text" autocomplete="off" class="input-text input-autocomplete" data-selected-value="" />'); 2254 return field; 2255 2256 }; 2257 2258 var $selection = null; 2259 this.onDisplay = function ($input, $label, $container) 2260 { 2261 $selection = $('<div class="autocomplete-selection" />').hide().appendTo($container); 2262 $('<span />').appendTo($selection); 2263 $('<i class="close fa fa-times" />').appendTo($selection); 2264 $selection.on('click', '.close', function () 2265 { 2266 $input.attr('data-selected-value', ''); 2267 $input.val(''); 2268 $selection.hide(); 2269 $input.show(); 2270 $input.trigger('autocompleteChanged'); 2271 }); 2272 2273 2274 $container.addClass('ui-front'); 2275 $input.autocomplete({ 2276 source: function (req, callback) 2277 { 2278 ajax({ 2279 action: data.action, 2280 loader: false, 2281 loadingText: '', 2282 connector: false, 2283 vars: $.extend(true, data.queryString, { 2284 provider: data.provider, 2285 term: req.term 2286 }), 2287 onComplete: function (json) 2288 { 2289 callback(json.data); 2290 } 2291 }); 2292 }, 2293 open: function (e, ui) 2294 { 2295 $container.addClass('focused'); 2296 }, 2297 close: function (e, ui) 2298 { 2299 $container.removeClass('focused'); 2300 }, 2301 select: function (e, ui) 2302 { 2303 $input.attr('data-selected-value', ui.item.value); 2304 $input.val(ui.item.label); 2305 $input.hide(); 2306 $selection.show(); 2307 $selection.find('span').html(ui.item.label).show(); 2308 $input.trigger('autocompleteChanged'); 2309 THIS.triggerChanged(); 2310 return false; 2311 }, 2312 autoFocus: true 2313 }).autocomplete('instance')._renderItem = function (ul, item) 2314 { 2315 var $li = $('<li />').appendTo(ul); 2316 var $div = $('<div />').appendTo($li); 2317 2318 if (item.imageurl !== null && item.imageurl !== '') 2319 { 2320 $('<div class="image" />').css('backgroundImage', 'url(' + item.imageurl + ')').appendTo($div); 2321 $li.attr('data-image', true); 2322 } 2323 2324 $('<div class="ac-label" />').html(item.label).appendTo($div); 2325 return $li; 2326 }; 2327 2328 if (data.value !== '') 2329 { 2330 $input.attr('data-selected-value', data.value); 2331 $input.hide(); 2332 $selection.find('span').html(data.value); 2333 $selection.show(); 2334 } 2335 2336 2337 2338 }; 2339 2340 this.getValue = function () 2341 { 2342 return THIS.$input.attr('data-selected-value'); 2343 }; 2344 2345 this.validate = function () 2346 { 2347 return true; 2348 }; 2349 2350 this.getFieldsToHide = function () 2351 { 2352 if (typeof (data.fieldsToHideOnSelect) === 'undefined') 2353 { 2354 return []; 2355 } 2356 2357 if (data.fieldsToHideOnSelect === null) 2358 { 2359 return []; 2360 } 2361 2362 var currentValue = THIS.getValue(); 2363 if (currentValue === '') 2364 { 2365 return []; 2366 } 2367 2368 return data.fieldsToHideOnSelect; 2369 }; 2370 2371 this.receiveExpectedValue = receiveExpectedValue; 2372 function receiveExpectedValue(key, value) 2373 { 2374 if (typeof (data.queryString) === 'undefined' || data.queryString === null) 2375 { 2376 data.queryString = {}; 2377 } 2378 2379 data.queryString[key] = value; 2380 //console.log(data.variable, 'received expected value from ' + key, value); 2381 } 2382 } 2383 }); 2384 2385 function Form(data, callback) 2386 { 2387 var THIS = this; 2388 var FIELDS = {}; 2389 2390 var $div = null; 2391 this.getElement = function () 2392 { 2393 return $div; 2394 }; 2395 2396 this.getField = function (fieldName) 2397 { 2398 if (typeof (FIELDS[fieldName]) === 'undefined') 2399 { 2400 console.warn('FieldsAPI.Form', 'field not found', fieldName, FIELDS); 2401 return null; 2402 } 2403 2404 return FIELDS[fieldName]; 2405 } 2406 2407 this.getFields = function () 2408 { 2409 return FIELDS; 2410 }; 2411 2412 var $errorMessage = null; 2413 2414 this.toHtml = toHtml; 2415 function toHtml() 2416 { 2417 return $div; 2418 /*
2419 var div = $('<div class="do-input-panel" />'); 2420 getBody().appendTo(div); 2421 2422 $errorMessage = $('<div class="error" />').hide().appendTo(div); 2423 2424 var $fields = $('<div class="fields" />').appendTo(div); 2425 2426 if (data.input.length < data.inputColumns) 2427 { 2428 data.inputColumns = data.input.length; 2429 } 2430 2431 $fields.attr('data-columns', data.inputColumns); 2432 2433 2434 data.input.forEach(function (fieldData) 2435 { 2436 var fieldDef = FIELDS_API.get(fieldData); 2437 var $field = fieldDef.addTo($fields); 2438 2439 FIELDS[fieldData.variable] = fieldDef; 2440 }); 2441 getButtons().appendTo(div); 2442 getSubmitButton().appendTo(div); 2443 startListeners(div); 2444 $div = div; 2445 revealFields(); 2446 updateSubmitButton(); 2447 return div; 2448 */ 2449 } 2450 2451 function factory() 2452 { 2453 var div = $('<div class="do-input-panel" />'); 2454 getBody().appendTo(div); 2455 2456 $errorMessage = $('<div class="error" />').hide().appendTo(div); 2457 2458 var $fields = $('<div class="fields" />').appendTo(div); 2459 2460 if (data.input.length < data.inputColumns) 2461 { 2462 data.inputColumns = data.input.length; 2463 } 2464 2465 $fields.attr('data-columns', data.inputColumns); 2466 2467 2468 data.input.forEach(function (fieldData) 2469 { 2470 var fieldDef = FIELDS_API.get(fieldData); 2471 var $field = fieldDef.addTo($fields); 2472 2473 FIELDS[fieldData.variable] = fieldDef; 2474 }); 2475 $footer = getFooter().appendTo(div); 2476 $submitButtonContainer = getSubmitButton().appendTo(div); 2477 startListeners(div); 2478 revealFields(); 2479 updateSubmitButton(); 2480 return div; 2481 } 2482 2483 function getBody() 2484 { 2485 var div = $('<div />'); 2486 if (data.inputBody !== '') 2487 { 2488 $('<div class="do-input-body" />').html(data.inputBody).appendTo(div);//.append(data.inputBody); 2489 } 2490 2491 if (typeof (data.errorMessage) === 'string' && data.errorMessage !== '') 2492 { 2493 $('<h3 class="error" />').html(data.errorMessage).appendTo(div); 2494 } 2495 2496 return div; 2497 } 2498 2499 var $submitButtonContainer = null; 2500 function getSubmitButton() 2501 { 2502 var div = $('<div class="do-input-container do-submit-container" />'); 2503 if (data.submitButtonDisabled) 2504 { 2505 return div; 2506 } 2507 var button = $('<button class="do-submit" />').appendTo(div); 2508 $('<span />').html(data.inputSubmitLabel).appendTo(button); 2509 $('<i class="fa fa-chevron-right" />').appendTo(button); 2510 return div; 2511 } 2512 2513 var $footer = null; 2514 this.withFooter = withFooter; 2515 function withFooter($content) 2516 { 2517 $footer.append($content); 2518 return THIS; 2519 } 2520 2521 function getFooter() 2522 { 2523 var div = $('<div class="do-input-buttons do-footer" />'); 2524 data.inputButtons.forEach(function (buttonData) 2525 { 2526 var button = $('<a class="button" />').doInputButton(buttonData); 2527 button.appendTo(div); 2528 }); 2529 return div; 2530 } 2531 2532 function startListeners(panel) 2533 { 2534 panel.on('click', 'button.do-submit', function () 2535 { 2536 onSubmit(); 2537 }); 2538 2539 panel.on('keyup', 'textarea', function (e) 2540 { 2541 updateSubmitButton(); 2542 e.stopPropagation(); 2543 }); 2544 2545 panel.on('change', 'textarea', function (e) 2546 { 2547 //triggerOnChange(); 2548 updateSubmitButton(); 2549 e.stopPropagation(); 2550 }); 2551 2552 panel.on('keyup', 'input', function (e) 2553 { 2554 updateSubmitButton(); 2555 if (e.which === 13) 2556 { 2557 onSubmit(); 2558 } 2559 }); 2560 2561 panel.on('change', 'select, input', function () 2562 { 2563 revealFields(); 2564 triggerOnChange(); //may cause problems? 2565 updateSubmitButton(); 2566 }); 2567 2568 panel.on('click', 'input[type="checkbox"]', function () 2569 { 2570 revealFields(); 2571 triggerOnChange(); 2572 updateSubmitButton(); 2573 }); 2574 2575 panel.on('htmlchanged', function () 2576 { 2577 triggerOnChange(); 2578 updateSubmitButton(); 2579 }); 2580 2581 panel.on('autocompleteChanged', function () 2582 { 2583 revealFields(); 2584 triggerOnChange(); 2585 updateSubmitButton(); 2586 2587 }); 2588 2589 panel.on('fieldValueChanged', function (e, sender) 2590 { 2591 var value = sender.getValue(); 2592 $.each(FIELDS, function (key, field) 2593 { 2594 var expectedValues = field.getExpectedValues();
2595 if (expectedValues !== null) 2596 { 2597 if (expectedValues.indexOf(sender.variable) > -1) 2598 { 2599 field.receiveExpectedValue(sender.variable, value); 2600 } 2601 } 2602 }); 2603 triggerOnChange(); 2604 updateSubmitButton(); 2605 }); 2606 2607 } 2608 2609 this.validate = validate; 2610 function validate(addWarnings) 2611 { 2612 if (typeof (addWarnings) === 'undefined') 2613 { 2614 addWarnings = true; 2615 } 2616 2617 var result = true; 2618 $.each(FIELDS, function (key, field) 2619 { 2620 if (!field.validate()) 2621 { 2622 result = false; 2623 if (addWarnings) 2624 { 2625 field.addWarning(); 2626 } 2627 } 2628 else 2629 { 2630 if (addWarnings) 2631 { 2632 field.removeWarning(); 2633 } 2634 2635 } 2636 }); 2637 return result; 2638 } 2639 2640 this.getValues = getValues; 2641 function getValues() 2642 { 2643 var values = {}; 2644 2645 data.input.forEach(function (fieldData) 2646 { 2647 var key = fieldData.variable; 2648 var field = FIELDS[key]; 2649 var value = field.getValue(); 2650 2651 if (typeof (values[key]) !== 'undefined') 2652 { 2653 console.warn('fieldsAPI', 'The field [' + key + '] is defined more than once...'); 2654 } 2655 2656 values[key] = value; 2657 2658 var extraValues = field.getExtraValues(); 2659 if (typeof (extraValues) === 'object') 2660 { 2661 $.each(extraValues, function (k, v) 2662 { 2663 values[key + k] = v; 2664 2665 }); 2666 } 2667 2668 fieldData.value = value; 2669 }); 2670 2671 return values; 2672 } 2673 2674 function isReadyToSubmit() 2675 { 2676 return validate(false); 2677 } 2678 2679 function updateSubmitButton() 2680 { 2681 $submitButtonContainer.attr('data-submit-ready', isReadyToSubmit()); 2682 //$div.find('.do-submit-container').attr('data-submit-ready', isReadyToSubmit()); 2683 } 2684 2685 function allowResubmit() 2686 { 2687 return $div.parent().attr('data-allow-resubmit') === 'true'; 2688 } 2689 2690 var isAllowMultiSubmit = false; 2691 this.allowMultiSubmit = allowMultiSubmit; 2692 function allowMultiSubmit() 2693 { 2694 isAllowMultiSubmit = true; 2695 return THIS; 2696 } 2697 2698 var isSubmitted = false; 2699 function onSubmit() 2700 { 2701 if (!validate(true)) 2702 { 2703 return; 2704 } 2705 2706 //if (!allowResubmit() && isSubmitted) 2707 if (!isAllowMultiSubmit && isSubmitted) 2708 { 2709 console.warn('fieldsapi.form', 'already submitted'); 2710 return; 2711 } 2712 2713 clearErrrorMessage(); 2714 2715 isSubmitted = true; 2716 callback(getValues(), function (errorMessage) 2717 { 2718 setErrorMessage(errorMessage); 2719 console.warn('fieldsapi.form', 'submit failed'); 2720 isSubmitted = false; 2721 updateSubmitButton(); 2722 }); 2723 } 2724 2725 function revealFields() 2726 { 2727 var fieldsToReveal = []; 2728 var fieldsToHide = []; 2729 2730 $.each(FIELDS, function (name, field) 2731 { 2732 try 2733 { 2734 var toReveal = field.followUps.getFieldsToReveal(field.getValue()); 2735 //console.log('Form.revealFields', toReveal); 2736 if (toReveal.length > 0) 2737 { 2738 toReveal.forEach(function (f) 2739 { 2740 fieldsToReveal.push(f); 2741 }); 2742 } 2743 2744 var toHide = field.getFieldsToHide(); 2745 if (toHide.length > 0) 2746 { 2747 toHide.forEach(function (f) 2748 {
2749 fieldsToHide.push(f); 2750 }); 2751 } 2752 2753 } 2754 catch (e) 2755 { 2756 console.warn('fields-api.Form.revealFields()', e); 2757 } 2758 2759 field.unReveal(); //reset 2760 2761 /* 2762 //hide followUps here 2763 toReveal.forEach(function (fieldName) 2764 { 2765 if (typeof (FIELDS[fieldName]) !== 'undefined') 2766 { 2767 FIELDS[fieldName].unReveal(); 2768 console.warn('Form', fieldName, 'unReveal'); 2769 } 2770 }); 2771 */ 2772 field.unHide(); 2773 }); 2774 2775 fieldsToReveal.forEach(function (fieldName) 2776 { 2777 if (typeof (FIELDS[fieldName]) !== 'undefined') 2778 { 2779 FIELDS[fieldName].reveal(); 2780 //console.warn('Form', fieldName, 'reveal'); 2781 } 2782 }); 2783 2784 fieldsToHide.forEach(function (fieldName) 2785 { 2786 if (typeof (FIELDS[fieldName]) !== 'undefined') 2787 { 2788 FIELDS[fieldName].hide(); 2789 } 2790 2791 }); 2792 } 2793 2794 function clearErrrorMessage() 2795 { 2796 $errorMessage.html('').hide().removeClass('active'); 2797 } 2798 2799 function setErrorMessage(message) 2800 { 2801 $errorMessage.html(message).show().addClass('active'); 2802 } 2803 2804 var plugins = []; 2805 function addPlugins() 2806 { 2807 if (typeof (data.plugins) !== 'object') 2808 { 2809 return; 2810 } 2811 2812 if (data.plugins.length === 0) 2813 { 2814 return; 2815 } 2816 2817 plugins = []; 2818 data.plugins.forEach(function (pluginName) 2819 { 2820 var plugin = FIELDS_API.plugins.get(pluginName); 2821 if (plugin !== null) 2822 { 2823 plugins.push(new plugin(THIS)); 2824 } 2825 }); 2826 2827 2828 } 2829 2830 var onChangeCallbacks = []; 2831 this.onChange = onChange; 2832 function onChange(callback) 2833 { 2834 onChangeCallbacks.push(callback); 2835 return THIS; 2836 } 2837 2838 function triggerOnChange() 2839 { 2840 var values = getValues(); 2841 onChangeCallbacks.forEach(function (cb) 2842 { 2843 cb(values); 2844 }); 2845 } 2846 2847 function start() 2848 { 2849 $div = factory(); 2850 addPlugins(); 2851 2852 } 2853 2854 start(); 2855 } 2856 2857 function TabbedForm(panelInputData, callback) 2858 { 2859 var THIS = this; 2860 var maxIndex = panelInputData.tabs.length - 1; 2861 var currentIndex = -1; 2862 var $slider = null; 2863 var $controls = null; 2864 var $element = null; 2865 var $breadcrumbsContainer = null; 2866 var $errorMessage = null; 2867 this.$breadcrumbsContainer = null; 2868 this.$pages = null; 2869 var tabs = []; 2870 2871 this.toHtml = toHtml; 2872 this.getElement = toHtml; 2873 function toHtml() 2874 { 2875 if ($element !== null) 2876 { 2877 return $element; 2878 } 2879
2880 var $container = $('<div class="do-input-tabbed-form" />'); 2881 2882 if (typeof (panelInputData.inputBody) !== 'undefined') 2883 { 2884 if (panelInputData.inputBody !== null) 2885 { 2886 $('<div class="body" />').html(panelInputData.inputBody).appendTo($container); 2887 } 2888 } 2889 2890 if (typeof (panelInputData.errorMessage) === 'string' && panelInputData.errorMessage !== '') 2891 { 2892 $('<h3 class="error" />').html(panelInputData.errorMessage).appendTo($container); 2893 } 2894 2895 2896 $element = $container; 2897 $breadcrumbsContainer = $('<div class="breadcrumbs" />').appendTo($container); 2898 THIS.$breadcrumbsContainer = $breadcrumbsContainer; 2899 2900 $errorMessage = $('<div class="error-message" />').appendTo($container); 2901 2902 $slider = $('<div class="slider" />').appendTo($container); 2903 $slider.on('keyup', function () 2904 { 2905 setTimeout(function () 2906 { 2907 $slider.scrollLeft(0); 2908 }, 100); 2909 }); 2910 2911 var $pages = $('<div class="category-sliders" />').appendTo($slider); 2912 THIS.$pages = $pages; 2913 2914 $controls = $('<div class="controls" />').appendTo($container); 2915 $('<a class="button previous" data-previous-button><i class="fa fa-chevron-left"></i><span>Previous</span></a>').appendTo($controls); 2916 $('<a class="button next" data-next-button><span>Next</span><i class="fa fa-chevron-right"></i></a>').appendTo($controls); 2917 var $submitButton = $('<a class="button submit" data-submit-button role="button" />').appendTo($controls); 2918 $('<span />').html(panelInputData.inputSubmitLabel).appendTo($submitButton); 2919 $('<i class="fa fa-chevron-right" />').appendTo($submitButton); 2920 setFieldTabIndexes(); 2921 var index = 0;
2922 panelInputData.tabs.forEach(function (input) 2923 { 2924 tabs.push(new TabbedFormTab(THIS, input, index)); 2925 index++; 2926 }); 2927 2928 //getSubmitButton().appendTo($controls); 2929 startListeners($pages); 2930 2931 $controls.on('click', '.button.submit', function () 2932 { 2933 onSubmit(); 2934 }); 2935 2936 $controls.on('click', '.button.next', function () 2937 { 2938 next(); 2939 }); 2940 2941 $controls.on('click', '.button.previous', function () 2942 { 2943 previous(); 2944 }); 2945 2946 $breadcrumbsContainer.on('click', '.breadcrumb', function () 2947 { 2948 toPage($(this).index()); 2949 }); 2950 2951 updateSubmitButton(); 2952 toPage(0); 2953 return $container; 2954 } 2955 2956 2957 function setFieldTabIndexes() 2958 { 2959 var index = 100; 2960 panelInputData.tabs.forEach(function (tab) 2961 { 2962 tab.input.forEach(function (field) 2963 { 2964 field.index = index; 2965 index++; 2966 }); 2967 }); 2968 2969 } 2970 2971 2972 function startListeners(panel) 2973 { 2974 2975 panel.on('keyup', 'textarea', function (e) 2976 { 2977 updateSubmitButton(); 2978 e.stopPropagation(); 2979 }); 2980 2981 panel.on('keyup', 'input', function (e) 2982 { 2983 updateSubmitButton(); 2984 /* 2985 if (e.which === 13) 2986 { 2987 if (currentIndex === maxIndex) 2988 { 2989 onSubmit(); 2990 } else 2991 { 2992 next(); 2993 } 2994 2995 } 2996 */ 2997 }); 2998 2999 panel.on('focus', '.do-input-panel input,select,textarea', function () 3000 { 3001 var index = $(this).parents().filter('.do-input-panel').index(); 3002 toPage(index); 3003 }); 3004 3005 panel.on('change', 'select', function () 3006 { 3007 updateSubmitButton(); 3008 }); 3009 3010 panel.on('click', 'input[type="checkbox"]', function () 3011 { 3012 updateSubmitButton(); 3013 }); 3014 3015 panel.on('htmlchanged', function () 3016 { 3017 updateSubmitButton(); 3018 }); 3019 3020 panel.on('fieldValueChanged', function (e, sender) 3021 { 3022 updateSubmitButton();
3023 tabs.forEach(function (tab) 3024 { 3025 tab.receiveExpectedValue(sender); 3026 }); 3027 3028 }); 3029 3030 3031 3032 } 3033 3034 this.validate = validate; 3035 function validate(addWarnings) 3036 { 3037 if (typeof (addWarnings) === 'undefined') 3038 { 3039 addWarnings = true; 3040 } 3041 3042 var result = true; 3043 var firstInvalidatedTabIndex = null; 3044 3045 var index = 0; 3046 tabs.forEach(function (tab) 3047 { 3048 if (!tab.validate(addWarnings)) 3049 { 3050 if (firstInvalidatedTabIndex === null) 3051 { 3052 firstInvalidatedTabIndex = index; 3053 } 3054 result = false; 3055 } 3056 index++; 3057 }); 3058 3059 if (addWarnings) 3060 { 3061 if (firstInvalidatedTabIndex !== null) 3062 { 3063 toPage(firstInvalidatedTabIndex); 3064 } 3065 } 3066 3067 return result; 3068 } 3069 3070 function isReadyToSubmit() 3071 { 3072 return validate(false); 3073 } 3074 3075 3076 this.getValues = getValues; 3077 function getValues() 3078 { 3079 var values = {}; 3080 tabs.forEach(function (tab) 3081 { 3082 $.each(tab.getValues(), function (k, v) 3083 { 3084 if (typeof (values[k]) !== 'undefined') 3085 { 3086 console.warn('fieldsAPI', 'The field [' + k + '] is defined more than once...'); 3087 } 3088 values[k] = v; 3089 }); 3090 //values = $.extend(values, tab.getValues()); 3091 }); 3092 return values; 3093 } 3094 3095 var isAllowMultiSubmit = false; 3096 this.allowMultiSubmit = allowMultiSubmit; 3097 function allowMultiSubmit() 3098 { 3099 isAllowMultiSubmit = true; 3100 return THIS; 3101 } 3102 3103 function onSubmit() 3104 { 3105 clearErrrorMessage(); 3106 if (!validate()) 3107 { 3108 setErrorMessage('<p>Please fill in the missing information outlined below.</p>'); 3109 return; 3110 } 3111 3112 callback(getValues()); 3113 } 3114 3115 function updateSubmitButton() 3116 { 3117 $controls.attr('data-submit-ready', isReadyToSubmit()); 3118 } 3119 3120 function clearErrrorMessage() 3121 { 3122 $errorMessage.html('').removeClass('active'); 3123 } 3124 3125 function setErrorMessage(message) 3126 { 3127 $errorMessage.html(message).addClass('active'); 3128 } 3129 3130 3131 //CONTROLS 3132 3133 3134 function toPage(index) 3135 { 3136 if (currentIndex === index) 3137 { 3138 return; 3139 } 3140 3141 $slider.find('.do-input-panel').removeClass('active'); 3142 $breadcrumbsContainer.find('.breadcrumb').removeClass('active'); 3143 3144 //$slider.find('.do-input-panel').eq(index).addClass('active').data('TabbedFormTab').focus(); 3145 $slider.find('.do-input-panel').eq(index).data('TabbedFormTab').focus(); 3146 $element.attr('data-page', index); 3147 //$slider.addClass('started'); 3148 currentIndex = index; 3149 //var $breadcrumbs = $breadcrumbsContainer.find('.breadcrumb'); 3150 //$breadcrumbs.removeClass('active'); 3151 //$breadcrumbs.eq(index).addClass('active'); 3152 updateControls(currentIndex); 3153 } 3154 3155 function updateControls(currentIndex) 3156 { 3157 if (currentIndex === 0) 3158 { 3159 $controls.addClass('first'); 3160 } else 3161 { 3162 $controls.removeClass('first'); 3163 } 3164 3165 if (currentIndex === maxIndex) 3166 { 3167 $controls.addClass('last'); 3168 } else 3169 { 3170 $controls.removeClass('last'); 3171 } 3172 3173 updateSubmitButton(); 3174 } 3175 3176 function scrollToTop() 3177 { 3178 window.scrollTo(0, $breadcrumbsContainer[0].getBoundingClientRect().top); 3179 } 3180 3181 3182 function next() 3183 { 3184 var index = currentIndex + 1; 3185 if (index > maxIndex) 3186 { 3187 index = maxIndex; 3188 } 3189 toPage(index); 3190 scrollToTop(); 3191 } 3192 3193 function previous() 3194 { 3195 var index = currentIndex - 1; 3196 if (index < 0) 3197 { 3198 index = 0; 3199 } 3200 toPage(index); 3201 scrollToTop(); 3202 } 3203 3204 var plugins = []; 3205 function addPlugins() 3206 { 3207 if (typeof (panelInputData.plugins) !== 'object') 3208 { 3209 return; 3210 } 3211 3212 if (panelInputData.plugins.length === 0) 3213 { 3214 return; 3215 } 3216 3217 plugins = []; 3218 panelInputData.plugins.forEach(function (pluginName) 3219 { 3220 var plugin = FIELDS_API.plugins.get(pluginName); 3221 if (plugin !== null) 3222 { 3223 plugins.push(new plugin(THIS)); 3224 } 3225 }); 3226 3227 3228 } 3229 3230 this.getField = getField; 3231 function getField(name) 3232 { 3233 var result = null;
3234 tabs.forEach(function (tab) 3235 { 3236 if (result === null) 3237 { 3238 result = tab.getField(name); 3239 } 3240 3241 }); 3242 3243 if (result === null) 3244 { 3245 console.warn('Field not found', name); 3246 } 3247 3248 return result; 3249 } 3250 3251 function start() 3252 { 3253 addPlugins(); 3254 3255 } 3256 3257 start(); 3258 } 3259 3260 function TabbedFormTab(form, data, index) 3261 { 3262 var THIS = this; 3263 var FIELDS = {}; 3264 var $breadcrumb = null; 3265 var $panel = null; 3266 3267 function start() 3268 { 3269 $breadcrumb = getTabBreadcrumb().appendTo(form.$breadcrumbsContainer); 3270 $panel = getTabHtml().appendTo(form.$pages); 3271 3272 3273 $panel.on('change', 'select, input', function () 3274 { 3275 revealFields(); 3276 }); 3277 3278 $panel.on('click', 'input[type="checkbox"]', function () 3279 { 3280 revealFields(); 3281 }); 3282 3283 $panel.on('autocompleteChanged', function () 3284 { 3285 revealFields(); 3286 }); 3287 revealFields(); 3288 3289 $panel.data('TabbedFormTab', THIS); 3290 } 3291 3292 function getTabBreadcrumb() 3293 { 3294 var $div = $('<div class="breadcrumb" />').attr('data-index', index); 3295 var name = $('<div class="name" />').appendTo($div); 3296 $('<span />').html(data.inputTitle).appendTo(name); 3297 $('<i class="fa fa-exclamation-triangle" />').prependTo(name); 3298 $('<i class="fa fa-check-circle" />').appendTo(name); 3299 return $div; 3300 } 3301 3302 var $fields = null; 3303 3304 function getTabHtml() 3305 { 3306 var div = $('<div class="do-input-panel" />'); 3307 getBody().appendTo(div); 3308 3309 $fields = $('<div class="fields" />').appendTo(div); 3310 3311 if (data.input.length < data.inputColumns) 3312 { 3313 data.inputColumns = data.input.length; 3314 } 3315 3316 $fields.attr('data-columns', data.inputColumns); 3317 3318 data.input.forEach(function (fieldData) 3319 { 3320 var fieldDef = FIELDS_API.get(fieldData); 3321 var $field = fieldDef.addTo($fields); 3322 3323 FIELDS[fieldData.variable] = fieldDef; 3324 }); 3325 3326 return div; 3327 } 3328 3329 function getBody() 3330 { 3331 var div = $('<div />'); 3332 3333 if (data.inputBody !== '') 3334 { 3335 $('<div class="do-input-body" />').html(data.inputBody).appendTo(div); 3336 } 3337 return div; 3338 } 3339 3340 this.validate = validate; 3341 function validate(addWarnings) 3342 { 3343 if (typeof (addWarnings) === 'undefined') 3344 { 3345 addWarnings = true; 3346 } 3347 3348 var result = true; 3349 3350 if (addWarnings) 3351 { 3352 clearValidation(); 3353 } 3354 3355 $.each(FIELDS, function (key, field) 3356 { 3357 if (!field.validate()) 3358 { 3359 result = false; 3360 if (addWarnings) 3361 { 3362 field.addWarning(); 3363 } 3364 3365 } 3366 else 3367 { 3368 if (addWarnings) 3369 { 3370 field.removeWarning(); 3371 } 3372 3373 } 3374 }); 3375 3376 if (addWarnings) 3377 { 3378 if (result === false) 3379 { 3380 setAsValidationFailed(); 3381 } 3382 else 3383 { 3384 setAsValidationSuccess(); 3385 } 3386 } 3387 return result; 3388 } 3389 3390 function clearValidation() 3391 { 3392 $breadcrumb.removeClass('validation-failed').removeClass('validation-succeeded'); 3393 } 3394 3395 function setAsValidationFailed() 3396 { 3397 $breadcrumb.addClass('validation-failed'); 3398 } 3399 3400 function setAsValidationSuccess() 3401 { 3402 $breadcrumb.addClass('validation-succeeded'); 3403 } 3404 3405 this.getValues = getValues; 3406 function getValues() 3407 { 3408 var values = {}; 3409 $.each(FIELDS, function (name, field) 3410 { 3411 //var key = field.variable; 3412 //var field = FIELDS[key]; 3413 if (typeof (values[name]) !== 'undefined') 3414 { 3415 console.warn('fieldsAPI', 'The field ' + name + ' is defined more than once'); 3416 } 3417 3418 var value = field.getValue(); 3419 values[name] = value; 3420 var extraValues = field.getExtraValues(); 3421 if (typeof (extraValues) === 'object') 3422 { 3423 $.each(extraValues, function (k, v) 3424 { 3425 values[name+k] = v; 3426 3427 }); 3428 } 3429 3430 //fieldData.value = value; 3431 3432 }); 3433 3434 /* 3435 data.input.forEach(function (fieldData) 3436 { 3437 var key = fieldData.variable; 3438 var field = FIELDS[key]; 3439 var value = field.getValue(); 3440 values[key] = value; 3441 fieldData.value = value; 3442 }); 3443 */ 3444 return values; 3445 } 3446 3447 function revealFields() 3448 { 3449 //console.log('revealFields()'); 3450 var fieldsToReveal = []; 3451 var fieldsToHide = []; 3452 //var inputsToAdd = []; 3453 3454 $.each(FIELDS, function (name, field) 3455 { 3456 try 3457 {
3458 var toReveal = field.followUps.getFieldsToReveal(field.getValue()); 3459 //console.log(name, toReveal); 3460 if (toReveal.length > 0) 3461 { 3462 toReveal.forEach(function (f) 3463 { 3464 fieldsToReveal.push(f); 3465 }); 3466 } 3467 3468 var toHide = field.getFieldsToHide(); 3469 if (toHide.length > 0) 3470 { 3471 toHide.forEach(function (f) 3472 { 3473 fieldsToHide.push(f); 3474 }); 3475 } 3476 3477 3478 3479 3480 } 3481 3482 catch (e) 3483 { 3484 console.warn('fields-api.TabbedFormTab.revealFields()', e); 3485 } 3486 3487 field.unReveal(); //reset 3488 field.unHide(); 3489 }); 3490 3491 fieldsToReveal.forEach(function (fieldName) 3492 { 3493 if (typeof (FIELDS[fieldName]) !== 'undefined') 3494 { 3495 FIELDS[fieldName].reveal(); 3496 } 3497 else 3498 { 3499 console.warn('fieldsToReveal', 'could not find field: ' + fieldName); 3500 } 3501 }); 3502 3503 fieldsToHide.forEach(function (fieldName) 3504 { 3505 if (typeof (FIELDS[fieldName]) !== 'undefined') 3506 { 3507 FIELDS[fieldName].hide(); 3508 } 3509 else 3510 { 3511 console.warn('fieldsToHide', 'could not find field: ' + fieldName); 3512 } 3513 3514 }); 3515 3516 insertFields(); 3517 3518 /* 3519 inputsToAdd.forEach(function (input) 3520 { 3521 input.input.forEach(function (fieldData) 3522 { 3523 if (typeof (FIELDS[fieldData.variable]) === 'undefined') 3524 { 3525 var fieldDef = FIELDS_API.get(fieldData); 3526 var $field = fieldDef.addTo($fields); 3527 FIELDS[fieldData.variable] = fieldDef; 3528 data.input.push(fieldData); 3529 } 3530 }); 3531 console.log('inputToAdd', input); 3532 }); 3533 */ 3534 } 3535 3536 function insertFields() 3537 { 3538 $.each(FIELDS, function (name, field) 3539 { 3540 insertFieldFields(field); 3541 }); 3542 } 3543 3544 function insertFieldFields(field) 3545 { 3546 var toInserts = field.followUps.getFieldsToInsert(); 3547 //console.log('insertFieldFields', field.variable, toInserts); 3548 3549 var inserted = []; 3550 3551 toInserts.forEach(function (fieldData) 3552 { 3553 inserted.push(fieldData.variable); 3554 if (typeof (FIELDS[fieldData.variable]) === 'undefined') 3555 { 3556 var fieldDef = FIELDS_API.get(fieldData); 3557 //var $field = fieldDef.addTo($fields); 3558 var $subForm = field.$container.find('.sub-form'); 3559 if ($subForm.length === 0) 3560 { 3561 $subForm = $('<div class="sub-form" />').appendTo(field.$container); 3562 } 3563 3564 var $field = fieldDef.addTo($subForm); 3565 3566 $field.attr('data-inserted-by', field.variable); 3567 FIELDS[fieldData.variable] = fieldDef; 3568 //console.log('inserted', fieldData.variable); 3569 } 3570 }); 3571 3572 $fields.find('[data-inserted-by="' + field.variable + '"]').each(function () 3573 { 3574 var $field = $(this); 3575 var key = $field.data('variable'); 3576 if (inserted.indexOf(key) === -1) 3577 { 3578 removeField(key); 3579 } 3580 }); 3581 3582 } 3583 3584 function removeField(fieldVariable) 3585 { 3586 //console.log('removeField', fieldVariable); 3587 var fields = {}; 3588 $.each(FIELDS, function (name, field) 3589 { 3590 if (name !== fieldVariable) 3591 { 3592 fields[name] = field; 3593 } 3594 }); 3595 3596 $fields.find('[data-variable="' + fieldVariable + '"]').remove(); 3597 FIELDS = fields; 3598 } 3599 3600 this.receiveExpectedValue = receiveExpectedValue; 3601 function receiveExpectedValue(sender) 3602 { 3603 var value = sender.getValue(); 3604 $.each(FIELDS, function (key, field) 3605 { 3606 var expectedValues = field.getExpectedValues(); 3607 if (expectedValues !== null) 3608 { 3609 if (expectedValues.indexOf(sender.variable) > -1) 3610 { 3611 field.receiveExpectedValue(sender.variable, value); 3612 } 3613 } 3614 }); 3615 } 3616 3617 this.focus = focus; 3618 function focus() 3619 { 3620 $panel.addClass('active'); 3621 $breadcrumb.addClass('active'); 3622 $.each(FIELDS, function (k, field) 3623 { 3624 field.onTabFocus(); 3625 }); 3626 } 3627 3628 this.getField = getField; 3629 function getField(name) 3630 { 3631 if (typeof (FIELDS[name]) === 'undefined') 3632 { 3633 return null; 3634 } 3635 3636 return FIELDS[name]; 3637 3638 } 3639 3640 start(); 3641 } 3642 3643 }); 3644 3645 3646})();
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.