1var defaultState; // first state of app 2var initialState; 3 4document.addEventListener('DOMContentLoaded', function() { 5 6 /** 7 * When app first starts we create the initial state of the redux store from 8 * data embeded in the html on the page. 9 * 10 * We keep a backup of this initial state in `defaultState` 11 * 12 * @return {Object} The initial state of the store 13 */ 14 initialState = function initialState() { 15 var fields = d$$('.js-form-element'); 16 17 var initState = { 18 canSubmitForm: false, 19 formDirty : false, // true if submit button was pressed 20 fields : {}, 21 }; 22 23 fields.forEach(function(field) { 24 var name = field.getAttribute('data-name'); 25 var fieldType = field.getAttribute('data-field-type'); 26 27 // All fields needs a name 28 if(name === null || name === '') 29 console.error('There is no name for: ', field); 30 31 // All fields need different names 32 if(initState.fields[name]) 33 console.error('There are multiple fields with the name: ' + name); 34 35 // All fields needs a type 36 if(fieldType === null || fieldType === '') 37 console.error('There is no field type for: ', field); 38 39 // field wrappers are only tracked if they have errors 40 if(fieldType === 'field-wrapper') { 41 var errors = field.querySelectorAll('[data-name="' + name + '"] > .js-error'); // see if there are error messages 42 if(errors.length > 0) 43 initState.fields[name] = initMethods[fieldType](field); 44 } 45 else if(initMethods[fieldType]) 46 initState.fields[name] = initMethods[fieldType](field); 47 48 }); 49 50 defaultState = initState; 51 return initState; 52 } 53 54 /** 55 * A higher-order function that takes function which return the value from an input type 56 * and wraps them with all the other behavior an init function needs; 57 * 58 * @param {Function} fn A function that, given a field an inputs, returns a value 59 * @return {Function} A function that will handle getting the initial value for an input 60 */ 61 function generateInitFunc(fn) { 62 return function(field) { 63 var fieldName = field.getAttribute('data-name'); 64 var typeOfField = field.getAttribute('data-field-type'); 65 var inputs = field.querySelectorAll('.js-input'); 66 var value = (typeOfField === 'field-wrapper') ? '' : fn(field, inputs); 67 var dirty = ( 68 (typeOfField !== 'field-wrapper') ? false 69 : (typeOfField === 'input-radio-collection') ? value.length > 0 70 : (value !== null && value !== '') 71 ); 72 var subFields = typeOfField === 'field-wrapper' ? value : []; 73 var errors = initializeErrors(d$$('[data-name="' + fieldName + '"] > .js-error')); 74 75 return { 76 value : value, 77 dirty : dirty, 78 errors : errors, 79 serverErrors: false, 80 subFields : subFields, 81 }; 82 } 83 } 84 85 /** 86 * Generate error state data from DOM 87 * 88 * @param {NodeList} errors list of labels with error state information 89 * @return {array} represents the error state for an input 90 */ 91 function initializeErrors(errors){ 92 return errors.map(function(label) { 93 var validator = label.getAttribute('data-validator'); 94 var args = validator.split(','); 95 96 return (validator === '') 97 ? null 98 : { 99 validator: validator, 100 validationFunc: args[0], 101 args : args.splice(1), 102 hasError : false, 103 } 104 }).filter(nullFilter); 105 } 106 107 /** 108 * Because a number of the inputs are initialized in the same manner, this 109 * function is sufficient to use. 110 * 111 * @param {Object} field The field element itself 112 * @param {NodeList} inputs The inputs in the field 113 * @return {string} The initial value of the field for the store 114 */ 115 function simpleFieldInitializer(field, inputs) { 116 var input = inputs[0]; 117 var defaultValue = input.value || field.getAttribute('data-default-value'); 118 119 if(defaultValue) 120 field.classList.add('field-entered'); 121 122 if(field.getAttribute('data-default-value') !== null) 123 input.value = defaultValue; 124 125 field.setAttribute('data-disabled', input.disabled); 126 127 return input.value || ''; 128 } 129 130 // functions for creating an initial state from a field 131 // All they are expected to do is return the initial value of the field 132 // N.B. All functions are generated using a higher order function 133 var initMethods = { 134 'input-text' : generateInitFunc(simpleFieldInitializer), 135 'input-textarea' : generateInitFunc(simpleFieldInitializer), 136 'input-text-optional-mask' : generateInitFunc(simpleFieldInitializer), 137 'input-select' : generateInitFunc(simpleFieldInitializer), 138 // collections 139 'input-radio-collection' : generateInitFunc(function(field, inputs) { 140 var defaultValue = ''; 141 var disabled = false;
142 143 // If we have a default value, turn that on 144 inputs.forEach(function(input) { 145 if(input.checked) 146 defaultValue = input.value; 147 148 disabled = disabled || input.disabled; 149 }); 150 151 field.setAttribute('data-disabled', disabled); 152 153 return defaultValue || null; 154 }), 155 'input-checkbox-collection' : generateInitFunc(function(field, inputs) { 156 var defaultValues = []; 157 var disabled = false; 158 159 inputs.map(function(input) { 160 disabled = disabled || input.disabled; 161 return input.checked ? input.value : null; 162 }).filter(nullFilter); 163 164 field.setAttribute('data-disabled', disabled); 165 166 return defaultValues; 167 }), 168 'field-wrapper': generateInitFunc(function(field) { 169 var name = field.getAttribute('data-name'); 170 var subFields = d$$('[data-name="' + name + '"] > .js-form-element'); 171 return subFields.map(function(field) { 172 return field.getAttribute('data-name'); 173 }); 174 }), // value for field-wrapper is '' 175 } 176 177})
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.