@naikus/stage
Version:
Check out the live [demo](https://codepen.io/naikus/project/full/AzkkER) (POC uses plain javascript and HTML)
1 lines • 13.4 kB
JavaScript
!function(t,e){var n=function(t,e){var n=t.document,r=t.setTimeout,i=t.XMLHttpRequest,o=t.getComputedStyle,a=t.requestAnimationFrame,s=(l=function(){},u=Object.create||function(t){function e(){}return e.prototype=t,new e},d=Array.prototype,f=Object.prototype,p=d.slice,h=f.toString,{extend:function(t,e){var n=e._constructor||l;function r(){t.apply&&t.apply(this,arguments),n.apply(this,arguments)}delete e._constructor;var i=r.prototype=u(t.prototype);for(var o in e)e.hasOwnProperty(o)&&(i[o]=e[o]);return i.constructor=r,r},shallowCopy:function(){for(var t,e=arguments[0],n=Array.prototype.slice.call(arguments,1),r=0,i=n.length;r<i;r++)for(var o in t=n[r])e[o]=t[o];return e},ownsProperty:function(t,e){if(t.hasOwnProperty)return t.hasOwnProperty(e);var n=t[e];return void 0!==n&&t.constructor.prototype[e]!==n},slice:function(t,e,n){var r,i,o=t.length,a=e||0,s=n||o;if("[object Array]"===h.call(t))r=p.call(t,a,s);else for(s<0&&(s=o-s),r=[],i=a;i<s;i++)r[r.length]=t[i];return r},trim:function(t){return t.replace(/^\s+|\s+$/g,"")}}),c=function(){var e={},r=!!t.ActiveXObject,i=/^\s*<(!--\s*.*)?(\w+)[^>]*>/,a=n.createElement("div"),c=n.createElement("table"),l=n.createElement("tr"),u={"*":a,tbody:c,tfoot:c,tr:n.createElement("tbody"),td:l,th:l},d=typeof("function"===t.Event);function f(t){return e[t]||(e[t]=new RegExp("(^|\\s+)"+t+"(?:\\s+|$)"))}function p(t,e,n){var r=t.classList;return!(!r||!e)&&(r.replace(e,n),!0)}function h(t,e){return f(e).test(t.className)}function v(t,e,r){var i=n.createEvent("Event");return i.initEvent(t,r.bubbles,r.cancelable),i.srcElement=e,i}return{selectOne:function(t,e){return"string"==typeof t?(e||n).querySelector(t):t},select:function(t,e){return"string"==typeof t?(e||n).querySelectorAll(t):t},asFragment:function(t,e){var o,c,l,d,f;e||(e=(c=i.exec(t))?c[2]:null),o=(u[e]||a).cloneNode(),r&&("tbody"===(d=o.tagName.toLowerCase())||"table"===d||"thead"===d||"tfoot"===d)?l=function(t,e,n){var r=a.cloneNode();return e+="",r.innerHTML=["<",t,">",e,"</",t,">"].join(""),n?r.firstChild.firstChild.childNodes:r.firstChild.childNodes}("table",t,!0):(o.innerHTML=""+t,l=o.childNodes),l=s.slice(l),f=n.createDocumentFragment();for(var p=0,h=l.length;p<h;p+=1)f.appendChild(l[p]);return f},dispatchEvent:function(t,e){var r,i=e.element||n,o=e.data;if(d)try{r=new Event(t,{bubbles:e.bubbles||!1,cancelable:e.cancelable||!1})}catch(s){r=v(t,i,e)}else r=v(t,i,e);for(var a in o)r[a]=o[a];return i.dispatchEvent(r)},hasClass:h,addClass:function(t,e){return h(t,e)||function(t,e){var n=t.classList;return!(!n||!e)&&(n.add(e),!0)}(t,e)||(t.className+=" "+e),this},removeClass:function(t,e){return h(t,e)&&!function(t,e){var n=t.classList;return!(!n||!e)&&(n.remove(e),!0)}(t,e)&&(t.className=s.trim(t.className.replace(f(e),"$1"))),this},replaceClass:function(t,e,n){var r;if(t.length)for(var i=0,o=t.length;i<o;i+=1)p(r=t[i],e,n)||(r.className=s.trim(r.className.replace(f(e),n)));else p(r=t,e,n)||(r.className=s.trim(r.className.replace(f(e),n)));return this},getComputedStyle:function(t){return o?o(t):t.currentStyle},data:function(t){var e=arguments[1],n=arguments[2],r=t.__stagedata__;return r||(r=t.__stagedata__={}),2===arguments.length?r[e]:(3===arguments.length&&(r[e]=n),this)}}}();var l,u,d,f,p,h;return function(){var e,o,l,u,d={},f=a||t.mozRequestAnimationFrame||t.webkitRequestAnimationFrame||t.msRequestAnimationFrame||function(t){return r(t,1e3/60)},p=(e=["","Webkit","Moz","O","ms","MS"],o=["transitionend","webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd"],l=["animationend","webkitAnimationEnd","animationend","oAnimationEnd","animationend"],u=n.createElement("div").style,{transition:function(){for(var t,n,r=0,i=e.length;r<i;r+=1)if("undefined"!=typeof u[n=(t=e[r])?t+"Transition":"transition"])return{property:n,end:o[r]};return{}}(),animation:function(){for(var t,n,r=0,i=e.length;r<i;r+=1)if("undefined"!=typeof u[n=(t=e[r])?t+"Animation":"animation"])return{property:n,end:l[r]};return{}}()}),h={transitionDelay:100,transition:"slide",debug:!1},v=/\.js$/;function m(t,e,r){var i=n.createElement("script");i.onerror=function(){r({error:!0,src:t})},"onreadystatechange"in i?i.onreadystatechange=function(){"loaded"!==this.readyState&&"complete"!==this.readyState||r({src:t})}:i.onload=function(){r({src:t})},i.src=t,i.async=1,e.appendChild(i)}function w(t){return c.selectOne("[view-data-id="+t+"]")||n.createElement("div")}function g(t,e,r){var o=t.path,a=t.id;!function(t){var e=new i,n=!1,r=t.path,o=t.method||"GET",a=t.success,s=t.fail,c="undefined"==typeof t.timeout?3e4:t.timeout;e.open(o,r,!0),e.timeout=c,e.addEventListener("readystatechange",(function(){var t,r=e.readyState;2!==r&&3!==r||(n=!0),4===r&&((t=e.status)>=200&&t<400||0===t&&n?a&&a(e):s&&s(t,e))})),e.addEventListener("timeout",(function(){s&&s("timeout",e)})),e.send()}({path:o,method:"GET",success:function(t){var i=w(a),l=c.asFragment(t.responseText),u=s.slice(c.select("script",l)).filter((function(t){return-1!==(t.getAttribute("type")||"text/javascript").indexOf("/javascript")})),d=function(t){var e,a;t&&t.error&&console.error("Error loading script",t.src,t.error),u.length?(a=(e=u.shift()).getAttribute("src"))?m(a,i,d):(!function(t,e,r){var i=n.createElement("script");i.textContent=r?"(function() {\n"+t+"\n})();":t,e.appendChild(i)}(e.textContent,i),d()):r({path:o,error:!1,element:i})};u.forEach((function(t){t.parentNode.removeChild(t)})),i.className="view-holder",i.setAttribute("data-view-id",a),i.setAttribute("data-view-template",o),i.appendChild(l),e.appendChild(i),d()},fail:function(t,e){r({path:o,error:t||!0,xhr:e})}})}function y(t,e){var n,r,i=t.id,o='[data-view="'+i+'"]',a='[data-view-template="'+t.path+'"]';return(r=c.selectOne(o,e))||(r=function(t,e){var n=c.asFragment(t).firstChild;return c.addClass(n,"stage-view"),n.setAttribute("data-view",e),n}(t.template||'<div class="stage-view"></div>',i),r=(n=c.selectOne(a,e))?n.insertBefore(r,n.firstChild):e.appendChild(r))}function C(t,e){var n=d[t];return n||(n=d[t]={id:t,config:e||{}}),n}function E(t,e,n,r){this.id=t,this.element=e,this.controller=n,this.config=r}function b(){}function V(e){var n,i,o=s.shallowCopy({},h,e),a=c.selectOne(o.viewport),l={},u=o.transition,C=function(){var t,e,n,r=!1,i={};function o(t){var e=c.getComputedStyle(t),n=e["transition-property"]||e["-webkit-transition-property"]||e["-moz-transitionProperty"];return n?n.split(",").length:0}return{name:function(){return arguments.length?(t=arguments[0],this):t},from:function(t){return e=t.id,i[t.id]=o(t.element),this},to:function(t){return n=t.id,i[t.id]=o(t.element),this},transitionEnded:function(t){var o;return i[t.id]-=1,o=!i[t.id],r=i[e]||i[n],o},inProgress:function(){return arguments.length?(r=arguments[0],this):r},clear:function(){delete i[e],delete i[n],r=!1,e=n=null}}}(),V=[];if(e.debug&&console.debug("Stage options ",o),!a||1!==a.nodeType)throw new Error("Use a valid element as view port");function k(){for(var t in l){var e=l[t];e&&e.controller&&e.controller.destroy()}}function A(t,e){var i,h=l[t],v=e.replace,m=d[t].config.transition,w="transition"in e?e.transition:m||u,g=function(){i&&S("out",i),S("in",h),f((function(){i&&function(t,e){t.stack(),p.transition.end&&e||P({target:t.element,propertyName:"no-transition"})}(i,w),function(t,e){t.bringIn(),p.transition.end&&e||P({target:t.element,propertyName:"no-transition"})}(h,w)}))};e.viewAction="push";var k=C.name();if(k!==w&&(C.name(w),k&&c.removeClass(a,k),c.addClass(a,w)),i=V.length?V[V.length-1]:null){if(i.id===t)return i.controller.update(e),void C.clear();C.from(i),e.fromView=i.id}c.addClass(a,"view-transitioning"),h?h.unStack().show(!0):((h=function(t){var e,r=d[t],i=r.config,o=y(r,a);if(!o)throw new Error("UI for view "+t+" not found.");return o.addEventListener(p.transition.end||"transitionend",P,!1),o.addEventListener(p.animation.end||"animationend",P,!1),e=new(s.extend(b,r.factory(n,o,i))),l[t]=new E(t,o,e,i)}(t)).show(!0),h.controller.initialize(e)),h.transition=w,C.to(h),i&&i.controller.deactivate(),V.push(h),2===h.controller.activate.length?h.controller.activate(e,(function(){r(g,o.transitionDelay)})):(h.controller.activate(e),r(g,o.transitionDelay)),v&&i&&V.splice(V.length-2,1)}function N(t,e){var n,i,s,l,u=C.name(),d=function(){S("out",n),S("in",i),f((function(){!function(t,e){t.pop(),p.transition.end&&e||P({target:t.element,propertyName:"no-transition"})}(n,u),function(t,e){t.unStack("unstack").bringIn(),p.transition.end&&e||P({target:t.element,propertyName:"no-transition"})}(i,u)}))};if(n=V[V.length-1],e){if(-1===(s=function(t){var e,n;for(e=0,n=V.lenth;e<n&&V[e].id!==t;e+=1);return e===n?-1:e}(e)))throw C.clear(),new Error("View "+e+" is not on stack");if(s===V.length-1)throw C.clear(),new Error("Cannot pop to the current view: "+e);i=V[s],l=s+1}else i=V[V.length-2];i.stack(),c.addClass(a,"view-transitioning"),i.show(!0),C.from(n).to(i),t.fromView=n.id,t.viewAction="pop",n.controller.deactivate(),e?V.splice(l,V.length-l):V.pop(),2===i.controller.activate.length?i.controller.activate(t,(function(){r(d,o.transitionDelay)})):(i.controller.activate(t),r(d,o.transitionDelay))}function S(t,e){c.dispatchEvent("beforeviewtransition"+t,{element:a,data:{viewId:e.id}}),c.dispatchEvent("beforetransition"+t,{element:e.element})}function P(t){var e,n,r,i,o=t.target.getAttribute("data-view");o&&(e=l[o],C.transitionEnded(e)&&(e.isIn()?(e.wasUnStacked()&&e.reset("unstack"),n="in"):e.wasPopped()?(e.reset(["showing","pop"]),n="out"):e.isStacked()&&(e.show(!1),n="out"),function(t,e){c.dispatchEvent("viewtransition"+t,{element:a,data:{viewId:e.id}}),c.dispatchEvent("transition"+t,{element:e.element})}(n,e),C.inProgress()||(C.clear(),c.removeClass(a,"view-transitioning"),(r=C.name())!==(i=V[V.length-1]).transition&&(c.replaceClass(a,r,i.transition),C.name(i.transition)))))}t.addEventListener("pagehide",(function(t){t.persisted||k()}));var I,x,O=(x=i={getViewPort:function(){return a},pushView:function(t,e){var n=l[t],r=s.shallowCopy({},e);if(C.inProgress())return console.log("pushView() View transitioin in progress. Ignoring this call"),void console.debug("Did you forget to define the transition in css?");C.inProgress(!0),n?A(t,r):this.loadView(t,(function(e){e.error?(C.clear(),console.error("Error loading view",e)):A(t,r)}))},popView:function(t){var e=s.shallowCopy({},t),n=e.toView;if(C.inProgress())console.debug("popView() View transitioin in progress. Ignoring this call");else{if(V.length<2)throw new Error("Can't pop. One or less view(s)");C.inProgress(!0),N(e,n)}},currentView:function(){var t=V[V.length-1];return t?t.id:null},previousView:function(){var t;return V.length>=2&&(t=V[V.length-2])?t.id:null},indexOfView:function(t){var e=-1;return V.some((function(n,r){return n.id===t&&(e=r,!0)})),e},isTransitionInProgress:function(){return C.inProgress()},loadView:function(t,e){var n,r=d[t],i=function(n){e({viewId:t,error:n.error,path:n.path}),c.dispatchEvent("viewloadend",{element:a,data:{viewId:t,error:n.error}})};if(r)r.factory?e({viewId:t}):(c.dispatchEvent("viewloadstart",{element:a,data:{viewId:t}}),n=r.path,v.test(n)?function(t,e,n){var r=t.id,i=t.path,o=w(r);o.className="view-holder",o.setAttribute("data-view-id",r),o.setAttribute("data-view-template",i),m(i,o=e.appendChild(o),(function(t){n({path:t.src,element:o,error:t.error})}))}(r,a,i):g(r,a,i));else{var o=new Error("View not defined: "+t);e({viewId:t,error:o})}},getViewController:function(t){return l[t].controller},getViewContext:function(){return n},getViewConfig:function(t){return l[t].config},getViewDefinition:function(t){return d[t]},destroy:function(){k(),l={},V=[],a.innerHTML=""}},{getViewPort:function(){return x.getViewPort()},pushView:function(t,e){return x.pushView(t,e)},popView:function(t){return x.popView(t)},currentView:function(){return x.currentView()},previousView:function(){return x.previousView()}}),L=o.contextFactory;return"function"==typeof L&&(I=L(i,e)),n=I?s.shallowCopy({},O,I):O,i}return E.prototype={constructor:E,show:function(t){return!1===t?c.removeClass(this.element,"showing"):c.addClass(this.element,"showing"),this},bringIn:function(){c.addClass(this.element,"in")},isIn:function(){return c.hasClass(this.element,"in")},stack:function(){return c.hasClass(this.element,"stack")||c.replaceClass(this.element,"in","stack"),this},isStacked:function(){return c.hasClass(this.element,"stack")},unStack:function(t){return t?c.replaceClass(this.element,"stack","unstack"):c.removeClass(this.element,"stack"),this},wasUnStacked:function(){return c.hasClass(this.element,"unstack")},pop:function(){return c.replaceClass(this.element,"in","pop"),this},wasPopped:function(){return c.hasClass(this.element,"pop")},reset:function(t){if("string"==typeof t)c.removeClass(this.element,t);else{var e=this;t.forEach((function(t){c.removeClass(e.element,t)}))}}},b.prototype={constructor:b,initialize:function(){},activate:function(){},update:function(){},deactivate:function(){},destroy:function(){}},V.defineView=function(t,e){var n=t.id,r=t.factory,i=t.template||'<div class="stage-view" data-view="'+n+'"></div>',o=C(n,e||{});o.factory=r,o.template=i},V.views=function(t){var e;for(var n in t)s.ownsProperty(t,n)&&(C(n,(e=t[n]).config).path=e.path)},V.view=function(t,e,n){C(t,n).path=e},V}()}(t);"function"==typeof define&&define.amd?define((function(){return n})):"object"==typeof module&&module.exports?module.exports=n:t.Stage=n}("undefined"==typeof window?this:window);