Skip to content
Browse files

Close #22 custom loader

  • Loading branch information...
1 parent 91f2d95 commit 92e13dd0422849488434deec61a8f8a7c7977d57 @finnsson committed Sep 1, 2012
Showing with 753 additions and 36 deletions.
  1. +76 −20 README.md
  2. +22 −0 demo/demo.js
  3. +22 −0 demo/diagrams.md
  4. +96 −0 demo/index.html
  5. +505 −2 demo/pager.amd.min.js
  6. +2 −2 dist/pager.amd.min.js
  7. +2 −2 dist/pager.min.js
  8. +1 −1 lib/qunit-until.js
  9. +23 −5 pager.js
  10. +4 −4 test/should_trigger_before_after_hide_show.html
View
96 README.md
@@ -341,8 +341,6 @@ There are four alternatives:
The click data-binding can be used to run validations before navigations. Just do not `return true`
to prevent the navigation from happening.
-## In the pipeline
-
### Should be possible to supply custom showElement and hideElement-methods
@@ -351,32 +349,53 @@ to prevent the navigation from happening.
</div>
// new default hide
- pager.hideElement = function(callback) {
- $(this.element).slideUp(600);
+ pager.hideElement = function(page, callback) {
+ $(page.element).slideUp(600);
if(callback) {
callback();
}
};
// new default show
- pager.showElement = function(callback) {
- $(this.element).slideDown(600);
+ pager.showElement = function(page, callback) {
+ $(page.element).slideDown(600);
if(callback) {
callback();
}
};
- var showFry = function(callback) {
- $(this.element).fadeIn(500, callback);
+ var showFry = function(page, callback) {
+ $(page.element).fadeIn(500, callback);
};
- var hideFry = function(callback) {
- $(this.element).fadeOut(500, callback);
+ var hideFry = function(page, callback) {
+ $(page.element).fadeOut(500, callback);
};
### Should be possible to specify loaders in pages
+ <div data-bind="page: {id: 'zoidberg', title: 'Zoidberg', loader: loader, sourceOnShow: 'zoidberg.html'}" />
+
+where
+
+ textLoader: function(page, element) {
+ var loader = {};
+ var txt = $('<div></div>', {text: 'Loading ' + page.getValue().title});
+ loader.load = function() {
+ $(element).append(txt);
+ };
+ loader.unload = function() {
+ txt.remove();
+ };
+ return loader;
+ }
+
### Should be possible to specify global loaders
+ // see textLoader above
+ pager.loader = textLoader;
+
+## In the pipeline
+
### Tab panel custom widget
### Wildcards should deep-load content if configured so
@@ -386,22 +405,59 @@ to prevent the navigation from happening.
<div data-bind="page: {id: '?', deep: true, sourceOnShow: '{?}.html'}>
</div>
+### Should be possible to react to a failed navigation
+
+Both Page-objects and pager should send events whenever a navigation failed (i.e. no matching page for the route).
+
## Backlog
There are a lot of features waiting to be implemented. Here are some of them.
-### Custom Widgets
+### Should be possible to load view content using a custom method
-#### Site map custom widget
+In order to facilitate programming in the large it is useful to be able to extract views as separate components.
+These views should not be forced to be stored as html-fragments or be loaded with jQuery.
-### Should be possible to use a page as template for other pages
+Thus a way to inject custom views should be possible. This is done using the `sourcer`-property.
- <div id="sourceTpl" data-tpl="page: {sourceCache: true, sourceOnShow: '{?}.html'}">
- <div class="loader">
- The page is loading...
- </div>
- </div>
+The `sourcer`-property takes a method that should take a `pager.Page` as first argument and return nothing.
- <div data-bind="page: {id: 'fry', tpl: 'sourceTpl'}">
- </div>
+ <div data-bind="page: {id: 'zoidberg', sourcer: view('character/zoidberg')}" />
+
+where
+
+ window.view = function(viewModule) {
+ return function(page) {
+ require(viewModule, function(viewString) {
+ $(page.element).html(viewString);
+ });
+ };
+ };
+
+if
+
+ // file: character/zoidberg.js
+ define(function() {
+ return '<h1>Zoidberg</h1>;
+ });
+
+### Document all the source code
+
+The source code should be documented using either JsDuck or Docco.
+
+### Document architecture and guiding principles
+
+The architecture - and guiding principles - should be documentet.
+
+
+* Dependencies (jQuery, KnockoutJS, Underscore.js)
+* how the tool-chain is used (grunt qunit > grunt min),
+* working process (README.md > GitHub Issues > QUnit-test > pager.js > demo-page),
+* code architecture (pager , Page, ChildManager).
+
+### Should be possible to listen to page-navigations and prevent them
+
+Using HTML5 and pushState it might be possible to correctly listen to page-navigations
+and prevent them without complications to the history-management. Listening to click-events
+is the recommended way at the moment.
View
22 demo/demo.js
@@ -7,6 +7,28 @@ require(['jquery', 'knockout', 'underscore', 'pager', 'bootstrap'], function ($,
},
beforeFryIsHidden:function () {
$('body').stop().css("background-color", "#FFFFFF");
+ },
+ showFry:function (page, callback) {
+ $(page.element).fadeIn(1000, callback);
+ },
+ hideFry:function (page, callback) {
+ $(page.element).fadeOut(1000, function () {
+ $(page.element).hide();
+ if (callback) {
+ callback();
+ }
+ });
+ },
+ textLoader: function(page, element) {
+ var loader = {};
+ var txt = $('<div></div>', {text: 'Loading ' + page.getValue().title});
+ loader.load = function() {
+ $(element).append(txt);
+ };
+ loader.unload = function() {
+ txt.remove();
+ };
+ return loader;
}
};
View
22 demo/diagrams.md
@@ -0,0 +1,22 @@
+# Diagrams
+
+This is the source code for [yUML](http://yuml.me/diagram/scruffy/class/draw)
+
+## KnockoutJS
+
+ [Model]<*->[ViewModel]
+ [ViewModel]-*>[View]
+ [View]<-[User interaction]
+
+## Normal routing
+
+ [Model]<*->[ViewModel]
+ [ViewModel]-*>[View]
+ [View]<-[User interaction]
+ [HashChange]->[Router]
+ [Router]-*>[Router Functions]
+ [Router Functions]->[ViewModel]
+
+
+## Pager.js
+
View
96 demo/index.html
@@ -747,6 +747,7 @@ <h3 data-bind="text: name"></h3>
</ul>
<a href="#custom_js_when_navigating/fry">Show Fry</a>
+
<div data-bind="page: {id: 'fry', beforeHide: beforeFryIsHidden, afterShow: afterFryIsDisplayed}">
Fry
<a class="btn" href="#custom_js_when_navigating">Hide Fry</a>
@@ -773,6 +774,101 @@ <h3 data-bind="text: name"></h3>
</pre>
+ <a href="#custom_hide_show">Read about custom hide- and show-methods</a>
+
+</div>
+
+<div data-bind="page: {id: 'custom_hide_show', title: 'Custom Hide- and Show-methods'}">
+ <header class="jumbotron subhead">
+ <h1>Custom Hide- and Show-methods</h1>
+
+ <p class="lead">
+ You might want to use a custom animation or custom behaviour for a page.
+ This is easily done by using the <code>showElement</code> and <code>hideElement</code>-properties.
+
+ These properties should be supplied with a method that takes two arguments: the first if the page
+ and the second is a callback that should be executed.
+ </p>
+ </header>
+
+ <a href="#custom_hide_show/fry">Show Fry</a>
+ <div data-bind="page: {id: 'fry', showElement: showFry, hideElement: hideFry}">
+ <h2>Fry</h2>
+ <a class="btn" data-bind="page-href: '../'">Hide Fry</a>
+ </div>
+
+ <pre class="linenums prettyprint">
+&lt;div data-bind="page: {id: 'fry', showElement: showFry, hideElement: hideFry}"&gt;
+ &lt;h2&gt;Fry&lt;/h2&gt;
+ &lt;a class="btn" data-bind="page-href: '../'"&gt;Hide Fry&lt;/a&gt;
+&lt;/div&gt;
+ </pre>
+
+ <p>where</p>
+
+ <pre class="prettyprint linenums">
+showFry:function (page, callback) {
+ $(page.element).fadeIn(1000, callback);
+};
+hideFry:function (page, callback) {
+ $(page.element).fadeOut(1000, function () {
+ $(page.element).hide();
+ if (callback) {
+ callback();
+ }
+ });
+};
+ </pre>
+
+ <a href="#loader">Read about custom loaders</a>
+
+</div>
+
+<div data-bind="page: {id: 'loader', title: 'Loaders'}">
+ <header class="jumbotron subhead">
+ <h1>Loaders</h1>
+
+ <p class="lead">
+ It is possible to specify both locally an globally a loader to be used.
+
+ Use <code>loader: loader</code> for specifying a loader for a page
+ and <code>pager.loader = function(page, element) { ... }</code> for specifying
+ a default-loader for all pages.
+ The loader-method should return an object with two methods: <code>load</code>,
+ and <code>unload</code>.
+ </p>
+ </header>
+
+ <a href="#loader/Sabrepulse">Load Sabrepulse</a>
+
+ <div data-bind="page: {id: 'Sabrepulse', frame: 'iframe', title: 'Sabrepulse', loader: textLoader, sourceOnShow: 'https://embed.spotify.com/?uri=spotify:album:43tqiFDcU8JcMVSYj6NTi3'}">
+ <iframe width="300" height="380" frameborder="0" allowtransparency="true"></iframe>
+ </div>
+
+ <pre class="prettyprint linenums">
+&lt;div data-bind="page: {id: 'Sabrepulse', title: 'Sabrepulse', loader: textLoader, sourceOnShow: 'https://embed.spotify.com/?uri=spotify:album:43tqiFDcU8JcMVSYj6NTi3'}"&gt;
+ &lt;iframe width="300" height="380" frameborder="0" allowtransparency="true"&gt;&lt;/iframe&gt;
+&lt;/div&gt;
+ </pre>
+
+ <p>where</p>
+
+ <pre class="prettyprint linenums">
+textLoader: function(page, element) {
+ var loader = {};
+ var txt = $("&lt;div&gt;&lt;/div>",
+ {text: 'Loading ' + page.getValue().title}
+ );
+ loader.load = function() {
+ $(element).append(txt);
+ };
+ loader.unload = function() {
+ txt.remove();
+ };
+ return loader;
+}
+ </pre>
+
</div>
View
507 demo/pager.amd.min.js
@@ -1,4 +1,507 @@
-/*! pager.js - v0.3.0 - 2012-08-29
+/*! pager.js - v0.3.0 - 2012-09-01
* http://oscar.finnsson.nu/pagerjs/
* Copyright (c) 2012 Oscar Finnsson; Licensed MIT */
-define(["jquery","underscore","knockout"],function(a,b,c){var d={},e={};return e.value=c.utils.unwrapObservable,e.arrayValue=function(a){return b.map(a,function(a){return e.value(a)})},d.ChildManager=function(a,d){this.currentChildO=c.observable(null);var e=this;this.page=d,this.hideChild=function(){e.currentChild&&e.currentChild.getId()!=="start"&&(e.currentChild.hidePage(function(){}),e.currentChild=null,e.currentChildO(null))},this.showChild=function(c){var d=e.currentChild;e.currentChild=null;var f=!1,g=c[0],h=null;b.each(a(),function(a){if(!f){var b=a.getId();if(b===g||(g===""||g==null)&&b==="start")f=!0,e.currentChild=a;b==="?"&&(h=a)}});var i=!1,j=e;while(!e.currentChild&&j.page.parentPage&&!j.page.getValue().modal){var k=j.page.parentPage.children;b.each(k(),function(a){if(!f){var b=a.getId(),c=a.getValue().modal;if(c){if(b===g||(g===""||g==null)&&b==="start")f=!0,e.currentChild=a,i=!0;b==="?"&&!h&&(h=a,i=!0)}}}),e.currentChild||(j=j.page.parentPage.childManager)}!e.currentChild&&h&&(e.currentChild=h,e.currentChild.currentId=g),e.currentChild&&(e.currentChildO(e.currentChild),i?e.currentChild.currentParentPage(e.page):e.currentChild.currentParentPage(null)),d&&d===e.currentChild?e.currentChild.showPage(c.slice(1)):d?d.hidePage(function(){e.currentChild&&e.currentChild.showPage(c.slice(1))}):e.currentChild&&e.currentChild.showPage(c.slice(1))}},d.start=function(b){var c=function(){d.routeFromHashToPage(window.location.hash)};a(window).bind("hashchange",c),c()},d.extendWithPage=function(a){a.$page=new d.Page,d.childManager=new d.ChildManager(a.$page.children,a.$page),a.$page.childManager=d.childManager},d.routeFromHashToPage=function(a){a[0]==="#"&&(a=a.slice(1));var b=a.split("/");d.childManager.showChild(b)},d.Page=function(a,b,e,f,g){this.element=a,this.valueAccessor=b,this.allBindingsAccessor=e,this.viewModel=f,this.bindingContext=g,this.children=c.observableArray([]),this.childManager=new d.ChildManager(this.children,this),this.parentPage=null,this.currentId=null,this.currentParentPage=c.observable(null)},d.Page.prototype.showPage=function(a){this.show(),this.childManager.showChild(a)},d.Page.prototype.hidePage=function(a){this.hideElementWrapper(a),this.childManager.hideChild()},d.Page.prototype.init=function(){var a=this.getValue();this.parentPage=this.getParentPage(),this.parentPage.children.push(this),this.hideElement(),a.source&&this.loadSource(a.source);var b=null;return a["with"]?b=e.value(a["with"]):a.withOnShow?b={}:b=this.viewModel,this.childBindingContext=this.bindingContext.createChildContext(b),c.utils.extend(this.childBindingContext,{$page:this}),a.withOnShow||c.applyBindingsToDescendants(this.childBindingContext,this.element),{controlsDescendantBindings:!0}},d.Page.prototype.getValue=function(){return e.value(this.valueAccessor())},d.Page.prototype.getParentPage=function(){return this.bindingContext.$page||this.bindingContext.$data.$page},d.Page.prototype.getId=function(){return e.value(this.getValue().id)},d.Page.prototype.sourceUrl=function(a){var b=this;return this.getId()==="?"?c.computed(function(){return e.value(a).replace("{1}",b.currentId)}):c.computed(function(){return e.value(a)})},d.Page.prototype.loadSource=function(b){var d=this.getValue(),f=this,g=this.element;if(d.frame==="iframe"){var h=a("iframe",a(g));h.length===0&&(h=a("<iframe></iframe>"),a(g).append(h)),d.sourceLoaded&&h.one("load",d.sourceLoaded),c.applyBindingsToNode(h[0],{attr:{src:this.sourceUrl(b)}})}else c.computed(function(){var h=e.value(this.sourceUrl(b));a(g).load(h,function(){c.applyBindingsToDescendants(f.childBindingContext,f.element),d.sourceLoaded&&d.sourceLoaded.apply(f,arguments)})},this)},d.Page.prototype.show=function(a){var d=this.element,e=this.getValue();this.showElementWrapper(a),this.getValue().title&&(window.document.title=this.getValue().title),e.withOnShow&&(this.withOnShowLoaded||(this.withOnShowLoaded=!0,e.withOnShow(b.bind(function(a){var b=this.bindingContext.createChildContext(a);c.utils.extend(b,{$page:this}),c.applyBindingsToDescendants(b,this.element)},this)))),e.sourceOnShow&&(!e.sourceCache||!d.__pagerLoaded__||typeof e.sourceCache=="number"&&d.__pagerLoaded__+e.sourceCache*1e3<Date.now())&&(d.__pagerLoaded__=Date.now(),this.loadSource(e.sourceOnShow))},d.Page.prototype.showElementWrapper=function(a){this.getValue().beforeShow&&this.getValue().beforeShow(this),this.showElement(a),this.getValue().afterShow&&this.getValue().afterShow(this)},d.Page.prototype.showElement=function(b){this.getValue().showElement?this.getValue().showElement.call(this,b):d.showElement?d.showElement.call(this,b):a(this.element).show(b)},d.Page.prototype.hideElementWrapper=function(a){this.getValue().beforeHide&&this.getValue().beforeHide(this),this.hideElement(a),this.getValue().afterHide&&this.getValue().afterHide(this)},d.Page.prototype.hideElement=function(b){this.getValue().hideElement?this.getValue().hideElement.call(this,b):d.hideElement?d.hideElement.call(this,b):(a(this.element).hide(),b&&b())},d.Page.prototype.isVisible=function(){return a(this.element).is(":visible")},d.Page.prototype.getFullRoute=function(){return c.computed(function(){if(this.currentParentPage&&this.currentParentPage()){var a=this.currentParentPage().getFullRoute()();return a.push(this.getId()),a}if(this.parentPage){var a=this.parentPage.getFullRoute()();return a.push(this.getId()),a}return[]},this)},c.bindingHandlers.page={init:function(a,b,c,e,f){var g=new d.Page(a,b,c,e,f);return g.init()},update:function(a,b,c,d,e){}},d.useHTML5history=!1,d.rootURI="/",c.bindingHandlers["page-href"]={init:function(b,f,g,h,i){var j=i.$page||i.$data.$page,k=j,l=c.computed(function(){var c=e.value(f()),d=0;while(c.substring(0,3)==="../")d++,c=c.slice(3);var g=k.getFullRoute()(),h=g.slice(0,g.length-d).join("/"),i=(h===""?"":h+"/")+c,j={href:"#"+i};return a(b).attr(j),i});d.useHTML5history&&window.history&&history.pushState&&a(b).click(function(a){a.preventDefault(),history.pushState(null,null,d.rootURI+l()),d.childManager.showChild(l().split("/"))})},update:function(){}},d.PageAccordionItem=function(a,b,c,e,f){d.Page.apply(this,arguments)},d.PageAccordionItem.prototype=new d.Page,d.PageAccordionItem.prototype.getAccordionBody=function(){return a(this.element).children()[1]},d.PageAccordionItem.prototype.hideElement=function(b){this.pageAccordionItemHidden?(a(this.getAccordionBody()).slideUp(),b&&b()):(this.pageAccordionItemHidden=!0,a(this.getAccordionBody()).hide())},d.PageAccordionItem.prototype.showElement=function(b){a(this.getAccordionBody()).slideDown(),b&&b()},c.bindingHandlers["page-accordion-item"]={init:function(a,b,c,e,f){var g=new d.PageAccordionItem(a,b,c,e,f);g.init()},update:function(){}},d});
+
+define(['jquery','underscore','knockout'], function($,_,ko) {
+
+var pager = {};
+
+// common KnockoutJS helpers
+var _ko = {};
+
+_ko.value = ko.utils.unwrapObservable;
+
+_ko.arrayValue = function (arr) {
+ return _.map(arr, function (e) {
+ return _ko.value(e);
+ });
+};
+
+pager.ChildManager = function (children, page) {
+
+ //this.currentChild = children[0];
+ this.currentChildO = ko.observable(null);
+ var me = this;
+ this.page = page;
+
+ this.hideChild = function () {
+ if (me.currentChild) {
+ if (me.currentChild.getId() !== 'start') {
+ me.currentChild.hidePage(function () {
+ });
+ me.currentChild = null;
+ me.currentChildO(null);
+ }
+ }
+ };
+
+ /*
+
+ Will show or hide child pages
+
+ Goals:
+ 1. Get rid of parent
+ 2. Make use of children
+ */
+ this.showChild = function (route) {
+ var oldCurrentChild = me.currentChild;
+ me.currentChild = null;
+ var match = false;
+ var currentRoute = route[0];
+ var wildcard = null;
+ _.each(children(), function (child) {
+ if (!match) {
+ var id = child.getId();
+ if (id === currentRoute ||
+ ((currentRoute === '' || currentRoute == null) && id === 'start')) {
+ match = true;
+ me.currentChild = child;
+ }
+ if (id === '?') {
+ wildcard = child;
+ }
+ }
+ });
+ // find modals in parent - but only if 1) no match is found, 2) this page got a parent and 3) this page is not a modal!
+ var isModal = false;
+
+ var currentChildManager = me;
+
+ while(!me.currentChild && currentChildManager.page.parentPage && !currentChildManager.page.getValue().modal) {
+ var parentChildren = currentChildManager.page.parentPage.children;
+ _.each(parentChildren(), function (child) {
+ if (!match) {
+ var id = child.getId();
+ var modal = child.getValue().modal;
+ if (modal) {
+ if (id === currentRoute ||
+ ((currentRoute === '' || currentRoute == null) && id === 'start')) {
+ match = true;
+ me.currentChild = child;
+ isModal = true;
+ }
+ if (id === '?' && !wildcard) {
+ wildcard = child;
+ isModal = true;
+ }
+ }
+ }
+ });
+ if(!me.currentChild) {
+ currentChildManager = currentChildManager.page.parentPage.childManager;
+ }
+ }
+
+ if (!me.currentChild && wildcard) {
+ me.currentChild = wildcard;
+ me.currentChild.currentId = currentRoute;
+ }
+ if (me.currentChild) {
+ me.currentChildO(me.currentChild);
+
+ if(isModal) {
+ me.currentChild.currentParentPage(me.page);
+ } else {
+ me.currentChild.currentParentPage(null);
+ }
+
+ }
+ if (oldCurrentChild && oldCurrentChild === me.currentChild) {
+ me.currentChild.showPage(route.slice(1));
+ } else if (oldCurrentChild) {
+ oldCurrentChild.hidePage(function () {
+ if (me.currentChild) {
+ me.currentChild.showPage(route.slice(1));
+ }
+ });
+ } else if (me.currentChild) {
+ me.currentChild.showPage(route.slice(1));
+ }
+ };
+};
+
+pager.start = function (viewModel) {
+
+ var onHashChange = function () {
+ pager.routeFromHashToPage(window.location.hash);
+ };
+ $(window).bind('hashchange', onHashChange);
+ onHashChange();
+};
+
+pager.extendWithPage = function (viewModel) {
+ viewModel.$page = new pager.Page();
+
+ pager.childManager = new pager.ChildManager(viewModel.$page.children, viewModel.$page);
+ viewModel.$page.childManager = pager.childManager;
+};
+
+
+pager.routeFromHashToPage = function (hash) {
+ // skip #
+ if (hash[0] === '#') {
+ hash = hash.slice(1);
+ }
+ // split on '/'
+ var hashRoute = hash.split('/');
+
+ pager.childManager.showChild(hashRoute);
+
+};
+
+/**
+ * @class pager.Page
+ */
+
+/**
+ * @param element
+ * @param valueAccessor
+ * @param allBindingsAccessor
+ * @param viewModel
+ * @param bindingContext
+ * @constructor
+ */
+pager.Page = function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
+ this.element = element;
+ this.valueAccessor = valueAccessor;
+ this.allBindingsAccessor = allBindingsAccessor;
+ this.viewModel = viewModel;
+ this.bindingContext = bindingContext;
+
+ this.children = ko.observableArray([]);
+
+ this.childManager = new pager.ChildManager(this.children, this);
+ this.parentPage = null;
+ this.currentId = null;
+
+ this.currentParentPage = ko.observable(null);
+};
+
+pager.Page.prototype.showPage = function (route) {
+ this.show();
+ this.childManager.showChild(route);
+};
+
+pager.Page.prototype.hidePage = function (callback) {
+ this.hideElementWrapper(callback);
+ this.childManager.hideChild();
+};
+
+/**
+ * @method init
+ * @return {Object}
+ */
+pager.Page.prototype.init = function () {
+
+ var value = this.getValue();
+ this.parentPage = this.getParentPage();
+ this.parentPage.children.push(this);
+
+
+ this.hideElement();
+
+ // Fetch source
+ if (value.source) {
+ this.loadSource(value.source);
+ }
+
+ var ctx = null;
+ if (value['with']) {
+ ctx = _ko.value(value['with']);
+ } else if (value['withOnShow']) {
+ ctx = {};
+ } else {
+ ctx = this.viewModel;
+ }
+ this.childBindingContext = this.bindingContext.createChildContext(ctx);
+
+ ko.utils.extend(this.childBindingContext, {$page:this});
+ if (!value['withOnShow']) {
+ ko.applyBindingsToDescendants(this.childBindingContext, this.element);
+ }
+ return { controlsDescendantBindings:true};
+};
+
+/**
+ * @method getValue
+ * @return {*}
+ */
+pager.Page.prototype.getValue = function () {
+ return _ko.value(this.valueAccessor());
+};
+
+/**
+ * @method getParentPage
+ * @return {*}
+ */
+pager.Page.prototype.getParentPage = function () {
+ return this.bindingContext.$page || this.bindingContext.$data.$page;
+};
+
+pager.Page.prototype.getId = function () {
+ return _ko.value(this.getValue().id);
+};
+
+/**
+ * @method sourceUrl
+ * @param source
+ * @return {*}
+ */
+pager.Page.prototype.sourceUrl = function (source) {
+ var me = this;
+ if (this.getId() === '?') {
+ return ko.computed(function () {
+ // TODO: maybe make currentId an ko.observable?
+ return _ko.value(source).replace('{1}', me.currentId);
+ });
+ } else {
+ return ko.computed(function () {
+ return _ko.value(source);
+ });
+ }
+};
+
+/**
+ * @method loadSource
+ * @param source
+ */
+pager.Page.prototype.loadSource = function (source) {
+ var value = this.getValue();
+ var me = this;
+ var element = this.element;
+ var loader = null;
+ if (value.frame === 'iframe') {
+ var iframe = $('iframe', $(element));
+ if (iframe.length === 0) {
+ iframe = $('<iframe></iframe>');
+ $(element).append(iframe);
+ }
+ if(value.loader) {
+ loader = _ko.value(value.loader)(me, iframe);
+ loader.load();
+ }
+ if (value.sourceLoaded) {
+ iframe.one('load', function() {
+ if(loader) {
+ loader.unload();
+ }
+ value.sourceLoaded();
+ });
+ }
+ // TODO: remove src binding and add this binding
+ ko.applyBindingsToNode(iframe[0], {
+ attr:{
+ src:this.sourceUrl(source)
+ }
+ });
+ } else {
+ if(value.loader) {
+ loader = _ko.value(value.loader)(me, me.element);
+ loader.load();
+ }
+ // TODO: remove all children and add sourceUrl(source)
+ ko.computed(function () {
+ var s = _ko.value(this.sourceUrl(source));
+ $(element).load(s, function () {
+ if(loader) {
+ loader.unload();
+ }
+ ko.applyBindingsToDescendants(me.childBindingContext, me.element);
+ if (value.sourceLoaded) {
+ value.sourceLoaded.apply(me, arguments);
+ }
+ });
+ }, this);
+ }
+};
+
+/**
+ * @method show
+ */
+pager.Page.prototype.show = function (callback) {
+ var element = this.element;
+ var value = this.getValue();
+ this.showElementWrapper(callback);
+ if (this.getValue().title) {
+ window.document.title = this.getValue().title;
+ }
+ if (value.withOnShow) {
+ if (!this.withOnShowLoaded) {
+ this.withOnShowLoaded = true;
+ value.withOnShow(_.bind(function (vm) {
+ var childBindingContext = this.bindingContext.createChildContext(vm);
+
+ ko.utils.extend(childBindingContext, {$page:this});
+ ko.applyBindingsToDescendants(childBindingContext, this.element);
+ }, this));
+ }
+ }
+
+ // Fetch source
+ if (value.sourceOnShow) {
+ if (!value.sourceCache ||
+ !element.__pagerLoaded__ ||
+ (typeof(value.sourceCache) === 'number' && element.__pagerLoaded__ + value.sourceCache * 1000 < Date.now())) {
+ element.__pagerLoaded__ = Date.now();
+ this.loadSource(value.sourceOnShow);
+ }
+ }
+};
+
+pager.Page.prototype.showElementWrapper = function (callback) {
+ if (this.getValue().beforeShow) {
+ this.getValue().beforeShow(this);
+ }
+ this.showElement(callback);
+ if (this.getValue().afterShow) {
+ this.getValue().afterShow(this);
+ }
+};
+
+pager.Page.prototype.showElement = function (callback) {
+ if (this.getValue().showElement) {
+ this.getValue().showElement(this, callback);
+ } else if (pager.showElement) {
+ pager.showElement(this, callback);
+ } else {
+ $(this.element).show(callback);
+ }
+};
+
+pager.Page.prototype.hideElementWrapper = function (callback) {
+ if (this.getValue().beforeHide) {
+ this.getValue().beforeHide(this);
+ }
+ this.hideElement(callback);
+ if (this.getValue().afterHide) {
+ this.getValue().afterHide(this);
+ }
+};
+
+pager.Page.prototype.hideElement = function (callback) {
+ if (this.getValue().hideElement) {
+ this.getValue().hideElement(this, callback);
+ } else if (pager.hideElement) {
+ pager.hideElement(this, callback);
+ } else {
+ $(this.element).hide();
+ if (callback) {
+ callback();
+ }
+ }
+};
+
+pager.Page.prototype.isVisible = function () {
+ return $(this.element).is(':visible');
+};
+
+pager.Page.prototype.getFullRoute = function () {
+ return ko.computed(function () {
+ if (this.currentParentPage && this.currentParentPage()) {
+ var res = this.currentParentPage().getFullRoute()();
+ res.push(this.getId());
+ return res;
+ } else if (this.parentPage) {
+ var res = this.parentPage.getFullRoute()();
+ res.push(this.getId());
+ return res;
+ } else { // is root page
+ return [];
+ }
+ }, this);
+};
+
+ko.bindingHandlers.page = {
+ init:function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
+ var page = new pager.Page(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
+ return page.init();
+ },
+ update:function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
+ }
+};
+
+// page-href
+
+pager.useHTML5history = false;
+pager.rootURI = '/';
+
+// TODO: extract this into a separate class pager.PageHref
+ko.bindingHandlers['page-href'] = {
+ init:function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
+ var $page = bindingContext.$page || bindingContext.$data.$page;
+ var page = $page;
+
+ // The href reacts to changes in the value
+ var path = ko.computed(function () {
+ var value = _ko.value(valueAccessor());
+ var parentsToTrim = 0;
+ while (value.substring(0, 3) === '../') {
+ parentsToTrim++;
+ value = value.slice(3);
+ }
+
+ var fullRoute = page.getFullRoute()();
+ var parentPath = fullRoute.slice(0, fullRoute.length - parentsToTrim).join('/');
+ var fullPath = (parentPath === '' ? '' : parentPath + '/') + value;
+ var attr = {
+ 'href':'#' + fullPath
+ };
+ $(element).attr(attr);
+ return fullPath;
+ });
+
+ if (pager.useHTML5history && window.history && history.pushState) {
+ $(element).click(function (e) {
+ e.preventDefault();
+ history.pushState(null, null, pager.rootURI + path());
+ pager.childManager.showChild(path().split('/'));
+
+ });
+ }
+
+
+ },
+ update:function () {
+ }
+};
+
+// page-accordion-item
+
+pager.PageAccordionItem = function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
+ pager.Page.apply(this, arguments);
+};
+
+pager.PageAccordionItem.prototype = new pager.Page();
+
+pager.PageAccordionItem.prototype.getAccordionBody = function () {
+ return $(this.element).children()[1];
+};
+
+pager.PageAccordionItem.prototype.hideElement = function (callback) {
+ if (!this.pageAccordionItemHidden) {
+ this.pageAccordionItemHidden = true;
+ $(this.getAccordionBody()).hide();
+ } else {
+ $(this.getAccordionBody()).slideUp();
+ if (callback) {
+ callback();
+ }
+ }
+};
+
+pager.PageAccordionItem.prototype.showElement = function (callback) {
+ $(this.getAccordionBody()).slideDown();
+ if (callback) {
+ callback();
+ }
+};
+
+ko.bindingHandlers['page-accordion-item'] = {
+ init:function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
+ var pageAccordionItem = new pager.PageAccordionItem(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
+ pageAccordionItem.init();
+ },
+ update:function () {
+ }
+};
+return pager;});
View
4 dist/pager.amd.min.js
@@ -1,4 +1,4 @@
-/*! pager.js - v0.3.0 - 2012-08-29
+/*! pager.js - v0.3.0 - 2012-09-01
* http://oscar.finnsson.nu/pagerjs/
* Copyright (c) 2012 Oscar Finnsson; Licensed MIT */
-define(["jquery","underscore","knockout"],function(a,b,c){var d={},e={};return e.value=c.utils.unwrapObservable,e.arrayValue=function(a){return b.map(a,function(a){return e.value(a)})},d.ChildManager=function(a,d){this.currentChildO=c.observable(null);var e=this;this.page=d,this.hideChild=function(){e.currentChild&&e.currentChild.getId()!=="start"&&(e.currentChild.hidePage(function(){}),e.currentChild=null,e.currentChildO(null))},this.showChild=function(c){var d=e.currentChild;e.currentChild=null;var f=!1,g=c[0],h=null;b.each(a(),function(a){if(!f){var b=a.getId();if(b===g||(g===""||g==null)&&b==="start")f=!0,e.currentChild=a;b==="?"&&(h=a)}});var i=!1,j=e;while(!e.currentChild&&j.page.parentPage&&!j.page.getValue().modal){var k=j.page.parentPage.children;b.each(k(),function(a){if(!f){var b=a.getId(),c=a.getValue().modal;if(c){if(b===g||(g===""||g==null)&&b==="start")f=!0,e.currentChild=a,i=!0;b==="?"&&!h&&(h=a,i=!0)}}}),e.currentChild||(j=j.page.parentPage.childManager)}!e.currentChild&&h&&(e.currentChild=h,e.currentChild.currentId=g),e.currentChild&&(e.currentChildO(e.currentChild),i?e.currentChild.currentParentPage(e.page):e.currentChild.currentParentPage(null)),d&&d===e.currentChild?e.currentChild.showPage(c.slice(1)):d?d.hidePage(function(){e.currentChild&&e.currentChild.showPage(c.slice(1))}):e.currentChild&&e.currentChild.showPage(c.slice(1))}},d.start=function(b){var c=function(){d.routeFromHashToPage(window.location.hash)};a(window).bind("hashchange",c),c()},d.extendWithPage=function(a){a.$page=new d.Page,d.childManager=new d.ChildManager(a.$page.children,a.$page),a.$page.childManager=d.childManager},d.routeFromHashToPage=function(a){a[0]==="#"&&(a=a.slice(1));var b=a.split("/");d.childManager.showChild(b)},d.Page=function(a,b,e,f,g){this.element=a,this.valueAccessor=b,this.allBindingsAccessor=e,this.viewModel=f,this.bindingContext=g,this.children=c.observableArray([]),this.childManager=new d.ChildManager(this.children,this),this.parentPage=null,this.currentId=null,this.currentParentPage=c.observable(null)},d.Page.prototype.showPage=function(a){this.show(),this.childManager.showChild(a)},d.Page.prototype.hidePage=function(a){this.hideElementWrapper(a),this.childManager.hideChild()},d.Page.prototype.init=function(){var a=this.getValue();this.parentPage=this.getParentPage(),this.parentPage.children.push(this),this.hideElement(),a.source&&this.loadSource(a.source);var b=null;return a["with"]?b=e.value(a["with"]):a.withOnShow?b={}:b=this.viewModel,this.childBindingContext=this.bindingContext.createChildContext(b),c.utils.extend(this.childBindingContext,{$page:this}),a.withOnShow||c.applyBindingsToDescendants(this.childBindingContext,this.element),{controlsDescendantBindings:!0}},d.Page.prototype.getValue=function(){return e.value(this.valueAccessor())},d.Page.prototype.getParentPage=function(){return this.bindingContext.$page||this.bindingContext.$data.$page},d.Page.prototype.getId=function(){return e.value(this.getValue().id)},d.Page.prototype.sourceUrl=function(a){var b=this;return this.getId()==="?"?c.computed(function(){return e.value(a).replace("{1}",b.currentId)}):c.computed(function(){return e.value(a)})},d.Page.prototype.loadSource=function(b){var d=this.getValue(),f=this,g=this.element;if(d.frame==="iframe"){var h=a("iframe",a(g));h.length===0&&(h=a("<iframe></iframe>"),a(g).append(h)),d.sourceLoaded&&h.one("load",d.sourceLoaded),c.applyBindingsToNode(h[0],{attr:{src:this.sourceUrl(b)}})}else c.computed(function(){var h=e.value(this.sourceUrl(b));a(g).load(h,function(){c.applyBindingsToDescendants(f.childBindingContext,f.element),d.sourceLoaded&&d.sourceLoaded.apply(f,arguments)})},this)},d.Page.prototype.show=function(a){var d=this.element,e=this.getValue();this.showElementWrapper(a),this.getValue().title&&(window.document.title=this.getValue().title),e.withOnShow&&(this.withOnShowLoaded||(this.withOnShowLoaded=!0,e.withOnShow(b.bind(function(a){var b=this.bindingContext.createChildContext(a);c.utils.extend(b,{$page:this}),c.applyBindingsToDescendants(b,this.element)},this)))),e.sourceOnShow&&(!e.sourceCache||!d.__pagerLoaded__||typeof e.sourceCache=="number"&&d.__pagerLoaded__+e.sourceCache*1e3<Date.now())&&(d.__pagerLoaded__=Date.now(),this.loadSource(e.sourceOnShow))},d.Page.prototype.showElementWrapper=function(a){this.getValue().beforeShow&&this.getValue().beforeShow(this),this.showElement(a),this.getValue().afterShow&&this.getValue().afterShow(this)},d.Page.prototype.showElement=function(b){this.getValue().showElement?this.getValue().showElement.call(this,b):d.showElement?d.showElement.call(this,b):a(this.element).show(b)},d.Page.prototype.hideElementWrapper=function(a){this.getValue().beforeHide&&this.getValue().beforeHide(this),this.hideElement(a),this.getValue().afterHide&&this.getValue().afterHide(this)},d.Page.prototype.hideElement=function(b){this.getValue().hideElement?this.getValue().hideElement.call(this,b):d.hideElement?d.hideElement.call(this,b):(a(this.element).hide(),b&&b())},d.Page.prototype.isVisible=function(){return a(this.element).is(":visible")},d.Page.prototype.getFullRoute=function(){return c.computed(function(){if(this.currentParentPage&&this.currentParentPage()){var a=this.currentParentPage().getFullRoute()();return a.push(this.getId()),a}if(this.parentPage){var a=this.parentPage.getFullRoute()();return a.push(this.getId()),a}return[]},this)},c.bindingHandlers.page={init:function(a,b,c,e,f){var g=new d.Page(a,b,c,e,f);return g.init()},update:function(a,b,c,d,e){}},d.useHTML5history=!1,d.rootURI="/",c.bindingHandlers["page-href"]={init:function(b,f,g,h,i){var j=i.$page||i.$data.$page,k=j,l=c.computed(function(){var c=e.value(f()),d=0;while(c.substring(0,3)==="../")d++,c=c.slice(3);var g=k.getFullRoute()(),h=g.slice(0,g.length-d).join("/"),i=(h===""?"":h+"/")+c,j={href:"#"+i};return a(b).attr(j),i});d.useHTML5history&&window.history&&history.pushState&&a(b).click(function(a){a.preventDefault(),history.pushState(null,null,d.rootURI+l()),d.childManager.showChild(l().split("/"))})},update:function(){}},d.PageAccordionItem=function(a,b,c,e,f){d.Page.apply(this,arguments)},d.PageAccordionItem.prototype=new d.Page,d.PageAccordionItem.prototype.getAccordionBody=function(){return a(this.element).children()[1]},d.PageAccordionItem.prototype.hideElement=function(b){this.pageAccordionItemHidden?(a(this.getAccordionBody()).slideUp(),b&&b()):(this.pageAccordionItemHidden=!0,a(this.getAccordionBody()).hide())},d.PageAccordionItem.prototype.showElement=function(b){a(this.getAccordionBody()).slideDown(),b&&b()},c.bindingHandlers["page-accordion-item"]={init:function(a,b,c,e,f){var g=new d.PageAccordionItem(a,b,c,e,f);g.init()},update:function(){}},d});
+define(["jquery","underscore","knockout"],function(a,b,c){var d={},e={};return e.value=c.utils.unwrapObservable,e.arrayValue=function(a){return b.map(a,function(a){return e.value(a)})},d.ChildManager=function(a,d){this.currentChildO=c.observable(null);var e=this;this.page=d,this.hideChild=function(){e.currentChild&&e.currentChild.getId()!=="start"&&(e.currentChild.hidePage(function(){}),e.currentChild=null,e.currentChildO(null))},this.showChild=function(c){var d=e.currentChild;e.currentChild=null;var f=!1,g=c[0],h=null;b.each(a(),function(a){if(!f){var b=a.getId();if(b===g||(g===""||g==null)&&b==="start")f=!0,e.currentChild=a;b==="?"&&(h=a)}});var i=!1,j=e;while(!e.currentChild&&j.page.parentPage&&!j.page.getValue().modal){var k=j.page.parentPage.children;b.each(k(),function(a){if(!f){var b=a.getId(),c=a.getValue().modal;if(c){if(b===g||(g===""||g==null)&&b==="start")f=!0,e.currentChild=a,i=!0;b==="?"&&!h&&(h=a,i=!0)}}}),e.currentChild||(j=j.page.parentPage.childManager)}!e.currentChild&&h&&(e.currentChild=h,e.currentChild.currentId=g),e.currentChild&&(e.currentChildO(e.currentChild),i?e.currentChild.currentParentPage(e.page):e.currentChild.currentParentPage(null)),d&&d===e.currentChild?e.currentChild.showPage(c.slice(1)):d?d.hidePage(function(){e.currentChild&&e.currentChild.showPage(c.slice(1))}):e.currentChild&&e.currentChild.showPage(c.slice(1))}},d.start=function(b){var c=function(){d.routeFromHashToPage(window.location.hash)};a(window).bind("hashchange",c),c()},d.extendWithPage=function(a){a.$page=new d.Page,d.childManager=new d.ChildManager(a.$page.children,a.$page),a.$page.childManager=d.childManager},d.routeFromHashToPage=function(a){a[0]==="#"&&(a=a.slice(1));var b=a.split("/");d.childManager.showChild(b)},d.Page=function(a,b,e,f,g){this.element=a,this.valueAccessor=b,this.allBindingsAccessor=e,this.viewModel=f,this.bindingContext=g,this.children=c.observableArray([]),this.childManager=new d.ChildManager(this.children,this),this.parentPage=null,this.currentId=null,this.currentParentPage=c.observable(null)},d.Page.prototype.showPage=function(a){this.show(),this.childManager.showChild(a)},d.Page.prototype.hidePage=function(a){this.hideElementWrapper(a),this.childManager.hideChild()},d.Page.prototype.init=function(){var a=this.getValue();this.parentPage=this.getParentPage(),this.parentPage.children.push(this),this.hideElement(),a.source&&this.loadSource(a.source);var b=null;return a["with"]?b=e.value(a["with"]):a.withOnShow?b={}:b=this.viewModel,this.childBindingContext=this.bindingContext.createChildContext(b),c.utils.extend(this.childBindingContext,{$page:this}),a.withOnShow||c.applyBindingsToDescendants(this.childBindingContext,this.element),{controlsDescendantBindings:!0}},d.Page.prototype.getValue=function(){return e.value(this.valueAccessor())},d.Page.prototype.getParentPage=function(){return this.bindingContext.$page||this.bindingContext.$data.$page},d.Page.prototype.getId=function(){return e.value(this.getValue().id)},d.Page.prototype.sourceUrl=function(a){var b=this;return this.getId()==="?"?c.computed(function(){return e.value(a).replace("{1}",b.currentId)}):c.computed(function(){return e.value(a)})},d.Page.prototype.loadSource=function(b){var d=this.getValue(),f=this,g=this.element;d.loader&&e.value(d.loader)(f);if(d.frame==="iframe"){var h=a("iframe",a(g));h.length===0&&(h=a("<iframe></iframe>"),a(g).append(h)),d.sourceLoaded&&h.one("load",d.sourceLoaded),c.applyBindingsToNode(h[0],{attr:{src:this.sourceUrl(b)}})}else c.computed(function(){var h=e.value(this.sourceUrl(b));a(g).load(h,function(){c.applyBindingsToDescendants(f.childBindingContext,f.element),d.sourceLoaded&&d.sourceLoaded.apply(f,arguments)})},this)},d.Page.prototype.show=function(a){var d=this.element,e=this.getValue();this.showElementWrapper(a),this.getValue().title&&(window.document.title=this.getValue().title),e.withOnShow&&(this.withOnShowLoaded||(this.withOnShowLoaded=!0,e.withOnShow(b.bind(function(a){var b=this.bindingContext.createChildContext(a);c.utils.extend(b,{$page:this}),c.applyBindingsToDescendants(b,this.element)},this)))),e.sourceOnShow&&(!e.sourceCache||!d.__pagerLoaded__||typeof e.sourceCache=="number"&&d.__pagerLoaded__+e.sourceCache*1e3<Date.now())&&(d.__pagerLoaded__=Date.now(),this.loadSource(e.sourceOnShow))},d.Page.prototype.showElementWrapper=function(a){this.getValue().beforeShow&&this.getValue().beforeShow(this),this.showElement(a),this.getValue().afterShow&&this.getValue().afterShow(this)},d.Page.prototype.showElement=function(b){this.getValue().showElement?this.getValue().showElement(this,b):d.showElement?d.showElement(this,b):a(this.element).show(b)},d.Page.prototype.hideElementWrapper=function(a){this.getValue().beforeHide&&this.getValue().beforeHide(this),this.hideElement(a),this.getValue().afterHide&&this.getValue().afterHide(this)},d.Page.prototype.hideElement=function(b){this.getValue().hideElement?this.getValue().hideElement(this,b):d.hideElement?d.hideElement(this,b):(a(this.element).hide(),b&&b())},d.Page.prototype.isVisible=function(){return a(this.element).is(":visible")},d.Page.prototype.getFullRoute=function(){return c.computed(function(){if(this.currentParentPage&&this.currentParentPage()){var a=this.currentParentPage().getFullRoute()();return a.push(this.getId()),a}if(this.parentPage){var a=this.parentPage.getFullRoute()();return a.push(this.getId()),a}return[]},this)},c.bindingHandlers.page={init:function(a,b,c,e,f){var g=new d.Page(a,b,c,e,f);return g.init()},update:function(a,b,c,d,e){}},d.useHTML5history=!1,d.rootURI="/",c.bindingHandlers["page-href"]={init:function(b,f,g,h,i){var j=i.$page||i.$data.$page,k=j,l=c.computed(function(){var c=e.value(f()),d=0;while(c.substring(0,3)==="../")d++,c=c.slice(3);var g=k.getFullRoute()(),h=g.slice(0,g.length-d).join("/"),i=(h===""?"":h+"/")+c,j={href:"#"+i};return a(b).attr(j),i});d.useHTML5history&&window.history&&history.pushState&&a(b).click(function(a){a.preventDefault(),history.pushState(null,null,d.rootURI+l()),d.childManager.showChild(l().split("/"))})},update:function(){}},d.PageAccordionItem=function(a,b,c,e,f){d.Page.apply(this,arguments)},d.PageAccordionItem.prototype=new d.Page,d.PageAccordionItem.prototype.getAccordionBody=function(){return a(this.element).children()[1]},d.PageAccordionItem.prototype.hideElement=function(b){this.pageAccordionItemHidden?(a(this.getAccordionBody()).slideUp(),b&&b()):(this.pageAccordionItemHidden=!0,a(this.getAccordionBody()).hide())},d.PageAccordionItem.prototype.showElement=function(b){a(this.getAccordionBody()).slideDown(),b&&b()},c.bindingHandlers["page-accordion-item"]={init:function(a,b,c,e,f){var g=new d.PageAccordionItem(a,b,c,e,f);g.init()},update:function(){}},d});
View
4 dist/pager.min.js
@@ -1,4 +1,4 @@
-/*! pager.js - v0.3.0 - 2012-08-29
+/*! pager.js - v0.3.0 - 2012-09-01
* http://oscar.finnsson.nu/pagerjs/
* Copyright (c) 2012 Oscar Finnsson; Licensed MIT */
-var pager={},_ko={};_ko.value=ko.utils.unwrapObservable,_ko.arrayValue=function(a){return _.map(a,function(a){return _ko.value(a)})},pager.ChildManager=function(a,b){this.currentChildO=ko.observable(null);var c=this;this.page=b,this.hideChild=function(){c.currentChild&&c.currentChild.getId()!=="start"&&(c.currentChild.hidePage(function(){}),c.currentChild=null,c.currentChildO(null))},this.showChild=function(b){var d=c.currentChild;c.currentChild=null;var e=!1,f=b[0],g=null;_.each(a(),function(a){if(!e){var b=a.getId();if(b===f||(f===""||f==null)&&b==="start")e=!0,c.currentChild=a;b==="?"&&(g=a)}});var h=!1,i=c;while(!c.currentChild&&i.page.parentPage&&!i.page.getValue().modal){var j=i.page.parentPage.children;_.each(j(),function(a){if(!e){var b=a.getId(),d=a.getValue().modal;if(d){if(b===f||(f===""||f==null)&&b==="start")e=!0,c.currentChild=a,h=!0;b==="?"&&!g&&(g=a,h=!0)}}}),c.currentChild||(i=i.page.parentPage.childManager)}!c.currentChild&&g&&(c.currentChild=g,c.currentChild.currentId=f),c.currentChild&&(c.currentChildO(c.currentChild),h?c.currentChild.currentParentPage(c.page):c.currentChild.currentParentPage(null)),d&&d===c.currentChild?c.currentChild.showPage(b.slice(1)):d?d.hidePage(function(){c.currentChild&&c.currentChild.showPage(b.slice(1))}):c.currentChild&&c.currentChild.showPage(b.slice(1))}},pager.start=function(a){var b=function(){pager.routeFromHashToPage(window.location.hash)};$(window).bind("hashchange",b),b()},pager.extendWithPage=function(a){a.$page=new pager.Page,pager.childManager=new pager.ChildManager(a.$page.children,a.$page),a.$page.childManager=pager.childManager},pager.routeFromHashToPage=function(a){a[0]==="#"&&(a=a.slice(1));var b=a.split("/");pager.childManager.showChild(b)},pager.Page=function(a,b,c,d,e){this.element=a,this.valueAccessor=b,this.allBindingsAccessor=c,this.viewModel=d,this.bindingContext=e,this.children=ko.observableArray([]),this.childManager=new pager.ChildManager(this.children,this),this.parentPage=null,this.currentId=null,this.currentParentPage=ko.observable(null)},pager.Page.prototype.showPage=function(a){this.show(),this.childManager.showChild(a)},pager.Page.prototype.hidePage=function(a){this.hideElementWrapper(a),this.childManager.hideChild()},pager.Page.prototype.init=function(){var a=this.getValue();this.parentPage=this.getParentPage(),this.parentPage.children.push(this),this.hideElement(),a.source&&this.loadSource(a.source);var b=null;return a["with"]?b=_ko.value(a["with"]):a.withOnShow?b={}:b=this.viewModel,this.childBindingContext=this.bindingContext.createChildContext(b),ko.utils.extend(this.childBindingContext,{$page:this}),a.withOnShow||ko.applyBindingsToDescendants(this.childBindingContext,this.element),{controlsDescendantBindings:!0}},pager.Page.prototype.getValue=function(){return _ko.value(this.valueAccessor())},pager.Page.prototype.getParentPage=function(){return this.bindingContext.$page||this.bindingContext.$data.$page},pager.Page.prototype.getId=function(){return _ko.value(this.getValue().id)},pager.Page.prototype.sourceUrl=function(a){var b=this;return this.getId()==="?"?ko.computed(function(){return _ko.value(a).replace("{1}",b.currentId)}):ko.computed(function(){return _ko.value(a)})},pager.Page.prototype.loadSource=function(a){var b=this.getValue(),c=this,d=this.element;if(b.frame==="iframe"){var e=$("iframe",$(d));e.length===0&&(e=$("<iframe></iframe>"),$(d).append(e)),b.sourceLoaded&&e.one("load",b.sourceLoaded),ko.applyBindingsToNode(e[0],{attr:{src:this.sourceUrl(a)}})}else ko.computed(function(){var e=_ko.value(this.sourceUrl(a));$(d).load(e,function(){ko.applyBindingsToDescendants(c.childBindingContext,c.element),b.sourceLoaded&&b.sourceLoaded.apply(c,arguments)})},this)},pager.Page.prototype.show=function(a){var b=this.element,c=this.getValue();this.showElementWrapper(a),this.getValue().title&&(window.document.title=this.getValue().title),c.withOnShow&&(this.withOnShowLoaded||(this.withOnShowLoaded=!0,c.withOnShow(_.bind(function(a){var b=this.bindingContext.createChildContext(a);ko.utils.extend(b,{$page:this}),ko.applyBindingsToDescendants(b,this.element)},this)))),c.sourceOnShow&&(!c.sourceCache||!b.__pagerLoaded__||typeof c.sourceCache=="number"&&b.__pagerLoaded__+c.sourceCache*1e3<Date.now())&&(b.__pagerLoaded__=Date.now(),this.loadSource(c.sourceOnShow))},pager.Page.prototype.showElementWrapper=function(a){this.getValue().beforeShow&&this.getValue().beforeShow(this),this.showElement(a),this.getValue().afterShow&&this.getValue().afterShow(this)},pager.Page.prototype.showElement=function(a){this.getValue().showElement?this.getValue().showElement.call(this,a):pager.showElement?pager.showElement.call(this,a):$(this.element).show(a)},pager.Page.prototype.hideElementWrapper=function(a){this.getValue().beforeHide&&this.getValue().beforeHide(this),this.hideElement(a),this.getValue().afterHide&&this.getValue().afterHide(this)},pager.Page.prototype.hideElement=function(a){this.getValue().hideElement?this.getValue().hideElement.call(this,a):pager.hideElement?pager.hideElement.call(this,a):($(this.element).hide(),a&&a())},pager.Page.prototype.isVisible=function(){return $(this.element).is(":visible")},pager.Page.prototype.getFullRoute=function(){return ko.computed(function(){if(this.currentParentPage&&this.currentParentPage()){var a=this.currentParentPage().getFullRoute()();return a.push(this.getId()),a}if(this.parentPage){var a=this.parentPage.getFullRoute()();return a.push(this.getId()),a}return[]},this)},ko.bindingHandlers.page={init:function(a,b,c,d,e){var f=new pager.Page(a,b,c,d,e);return f.init()},update:function(a,b,c,d,e){}},pager.useHTML5history=!1,pager.rootURI="/",ko.bindingHandlers["page-href"]={init:function(a,b,c,d,e){var f=e.$page||e.$data.$page,g=f,h=ko.computed(function(){var c=_ko.value(b()),d=0;while(c.substring(0,3)==="../")d++,c=c.slice(3);var e=g.getFullRoute()(),f=e.slice(0,e.length-d).join("/"),h=(f===""?"":f+"/")+c,i={href:"#"+h};return $(a).attr(i),h});pager.useHTML5history&&window.history&&history.pushState&&$(a).click(function(a){a.preventDefault(),history.pushState(null,null,pager.rootURI+h()),pager.childManager.showChild(h().split("/"))})},update:function(){}},pager.PageAccordionItem=function(a,b,c,d,e){pager.Page.apply(this,arguments)},pager.PageAccordionItem.prototype=new pager.Page,pager.PageAccordionItem.prototype.getAccordionBody=function(){return $(this.element).children()[1]},pager.PageAccordionItem.prototype.hideElement=function(a){this.pageAccordionItemHidden?($(this.getAccordionBody()).slideUp(),a&&a()):(this.pageAccordionItemHidden=!0,$(this.getAccordionBody()).hide())},pager.PageAccordionItem.prototype.showElement=function(a){$(this.getAccordionBody()).slideDown(),a&&a()},ko.bindingHandlers["page-accordion-item"]={init:function(a,b,c,d,e){var f=new pager.PageAccordionItem(a,b,c,d,e);f.init()},update:function(){}};
+var pager={},_ko={};_ko.value=ko.utils.unwrapObservable,_ko.arrayValue=function(a){return _.map(a,function(a){return _ko.value(a)})},pager.ChildManager=function(a,b){this.currentChildO=ko.observable(null);var c=this;this.page=b,this.hideChild=function(){c.currentChild&&c.currentChild.getId()!=="start"&&(c.currentChild.hidePage(function(){}),c.currentChild=null,c.currentChildO(null))},this.showChild=function(b){var d=c.currentChild;c.currentChild=null;var e=!1,f=b[0],g=null;_.each(a(),function(a){if(!e){var b=a.getId();if(b===f||(f===""||f==null)&&b==="start")e=!0,c.currentChild=a;b==="?"&&(g=a)}});var h=!1,i=c;while(!c.currentChild&&i.page.parentPage&&!i.page.getValue().modal){var j=i.page.parentPage.children;_.each(j(),function(a){if(!e){var b=a.getId(),d=a.getValue().modal;if(d){if(b===f||(f===""||f==null)&&b==="start")e=!0,c.currentChild=a,h=!0;b==="?"&&!g&&(g=a,h=!0)}}}),c.currentChild||(i=i.page.parentPage.childManager)}!c.currentChild&&g&&(c.currentChild=g,c.currentChild.currentId=f),c.currentChild&&(c.currentChildO(c.currentChild),h?c.currentChild.currentParentPage(c.page):c.currentChild.currentParentPage(null)),d&&d===c.currentChild?c.currentChild.showPage(b.slice(1)):d?d.hidePage(function(){c.currentChild&&c.currentChild.showPage(b.slice(1))}):c.currentChild&&c.currentChild.showPage(b.slice(1))}},pager.start=function(a){var b=function(){pager.routeFromHashToPage(window.location.hash)};$(window).bind("hashchange",b),b()},pager.extendWithPage=function(a){a.$page=new pager.Page,pager.childManager=new pager.ChildManager(a.$page.children,a.$page),a.$page.childManager=pager.childManager},pager.routeFromHashToPage=function(a){a[0]==="#"&&(a=a.slice(1));var b=a.split("/");pager.childManager.showChild(b)},pager.Page=function(a,b,c,d,e){this.element=a,this.valueAccessor=b,this.allBindingsAccessor=c,this.viewModel=d,this.bindingContext=e,this.children=ko.observableArray([]),this.childManager=new pager.ChildManager(this.children,this),this.parentPage=null,this.currentId=null,this.currentParentPage=ko.observable(null)},pager.Page.prototype.showPage=function(a){this.show(),this.childManager.showChild(a)},pager.Page.prototype.hidePage=function(a){this.hideElementWrapper(a),this.childManager.hideChild()},pager.Page.prototype.init=function(){var a=this.getValue();this.parentPage=this.getParentPage(),this.parentPage.children.push(this),this.hideElement(),a.source&&this.loadSource(a.source);var b=null;return a["with"]?b=_ko.value(a["with"]):a.withOnShow?b={}:b=this.viewModel,this.childBindingContext=this.bindingContext.createChildContext(b),ko.utils.extend(this.childBindingContext,{$page:this}),a.withOnShow||ko.applyBindingsToDescendants(this.childBindingContext,this.element),{controlsDescendantBindings:!0}},pager.Page.prototype.getValue=function(){return _ko.value(this.valueAccessor())},pager.Page.prototype.getParentPage=function(){return this.bindingContext.$page||this.bindingContext.$data.$page},pager.Page.prototype.getId=function(){return _ko.value(this.getValue().id)},pager.Page.prototype.sourceUrl=function(a){var b=this;return this.getId()==="?"?ko.computed(function(){return _ko.value(a).replace("{1}",b.currentId)}):ko.computed(function(){return _ko.value(a)})},pager.Page.prototype.loadSource=function(a){var b=this.getValue(),c=this,d=this.element;b.loader&&_ko.value(b.loader)(c);if(b.frame==="iframe"){var e=$("iframe",$(d));e.length===0&&(e=$("<iframe></iframe>"),$(d).append(e)),b.sourceLoaded&&e.one("load",b.sourceLoaded),ko.applyBindingsToNode(e[0],{attr:{src:this.sourceUrl(a)}})}else ko.computed(function(){var e=_ko.value(this.sourceUrl(a));$(d).load(e,function(){ko.applyBindingsToDescendants(c.childBindingContext,c.element),b.sourceLoaded&&b.sourceLoaded.apply(c,arguments)})},this)},pager.Page.prototype.show=function(a){var b=this.element,c=this.getValue();this.showElementWrapper(a),this.getValue().title&&(window.document.title=this.getValue().title),c.withOnShow&&(this.withOnShowLoaded||(this.withOnShowLoaded=!0,c.withOnShow(_.bind(function(a){var b=this.bindingContext.createChildContext(a);ko.utils.extend(b,{$page:this}),ko.applyBindingsToDescendants(b,this.element)},this)))),c.sourceOnShow&&(!c.sourceCache||!b.__pagerLoaded__||typeof c.sourceCache=="number"&&b.__pagerLoaded__+c.sourceCache*1e3<Date.now())&&(b.__pagerLoaded__=Date.now(),this.loadSource(c.sourceOnShow))},pager.Page.prototype.showElementWrapper=function(a){this.getValue().beforeShow&&this.getValue().beforeShow(this),this.showElement(a),this.getValue().afterShow&&this.getValue().afterShow(this)},pager.Page.prototype.showElement=function(a){this.getValue().showElement?this.getValue().showElement(this,a):pager.showElement?pager.showElement(this,a):$(this.element).show(a)},pager.Page.prototype.hideElementWrapper=function(a){this.getValue().beforeHide&&this.getValue().beforeHide(this),this.hideElement(a),this.getValue().afterHide&&this.getValue().afterHide(this)},pager.Page.prototype.hideElement=function(a){this.getValue().hideElement?this.getValue().hideElement(this,a):pager.hideElement?pager.hideElement(this,a):($(this.element).hide(),a&&a())},pager.Page.prototype.isVisible=function(){return $(this.element).is(":visible")},pager.Page.prototype.getFullRoute=function(){return ko.computed(function(){if(this.currentParentPage&&this.currentParentPage()){var a=this.currentParentPage().getFullRoute()();return a.push(this.getId()),a}if(this.parentPage){var a=this.parentPage.getFullRoute()();return a.push(this.getId()),a}return[]},this)},ko.bindingHandlers.page={init:function(a,b,c,d,e){var f=new pager.Page(a,b,c,d,e);return f.init()},update:function(a,b,c,d,e){}},pager.useHTML5history=!1,pager.rootURI="/",ko.bindingHandlers["page-href"]={init:function(a,b,c,d,e){var f=e.$page||e.$data.$page,g=f,h=ko.computed(function(){var c=_ko.value(b()),d=0;while(c.substring(0,3)==="../")d++,c=c.slice(3);var e=g.getFullRoute()(),f=e.slice(0,e.length-d).join("/"),h=(f===""?"":f+"/")+c,i={href:"#"+h};return $(a).attr(i),h});pager.useHTML5history&&window.history&&history.pushState&&$(a).click(function(a){a.preventDefault(),history.pushState(null,null,pager.rootURI+h()),pager.childManager.showChild(h().split("/"))})},update:function(){}},pager.PageAccordionItem=function(a,b,c,d,e){pager.Page.apply(this,arguments)},pager.PageAccordionItem.prototype=new pager.Page,pager.PageAccordionItem.prototype.getAccordionBody=function(){return $(this.element).children()[1]},pager.PageAccordionItem.prototype.hideElement=function(a){this.pageAccordionItemHidden?($(this.getAccordionBody()).slideUp(),a&&a()):(this.pageAccordionItemHidden=!0,$(this.getAccordionBody()).hide())},pager.PageAccordionItem.prototype.showElement=function(a){$(this.getAccordionBody()).slideDown(),a&&a()},ko.bindingHandlers["page-accordion-item"]={init:function(a,b,c,d,e){var f=new pager.PageAccordionItem(a,b,c,d,e);f.init()},update:function(){}};
View
2 lib/qunit-until.js
@@ -4,5 +4,5 @@ var until = function(testFn, thenFn) {
clearInterval(intervalID);
thenFn();
}
- }, 200);
+ }, 50);
};
View
28 pager.js
@@ -263,14 +263,25 @@ pager.Page.prototype.loadSource = function (source) {
var value = this.getValue();
var me = this;
var element = this.element;
+ var loader = null;
+ var loaderMethod = value.loader || pager.loader;
if (value.frame === 'iframe') {
var iframe = $('iframe', $(element));
if (iframe.length === 0) {
iframe = $('<iframe></iframe>');
$(element).append(iframe);
}
+ if(loaderMethod) {
+ loader = _ko.value(loaderMethod)(me, iframe);
+ loader.load();
+ }
if (value.sourceLoaded) {
- iframe.one('load', value.sourceLoaded);
+ iframe.one('load', function() {
+ if(loader) {
+ loader.unload();
+ }
+ value.sourceLoaded();
+ });
}
// TODO: remove src binding and add this binding
ko.applyBindingsToNode(iframe[0], {
@@ -279,10 +290,17 @@ pager.Page.prototype.loadSource = function (source) {
}
});
} else {
+ if(loaderMethod) {
+ loader = _ko.value(loaderMethod)(me, me.element);
+ loader.load();
+ }
// TODO: remove all children and add sourceUrl(source)
ko.computed(function () {
var s = _ko.value(this.sourceUrl(source));
$(element).load(s, function () {
+ if(loader) {
+ loader.unload();
+ }
ko.applyBindingsToDescendants(me.childBindingContext, me.element);
if (value.sourceLoaded) {
value.sourceLoaded.apply(me, arguments);
@@ -337,9 +355,9 @@ pager.Page.prototype.showElementWrapper = function (callback) {
pager.Page.prototype.showElement = function (callback) {
if (this.getValue().showElement) {
- this.getValue().showElement.call(this, callback);
+ this.getValue().showElement(this, callback);
} else if (pager.showElement) {
- pager.showElement.call(this, callback);
+ pager.showElement(this, callback);
} else {
$(this.element).show(callback);
}
@@ -357,9 +375,9 @@ pager.Page.prototype.hideElementWrapper = function (callback) {
pager.Page.prototype.hideElement = function (callback) {
if (this.getValue().hideElement) {
- this.getValue().hideElement.call(this, callback);
+ this.getValue().hideElement(this, callback);
} else if (pager.hideElement) {
- pager.hideElement.call(this, callback);
+ pager.hideElement(this, callback);
} else {
$(this.element).hide();
if (callback) {
View
8 test/should_trigger_before_after_hide_show.html
@@ -29,14 +29,14 @@
var afterHideFirst = ko.observable(false);
var viewModel = {
- hideElement:function (callback) {
- $(this.element).slideUp(600);
+ hideElement:function (page, callback) {
+ $(page.element).slideUp(600);
if (callback) {
callback();
}
},
- showElement:function (callback) {
- $(this.element).slideDown(600, callback);
+ showElement:function (page, callback) {
+ $(page.element).slideDown(600, callback);
},
beforeShowFirst:function () {
beforeShowFirst(true);

0 comments on commit 92e13dd

Please sign in to comment.
Something went wrong with that request. Please try again.