PHP Classes

File: public/js/lib/director/lib/director/browser.js

Recommend this page to a friend!
  Classes of Sergey Beskorovayniy   Silex MVC Blog   public/js/lib/director/lib/director/browser.js   Download  
File: public/js/lib/director/lib/director/browser.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Silex MVC Blog
MVC based blog using on the Silex micro-framework
Author: By
Last change:
Date: 8 years ago
Size: 7,294 bytes
 

Contents

Class file image Download
/* * browser.js: Browser specific functionality for director. * * (C) 2011, Charlie Robbins, Paolo Fragomeni, & the Contributors. * MIT LICENSE * */ var dloc = document.location; function dlocHashEmpty() { // Non-IE browsers return '' when the address bar shows '#'; Director's logic // assumes both mean empty. return dloc.hash === '' || dloc.hash === '#'; } var listener = { mode: 'modern', hash: dloc.hash, history: false, check: function () { var h = dloc.hash; if (h != this.hash) { this.hash = h; this.onHashChanged(); } }, fire: function () { if (this.mode === 'modern') { this.history === true ? window.onpopstate() : window.onhashchange(); } else { this.onHashChanged(); } }, init: function (fn, history) { var self = this; this.history = history; if (!Router.listeners) { Router.listeners = []; } function onchange(onChangeEvent) { for (var i = 0, l = Router.listeners.length; i < l; i++) { Router.listeners[i](onChangeEvent); } } //note IE8 is being counted as 'modern' because it has the hashchange event if ('onhashchange' in window && (document.documentMode === undefined || document.documentMode > 7)) { // At least for now HTML5 history is available for 'modern' browsers only if (this.history === true) { // There is an old bug in Chrome that causes onpopstate to fire even // upon initial page load. Since the handler is run manually in init(), // this would cause Chrome to run it twise. Currently the only // workaround seems to be to set the handler after the initial page load // http://code.google.com/p/chromium/issues/detail?id=63040 setTimeout(function() { window.onpopstate = onchange; }, 500); } else { window.onhashchange = onchange; } this.mode = 'modern'; } else { // // IE support, based on a concept by Erik Arvidson ... // var frame = document.createElement('iframe'); frame.id = 'state-frame'; frame.style.display = 'none'; document.body.appendChild(frame); this.writeFrame(''); if ('onpropertychange' in document && 'attachEvent' in document) { document.attachEvent('onpropertychange', function () { if (event.propertyName === 'location') { self.check(); } }); } window.setInterval(function () { self.check(); }, 50); this.onHashChanged = onchange; this.mode = 'legacy'; } Router.listeners.push(fn); return this.mode; }, destroy: function (fn) { if (!Router || !Router.listeners) { return; } var listeners = Router.listeners; for (var i = listeners.length - 1; i >= 0; i--) { if (listeners[i] === fn) { listeners.splice(i, 1); } } }, setHash: function (s) { // Mozilla always adds an entry to the history if (this.mode === 'legacy') { this.writeFrame(s); } if (this.history === true) { window.history.pushState({}, document.title, s); // Fire an onpopstate event manually since pushing does not obviously // trigger the pop event. this.fire(); } else { dloc.hash = (s[0] === '/') ? s : '/' + s; } return this; }, writeFrame: function (s) { // IE support... var f = document.getElementById('state-frame'); var d = f.contentDocument || f.contentWindow.document; d.open(); d.write("<script>_hash = '" + s + "'; onload = parent.listener.syncHash;<script>"); d.close(); }, syncHash: function () { // IE support... var s = this._hash; if (s != dloc.hash) { dloc.hash = s; } return this; }, onHashChanged: function () {} }; var Router = exports.Router = function (routes) { if (!(this instanceof Router)) return new Router(routes); this.params = {}; this.routes = {}; this.methods = ['on', 'once', 'after', 'before']; this.scope = []; this._methods = {}; this._insert = this.insert; this.insert = this.insertEx; this.historySupport = (window.history != null ? window.history.pushState : null) != null this.configure(); this.mount(routes || {}); }; Router.prototype.init = function (r) { var self = this , routeTo; this.handler = function(onChangeEvent) { var newURL = onChangeEvent && onChangeEvent.newURL || window.location.hash; var url = self.history === true ? self.getPath() : newURL.replace(/.*#/, ''); self.dispatch('on', url.charAt(0) === '/' ? url : '/' + url); }; listener.init(this.handler, this.history); if (this.history === false) { if (dlocHashEmpty() && r) { dloc.hash = r; } else if (!dlocHashEmpty()) { self.dispatch('on', '/' + dloc.hash.replace(/^(#\/|#|\/)/, '')); } } else { if (this.convert_hash_in_init) { // Use hash as route routeTo = dlocHashEmpty() && r ? r : !dlocHashEmpty() ? dloc.hash.replace(/^#/, '') : null; if (routeTo) { window.history.replaceState({}, document.title, routeTo); } } else { // Use canonical url routeTo = this.getPath(); } // Router has been initialized, but due to the chrome bug it will not // yet actually route HTML5 history state changes. Thus, decide if should route. if (routeTo || this.run_in_init === true) { this.handler(); } } return this; }; Router.prototype.explode = function () { var v = this.history === true ? this.getPath() : dloc.hash; if (v.charAt(1) === '/') { v=v.slice(1) } return v.slice(1, v.length).split("/"); }; Router.prototype.setRoute = function (i, v, val) { var url = this.explode(); if (typeof i === 'number' && typeof v === 'string') { url[i] = v; } else if (typeof val === 'string') { url.splice(i, v, s); } else { url = [i]; } listener.setHash(url.join('/')); return url; }; // // ### function insertEx(method, path, route, parent) // #### @method {string} Method to insert the specific `route`. // #### @path {Array} Parsed path to insert the `route` at. // #### @route {Array|function} Route handlers to insert. // #### @parent {Object} **Optional** Parent "routes" to insert into. // insert a callback that will only occur once per the matched route. // Router.prototype.insertEx = function(method, path, route, parent) { if (method === "once") { method = "on"; route = function(route) { var once = false; return function() { if (once) return; once = true; return route.apply(this, arguments); }; }(route); } return this._insert(method, path, route, parent); }; Router.prototype.getRoute = function (v) { var ret = v; if (typeof v === "number") { ret = this.explode()[v]; } else if (typeof v === "string"){ var h = this.explode(); ret = h.indexOf(v); } else { ret = this.explode(); } return ret; }; Router.prototype.destroy = function () { listener.destroy(this.handler); return this; }; Router.prototype.getPath = function () { var path = window.location.pathname; if (path.substr(0, 1) !== '/') { path = '/' + path; } return path; };