window.addEventListener ('load', function () { Vn.Web.initialize (); }); Vn.Web = { forms: {} ,activeForm: null ,activeCss: null ,requestedForm: null ,menuShown: false ,menuOptions: {} ,choosedOption: null ,initialize: function () { this.loadingCount = 0; this.loader = $('loader'); this.formHolder = $('form-holder'); this.hash = new Vn.Hash (); this.hashLink = new Vn.HashLink ({ hash: this.hash ,key: 'form' }); this.hashLink.on ('changed', this.onFormChange, this); this.conn = new Db.Conn (); this.conn.on ('error', this.onConnError, this); this.conn.on ('loading-changed', this.onConnLoading, this); this.conn.open (null, null, null, this.connOpened.bind (this)); $('background').onclick = function () {}; $('menu-button').addEventListener ('click', function (event) { event.stopPropagation (); if (!this.menuShown) this.showMenu (); else this.hideMenu (); }.bind (this)); $('menu-box').addEventListener ('click', function (event) { event.stopPropagation (); }); } ,showBackground: function () { $('background').style.display = 'block'; } ,hideBackground: function () { $('background').style.display = 'none'; } ,showMenu: function () { this.showBackground (); $('menu-box').style.display = 'block'; this.menuShown = true; this.hideMenuCallback = this.hideMenu.bind (this); document.addEventListener ('click', this.hideMenuCallback); } ,hideMenu: function () { this.hideBackground (); $('menu-box').style.display = 'none'; $('menu-button').style.display = 'initial'; this.menuShown = false; document.removeEventListener ('click', this.hideMenuCallback); this.hideMenuCallback = null; } ,connOpened: function (conn, success) { var sql = 'SELECT default_form, image_dir FROM config;' +'SELECT name FROM customer_view;' +'CALL form_list ();'; this.conn.execQuery (sql, this.onMainQueryDone.bind (this)); } ,onMainQueryDone: function (resultSet) { // Retrieving configuration parameters var res = resultSet.fetchResult (); var columns = res.columns; if (res.next ()) for (var i = 0; i < res.columns.length; i++) Vn.Config[columns[i].name] = res.get (columns[i].name); // Retrieving the user name var userName = resultSet.fetchValue (); if (userName) { var span = $('user-name'); span.appendChild (document.createTextNode (', '+ userName)); } // Retrieving menu sections var res = resultSet.fetchResult (); var sectionMap = {}; if (res) for (var i = 0; res.next (); i++) { var parent = res.get ('parent'); if (!sectionMap[parent]) sectionMap[parent] = []; sectionMap[parent].push (i); } this.createMenu (res, sectionMap, null, $('menu')); // Loading the default form this.onFormChange (); } ,onConnError: function (conn, error) { switch (error.domain) { case 'Auth': this.unload (); location.assign ('?page=login#!error='+ error.code); break; case 'Version': this.newVersion (error); break; case 'Conn': (new Htk.Toast ()).showError (error.message); break; default: console.warn (error.message); } } ,onConnLoading: function (conn, isLoading) { if (isLoading) this.loaderPush (); else this.loaderPop (); } ,loaderPush: function () { this.loadingCount++; if (this.loadingCount == 1) this.loader.style.visibility = 'visible'; } ,loaderPop: function () { if (this.loadingCount == 0) return; this.loadingCount--; if (this.loadingCount == 0) this.loader.style.visibility = 'hidden'; } ,newVersion: function (error) { if (this.skipVersion) return; this.skipVersion = true; var reload; var message = _('NewVersionAvailable') +"\n\n"+ error.message; if (error.code == 'criticalVersion') { alert (message) reload = true; } else reload = confirm (message); if (reload) { this.unload (); location.reload (); } } ,createMenu: function (res, sectionMap, parent, ul) { var sections = sectionMap[parent]; for (var i = 0; i < sections.length; i++) { res.row = sections[i]; var li = document.createElement ('li'); ul.appendChild (li); var a = document.createElement ('a'); a.href = this.hash.make ({'form': res.get ('path')}); this.menuOptions[res.get ('path')] = a; li.appendChild (a); var text = document.createTextNode (_(res.get ('description'))); a.appendChild (text); var formId = res.get ('id'); if (sectionMap[formId]) { var submenu = document.createElement ('ul'); submenu.className = 'submenu'; li.appendChild (submenu); li.addEventListener ('mouseover', this.onLiMouseHover.bind (this, submenu, a)); li.addEventListener ('mouseout', this.onLiMouseOut.bind (this)); this.createMenu (res, sectionMap, formId, submenu); } } } ,onLiMouseHover: function (submenu, parent) { if (Vn.isMobile ()) return; this.hideSubmenu (); this.activeSubmenu = submenu; var rect = parent.getBoundingClientRect (); submenu.style.display = 'inline'; submenu.style.left = rect.right +'px'; submenu.style.top = rect.top +'px'; } ,onLiMouseOut: function () { this.timeout = setTimeout (this.hideSubmenu.bind (this), 160); } ,hideSubmenu: function () { var submenu = this.activeSubmenu; if (submenu) { submenu.style.display = 'none'; clearTimeout (this.timeout); this.activeSubmenu = null; this.timeout = 0; } } ,onFormChange: function () { var formPath = this.hashLink.value; this.openForm (formPath ? formPath : Vn.Config['default_form'], null); } ,openForm: function (formPath, callback) { if (Vn.isMobile ()) this.hideMenu (); this.loaderPush (); this.requestedForm = formPath; var formInfo = this.forms[formPath]; var path = 'forms/'+ formPath; if (this.activeForm) { this.activeForm.close (); this.activeForm = null; } if (this.activeCss) { Vn.excludeCss (this.activeCss +'/style.css'); if (Vn.isMobile ()) Vn.excludeCss (this.activeCss +'/mobile.css'); } this.activeCss = path; Vn.includeCss (this.activeCss +'/style.css'); if (Vn.isMobile ()) Vn.includeCss (this.activeCss +'/mobile.css'); if (!formInfo) { var aux = formPath.split ('/'); var formName = aux[aux.length - 1]; var klass = 'Vn.'+ formName.charAt (0).toUpperCase (); klass += formName.substr (1).replace (/\w\-\w/g, function (token) { return token.charAt (0) + token.charAt (2).toUpperCase (); }); formInfo = { path: formPath ,klass: klass ,localeReady: false ,jsReady: false ,uiReady: false ,error: false ,ready: false ,callbacks: [] }; Vn.Locale.load (path, this.onFormLocaleReady.bind (this, formInfo)); Vn.includeJs (path +'/'+ formName +'.js', this.onFormJsReady.bind (this, formInfo)); Vn.loadXml ('forms/'+ formPath +'/ui.xml', this.onFormUiReady.bind (this, formInfo)); this.forms[formPath] = formInfo; } var newChoosedOption = this.menuOptions[formInfo.path]; if (newChoosedOption) { if (this.choosedOption) this.choosedOption.className = null; newChoosedOption.className = 'selected'; this.choosedOption = newChoosedOption; } if (callback) formInfo.callbacks.push (callback); if (formInfo.ready) this.onFormReady (formInfo); } ,onFormLocaleReady: function (formInfo, success) { formInfo.localeReady = true; this.onFormReady (formInfo); } ,onFormJsReady: function (formInfo, success) { formInfo.jsReady = true; formInfo.error = !success; this.onFormReady (formInfo); } ,onFormUiReady: function (formInfo, success) { formInfo.uiReady = true; formInfo.error = !success; this.onFormReady (formInfo); } ,onFormReady: function (formInfo) { if (!(formInfo.localeReady && formInfo.jsReady && formInfo.uiReady)) return; formInfo.ready = true; if (!formInfo.error) { if (formInfo.path == this.requestedForm) try { var klass = eval (formInfo.klass); this.activeForm = new klass (this, formInfo); this.activeForm.activate (); } catch (e) { formInfo.error = true; console.error (e); } } else (new Htk.Toast ()).showError (_('ErrorLoadingForm')); var callbacks = formInfo.callbacks; formInfo.callbacks = []; for (var i = 0; i < callbacks.length; i++) callbacks[i] (this.activeForm); this.loaderPop (); } ,unload: function () { this.hashLink.disconnect ('changed', this.onFormChange, this); this.conn.disconnect ('error', this.onConnError, this); this.conn.disconnect ('loading-changed', this.onConnLoading, this); } };