From c86f623e282f215d9f91f0c122f7f06bf5f3ce28 Mon Sep 17 00:00:00 2001 From: Matt Karl Date: Tue, 12 Aug 2014 23:00:30 -0400 Subject: [PATCH] Added a history test to improve for IE8 --- bower.json | 2 +- build.properties | 2 +- lib/canteen.debug.js | 64 +++++++++++++++++++++++++------------------- lib/canteen.js | 37 ++++++++++++++++++------- lib/canteen.min.js | 2 +- src/Canteen/Site.js | 35 ++++++++++++++++++------ 6 files changed, 94 insertions(+), 48 deletions(-) diff --git a/bower.json b/bower.json index 2908dd8..1f31379 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "canteen", - "version": "1.1.5", + "version": "1.1.6", "main": "lib/canteen.min.js", "dependencies": { "cloudkid-debug": "*", diff --git a/build.properties b/build.properties index 68b7dd7..a3ad75c 100644 --- a/build.properties +++ b/build.properties @@ -18,7 +18,7 @@ git.master=master compressor=uglifyjs js.validator=jshint -version=1.1.5 +version=1.1.6 output.name=canteen output.min=${build.dir}/${output.name}.min.js diff --git a/lib/canteen.debug.js b/lib/canteen.debug.js index 8bcdfbc..c0cea57 100644 --- a/lib/canteen.debug.js +++ b/lib/canteen.debug.js @@ -55,9 +55,10 @@ }; return this.each(function() { var uri, link = $(this), refresh = link.data("refresh"), href = link.attr("href"); - if ("undefined" != typeof refresh) return void link.untouch().touch(function(e) { - return checkConfirm(link) ? "soft" == refresh ? (e.preventDefault(), void site.refresh()) : void (href ? document.location.href = href : site.refresh(!1)) : void 0; - }); + if ("undefined" != typeof refresh) return link.untouch().touch(function(e) { + return checkConfirm(link) ? "soft" == refresh ? (e.preventDefault(), site.refresh(), + void 0) : (href ? document.location.href = href : site.refresh(!1), void 0) : void 0; + }), void 0; if (href && 0 === href.indexOf(basePath)) { uri = href.substr(basePath.length), link.untouch().touch(function(e) { e.preventDefault(), checkConfirm(link) && site.redirect(uri); @@ -130,11 +131,13 @@ for (var params = {}, i = 0, len = formData.length; len > i; i++) params[formData[i].name] = formData[i].value; return params.form ? !0 : (site.refresh(!0, params), !1); }, showResponse = function(response, statusText, xhr, form) { - if (-1 == response.search(/^{.*}$/)) return void Debug.error(response); - if (response = JSON.parse(response), "fatalError" == response.type) return void Debug.fatalError(response); + if (-1 == response.search(/^{.*}$/)) return Debug.error(response), void 0; + if (response = JSON.parse(response), "fatalError" == response.type) return Debug.fatalError(response), + void 0; var refresh = form.find('input[name="refresh"]'), asyncRefresh = refresh.data("async"); - return response.redirect !== undefined ? void site.redirect(response.redirect, !1, !0, asyncRefresh) : (Debug.log(response.messages.join("\n")), - !response.ifError && refresh.length && "true" == refresh.val() ? void site.refresh(asyncRefresh) : void Forms.formFeedback(form, response.messages, response.ifError)); + return response.redirect !== undefined ? (site.redirect(response.redirect, !1, !0, asyncRefresh), + void 0) : (Debug.log(response.messages.join("\n")), !response.ifError && refresh.length && "true" == refresh.val() ? (site.refresh(asyncRefresh), + void 0) : (Forms.formFeedback(form, response.messages, response.ifError), void 0)); }, options = { data: { async: !0 @@ -175,10 +178,12 @@ var url = this.gatewayUrl + service + "/" + method; parameters !== undefined && (url += "/" + ($.isArray(parameters) ? parameters.join("/") : String(parameters))), Debug.log(url), $.get(url, function(response) { - if (!response || "null" == response) return void callback(null); - if (-1 == response.search(/^{.*}$/)) return Debug.error(response), void callback(null); + if (!response || "null" == response) return callback(null), void 0; + if (-1 == response.search(/^{.*}$/)) return Debug.error(response), callback(null), + void 0; var data = JSON.parse(response); - return "fatalError" == data.type ? (Debug.fatalError(data), void callback(null)) : void callback(data); + return "fatalError" == data.type ? (Debug.fatalError(data), callback(null), void 0) : (callback(data), + void 0); }); }, p.destroy = function() { p = null; @@ -194,7 +199,7 @@ "use strict"; var EventDispatcher = Canteen.EventDispatcher, LocationUtils = Canteen.LocationUtils, Gateway = Canteen.Gateway, Forms = Canteen.Forms, Page = Canteen.Page, Site = function() { this.initialize(); - }, p = Site.prototype = new EventDispatcher(), _instance = null, _lastRequest = null, _currentId = null, _currentState = null, _pages = [], _currentPage = null, _defaultOptions = { + }, p = Site.prototype = new EventDispatcher(), _instance = null, _lastRequest = null, _currentId = null, _currentState = null, _historyEnabled = !0, _pages = [], _currentPage = null, _defaultOptions = { contentId: "#content", pageTitleId: "h1", pageLoadingId: "article", @@ -203,7 +208,7 @@ }; p.currentState = null, p.currentPage = null, p.gateway = null, p.parameters = null, p.options = {}, Site.ENTER = "enter", Site.EXIT = "exit", Site.READY = "ready", - Site.LOADING = "loading", Site.LOADING_DONE = "loadingDone", Site.VERSION = "1.1.5", + Site.LOADING = "loading", Site.LOADING_DONE = "loadingDone", Site.VERSION = "1.1.6", Site.instance = null, p.initialize = function() { if (_instance) throw "Site has already been created. Use Canteen.Site.instance"; Site.instance = _instance = this; @@ -211,25 +216,28 @@ (Canteen.settings.clientEnabled === undefined || Canteen.settings.clientEnabled) && ($(opts.siteLoadingId).addClass(opts.loadingClass), this.parameters = LocationUtils.getParameters(), Debug.enabled = Canteen.settings.debug, _currentId = 1, this.currentState = _currentState = Canteen.settings.uriRequest, - this._enableHistory(!0), this._fixInternalLinks(), this.gateway = new Gateway(Canteen.settings.gatewayPath, this._gatewayReady.bind(this))); + this._enableHistory(!(!global.history || !history.pushState)), _historyEnabled && this._fixInternalLinks(), + this.gateway = new Gateway(Canteen.settings.gatewayPath, this._gatewayReady.bind(this))); }, p._enableHistory = function(enable) { - $(global).off("statechange"), enable && $(global).on("statechange", this._onStateChange.bind(this)); + _historyEnabled = enable, $(global).off("statechange"), enable && $(global).on("statechange", this._onStateChange.bind(this)); }, p.redirect = function(uri, replaceInHistory, allowRefresh, asyncRefresh) { var state = Canteen.settings.basePath, siteTitle = $("
").html($("title").html()).text(); return replaceInHistory = replaceInHistory === undefined ? !1 : replaceInHistory, allowRefresh = allowRefresh === undefined ? !1 : allowRefresh, asyncRefresh = asyncRefresh === undefined ? !0 : asyncRefresh, - Canteen.settings.siteIndex != uri && (state += uri), _currentState == uri ? void (allowRefresh ? this.refresh(asyncRefresh) : Debug.log("Already on this page! (current: " + _currentState + ", request: " + uri + ")")) : void (replaceInHistory ? History.replaceState({ + Canteen.settings.siteIndex != uri && (state += uri), _currentState == uri ? (allowRefresh ? this.refresh(asyncRefresh) : Debug.log("Already on this page! (current: " + _currentState + ", request: " + uri + ")"), + void 0) : (_historyEnabled ? replaceInHistory ? History.replaceState({ state: _currentId }, siteTitle, state) : (_currentId++, History.pushState({ state: _currentId - }, siteTitle, state))); + }, siteTitle, state)) : document.location.href = state, void 0); }, p.refresh = function(async, params) { - async = async === undefined ? !0 : async, async ? this._updatePageContent(_currentState, params) : document.location.reload(!0); + async = async === undefined ? !0 : async, async && _historyEnabled ? this._updatePageContent(_currentState, params) : document.location.reload(!0); }, p._fixInternalLinks = function() { $("a").internalLink(this), Forms.setup(this, "true" === this.parameters.debugForms); }, p._onStateChange = function() { var state = History.getState(), uri = state.url.split(Canteen.settings.baseUrl)[1]; - return _currentState == uri ? void Debug.log("Already on this page! (" + uri + ")") : void this._updatePageContent(uri); + return _currentState == uri ? (Debug.log("Already on this page! (" + uri + ")"), + void 0) : (this._updatePageContent(uri), void 0); }, p._gatewayReady = function(success) { success ? Debug.log("Canteen is ready!") : Debug.error("Unable to setup gateway."); var options = this.options; @@ -254,24 +262,24 @@ }, p._updatePageContent = function(uri, params) { var site = this, options = this.options, page = this.getPageByUri(uri), url = Canteen.settings.baseUrl + uri; return this.trigger(Site.EXIT, _currentState), this.currentState = _currentState = uri, - page && page.content === _currentPage && !page.content.refresh(uri) ? void (page.content.uri = uri) : (_currentPage && (_currentPage.exit(), - _currentPage.active = !1, this.currentPage = _currentPage = null), Forms.destroy(), - _lastRequest = uri, params = params === undefined ? {} : params, params.async = !0, - this.trigger(Site.LOADING), $(options.pageLoadingId).removeClass(options.loadingClass).addClass(options.loadingClass), - Debug.log("Update Page Content : " + uri), void $.post(url, params, function(response) { + page && page.content === _currentPage && !page.content.refresh(uri) ? (page.content.uri = uri, + void 0) : (_currentPage && (_currentPage.exit(), _currentPage.active = !1, this.currentPage = _currentPage = null), + Forms.destroy(), _lastRequest = uri, params = params === undefined ? {} : params, + params.async = !0, this.trigger(Site.LOADING), $(options.pageLoadingId).removeClass(options.loadingClass).addClass(options.loadingClass), + Debug.log("Update Page Content : " + uri), $.post(url, params, function(response) { if (uri == _lastRequest) { if (_lastRequest = null, site.trigger(Site.LOADING_DONE), $(options.pageLoadingId).removeClass(options.loadingClass), - !response || "null" == response) return void Debug.error("No data for " + uri); - if (-1 == response.search(/^{.*}$/)) return void Debug.error(response); + !response || "null" == response) return Debug.error("No data for " + uri), void 0; + if (-1 == response.search(/^{.*}$/)) return Debug.error(response), void 0; var data = JSON.parse(response); - if ("fatalError" == data.type) return void Debug.fatalError(data); - if (data.redirect !== undefined) return void site.redirect(data.redirect, !0); + if ("fatalError" == data.type) return Debug.fatalError(data), void 0; + if (data.redirect !== undefined) return site.redirect(data.redirect, !0), void 0; $("body").attr("id", data.pageId), $(options.pageTitleId).html(data.title), $(options.contentId).html(data.content), document.title = $("
").html(data.fullTitle).text(), $("meta[name='keywords']").attr("content", data.keywords), $("meta[name='description']").attr("content", data.description), site._fixInternalLinks(), site._enterPage(); } - })); + }), void 0); }, namespace("Canteen").Site = Site, $(function() { new Site(); }); diff --git a/lib/canteen.js b/lib/canteen.js index c9c9ab6..6574815 100644 --- a/lib/canteen.js +++ b/lib/canteen.js @@ -1143,6 +1143,13 @@ * @private */ _currentState = null, + + /** + * If we should enable the HTML5 history + * @property {Boolean} _historyEnabled + * @private + */ + _historyEnabled = true, /** * An array of the pages @@ -1267,7 +1274,7 @@ * @property {String} VERSION * @readOnly */ - Site.VERSION = "1.1.5"; + Site.VERSION = "1.1.6"; /** * Get the singleton instance of the site @@ -1306,8 +1313,12 @@ // Setup history _currentId = 1; this.currentState = _currentState = Canteen.settings.uriRequest; - this._enableHistory(true); - this._fixInternalLinks(); + this._enableHistory(!!(global.history && history.pushState)); + + if (_historyEnabled) + { + this._fixInternalLinks(); + } // Initialize the gateway this.gateway = new Gateway( @@ -1324,6 +1335,7 @@ */ p._enableHistory = function(enable) { + _historyEnabled = enable; $(global).off('statechange'); if (enable) $(global).on('statechange', this._onStateChange.bind(this)); @@ -1372,15 +1384,22 @@ return; } - // Change the history state - if (replaceInHistory) + if (_historyEnabled) { - History.replaceState({state:_currentId}, siteTitle, state); + // Change the history state + if (replaceInHistory) + { + History.replaceState({state:_currentId}, siteTitle, state); + } + else + { + _currentId++; + History.pushState({state:_currentId}, siteTitle, state); + } } else { - _currentId++; - History.pushState({state:_currentId}, siteTitle, state); + document.location.href = state; } }; @@ -1393,7 +1412,7 @@ p.refresh = function(async, params) { async = async === undefined ? true : async; - if (async) + if (async && _historyEnabled) this._updatePageContent(_currentState, params); else document.location.reload(true); diff --git a/lib/canteen.min.js b/lib/canteen.min.js index 7d8cc27..5d07e35 100644 --- a/lib/canteen.min.js +++ b/lib/canteen.min.js @@ -1 +1 @@ -!function(){"use strict";Function.prototype.bind||(Function.prototype.bind=function(t){var e,n,r=this;if("function"!=typeof r)throw new TypeError;return e=Array.prototype.slice.call(arguments,1),n=function(){if(this instanceof n){var i,a,s;return i=function(){},i.prototype=r.prototype,a=new i,s=r.apply(a,e.concat(Array.prototype.slice.call(arguments))),Object(s)===s?s:a}return r.apply(t,e.concat(Array.prototype.slice.call(arguments)))}})}(),function(){Debug.fatalError=function(t){var e=t.message+"\non "+t.file+" (code: "+t.code+")\n";if(t.stackTrace)for(var n=0;ns;s++)a=i[s],this._listeners[a]=this._listeners[a]||[],-1===this._callbackIndex(a,e)&&this._listeners[a].push(e);else if("array"===n(e))for(var u=0,l=e.length;l>u;u++)this.on(t,e[u]);return this},i.off=function(t,r){if(t===e)this._listeners=[];else if("array"===n(r))for(var i=0,a=r.length;a>i;i++)this.off(t,r[i]);else for(var s=t.split(" "),o=null,u=0,l=s.length;l>u;u++)if(o=s[u],this._listeners[o]=this._listeners[o]||[],r===e)this._listeners[o].length=0;else{var c=this._callbackIndex(o,r);-1!==c&&this._listeners[t].splice(c,1)}return this},i._callbackIndex=function(t,e){for(var n=0,r=this._listeners[t].length;r>n;n++)if(this._listeners[t][n]===e)return n;return-1},namespace("Canteen").EventDispatcher=r}(window),$.fn.touch=function(t){return this.on("click",!1).on("touchclick",t)},$.fn.untouch=function(){return this.off("touchclick")},$.fn.internalLink=function(t){var e=Canteen.settings.basePath,n=Canteen.settings.siteIndex,r=t.currentState,i=function(t){if(t.hasClass("confirm")){var e=t.data("confirm")||"Are you sure you wish to continue?",n=confirm(e);return n}return!0};return this.each(function(){var a,s=$(this),o=s.data("refresh"),u=s.attr("href");if("undefined"!=typeof o)return void s.untouch().touch(function(e){return i(s)?"soft"==o?(e.preventDefault(),void t.refresh()):void(u?document.location.href=u:t.refresh(!1)):void 0});if(u&&0===u.indexOf(e)){a=u.substr(e.length),s.untouch().touch(function(e){e.preventDefault(),i(s)&&t.redirect(a)}).removeClass("selected");var l=new RegExp("^"+a.replace("/","/")+"(/.*)?$");(a==r||""!==r&&l.test(r)||a==n&&""===r)&&s.addClass("selected")}})},function(){"use strict";var t=function(){},e=864e5;t.NEVER_EXPIRE="neverExpire",t.clear=function(e){t.write(e,"",-1)},t.write=function(n,r,i){var a,s;i?(i==t.NEVER_EXPIRE?s=new Date(2147483646e3):(s=new Date,s.setTime(s.getTime()+i*e)),a="; expires="+s.toGMTString()):a="",document.cookie=n+"="+r+a+"; path=/"},t.read=function(t){var e,n=t+"=",r=document.cookie.split(";"),i=0;for(i=0;in?"":e.substr(n+1),i=r.indexOf("#"),r=0>i?r:r.substring(0,i),a=r.split("&");for(o in a)s=a[o].split("="),t[s[0]]=s[1];return t},namespace("Canteen").LocationUtils=t}(),function(t){"use strict";var e=function(){};e.ERROR="error",e.DISABLED="disabled",e.SELECTED="selected",e.REQUIRED="required",e.CONFIRM="confirm",e.FEEDBACK_ERROR="formError",e.FEEDBACK_SUCCESS="formSuccess",e.destroy=function(){$("input."+e.CONFIRM+", button."+e.CONFIRM).untouch(),$("form").resetForm().off("submit"),$(":submit").untouch()},e.setup=function(n,r){for(var i=new Array("text","button","reset","submit","checkbox","image","radio","file","password","date"),a=function(t){var e=$(t.target).closest("form"),n=e.find(":submit").eq(0);13==t.keyCode&&n&&(t.stopImmediatePropagation(),t.preventDefault(),n.trigger("touchclick"))},s=0,o=i.length;o>s;s++)$("input[type='"+i[s]+"']").removeClass(i[s]).addClass(i[s]).keyup(a);$("input."+e.CONFIRM+", button."+e.CONFIRM).untouch().touch(function(t){var n=$(this).data(e.CONFIRM)||"Are you sure you wish to continue?",r=confirm(n);return r?void 0:(t.stopImmediatePropagation(),!1)}),$('input[name="formSession"]').remove();var u=function(t,r){var i=r.find("."+e.REQUIRED).removeClass(e.ERROR),a=i.filter(function(){return!this.value}).addClass(e.ERROR);if(a.length>0){var s=function(){$(this).removeClass(e.ERROR).off("keydown")};return a.untouch().on("touchclick focus keydown",s),!1}for(var o={},u=0,l=t.length;l>u;u++)o[t[u].name]=t[u].value;return o.form?!0:(n.refresh(!0,o),!1)},l=function(r,i,a,s){if(-1==r.search(/^{.*}$/))return void Debug.error(r);if(r=JSON.parse(r),"fatalError"==r.type)return void Debug.fatalError(r);var o=s.find('input[name="refresh"]'),u=o.data("async");return r.redirect!==t?void n.redirect(r.redirect,!1,!0,u):!r.ifError&&o.length&&"true"==o.val()?void n.refresh(u):void e.formFeedback(s,r.messages,r.ifError)},c={data:{async:!0},beforeSubmit:u,success:l};$(":submit").touch(function(t){this.name&&this.value&&(c.data={async:!0},c.data[this.name]=this.value);var e=$(this).closest("form");e.length>0&&(t.preventDefault(),e.ajaxSubmit(c))}),$("form").on("submit",function(t){t.preventDefault(),$(this).ajaxSubmit(c)})},e.formFeedback=function(t,n,r){$("ul."+e.FEEDBACK_ERROR+", ul."+e.FEEDBACK_SUCCESS).remove();for(var i=r?e.FEEDBACK_ERROR:e.FEEDBACK_SUCCESS,a='
    ',s=0,o=n.length;o>s;s++)a+="
  • "+n[s]+"
  • ";a+="
";var u=t.find("legend");u.length?u.after(a):t.prepend(a)},namespace("Canteen").Forms=e}(),function(t){"use strict";var e=function(t,e){this.initialize(t,e)},n=e.prototype;n.gatewayUrl=null,n.initialize=function(t,e){this.gatewayUrl=t,"/"!=t.charAt(t.length-1)&&(this.gatewayUrl+="/"),this.get(function(t){var n=null===t||"error"==t.type;if(n)throw"Couldn't connect to gateway";e(!n)},"time","get-server-time")},n.get=function(e,n,r,i){var a=this.gatewayUrl+n+"/"+r;i!==t&&(a+="/"+($.isArray(i)?i.join("/"):String(i))),$.get(a,function(t){if(!t||"null"==t)return void e(null);if(-1==t.search(/^{.*}$/))return Debug.error(t),void e(null);var n=JSON.parse(t);return"fatalError"==n.type?(Debug.fatalError(n),void e(null)):void e(n)})},n.destroy=function(){n=null},namespace("Canteen").Gateway=e}(),function(){"use strict";var t=function(){},e=t.prototype;e.site=null,e.active=!1,e.uri=null,e.enter=function(){},e.exit=function(){},e.refresh=function(){return!0},e.resize=function(){},namespace("Canteen").Page=t}(),function(t,e,n){"use strict";var r=Canteen.EventDispatcher,i=Canteen.LocationUtils,a=Canteen.Gateway,s=Canteen.Forms,o=Canteen.Page,u=function(){this.initialize()},l=u.prototype=new r,c=null,f=null,h=null,d=null,g=[],p=null,v={contentId:"#content",pageTitleId:"h1",pageLoadingId:"article",siteLoadingId:"body",loadingClass:"loading"};l.currentState=null,l.currentPage=null,l.gateway=null,l.parameters=null,l.options={},u.ENTER="enter",u.EXIT="exit",u.READY="ready",u.LOADING="loading",u.LOADING_DONE="loadingDone",u.VERSION="1.1.5",u.instance=null,l.initialize=function(){if(c)throw"Site has already been created. Use Canteen.Site.instance";u.instance=c=this;var t=this.options=v;(Canteen.settings.clientEnabled===n||Canteen.settings.clientEnabled)&&(e(t.siteLoadingId).addClass(t.loadingClass),this.parameters=i.getParameters(),Debug.enabled=Canteen.settings.debug,h=1,this.currentState=d=Canteen.settings.uriRequest,this._enableHistory(!0),this._fixInternalLinks(),this.gateway=new a(Canteen.settings.gatewayPath,this._gatewayReady.bind(this)))},l._enableHistory=function(n){e(t).off("statechange"),n&&e(t).on("statechange",this._onStateChange.bind(this))},l.redirect=function(t,r,i,a){var s=Canteen.settings.basePath,o=e("
").html(e("title").html()).text();return r=r===n?!1:r,i=i===n?!1:i,a=a===n?!0:a,Canteen.settings.siteIndex!=t&&(s+=t),d==t?void(i&&this.refresh(a)):void(r?History.replaceState({state:h},o,s):(h++,History.pushState({state:h},o,s)))},l.refresh=function(t,e){t=t===n?!0:t,t?this._updatePageContent(d,e):document.location.reload(!0)},l._fixInternalLinks=function(){e("a").internalLink(this),s.setup(this,"true"===this.parameters.debugForms)},l._onStateChange=function(){var t=History.getState(),e=t.url.split(Canteen.settings.baseUrl)[1];d!=e&&this._updatePageContent(e)},l._gatewayReady=function(t){t||Debug.error("Unable to setup gateway.");var n=this.options;e(n.siteLoadingId).removeClass(n.loadingClass),e(window).on("resize",this.resize.bind(this)),this.resize(),this.trigger(u.READY),this._enterPage()},l.resize=function(){p&&p.active&&p.resize()},l.addPage=function(t,e){e instanceof o?(e.site=this,g.push({uri:t,content:e})):Debug.warn("The page your trying to add needs to extend Canteen.Page")},l._enterPage=function(){var t=this.getPageByUri(d);t&&(this.currentPage=p=t.content,p.uri=d,p.active=!0,p.enter(),this.resize()),this.trigger(u.ENTER,d)},l.getPageByUri=function(t){var e=g.length,n=0,r=null;if(0===e)return null;for(n=0;e>n;n++)if(r=g[n],r.uri===t||r.uri instanceof RegExp&&r.uri.test(t))return r;return null},l._updatePageContent=function(t,r){var i=this,a=this.options,o=this.getPageByUri(t),l=Canteen.settings.baseUrl+t;return this.trigger(u.EXIT,d),this.currentState=d=t,o&&o.content===p&&!o.content.refresh(t)?void(o.content.uri=t):(p&&(p.exit(),p.active=!1,this.currentPage=p=null),s.destroy(),f=t,r=r===n?{}:r,r.async=!0,this.trigger(u.LOADING),e(a.pageLoadingId).removeClass(a.loadingClass).addClass(a.loadingClass),void e.post(l,r,function(r){if(t==f){if(f=null,i.trigger(u.LOADING_DONE),e(a.pageLoadingId).removeClass(a.loadingClass),!r||"null"==r)return void Debug.error("No data for "+t);if(-1==r.search(/^{.*}$/))return void Debug.error(r);var s=JSON.parse(r);if("fatalError"==s.type)return void Debug.fatalError(s);if(s.redirect!==n)return void i.redirect(s.redirect,!0);e("body").attr("id",s.pageId),e(a.pageTitleId).html(s.title),e(a.contentId).html(s.content),document.title=e("
").html(s.fullTitle).text(),e("meta[name='keywords']").attr("content",s.keywords),e("meta[name='description']").attr("content",s.description),i._fixInternalLinks(),i._enterPage()}}))},namespace("Canteen").Site=u,e(function(){new u})}(window,jQuery); \ No newline at end of file +!function(){"use strict";Function.prototype.bind||(Function.prototype.bind=function(t){var e,n,r=this;if("function"!=typeof r)throw new TypeError;return e=Array.prototype.slice.call(arguments,1),n=function(){if(this instanceof n){var i,a,o;return i=function(){},i.prototype=r.prototype,a=new i,o=r.apply(a,e.concat(Array.prototype.slice.call(arguments))),Object(o)===o?o:a}return r.apply(t,e.concat(Array.prototype.slice.call(arguments)))}})}(),function(){Debug.fatalError=function(t){var e=t.message+"\non "+t.file+" (code: "+t.code+")\n";if(t.stackTrace)for(var n=0;no;o++)a=i[o],this._listeners[a]=this._listeners[a]||[],-1===this._callbackIndex(a,e)&&this._listeners[a].push(e);else if("array"===n(e))for(var u=0,l=e.length;l>u;u++)this.on(t,e[u]);return this},i.off=function(t,r){if(t===e)this._listeners=[];else if("array"===n(r))for(var i=0,a=r.length;a>i;i++)this.off(t,r[i]);else for(var o=t.split(" "),s=null,u=0,l=o.length;l>u;u++)if(s=o[u],this._listeners[s]=this._listeners[s]||[],r===e)this._listeners[s].length=0;else{var c=this._callbackIndex(s,r);-1!==c&&this._listeners[t].splice(c,1)}return this},i._callbackIndex=function(t,e){for(var n=0,r=this._listeners[t].length;r>n;n++)if(this._listeners[t][n]===e)return n;return-1},namespace("Canteen").EventDispatcher=r}(window),$.fn.touch=function(t){return this.on("click",!1).on("touchclick",t)},$.fn.untouch=function(){return this.off("touchclick")},$.fn.internalLink=function(t){var e=Canteen.settings.basePath,n=Canteen.settings.siteIndex,r=t.currentState,i=function(t){if(t.hasClass("confirm")){var e=t.data("confirm")||"Are you sure you wish to continue?",n=confirm(e);return n}return!0};return this.each(function(){var a,o=$(this),s=o.data("refresh"),u=o.attr("href");if("undefined"!=typeof s)return o.untouch().touch(function(e){return i(o)?"soft"==s?(e.preventDefault(),t.refresh(),void 0):(u?document.location.href=u:t.refresh(!1),void 0):void 0}),void 0;if(u&&0===u.indexOf(e)){a=u.substr(e.length),o.untouch().touch(function(e){e.preventDefault(),i(o)&&t.redirect(a)}).removeClass("selected");var l=new RegExp("^"+a.replace("/","/")+"(/.*)?$");(a==r||""!==r&&l.test(r)||a==n&&""===r)&&o.addClass("selected")}})},function(){"use strict";var t=function(){},e=864e5;t.NEVER_EXPIRE="neverExpire",t.clear=function(e){t.write(e,"",-1)},t.write=function(n,r,i){var a,o;i?(i==t.NEVER_EXPIRE?o=new Date(2147483646e3):(o=new Date,o.setTime(o.getTime()+i*e)),a="; expires="+o.toGMTString()):a="",document.cookie=n+"="+r+a+"; path=/"},t.read=function(t){var e,n=t+"=",r=document.cookie.split(";"),i=0;for(i=0;in?"":e.substr(n+1),i=r.indexOf("#"),r=0>i?r:r.substring(0,i),a=r.split("&");for(s in a)o=a[s].split("="),t[o[0]]=o[1];return t},namespace("Canteen").LocationUtils=t}(),function(t){"use strict";var e=function(){};e.ERROR="error",e.DISABLED="disabled",e.SELECTED="selected",e.REQUIRED="required",e.CONFIRM="confirm",e.FEEDBACK_ERROR="formError",e.FEEDBACK_SUCCESS="formSuccess",e.destroy=function(){$("input."+e.CONFIRM+", button."+e.CONFIRM).untouch(),$("form").resetForm().off("submit"),$(":submit").untouch()},e.setup=function(n,r){for(var i=new Array("text","button","reset","submit","checkbox","image","radio","file","password","date"),a=function(t){var e=$(t.target).closest("form"),n=e.find(":submit").eq(0);13==t.keyCode&&n&&(t.stopImmediatePropagation(),t.preventDefault(),n.trigger("touchclick"))},o=0,s=i.length;s>o;o++)$("input[type='"+i[o]+"']").removeClass(i[o]).addClass(i[o]).keyup(a);$("input."+e.CONFIRM+", button."+e.CONFIRM).untouch().touch(function(t){var n=$(this).data(e.CONFIRM)||"Are you sure you wish to continue?",r=confirm(n);return r?void 0:(t.stopImmediatePropagation(),!1)}),$('input[name="formSession"]').remove();var u=function(t,r){var i=r.find("."+e.REQUIRED).removeClass(e.ERROR),a=i.filter(function(){return!this.value}).addClass(e.ERROR);if(a.length>0){var o=function(){$(this).removeClass(e.ERROR).off("keydown")};return a.untouch().on("touchclick focus keydown",o),!1}for(var s={},u=0,l=t.length;l>u;u++)s[t[u].name]=t[u].value;return s.form?!0:(n.refresh(!0,s),!1)},l=function(r,i,a,o){if(-1==r.search(/^{.*}$/))return Debug.error(r),void 0;if(r=JSON.parse(r),"fatalError"==r.type)return Debug.fatalError(r),void 0;var s=o.find('input[name="refresh"]'),u=s.data("async");return r.redirect!==t?(n.redirect(r.redirect,!1,!0,u),void 0):!r.ifError&&s.length&&"true"==s.val()?(n.refresh(u),void 0):(e.formFeedback(o,r.messages,r.ifError),void 0)},c={data:{async:!0},beforeSubmit:u,success:l};$(":submit").touch(function(t){this.name&&this.value&&(c.data={async:!0},c.data[this.name]=this.value);var e=$(this).closest("form");e.length>0&&(t.preventDefault(),e.ajaxSubmit(c))}),$("form").on("submit",function(t){t.preventDefault(),$(this).ajaxSubmit(c)})},e.formFeedback=function(t,n,r){$("ul."+e.FEEDBACK_ERROR+", ul."+e.FEEDBACK_SUCCESS).remove();for(var i=r?e.FEEDBACK_ERROR:e.FEEDBACK_SUCCESS,a='
    ',o=0,s=n.length;s>o;o++)a+="
  • "+n[o]+"
  • ";a+="
";var u=t.find("legend");u.length?u.after(a):t.prepend(a)},namespace("Canteen").Forms=e}(),function(t){"use strict";var e=function(t,e){this.initialize(t,e)},n=e.prototype;n.gatewayUrl=null,n.initialize=function(t,e){this.gatewayUrl=t,"/"!=t.charAt(t.length-1)&&(this.gatewayUrl+="/"),this.get(function(t){var n=null===t||"error"==t.type;if(n)throw"Couldn't connect to gateway";e(!n)},"time","get-server-time")},n.get=function(e,n,r,i){var a=this.gatewayUrl+n+"/"+r;i!==t&&(a+="/"+($.isArray(i)?i.join("/"):String(i))),$.get(a,function(t){if(!t||"null"==t)return e(null),void 0;if(-1==t.search(/^{.*}$/))return Debug.error(t),e(null),void 0;var n=JSON.parse(t);return"fatalError"==n.type?(Debug.fatalError(n),e(null),void 0):(e(n),void 0)})},n.destroy=function(){n=null},namespace("Canteen").Gateway=e}(),function(){"use strict";var t=function(){},e=t.prototype;e.site=null,e.active=!1,e.uri=null,e.enter=function(){},e.exit=function(){},e.refresh=function(){return!0},e.resize=function(){},namespace("Canteen").Page=t}(),function(t,e,n){"use strict";var r=Canteen.EventDispatcher,i=Canteen.LocationUtils,a=Canteen.Gateway,o=Canteen.Forms,s=Canteen.Page,u=function(){this.initialize()},l=u.prototype=new r,c=null,f=null,h=null,d=null,g=!0,p=[],v=null,m={contentId:"#content",pageTitleId:"h1",pageLoadingId:"article",siteLoadingId:"body",loadingClass:"loading"};l.currentState=null,l.currentPage=null,l.gateway=null,l.parameters=null,l.options={},u.ENTER="enter",u.EXIT="exit",u.READY="ready",u.LOADING="loading",u.LOADING_DONE="loadingDone",u.VERSION="1.1.6",u.instance=null,l.initialize=function(){if(c)throw"Site has already been created. Use Canteen.Site.instance";u.instance=c=this;var r=this.options=m;(Canteen.settings.clientEnabled===n||Canteen.settings.clientEnabled)&&(e(r.siteLoadingId).addClass(r.loadingClass),this.parameters=i.getParameters(),Debug.enabled=Canteen.settings.debug,h=1,this.currentState=d=Canteen.settings.uriRequest,this._enableHistory(!(!t.history||!history.pushState)),g&&this._fixInternalLinks(),this.gateway=new a(Canteen.settings.gatewayPath,this._gatewayReady.bind(this)))},l._enableHistory=function(n){g=n,e(t).off("statechange"),n&&e(t).on("statechange",this._onStateChange.bind(this))},l.redirect=function(t,r,i,a){var o=Canteen.settings.basePath,s=e("
").html(e("title").html()).text();return r=r===n?!1:r,i=i===n?!1:i,a=a===n?!0:a,Canteen.settings.siteIndex!=t&&(o+=t),d==t?(i&&this.refresh(a),void 0):(g?r?History.replaceState({state:h},s,o):(h++,History.pushState({state:h},s,o)):document.location.href=o,void 0)},l.refresh=function(t,e){t=t===n?!0:t,t&&g?this._updatePageContent(d,e):document.location.reload(!0)},l._fixInternalLinks=function(){e("a").internalLink(this),o.setup(this,"true"===this.parameters.debugForms)},l._onStateChange=function(){var t=History.getState(),e=t.url.split(Canteen.settings.baseUrl)[1];d!=e&&this._updatePageContent(e)},l._gatewayReady=function(t){t||Debug.error("Unable to setup gateway.");var n=this.options;e(n.siteLoadingId).removeClass(n.loadingClass),e(window).on("resize",this.resize.bind(this)),this.resize(),this.trigger(u.READY),this._enterPage()},l.resize=function(){v&&v.active&&v.resize()},l.addPage=function(t,e){e instanceof s?(e.site=this,p.push({uri:t,content:e})):Debug.warn("The page your trying to add needs to extend Canteen.Page")},l._enterPage=function(){var t=this.getPageByUri(d);t&&(this.currentPage=v=t.content,v.uri=d,v.active=!0,v.enter(),this.resize()),this.trigger(u.ENTER,d)},l.getPageByUri=function(t){var e=p.length,n=0,r=null;if(0===e)return null;for(n=0;e>n;n++)if(r=p[n],r.uri===t||r.uri instanceof RegExp&&r.uri.test(t))return r;return null},l._updatePageContent=function(t,r){var i=this,a=this.options,s=this.getPageByUri(t),l=Canteen.settings.baseUrl+t;return this.trigger(u.EXIT,d),this.currentState=d=t,s&&s.content===v&&!s.content.refresh(t)?(s.content.uri=t,void 0):(v&&(v.exit(),v.active=!1,this.currentPage=v=null),o.destroy(),f=t,r=r===n?{}:r,r.async=!0,this.trigger(u.LOADING),e(a.pageLoadingId).removeClass(a.loadingClass).addClass(a.loadingClass),e.post(l,r,function(r){if(t==f){if(f=null,i.trigger(u.LOADING_DONE),e(a.pageLoadingId).removeClass(a.loadingClass),!r||"null"==r)return Debug.error("No data for "+t),void 0;if(-1==r.search(/^{.*}$/))return Debug.error(r),void 0;var o=JSON.parse(r);if("fatalError"==o.type)return Debug.fatalError(o),void 0;if(o.redirect!==n)return i.redirect(o.redirect,!0),void 0;e("body").attr("id",o.pageId),e(a.pageTitleId).html(o.title),e(a.contentId).html(o.content),document.title=e("
").html(o.fullTitle).text(),e("meta[name='keywords']").attr("content",o.keywords),e("meta[name='description']").attr("content",o.description),i._fixInternalLinks(),i._enterPage()}}),void 0)},namespace("Canteen").Site=u,e(function(){new u})}(window,jQuery); \ No newline at end of file diff --git a/src/Canteen/Site.js b/src/Canteen/Site.js index 6c48d1e..c52fd34 100644 --- a/src/Canteen/Site.js +++ b/src/Canteen/Site.js @@ -62,6 +62,13 @@ * @private */ _currentState = null, + + /** + * If we should enable the HTML5 history + * @property {Boolean} _historyEnabled + * @private + */ + _historyEnabled = true, /** * An array of the pages @@ -225,8 +232,12 @@ // Setup history _currentId = 1; this.currentState = _currentState = Canteen.settings.uriRequest; - this._enableHistory(true); - this._fixInternalLinks(); + this._enableHistory(!!(global.history && history.pushState)); + + if (_historyEnabled) + { + this._fixInternalLinks(); + } // Initialize the gateway this.gateway = new Gateway( @@ -243,6 +254,7 @@ */ p._enableHistory = function(enable) { + _historyEnabled = enable; $(global).off('statechange'); if (enable) $(global).on('statechange', this._onStateChange.bind(this)); @@ -291,15 +303,22 @@ return; } - // Change the history state - if (replaceInHistory) + if (_historyEnabled) { - History.replaceState({state:_currentId}, siteTitle, state); + // Change the history state + if (replaceInHistory) + { + History.replaceState({state:_currentId}, siteTitle, state); + } + else + { + _currentId++; + History.pushState({state:_currentId}, siteTitle, state); + } } else { - _currentId++; - History.pushState({state:_currentId}, siteTitle, state); + document.location.href = state; } }; @@ -312,7 +331,7 @@ p.refresh = function(async, params) { async = async === undefined ? true : async; - if (async) + if (async && _historyEnabled) this._updatePageContent(_currentState, params); else document.location.reload(true);