window.addEventListener ('load', function () { Vn.Web.initialize (); }); Vn.Web = { forms: {} ,activeForm: null ,activeFormPath: null ,requestedForm: null ,menuShown: false ,menuOptions: {} ,choosedOption: null ,initialize: function () { this.loadingCount = 0; this.loader = Vn.get ('loader'); this.formHolder = Vn.get ('form'); 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)); var menuButton = Vn.get ('menu-button'); menuButton.addEventListener ('click', this.onMenuClick.bind (this)); var menuBox = Vn.get ('menu-box'); menuBox.addEventListener ('click', function (event) { event.stopPropagation (); }); } ,onMenuClick: function (event) { event.stopPropagation (); if (!this.menuShown) this.showMenu (); else this.hideMenu (); } ,showMenu: function () { var menu = Vn.get ('menu-box'); menu.style.display = 'block'; var menuBackground = Vn.get ('menu-background'); menuBackground.style.display = 'block'; this.menuShown = true; this.hideMenuCallback = this.hideMenu.bind (this); document.addEventListener ('click', this.hideMenuCallback); } ,hideMenu: function () { var menu = Vn.get ('menu-box'); menu.style.display = 'none'; var menuBackground = Vn.get ('menu-background'); menuBackground.style.display = 'none'; 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 = Vn.get ('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, Vn.get ('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': alert (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); this.menuOptions[res.get ('path')] = li; var a = document.createElement ('a'); a.href = this.hash.make ({'form': res.get ('path')}); li.appendChild (a); var text = document.createTextNode (_(res.get ('description'))); a.appendChild (text); var formId = res.get ('id'); if (sectionMap[formId]) { var submenu; if (!Vn.isMobile ()) { 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)); } else submenu = ul; this.createMenu (res, sectionMap, formId, submenu); } } } ,onLiMouseHover: function (submenu, parent) { 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']); } ,openForm: function (formPath) { if (Vn.isMobile ()) this.hideMenu (); this.requestedForm = formPath; this.loadForm (formPath, this.onFormLoad.bind (this)); } ,loadForm: function (formPath, callback) { var formInfo = this.forms[formPath]; 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 ,xml: null ,ready: false ,callbacks: [] }; var path = 'forms/'+ formPath; Vn.Locale.load (path, this.onFormLocaleReady.bind (this, formInfo)); Vn.includeJs (path +'/'+ formName +'.js', this.onFormJsReady.bind (this, formInfo)); Vn.includeCss (path +'/style.css'); var request = new XMLHttpRequest (); request.onreadystatechange = this.onFormUiReady.bind (this, formInfo, request); request.open ('get', 'form.php?form='+ formPath, true); request.send (); this.forms[formPath] = formInfo; this.loaderPush (); } var newChoosedOption = this.menuOptions[formInfo.path]; if (newChoosedOption) { if (this.choosedOption) this.choosedOption.className = null; newChoosedOption.className = 'selected'; this.choosedOption = newChoosedOption; } if (callback) { if (formInfo.ready) callback (formInfo); else formInfo.callbacks.push (callback); } } ,onFormLocaleReady: function (formInfo) { formInfo.localeReady = true; this.onFormDownload (formInfo); } ,onFormJsReady: function (formInfo) { formInfo.jsReady = true; this.onFormDownload (formInfo); } ,onFormUiReady: function (formInfo, request) { if (request.readyState != 4) return; if (request.status == 200) formInfo.xml = request; this.onFormDownload (formInfo); } ,onFormDownload: function (formInfo) { if (!(formInfo.localeReady && formInfo.jsReady && formInfo.xml)) return; formInfo.ready = true; var callbacks = formInfo.callbacks; delete formInfo.callbacks; for (var i = 0; i < callbacks.length; i++) callbacks[i] (formInfo); this.loaderPop (); } ,onFormLoad: function (formInfo) { if (formInfo.path != this.requestedForm) return; if (this.activeForm) this.activeForm.close (); this.activeFormPath = formInfo.path; try { var klass = eval (formInfo.klass); this.activeForm = new klass (this, formInfo); this.activeForm.activate (); } catch (e) { console.error (e); } } ,unload: function () { this.hashLink.disconnect ('changed', this.onFormChange, this); this.conn.disconnect ('error', this.onConnError, this); this.conn.disconnect ('loading-changed', this.onConnLoading, this); } };