diff --git a/README.md b/README.md
index 482291c..8b3f18d 100644
--- a/README.md
+++ b/README.md
@@ -413,36 +413,60 @@ The source code is documented using JsDoc.
-## In the pipeline
-
-
### 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).
+
+ Go to random sub-page
+
+
+
+ Load View using Custom Method
+
+
+ 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.
+
+ Thus a way to inject custom views should be possible. This is done using the source
- or
+ sourceOnShow
-properties. Just supply a method instead of a string!
+
+ These properties takes a method that should take a pager.Page
as first argument, a callback,
+ and return nothing.
+
+
+
+
Load custom view using requireView-method
+
+
+
+
+
+
+<div data-bind="page: {id: 'zoidberg', sourceOnShow: requireView('zoidberg')}"/>
+
+
+ where
+
+
+window.requireView = function(viewModule) {
+ return function(page, callback) {
+ require([viewModule], function(viewString) {
+ $(page.element).html(viewString);
+ callback();
+ });
+ };
+};
+
diff --git a/demo/pager.amd.min.js b/demo/pager.amd.min.js
index a1d79be..40e9815 100644
--- a/demo/pager.amd.min.js
+++ b/demo/pager.amd.min.js
@@ -1,663 +1,4 @@
/*! pager.js - v0.3.0 - 2012-09-02
* http://oscar.finnsson.nu/pagerjs/
* Copyright (c) 2012 Oscar Finnsson; Licensed MIT */
-
-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);
- });
-};
-
-/**
- * @class pager.ChildManager
- */
-
-/**
- *
- * @param {pager.Page[]} children
- * @param {pager.Page} page
- * @constructor
- */
-pager.ChildManager = function (children, page) {
-
- 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);
- }
- }
- };
-
- /**
- *
- * @param {String[]} route
- */
- 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);
- }
-
- }
-
- var onFailed = function () {
- if (pager.navigationFailed) {
- pager.navigationFailed(me.page, route);
- }
- if (me.page.getValue().navigationFailed) {
- _ko.value(me.page.getValue().navigationFailed)(me.page, route);
- }
- };
-
- 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 {
- onFailed();
- }
- });
- } else if (me.currentChild) {
- me.currentChild.showPage(route.slice(1));
- } else {
- onFailed();
- }
- };
-};
-
-/**
- */
-pager.start = function () {
-
- var onHashChange = function () {
- pager.routeFromHashToPage(window.location.hash);
- };
- $(window).bind('hashchange', onHashChange);
- onHashChange();
-};
-
-/**
- *
- * @param viewModel
- */
-pager.extendWithPage = function (viewModel) {
- viewModel.$__page__ = new pager.Page();
-
- pager.childManager = new pager.ChildManager(viewModel.$__page__.children, viewModel.$__page__);
- viewModel.$__page__.childManager = pager.childManager;
-};
-
-/**
- *
- * Called when a route does not find a match.
- *
- * @type {Function}
- */
-pager.navigationFailed = null;
-
-
-/**
- *
- * @param {String} hash
- */
-pager.routeFromHashToPage = function (hash) {
- // skip #
- if (hash[0] === '#') {
- hash = hash.slice(1);
- }
- // split on '/'
- var hashRoute = decodeURIComponent(hash).split('/');
-
- pager.childManager.showChild(hashRoute);
-
-};
-
-/**
- * @class pager.Page
- */
-
-/**
- * @param {Node} element
- * @param {Observable} valueAccessor
- * @param allBindingsAccessor
- * @param {Observable} viewModel
- * @param bindingContext
- * @constructor
- */
-pager.Page = function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
- /**
- *
- * @type {Node}
- */
- this.element = element;
- /**
- *
- * @type {Observable}
- */
- this.valueAccessor = valueAccessor;
- /**
- *
- * @type {*}
- */
- this.allBindingsAccessor = allBindingsAccessor;
- /**
- *
- * @type {Observable}
- */
- this.viewModel = viewModel;
- /**
- *
- * @type {*}
- */
- this.bindingContext = bindingContext;
-
- /**
- *
- * @type {ObservableArray}
- */
- this.children = ko.observableArray([]);
-
- /**
- *
- * @type {pager.ChildManager}
- */
- this.childManager = new pager.ChildManager(this.children, this);
- /**
- *
- * @type {pager.Page}
- */
- this.parentPage = null;
- /**
- *
- * @type {String}
- */
- this.currentId = null;
-
- /**
- *
- * @type {Observable/pager.Page}
- */
- this.currentParentPage = ko.observable(null);
-
-
- /**
- *
- * @type {Observable}
- */
- this.isVisible = ko.observable(false);
-};
-
-/**
- * @method showPage
- * @param route
- */
-pager.Page.prototype.showPage = function (route) {
- this.isVisible(true);
- this.show();
- this.childManager.showChild(route);
-};
-
-/**
- * @method hidePage
- * @param {Function} callback
- */
-pager.Page.prototype.hidePage = function (callback) {
- this.isVisible(false);
- 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
- * @returns {Object} value
- */
-pager.Page.prototype.getValue = function () {
- if (this.valueAccessor) {
- return _ko.value(this.valueAccessor());
- } else {
- return {};
- }
-};
-
-/**
- * @method pager.Page#getParentPage
- * @return {pager.Page}
- */
-pager.Page.prototype.getParentPage = function () {
- // search this context/$data until either root is accessed or no page is found
- var bindingContext = this.bindingContext;
- while(bindingContext) {
- if(bindingContext.$page) {
- return bindingContext.$page;
- } else if(bindingContext.$data && bindingContext.$data.$__page__) {
- return bindingContext.$data.$__page__;
- }
- bindingContext = bindingContext.$parentContext;
- }
- return null;
-};
-
-/**
- * @method pager.Page#getId
- * @return String
- */
-pager.Page.prototype.getId = function () {
- return _ko.value(this.getValue().id);
-};
-
-
-/**
- *
- * @param {Observable/String} source
- * @return {Observable}
- */
-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;
- var loaderMethod = value.loader || pager.loader;
- if (value.frame === 'iframe') {
- var iframe = $('iframe', $(element));
- if (iframe.length === 0) {
- iframe = $('