var STATUS_OK = 0; var STATUS_INVALID = 1; var STATUS_REQUIRED = 2; var FIELD_TYPE_GENERIC = 0; var FIELD_TYPE_BUTTON = 1; var FIELD_TYPE_TEXTAREA = 2; var PreventFirstRequiredMessageShow = false; var g_requiredHandlers = new Object(); function ValidationHandler(messageBoxID, preventMessageShow, invalidStatus) { this.preventMessageShow = preventMessageShow; this.messageBoxID = messageBoxID; this.connectedFields = new Array(); this.invalidStatus = invalidStatus; this.isValid = false; } ValidationHandler.prototype = { AddField : function(field) { this.connectedFields.push(field); }, ProcessFieldStatus : function (field) { if(field.status != this.invalidStatus) { return true; } if (!this.isValid) return false; for(var i = 0; i < this.connectedFields.length; ++i) { if(this.connectedFields[i].status != this.invalidStatus) { return true; } } return false; }, UpdateState : function(field) { var valueIsValid = this.ProcessFieldStatus(field); if (valueIsValid && !this.isValid) { this.isValid = true; for (var i = 0; i < this.connectedFields.length; ++i) { var connectedField = this.connectedFields[i]; if (connectedField.GetStatus() == STATUS_OK) { connectedField.Highlight(false); } } } else { this.isValid = valueIsValid; } }, UpdateMessageBox : function(isFocused, message) { var show = !this.isValid; if (this.preventMessageShow && !isFocused && this.connectedFields.length == 1) { show = false; } this.preventMessageShow = false; UpdateMessageBox(show, this.messageBoxID, message); }, HideMessageBox : function() { if(this.connectedFields.length > 1) { for(var i = 0; i < this.connectedFields.length; ++i) { if(this.connectedFields[i].IsVisible()) { return; } } } UpdateMessageBox(false, this.messageBoxID, ""); }, IsValid : function() { return this.isValid; } }; function DummyValidationHandler() { } DummyValidationHandler.prototype = { UpdateState: function () { }, IsValid: function () { return true; }, HideMessageBox: function () { }, UpdateMessageBox : function () { } }; function HideFieldOperation(field) { this.field = field; } HideFieldOperation.prototype.Execute = function () { this.field.Hide(); } function ShowFieldOperation(field) { this.field = field; } ShowFieldOperation.prototype.Execute = function () { this.field.Show(); } function FieldControler() { this.fields = new Array(); this.updateInProgress = false; this.dynamicTableField = null; } function GetChangeEvent(fieldObject) { if(fieldObject.type && fieldObject.type.indexOf("select") == 0) { return "change"; } else { return "input"; } } FieldControler.prototype = { AddField: function (field) { if(this.fields.length > 0) { field.SetValue(this.fields[0].GetValue()); if(this.dynamicTableField && field.relatedControl && field.relatedControl.BindToDynamicTableField) { field.relatedControl.BindToDynamicTableField( this.dynamicTableField ); } } else { if(field.DynamicTableField != null) { this.dynamicTableField = field; } } this.fields.push(field); field.controler = this; if (field.relatedControl == null) { var fieldObject = field.GetObject(); fieldObject.addEventListener(GetChangeEvent(fieldObject), function () { field.controler.OnValueChanged(field, true); }); } }, OnValueChanged: function (sourceField, preventStatusUpdate) { if (this.updateInProgress) return; var newValue = sourceField.GetValue(); this.updateInProgress = true; for (var i = 0; i < this.fields.length; ++i) { var field = this.fields[i]; if (field == sourceField || field.isDeleted) continue; field.preventStatusUpdate = preventStatusUpdate; field.SetValue(newValue, "input"); field.preventStatusUpdate = false; } this.updateInProgress = false; }, OnUpdateStatus : function(sourceField) { for(var i = 0; i < this.fields.length; ++i) { var field = this.fields[i]; if (field == sourceField || field.isDeleted) continue; field.UpdateStatus(true); } } } function DocumentFormField(documentForm, id, name) { this.id = id; this.name = name; this.group = null; this.row = null; this.documentForm = documentForm; this.setValueCall = false; this.OnChange = null; this.ValidateValue = null; this.actualValue = null; this.checkedValue = "On"; this.relatedControl = null; this.controler = null; this.status = STATUS_OK; this.validationMessageBoxID = ""; this.requiredHandler = null; this.isRequired = false; this.preventStatusUpdate = false; this.type = FIELD_TYPE_GENERIC; this.isHighlighted = false; this.uiObject = null; this.parentCellUIObject = null; this.isFocused = false; this.eventValueChanged = new EventHandlers(this); this.enabled = true; this.requiredHandler = new DummyValidationHandler(); this.nameResolver = null; this.isDeleted = false; this.lastSetValue = null; } DocumentFormField.prototype = { GetObject: function () { return document.getElementById(this.id); //if (this.documentForm.doc == null) return null; //return this.documentForm.doc.getField(this.id); }, GetUIObject : function() { if(this.uiObject) return this.uiObject; if (this.parentCellUIObject) return this.parentCellUIObject; var parent = this.GetObject(); while(parent != null && !parent.classList.contains("fcell")) parent = parent.parentElement; this.parentCellUIObject = parent == null ? this.GetObject() : parent; return this.parentCellUIObject; }, GetDedicatedUIObject : function() { return this.uiObject ? this.uiObject : this.GetObject(); }, Show: function () { var docFieldObject = this.GetObject(); if (docFieldObject != null) { ShowObject(docFieldObject, true); } else { this.documentForm.AddInitFieldOperation(new ShowFieldOperation(this)); } }, Hide: function () { var docFieldObject = this.GetObject(); if (docFieldObject != null) { ShowObject(docFieldObject, false); } else { this.documentForm.AddInitFieldOperation(new HideFieldOperation(this)); } }, GetValue: function () { var fieldObject = this.GetObject(); if(fieldObject == null) { var dumpx = false; return null; } var result = fieldObject.value; return result == null ? "" : result; }, InitValue: function (value) { if (this.setValueCall) return; var fieldObject = this.GetObject(); this.setValueCall = true; fieldObject.value = value; DispatchEvent(fieldObject, "change"); DispatchEvent(fieldObject, "input"); if (this.IsTextArea()) { ResizeMultilineField(fieldObject); } this.setValueCall = false; if (this.relatedControl) { this.relatedControl.UpdateState(value); } }, SetValue: function (value, source) { if (this.setValueCall) return; var fieldObject = this.GetObject(); try { this.setValueCall = true; fieldObject.value = value; this.lastSetValue = value; DispatchEvent(fieldObject, "change"); // DispatchEvent(fieldObject, "input"); if (this.IsTextArea()) { ResizeMultilineField(fieldObject); } this.eventValueChanged.Fire(source); this.actualValue = null; if (this.relatedControl) { this.relatedControl.UpdateState(value); } if (this.controler != null) { this.controler.OnValueChanged(this, this.preventStatusUpdate); } this.CallOnChange(); this.UpdateStatus(false); } finally { this.setValueCall = false; } }, SetOnChange: function (onChangeFunction) { if (onChangeFunction == null) return; if (this.OnChange == null) { var self = this; var changeHandler = function () { self.preventStatusUpdate = true; self.CallOnChange(); self.preventStatusUpdate = false; }; this.AddChangedHandler(changeHandler); } this.OnChange = onChangeFunction; }, AddBlurHandler : function(handler) { var fieldObject = this.GetObject(); if(this.relatedControl == null && GetChangeEvent(fieldObject) == 'input') { fieldObject.addEventListener('blur', handler); return true; } else { return false; } }, AddChangedHandler : function(handler) { var self = this; var localHandler = function() { handler(self, "input"); }; if(this.relatedControl) { if(this.relatedControl.eventChanged) { this.relatedControl.eventChanged.AddHandler(localHandler); return; } } else { var fieldObject = this.GetObject(); fieldObject.addEventListener(GetChangeEvent(fieldObject), localHandler); this.eventValueChanged.AddHandler(handler); } }, RegisterForValidation : function() { DynamicValidation.AddField(this.id); }, SetupValidation : function(validateValueFunction, validationMessageBoxID, validationMessage, requiredMessageBoxID, requiredMessage, validateOnChange) { this.RegisterForValidation(); this.ValidateValue = validateValueFunction; this.validationMessageBoxID = validationMessageBoxID; this.validationMessage = validationMessage; this.requiredMessage = requiredMessage; if (requiredMessageBoxID != "") { if (g_requiredHandlers[requiredMessageBoxID]) { this.requiredHandler = g_requiredHandlers[requiredMessageBoxID]; } else { this.requiredHandler = new ValidationHandler(requiredMessageBoxID, PreventFirstRequiredMessageShow, STATUS_REQUIRED); g_requiredHandlers[requiredMessageBoxID] = this.requiredHandler; } } else { this.requiredHandler = new ValidationHandler("", PreventFirstRequiredMessageShow, STATUS_REQUIRED); } this.requiredHandler.AddField(this); var fieldObject = this.GetObject(); var event = validateOnChange ? 'change' : 'blur'; var self = this; fieldObject.addEventListener(event, function () { self.isFocused = false; self.UpdateStatus(true); if(self.controler != null) { self.controler.OnUpdateStatus(); } }); if(!validateOnChange) { fieldObject.addEventListener("input", function () { self.isFocused = true; }); } // this.UpdateStatus(); }, _UpdateStatusValue : function() { var fieldValue = this.GetValue(); if (this.isRequired && this.relatedControl && this.relatedControl.IsRequired) { if (this.relatedControl.IsRequired()) { this.status = STATUS_REQUIRED; return; } else { this.status = STATUS_OK; return; } } else if(fieldValue == "") { if(this.isRequired) { this.status = STATUS_REQUIRED; return; } else { this.status = STATUS_OK; return; } } if (this.CallValidateValue()) { this.status = STATUS_OK; } else { this.status = STATUS_INVALID; var htmlElement = document.getElementById(this.id); if (htmlElement.nodeName === "INPUT") { const idAlertValidInput = "idAlertValidInput"; var oldAlert = document.getElementById(idAlertValidInput); if (oldAlert) { document.body.removeChild(oldAlert); } var errorMsg = this.validationMessage; if (errorMsg.length > 0) { //var self = this; //setTimeout(function () { // document.getElementById(self.id).focus(); //}, //1); var newAlert = document.createElement("div"); newAlert.setAttribute("role", "alert"); newAlert.setAttribute("id", idAlertValidInput); newAlert.classList.add("ui-helper-hidden-accessible"); var content = document.createTextNode(errorMsg); newAlert.appendChild(content); document.body.appendChild(newAlert); } } } }, UpdateStatusValue : function() { this._UpdateStatusValue(); this.requiredHandler.UpdateState(this); if (this.status == STATUS_OK) { this.Highlight(false); } }, UpdateMessageBoxes : function() { this.requiredHandler.UpdateMessageBox(this.isFocused, this.requiredMessage); UpdateMessageBox(this.status == STATUS_INVALID, this.validationMessageBoxID, this.validationMessage); }, UpdateStatus : function(forceUpdate) { if (this.preventStatusUpdate && !forceUpdate) return; this.preventStatusUpdate = false; this.UpdateStatusValue(); if (this.IsVisible()) { this.UpdateMessageBoxes(); } if (this.page) { this.page.ProcessField(this); } }, CallValidateValue : function() { var fieldObject = this.GetObject(); if (fieldObject != null && fieldObject.checkValidity && !fieldObject.checkValidity()) { return false; } if(this.ValidateValue != null && !this.ValidateValue(this)) { return false; } return true; }, CallOnChange: function () { if (this.OnChange != null) { this.OnChange(this, this.documentForm); } }, GetValueAsNumber: function () { var result = parseFloat(this.GetValue()); if (isNaN(result)) return 0; return result; }, SetValueAsNumber: function (value) { this.SetValue(value.toString()); }, Enable: function () { if (this.relatedControl) { this.relatedControl.Enable(); } else { var control = document.getElementById(this.id); control.removeAttribute("disabled"); } this.enabled = true; this.UpdateStatus(); }, Disable: function () { if (this.relatedControl) { this.relatedControl.Disable(); } else { var control = document.getElementById(this.id); control.setAttribute("disabled", "disabled"); } this.enabled = false; this.UpdateStatus(); }, IsEnabled: function () { return this.enabled; }, IsVisible: function () { var e = this.uiObject ? this.uiObject : this.GetObject(); if (e == null) e = this.relatedControl; if (e == null) return true; return !!( e.offsetWidth || e.offsetHeight || e.getClientRects().length ); }, UpdateVisibility : function() { if (this.IsVisible()) { this.UpdateMessageBoxes(); } else { this.requiredHandler.HideMessageBox(); UpdateMessageBox(false, this.validationMessageBoxID, ""); } }, IsChecked: function () { if (this.relatedControl == null) { return false; } return this.relatedControl.IsChecked(); }, IsButton : function() { return this.type == FIELD_TYPE_BUTTON; }, IsTextArea : function() { return this.type == FIELD_TYPE_TEXTAREA; }, IsValid : function() { if (this.isFocused) { this.isFocused = false; this.UpdateStatus(); } if(this.GetStatus() != STATUS_OK && this.enabled) { return !this.IsVisible(); } return true; }, Highlight : function(on) { if (this.isHighlighted == on) return; this.isHighlighted = on; var object = this.GetDedicatedUIObject(); if (object == null) return; if(on) { object.parentNode.classList.add("highlightInvalidField"); } else { object.parentNode.classList.remove("highlightInvalidField"); } }, Focus: function () { var object = this.GetUIObject(); if(object != null) { object.focus(); } }, GetStatus : function() { if(this.status == STATUS_REQUIRED) { return this.requiredHandler.IsValid() ? STATUS_OK : STATUS_REQUIRED; } else { return this.status; } } }; function DocumentFormGroup(documentForm, name) { this.documentForm = documentForm; this.Fields = new Array(); this.name = name; } DocumentFormGroup.prototype = { Show: function () { for (var i = 0; i < this.Fields.length; ++i) { this.Fields[i].Show(); } }, Hide: function () { for (var i = 0; i < this.Fields.length; ++i) { this.Fields[i].Hide(); } }, AddField: function (field) { this.Fields.push(field); field.group = this; }, Enable: function () { for (var i = 0; i < this.Fields.length; ++i) { this.Fields[i].Enable(); } }, Disable: function () { for (var i = 0; i < this.Fields.length; ++i) { this.Fields[i].Disable(); } } }; function DocumentFormRow(table) { this.Fields = new Object(); this.table = table; } DocumentFormRow.prototype = { AddField: function (field, column) { this.Fields[column] = field; field.row = this; }, GetField: function (name) { var field = this.Fields[name]; if (typeof (field) == "undefined") return null; return field; } }; function DocumentFormTable(documentForm, name) { this.name = name; this.rowsMap = new Object(); this.rows = new Array(); this.documentForm = documentForm; } DocumentFormTable.prototype = { GetOrCreateRow: function (name) { var row = this.rowsMap[name]; if (this.documentForm.IsNull(row)) { row = new DocumentFormRow(this); this.rowsMap[name] = row; this.rows.push(row); } return row; } }; function DatePart(upper, lower) { this.upper = upper; this.lower = lower; this.value = 0; } DatePart.prototype = { Update: function (charCode) { if (charCode < 48 || charCode > 57) return false; this.value = this.value * 10 + charCode - 48; return true; }, CanUpdate: function (char) { return char == this.upper || char == this.lower; } }; function DocumentFormClass(docObject) { this.doc = docObject; this.Fields = new Object(); this.Groups = new Object(); this.Tables = new Object(); this.initFieldOperations = new Array(); this.FieldControlers = new Object(); this.AllFields = new Array(); this.nameResolver = null; this.addedFields = null; } DocumentFormClass.prototype = { IsNull: function (data) { return typeof (data) == "undefined" || data == null; }, AddInitFieldOperation: function (operation) { this.initFieldOperations.push(operation); }, Init: function () { for (var i = 0; i < this.initFieldOperations.length; ++i) { this.initFieldOperations[i].Execute(); } }, GetOrCreateGroup: function (groupName) { var group = this.GetGroup(groupName); if (group == null) { group = new DocumentFormGroup(this, groupName); this.Groups[groupName] = group; } return group; }, GetGroup: function (groupName) { var group = this.Groups[groupName]; if (this.IsNull(group)) { return null; } return group; }, GetOrCreateTable: function (tableName) { var table = this.GetTable(tableName); if (table == null) { table = new DocumentFormTable(this, tableName); this.Tables[tableName] = table; } return table; }, GetTable: function (tableName) { var table = this.Tables[tableName]; if (this.IsNull(table)) { return null; } return table; }, DeleteField : function(field) { field.isDeleted = true; }, AddField: function (id, name, relatedControl, groupName, tableName, rowName, columnName) { var alias = null; if(this.nameResolver) { var result = this.nameResolver(name); name = result.name; alias = result.alias; } var field = new DocumentFormField(this, id, name); field.relatedControl = relatedControl; if (field.relatedControl) { if (field.relatedControl.SetOwner) { field.relatedControl.SetOwner(field); } else { field.relatedControl.owner = field; } if(relatedControl.GetObject) { field.uiObject = relatedControl.GetObject(); } } if (groupName != "") { this.GetOrCreateGroup(groupName).AddField(field); } if (tableName != "") { var table = this.GetOrCreateTable(tableName); table.GetOrCreateRow(rowName).AddField(field, columnName); } this.Fields[id] = field; if(alias) { this.Fields[alias] = field; } if (id != name && name != "") { var originalField = this.GetField(name); if (originalField == null) { this.Fields[name] = field; this.AllFields.push(field); } else if (originalField.controler != null) { originalField.controler.AddField(field); } else if(name != "") { var fieldControler = new FieldControler(); fieldControler.AddField(originalField); fieldControler.AddField(field); } } if(this.addedFields) { this.addedFields.AddField(field); } return field; }, GetField: function (name) { var field = this.Fields[name]; if (this.IsNull(field)) return null; return field; }, ParseDate: function (value, pattern) { if (value.length != pattern.length) return null; var day = new DatePart('D', 'd'); var month = new DatePart('M', 'm'); var year = new DatePart('Y', 'y'); var dateParts = [day, month, year]; for (var i = 0; i < value.length; ++i) { var patternChar = pattern.charAt(i); var targetDatePart = null; for (var j = 0; j < dateParts.length; ++j) { if (dateParts[j].CanUpdate(patternChar)) { targetDatePart = dateParts[j]; break; } } if (targetDatePart != null) { if (!targetDatePart.Update(value.charCodeAt(i))) return null; } else if (patternChar != value.charAt(i)) { return null; } } if (year.value < 100) { if (year.value < 50) { year.value += 2000; } else { year.value += 1900; } } if (month.value == 0) month.value = 1; if (day.value == 0) day.value = 1; if (month.value > 12) return null; if (day.value > 31) return null; month.value -= 1; var result = new Date(year.value, month.value, day.value); if (result.getDate() != day.value || result.getMonth() != month.value || result.getFullYear() != year.value) { return null; } return result; }, GetFieldValue: function (name) { var field = this.GetField(name); if (field != null) return field.GetValue(); return ""; }, SetFieldValue: function (name, value) { var field = this.GetField(name); if (field != null) field.SetValue(value); } }; function DummyValidation() { return true; } function DocumentFormFieldsCollection() { this.fields = new Array(); this.children = new Array(); this.deleted = false; } DocumentFormFieldsCollection.prototype = { AddField : function(field) { this.fields.push(field); }, Delete : function() { if(this.deleted) return; this.deleted = true; this.fields.forEach(function(field){DocumentForm.DeleteField(field)}) this.children.forEach(function(child){child.Delete()}); }, AddChild: function(child) { this.children.push(child); } }; DocumentForm = new DocumentFormClass(null); function FormDataModel() { this.ResolveDocumentFormFieldName = function(name) { return name; } } function ValidationNode(data) { this.next = null; this.prev = null; this.firstChild = null; this.lastChild = null; this.parent = null; this.data = data; this.root = null; } ValidationNode.prototype = { AddChild: function (childNode) { if (this.firstChild == null) { this.firstChild = this.lastChild = childNode; } else { this.lastChild.next = childNode; childNode.prev = this.lastChild; this.lastChild = childNode; } childNode.parent = this; childNode.root = this.root; if(this.root) { this.root.NodeAdded(childNode); } }, RemoveChild: function (childNode) { if (childNode == this.firstChild) { this.firstChild = this.firstChild.next; if (this.firstChild == null) { this.lastChild = null; } else { this.firstChild.prev = null; } } else if (childNode == this.lastChild) { this.lastChild = this.lastChild.prev; this.lastChild.next = null; } else { childNode.prev.next = childNode.next; childNode.next.prev = childNode.prev; } childNode.parent = null; if(this.root) { this.root.NodeRemoved(childNode); } }, Remove: function () { if (this.parent == null) return; this.parent.RemoveChild(this); } } function ValidationRoot(id) { this.node = new ValidationNode(null); this.node.root = this; } ValidationRoot.prototype = { NodeAdded: function (node) { if(this.page) { this.page.AddDynamicValidation(node); } }, NodeRemoved: function (node) { if (this.page) { this.page.RemoveDynamicValidation(node); } } } function ValidationRootsClass() { this.roots = new Object(); } ValidationRootsClass.prototype = { Get : function(id) { var result = this.roots[id]; if (result) { return result; } result = new ValidationRoot(id); this.roots[id] = result; return result; }, Remove : function(id) { this.roots[id] = null; }, FindForElement: function (documentElement) { var validationRootElement = $(documentElement).closest(".validationRoot,.page").get(0); if (validationRootElement == null) return null; return this.Get(validationRootElement.id); } } ValidationRoots = new ValidationRootsClass(); function DynamicValidationClass() { this.validationsStack = new Array(); this.currentValidation = null; } DynamicValidationClass.prototype = { Push: function(validationNode) { if(typeof(validationNode) == 'string') { validationNode = ValidationRoots.Get(validationNode).node; } this.validationsStack.push(this.currentValidation); this.currentValidation = validationNode; }, Pop : function() { var result = this.currentValidation; this.currentValidation = this.validationsStack.pop(); return result; }, AddField : function(fieldID) { if(this.currentValidation != null) { if(this.currentValidation.data == null) this.currentValidation.data = new Array(); this.currentValidation.data.push(fieldID); } }, GetParent : function(documentElement) { if(this.currentValidation == null) { if (typeof (documentElement) == 'string') { documentElement = document.getElementById(documentElement); } return ValidationRoots.FindForElement(documentElement).node; } else { return this.currentValidation; } } }; DynamicValidation = new DynamicValidationClass();