UNPKG

page-app

Version:

Builder for rich single-page js apps (frontend)

283 lines (219 loc) 6.41 kB
/* global app */ (function ($, app) { var classes = { link: 'b-router_link', activeLink: 'b-router_link__active' }; app.createModule('router', function (sandbox) { var module = this, Router = function (index) { var startPage, router = this, data; this.indexPage = index || 'index'; this.update(); startPage = window.location.hash.split('#!')[1]; this.base = app.get('basePath') || ''; this.base += '/'; this.index = app.get('indexPath') || ''; if (startPage) { data = startPage.match(/(\?.*)$/); if (data) { startPage = startPage.split(data[0])[0]; data = data[1]; } else { data = {}; } } this.goTo(startPage || this.indexPage, data, true); sandbox.bind('route.router', function (e) { router.goTo(e.data.page, e.data); }); sandbox.bind('update.router', function () { router.update(); }); $(window).on('popstate', function (e) { var data = e && e.originalEvent ? e.originalEvent.state : null; router.checkPath(extractGetString(window.location.href), data); }); }; Router.prototype.resolveUrl = function (page) { var orig = page; if (page === this.indexPage) { page = this.index; } if (app.get('development')) { return this.base + this.index + '#!/' + (page === this.index ? orig : page); } return this.base + page; }; Router.prototype.cleanUrl = function (url) { url = url.split(this.base)[1] || url; url = url.replace(/(\/$)|(^\/)/g,''); return url; }; Router.prototype.update = function (inputsData) { var router = this; this.links = $('a[data-type=route]').addClass(classes.link); this.links.off('click.router').on('click.router', function (e) { var $this = $(this), href = $this.attr('href'), params, appName = app.get('name'); e.preventDefault(); href = href.split(router.base)[1] || href.split('/' + appName + '/')[1] || href; params = href.match(/(\?.*)$/); if (params) { href = href.split(params[0])[0]; params = params[1]; } href = router.cleanUrl(href); router.goTo(href, params); }); if (inputsData) { /* restoreInputs(module.node, inputsData); */ } }; Router.prototype.goTo = function (path, data, replace) { var getParams = '', origPath; /* var inputsData; */ path = this.cleanUrl(path); origPath = path; path = this.resolveUrl(path); if (typeof(data) === 'string') { path += data; getParams = data; } if (typeof(data) === 'object') { data = extend(parseGetParams(data), data); } else { data = parseGetParams(data); } if (path === (window.history.location || window.location).pathname) { replace = true; } if (replace) { app.replaceState(data, null, path); } else { app.pushState(data, null, path); } this.checkPath(getParams, data); }; Router.prototype.checkPath = function (getParams, data) { var router = this, path, url, url2; if (app.get('development')) { path = window.location.hash.split('#!')[1]; path = path.split('?')[0]; } else { path = (window.history.location || window.location).pathname.split(this.base)[1]; } path = router.cleanUrl(path); if (path === '' || path === this.index) { path = this.indexPage; } url = url2 = path; if (typeof(getParams) === 'string') { url += getParams; url2 += '/' + getParams; } this.links.removeClass(classes.activeLink); $('a[data-type=route][href="' + this.resolveUrl(url) + '"]').addClass(classes.activeLink); $('a[data-type=route][href="' + this.resolveUrl(url2) + '"]').addClass(classes.activeLink); if (this.loading) { this.loading.done(function () { router.makePage(path, data); }); } else { this.makePage(path, data); } }; Router.prototype.makePage = function (page, data) { var router = this, loader = $.Deferred(), tmpl, params = data && data._params ? data._params : data, inputsData = data && data._params ? data._inputsData : undefined; tmpl = 'pages/' + page; //возможно, сделать кеширование страниц //(нужно ли? может, проще чтоб всегда с нуля рендерелись) sandbox.emit('show.loader'); sandbox.bind('append', function () { sandbox.unbind('append'); sandbox.emit('hide.loader'); loader.resolve(); }); this.loading = loader; if (!dust.cache[tmpl]) { tmpl = '404'; params = { base: this.base + this.indexPage }; } sandbox.render(tmpl, params, function (err, html) { if (err) { throw err; } if (!html) { throw new Error('Empty page! page: `' + page + '`'); } sandbox.notify('destroy'); app.renderModules($(html), module.node, sandbox, function () { router.update(inputsData); sandbox.emit('page', {page: page}); }); }); }; new Router(this.options.index); }); function parseGetParams (getString) { var params, data = {}; if (typeof(getString) === 'string') { params = extractGetString(getString); if (!params) { return getString; } params = params.match(/^\?(.*)/); if (params && params[1]) { getString = params[1]; getString = getString.split('&'); getString.forEach(function (param) { param = param.split('='); if (param[0]) { param[0] = decodeURIComponent(param[0]); } if (param[1]) { param[1] = decodeURIComponent(param[1]); } if (data[param[0]]) { data[param[0]] = [data[param[0]]]; data[param[0]].push(param[1]); } else { data[param[0]] = param[1]; } }); return data; } } else if (getString && typeof(getString.page) === 'string') { return parseGetParams(getString.page); } return getString; } function extractGetString (href) { href = href.match(/(\?.*)$/); if (href) { return href[1]; } else { return undefined; } } } (jQuery, app)); /* global -app */