1'use strict' 2 3/** 4 * 5 * Dependencies: Validator object (validator.js) for doing basic validtion 6 */ 7const formUtils = function(){ 8 9 const getContainer = function(options){ 10 let container; 11 12 if (options.container){ 13 container = options.container; 14 } 15 else if (options.containerSelector) { 16 container = $(options.containerSelector); 17 } 18 else 19 container = $("body"); 20 21 return container; 22 } 23 24 25 //#region objectfiller 26 27 const objectFiller = {}; 28 29 /** 30 * Fills-out an objec from html fields 31 * @param {*} options 32 * containerSelector: string defining the container. 33 * container: jquery element, usually a div. Either containereSelector or container need to be fed 34 * skipSelector: elements fulfilling this criteria won't be included on the object 35 * dataIdAttribute: alternative identifier for fields, this is used on dynamic generated forms in which ids wouldn't be unique 36 * specialControlList : array of elements [{ name, is, get}] that contain functions to fill-out object values out of controls like kendo. 37 * name: Name of control, this is for developer reference only. 38 * is: Function that returns true if an html control is processed as a special control. 39 * get: Function used to get value fom control. 40 * @returns javascript object contianing fields 41 */ 42 objectFiller.htmlToObject = function(options){ 43 const objectToFill = {}; 44 let selector = "input{notSelector}, select{notSelector}, textarea{notSelector}"; 45 let notSelector = ""; 46 const container = getContainer(options); 47 48 49 if (options.skipSelector){ 50 notSelector += (notSelector === "" ? "" : ", ") + ":not(" + options.skipSelector + ")"; 51 } 52 selector = selector.replace(/{notSelector}/g, notSelector); 53 54 container.find(selector).each(function(i,e) { 55 const input = $(e); 56 const type = input.prop("type"); 57 let id; 58 const name = input.attr("name"); 59 let isInputChecked; 60 61 if (options.dataIdAttribute){ 62 id = input.data(options.dataIdAttribute); 63 } 64 else{ 65 id = input.attr("id"); 66 } 67 68 //begin: test and get value out of special control list (this is the list of controls that is injected) 69 let valueOptions = {}; 70 if (options.specialControlList && options.specialControlList.length > 0){ 71 valueOptions = testAndGetValueFromSpecialElementList(input, options.specialControlList); 72 if (valueOptions.foundInSpecialElementList) 73 objectToFill[id] = validator.stripHTMLTags(valueOptions.value); 74 } 75 if (valueOptions.foundInSpecialElementList) 76 return; 77 //end 78 79 if (type==="file" || type==="button" || type==="submit" || type==="color" 80 || type==="image" || type==="reset" || type==="search" 81 || ((!id || id === "") && type !== "radio") ){ 82 return; 83 } 84 85 //uses boolean 'checked' attribute to get selected radio and stores whatever value is stored on the control 86 if(type === "radio" ) { 87 88 if (input.is (":checked")){ 89 if (options.dataIdAttribute){ 90 objectToFill[id] = input.val(); 91 } 92 else{ 93 objectToFill[name] = input.val(); 94 } 95 } 96 97 } 98 99 //uses boolean 'checked' attribute as values for checkboxes 100 else if(type === "checkbox") { 101 isInputChecked = input.is(":checked"); 102 objectToFill[id] = isInputChecked ? "y" : "n"; 103 } 104 105 else { //all other elements for which 'val' applies, select and all input type={inputtype} 106 107 //for numeric inputs, set value to 'null' if value is empty 108 const isNumber = input.prop("type") === "number"; 109 110 if (isNumber && input.val() === ""){ 111 objectToFill[id] = "null"; 112 } 113 else 114 //objectToFill[id] = input.val(); 115 objectToFill[id] = validator.stripHTMLTags(input.val()); 116 } 117 }); 118 119 return objectToFill; 120 } 121 122 123 124 125 /** 126 * Fills-out html elements from a javascript object 127 * @param {*} options 128 * containerSelector: string defining the container, optional 129 * container: jquery element, usually a div, optional, 130 * data: Data to fill-out 131 * dataIdAttribute: alternative identifier for fields, this is used on dynamic generated forms in which ids wouldn't be unique 132 * specialControlList : array of elements [{ name, is, get}
132] that contain functions to fill-out object values out of controls like kendo. 133 * name: Name of control, this is for developer reference only. 134 * is: Function that returns true if an html control is processed as a special control. 135 * set: Function used to get value fom control. 136 * @returns 137 */ 138 objectFiller.objectToHtml = function(options){ 139 140 const container = getContainer(options); 141 142 for (const prop in options.data) { 143 144 let elementName = ""; 145 let elementById; 146 let elementByName; 147 let alreadyProcessedBySpecialElement = false; 148 149 //begin: test and get value out of special control list (this is the list of controls that is injected) 150 let valueOptions = {}; 151 let scElement; 152 if (options.specialControlList && options.specialControlList.length > 0){ 153 if (options.dataIdAttribute) 154 scElement = container.find("["+ options.dataIdAttribute + "=" + prop + "]"); 155 else 156 scElement = container.find("#" + prop); 157 valueOptions = testAndSetValueFromSpecialElementList($(scElement), options.data[prop], options.specialControlList); 158 if (valueOptions.foundInSpecialElementList) 159 alreadyProcessedBySpecialElement = true; 160 } 161 //end 162 163 164 if (options.dataIdAttribute){ 165 elementById = container.find("input["+ options.dataIdAttribute + "=" + prop + "], textarea["+ options.dataIdAttribute + "=" + prop + "], select["+ options.dataIdAttribute + "=" + prop + "]"); 166 elementByName = []; 167 } 168 else{ 169 elementByName = container.find("input[name='" + prop + "'], textarea[name='" + prop + "'], select[name='" + prop + "']"); 170 elementById = container.find("#" + prop); 171 } 172 173 if (Object.prototype.hasOwnProperty.call(options.data, prop) && (elementById.length || elementByName.length) && !alreadyProcessedBySpecialElement) { 174 175 const input = $(elementById); 176 if (!input.length){ 177 input = $($(elementByName)[0]);//assuming radiobutton 178 elementName = input.prop("name"); 179 } 180 if (!input) 181 return; //html element counterpart does not exist 182 183 const type = input.prop("type"); 184 185 if(type === "radio" ) { 186 if (options.data[prop]){ 187 if (options.dataIdAttribute ){ 188 container.find("input["+ options.dataIdAttribute + "=" + prop + "][value=" + options.data[prop] + "]").prop('checked', true); 189 } 190 else{ 191 $("input[name=" + elementName + "][value=" + options.data[prop] + "]").prop('checked', true); 192 } 193 } 194 } 195 196 else if(type === "checkbox") { 197 if(options.data[prop] ==="y") 198 input.prop("checked", true); 199 } 200 201 else { //all other elements for which 'val' applies, select and all input type={inputtype} 202 input.val(validator.stripHTMLTags(options.data[prop])); 203 } 204 205 } 206 } 207 } 208 209 function testAndGetValueFromSpecialElementList(element, specialControlList){ 210 let returnOptions = { value: null, foundInSpecialElementList:false}; 211 specialControlList.forEach(function(specialControl){ 212 if (specialControl.isSpecialElement(element)){ 213 returnOptions.value = specialControl.get(element); 214 returnOptions.foundInSpecialElementList = true; 215 } 216 }); 217 return returnOptions; 218 } 219 220 function testAndSetValueFromSpecialElementList(element, value, specialControlList){ 221 let returnOptions = { foundInSpecialElementList:false}; 222 specialControlList.forEach(function(specialControl){ 223 if (specialControl.isSpecialElement(element)){ 224 specialControl.set(element, value); 225 returnOptions.foundInSpecialElementList = true; 226 } 227 }); 228 return returnOptions; 229 } 230 231 //#endregion 232 233 234 235 //#region validation 236 237 /** 238 * main validation function, it includes validations for lists and real file components. 239 * @param {*} options
240 * containerSelector: String defining the form container. 241 * container: Jquery element, usually a div. Eitehr container or containerSelector parameter needs to be supplied 242 * dataIdAttribute: Optional alternative id for dynamically generated forms having no unique ids 243 * showFeedback: Shows feedback . .error css class is used to highlight controls that do not pass validation 244 * @returns true or false 245 */ 246 const validate = function(options){ 247 248 options.feedBack = options.showFeedback; 249 250 const okBasicValidation = validator.basicValidate(options); 251 const okValidationList = validateLists(options); 252 const okValidationRFFileViewer = validateRFVFileViewers(options); 253 254 const okValidation = okBasicValidation && okValidationList && okValidationRFFileViewer; 255 256 return okValidation; 257 } 258 259 /** 260 * validates required checkbox and radio lists 261 * by looking for elements having the 'listRequired' class assigned 262 * @param {*} options 263 * containerSelector: string definig the container, optional 264 * container: jquery element, usually a div, optional, 265 * dataIdAttribute: optional alternative id for dynamically generated forms having no unique ids 266 * @returns true or false 267 */ 268 function validateLists(options){ 269 let isValid = true; 270 const container = getContainer(options); 271 272 container.find("div[data-list-required=true]:visible").each(function (i, e) { 273 const container = $(e); 274 const validationGroup = container.data("validationGroup");; 275 const numElementsSelected = container.find("input[data-validation-group='" + validationGroup + "']:checked").length; 276 277 if (numElementsSelected === 0){ 278 if (options.feedBack) 279 container.addClass("invalid").attr("title", "Please select at least one option") 280 isValid = false; 281 } 282 else{ 283 container.removeClass("invalid").attr("title", null); 284 } 285 }); 286 287 return isValid; 288 } 289 290 /** 291 * look for any RF components (Divs having 'fileViewer' class) 292 * @param {*} options 293 * @returns 294 */ 295 function validateRFVFileViewers(options){ 296 let isValid = true; 297 const container = getContainer(options); 298 299 container.find("div.fileViewer.required:visible").each(function (i, e) { 300 const container = $(e); 301 const numFiles = container.find(".rf-row").length; 302 303 if (numFiles === 0){ 304 if (options.feedBack) 305 container.addClass("invalid").attr("title", "File is required") 306 isValid = false; 307 } 308 else{ 309 container.removeClass("invalid").attr("title", null); 310 } 311 }); 312 313 return isValid; 314 } 315 316 //#endregion 317 318 319 function cleanValidationErrorMarkers(options){ 320 $(options.containerSelector + " .invalid").removeClass("invalid").attr("title"); 321 // $(options.containerSelector + " input").removeClass("invalid").attr("title"); 322 // $(options.containerSelector + " textarea").removeClass("invalid").attr("title"); 323 // $(options.containerSelector + " select").removeClass("invalid").attr("title"); 324 } 325 326 327 $(document).ready(function(){ 328 //clears invalid visual clue on elements whenever a user modifies them 329 $(document).on("change", "select,input,textarea", function(){ 330 $(this).removeClass("invalid").attr("title", null); 331 }); 332 333 }); 334 335 return { 336 objectFiller, 337 validate, 338 cleanValidationErrorMarkers 339 } 340 341}();
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.