window.addEventListener ('load', function () { Vn.Web.initialize (); }); Vn.Web = { modules: {} ,activeForm: null ,requestedForm: null ,initialize: function () { this.loadingCount = 0; this.loader = Vn.get ('loader'); this.formHolder = Vn.get ('module'); this.hash = new Vn.Hash (); this.hashLink = new Vn.HashLink ({ hash: this.hash ,key: 'module' }); this.hashLink.on ('changed', this.onHashChange, 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)); } ,connOpened: function (conn, success) { var sql = 'SELECT default_module, image_dir FROM config'; this.conn.execQuery (sql, this.queryConfigDone.bind (this)); var sql = 'SELECT name FROM customer_view'; this.conn.execQuery (sql, this.queryUserDone.bind (this)); var sql = 'CALL module_list ()'; this.conn.execQuery (sql, this.onModuleListLoad.bind (this)); } ,queryConfigDone: function (resultSet) { 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); this.onHashChange (); } ,queryUserDone: function (resultSet) { var userName = resultSet.fetchValue (); if (userName) { var span = Vn.get ('user-name'); span.appendChild (document.createTextNode (', '+ userName)); } } ,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); } } ,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 (); } } ,onHashChange: function () { var x = this.hashLink.value; this.openModule (x ? x : Vn.Config['default_module']); } ,onModuleListLoad: function (resultSet) { 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')); } ,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 ({'module': res.get ('file')}); li.appendChild (a); var text = document.createTextNode (_(res.get ('description'))); a.appendChild (text); var moduleId = res.get ('id'); if (sectionMap[moduleId]) { 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, moduleId, submenu); } } } ,onLiMouseHover: function (submenu, parent) { this.hideSubmenu (); this.activeSubmenu = submenu; var rect = parent.getBoundingClientRect (); submenu.style.display = 'inline'; submenu.style.left = rect.left +'px'; submenu.style.top = rect.bottom +'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; } } ,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 () { this.loadingCount--; if (this.loadingCount == 0) this.loader.style.visibility = 'hidden'; } ,openModule: function (name) { this.requestedForm = name; this.loadModule (name, this.onModuleLoad.bind (this)); } ,onModuleLoad: function (module) { if (module.name != this.requestedForm) return; if (this.activeForm) this.activeForm.close (); var klassName = 'Vn.' + module.name.charAt (0).toUpperCase () + module.name.substr (1); try { var klass = eval (klassName); this.activeForm = new klass (this, module); this.activeForm.activate (); } catch (e) { console.error (e); } } ,loadModule: function (name, callback) { var x = this.modules[name]; if (!x) { x = { name: name ,status: 3 ,xml: null ,callbacks: [] }; if (callback) x.callbacks.push (callback); var path = 'modules/'+ name; Vn.Locale.load (path, this.onPartDownload.bind (this, x)); Vn.includeJs (path +'/'+ name +'.js', this.onPartDownload.bind (this, x)); Vn.includeCss (path +'/style.css'); var request = new XMLHttpRequest (); request.onreadystatechange = this.onXmlDownload.bind (this, x, request); request.open ('get', 'module.php?module='+ name, true); request.send (); this.modules[name] = x; this.loaderPush (); } else if (callback) { if (x.status == 0) callback (x); else x.callbacks.push (callback); } } ,onXmlDownload: function (module, request) { if (request.readyState != 4) return; if (request.status == 200) module.xml = request; this.onPartDownload (module); } ,onPartDownload: function (m) { m.status--; if (m.status != 0) return; var x = m.callbacks; delete m.callbacks; for (var i = 0; i < x.length; i++) x[i] (m); this.loaderPop (); } ,unload: function () { this.hashLink.disconnect ('changed', this.onHashChange, this); this.conn.disconnect ('error', this.onConnError, this); this.conn.disconnect ('loading-changed', this.onConnLoading, this); } };