diff --git a/example/buttons.html b/example/buttons.html index badc167552..b14323ee23 100644 --- a/example/buttons.html +++ b/example/buttons.html @@ -58,7 +58,9 @@ + + diff --git a/example/grid.html b/example/grid.html index fd98446cea..b598e9d00f 100644 --- a/example/grid.html +++ b/example/grid.html @@ -24,7 +24,9 @@ + + diff --git a/example/index.html b/example/index.html index c8769aa53c..5a874a4021 100644 --- a/example/index.html +++ b/example/index.html @@ -56,7 +56,9 @@ + + diff --git a/example/listview.html b/example/listview.html index 3993fafcf9..eb67231628 100644 --- a/example/listview.html +++ b/example/listview.html @@ -101,7 +101,9 @@ + + diff --git a/js/framework/framework-buttons.js b/js/framework/framework-buttons.js index a5b68dc7ad..e270498eff 100644 --- a/js/framework/framework-buttons.js +++ b/js/framework/framework-buttons.js @@ -26,4 +26,4 @@ document.addEventListener('touchend', framework.Button.prototype._onTouchEnd); document.addEventListener('touchcancel', framework.Button.prototype._onTouchEnd); -})(this, document, this.FM = this.FM || {}); +})(this, document, FM = this.FM || {}); diff --git a/js/framework/framework-events.js b/js/framework/framework-events.js index f67c220583..574f1d6c28 100644 --- a/js/framework/framework-events.js +++ b/js/framework/framework-events.js @@ -17,7 +17,9 @@ // Some convenient top-level event functions framework.trigger = function(type, data) { - window.dispatchEvent(new CustomEvent(type, data)); + window.dispatchEvent(new CustomEvent(type, { + detail: data + })); }; framework.on = function(type, callback, element) { @@ -94,4 +96,5 @@ window.addEventListener('touchend', _touchEnd); window.addEventListener('click', _click); window.addEventListener('popstate', _popstate); -})(this, document, this.FM = this.FM || {}); + +})(this, document, FM = this.FM || {}); diff --git a/js/framework/framework-init.js b/js/framework/framework-init.js index ffa11543b4..f9ce8f4f8f 100644 --- a/js/framework/framework-init.js +++ b/js/framework/framework-init.js @@ -1,31 +1,39 @@ (function(window, document, framework) { - // Start initalizing the framework function initalize() { - - - framework.trigger("initalized"); - } + // remove the ready listeners + document.removeEventListener( "DOMContentLoaded", initalize, false ); + window.removeEventListener( "load", initalize, false ); - // DOM has completed - function completed() { - // remove any listeners - document.removeEventListener( "DOMContentLoaded", completed, false ); - window.removeEventListener( "load", completed, false ); + // trigger that the DOM is ready framework.trigger("ready"); - - // init the framework - initalize(); + + // ensure that the start page has an id + var mainElement = document.querySelector("main"); + if(mainElement) { + if(!mainElement.id || mainElement.id === "") { + mainElement.id = "pg" + Math.floor( Math.random() * 999999 ); + } + + // remember what the active page's id is + framework.activePageId = mainElement.id; + + // inform the framework that the start page has been added to the DOM + framework.trigger("pagecreate", {id: mainElement.id, url: location.href}); + + // trigger that the start page is in view + framework.trigger("pageview"); + } } - // When the DOM is ready, call completed() + // When the DOM is ready, initalize the webapp if ( document.readyState === "complete" ) { // DOM is already ready - setTimeout( completed ); + setTimeout( initalize ); } else { // DOM isn't ready yet, add event listeners - document.addEventListener( "DOMContentLoaded", completed, false ); - window.addEventListener( "load", completed, false ); + document.addEventListener( "DOMContentLoaded", initalize, false ); + window.addEventListener( "load", initalize, false ); } -})(this, document, this.FM = this.FM || {}); \ No newline at end of file +})(this, document, FM = this.FM || {}); \ No newline at end of file diff --git a/js/framework/framework-list.js b/js/framework/framework-list.js index 74e696be59..b1da24e364 100644 --- a/js/framework/framework-list.js +++ b/js/framework/framework-list.js @@ -20,4 +20,4 @@ document.addEventListener('touchstart', framework.List.prototype._onTouchStart); document.addEventListener('touchend', framework.List.prototype._onTouchEnd); -})(this, document, this.FM = this.FM || {}); +})(this, document, FM = this.FM || {}); diff --git a/js/framework/framework-navigation.js b/js/framework/framework-navigation.js index 739b6af2ae..ce5fd4cfeb 100644 --- a/js/framework/framework-navigation.js +++ b/js/framework/framework-navigation.js @@ -1,19 +1,29 @@ (function(window, document, location, framework) { var - x; + x, + link; // Add listeners to each link in the document - framework.addLinkListeners = function() { + function addNavListeners() { for(x = 0; x < document.links.length; x++) { - document.links[x].addEventListener('click', linkClick, false); + link = document.links[x]; + // double check we didnt already add this event + if(!link._hasClick) { + link.addEventListener('click', linkClick, false); + link._hasClick = true; + } } } - // Remove listeners to each link in the document - framework.removeLinkListeners = function() { - for(x = 0; x < document.links.length; x++) { - document.links[x].removeEventListener('click', linkClick, false); + // Remove listeners from the links in the inactive page element + function removeInactivePageNavListeners(e) { + var element = document.getElementById(e.detail.id); + if(element) { + links = element.querySelectorAll("a"); + for(x = 0; x < links.length; x++) { + links[x].removeEventListener('click', linkClick, false); + } } } @@ -37,14 +47,25 @@ return false; } - // only intercept the nav click if they're going to the same domain + // only intercept the nav click if they're going to the same domain or page if (location.protocol === target.protocol && location.host === target.host) { - // this link is an anchor to the same page + + // trigger the event that a new page should be shown + framework.trigger("pageinit", target.href); + + // decide how to handle this click depending on the href if(target.getAttribute("href").indexOf("#") === 0) { + // this click is going to another element within this same page hashLinkClick(target); + } else { + // this click is going to another page in the same domain pageLinkClick(target); + } + + // stop the browser itself from continuing on with this click + // the above code will take care of the navigation e.preventDefault(); return false; } @@ -52,7 +73,6 @@ // they are navigating to another URL within the same domain function pageLinkClick(target) { - console.log("pageLinkClick, get:", target.href); push({ url: target.href @@ -64,14 +84,6 @@ console.log("hashLinkClick, get:", target.href); } - function touchEnd(e) { - framework.trigger("touchEnd"); - } - - function popstate(e) { - - } - function push(options) { framework.isRequesting = true; var xhr = new XMLHttpRequest(); @@ -89,12 +101,21 @@ } function successPageLoad(xhr, options) { - var data = parseXHR(xhr, options); framework.isRequesting = false; + + var data = parseXHR(xhr, options); + insertPageIntoDom(data); + + framework.trigger("pagetransition", { + newActivePageId: data.id, + url: data.url, + title: data.title + }); + } function failedPageLoad(options) { - framework.trigger("pageloadfailed"); + framework.trigger("pageinitfailed"); framework.isRequesting = false; } @@ -111,41 +132,62 @@ container = document.createElement('div'); container.innerHTML = xhr.responseText; + // get the title of the page tmp = container.querySelector("title"); if(tmp) { data.title = tmp.innerText; } else { - tmp = container.querySelector("h1"); - if(tmp) { - data.title = tmp.innerText; - } else { - data.title = data.url; - } + data.title = data.url; } + // get the main content of the page tmp = container.querySelector("main"); if(tmp) { - data.main = tmp.innerHTML; - } else { - tmp = container.querySelector("body"); - if(tmp) { - data.main = tmp.innerHTML; + // get an id for this element + if(!tmp.id || tmp.id === "") { + // it doesn't already have an id, so build a random one for it + data.id = "pg" + Math.floor( Math.random() * 999999 ); } else { - data.main = container.innerHTML; + // use their existing id + data.id = tmp.id; } + data.main = tmp.innerHTML; } return data; } - framework.on("ready", function(){ - // DOM is ready - framework.addLinkListeners(); - }); + function insertPageIntoDom(data) { + if(data && data.main) { + // get the first main element + var oldMainElement = document.querySelector("main"); - window.addEventListener('touchstart', function () { framework.isScrolling = false; }); - window.addEventListener('touchmove', function () { framework.isScrolling = true; }) - window.addEventListener('touchend', touchEnd); - window.addEventListener('popstate', popstate); + // build a new main element to hold the new data + var newMainElement = document.createElement("main"); + newMainElement.id = data.id; + newMainElement.innerHTML = data.main; -})(this, document, location, this.FM = this.FM || {}); \ No newline at end of file + // insert the new main element before the old main element + oldMainElement.parentNode.insertBefore(newMainElement, oldMainElement); + + // inform the framework that a new page has been added to the DOM + framework.trigger("pagecreate", { + id: data.id, + url: data.url, + title: data.title + }); + + } else { + // something is wrong with the data, trigger that the page init failed + framework.trigger("pageinitfailed"); + } + } + + // after a page has been added to the DOM + framework.on("pagecreate", addNavListeners); + + // before a page is about to be removed from the DOM + framework.on("pageremove", removeInactivePageNavListeners); + + +})(this, document, location, FM = this.FM || {}); \ No newline at end of file diff --git a/js/framework/framework-tabs.js b/js/framework/framework-tabs.js index 553cbc4454..0e33fb9ecc 100644 --- a/js/framework/framework-tabs.js +++ b/js/framework/framework-tabs.js @@ -22,4 +22,4 @@ document.addEventListener('touchstart', framework.Tabs.prototype._onTouchStart); document.addEventListener('touchend', framework.Tabs.prototype._onTouchEnd); -})(this, document, this.FM = this.FM || {}); +})(this, document, FM = this.FM || {}); diff --git a/js/framework/framework-template.js b/js/framework/framework-template.js new file mode 100644 index 0000000000..931b8ff8e7 --- /dev/null +++ b/js/framework/framework-template.js @@ -0,0 +1,59 @@ +'use strict'; + +(function(window, document, framework) { + + // Loop through each element in the DOM and collect up all + // the templates it has. A template either has data to supply + // to others, or it needs data from another template + function initTemplates() { + var + x, + el, + emptyTemplates = []; + + // collect up all the templates currently in the DOM + for(x=0; x