1 line
No EOL
4.5 KiB
JavaScript
1 line
No EOL
4.5 KiB
JavaScript
import dom from"./../dom.js";let base="",prevContext,prevPageContext,allRoutes=[];function page(path,routeInfo){routeInfo?(page.callbacks[path.toUpperCase()]=routeInfo,allRoutes.push(routeInfo)):page.start(path)}page.getRoutes=function(){return allRoutes},page.callbacks={},page.current="",page.base=function(path){if(0===arguments.length)return base;base=path};let loaded="complete"===document.readyState;function onWindowLoad(){setTimeout(function(){loaded=!0},0),dom.removeEventListener(window,"load",onWindowLoad,{once:!0})}function onpopstate(e){var path;loaded&&!ignorePopState(e)&&(e.state?(path=e.state.path,page.replace(path,e.state,null,!0)):page.show(location.pathname+location.hash,void 0,void 0,!1,!0))}function decodeURLEncodedURIComponent(val){return"string"!=typeof val?val:decodeURIComponent(val.replace(/\+/g," "))}function parseQueryStringToObject(str){var params={};if("string"!=typeof str)return{};var entries=new URLSearchParams(str).entries();let result=entries.next();for(;!result.done;){var pair=result.value;params[pair[0]]=pair[1],result=entries.next()}return params}function Context(path,state){var i=(path="/"===path[0]&&0!==path.indexOf(base)?base+"#!"+path:path).indexOf("?");this.canonicalPath=path,this.path=path.replace(base,"")||"/",this.path=this.path.replace("#!","")||"/",this.state=state||{},this.state.path=path,this.rawQueryString=~i?path.slice(i+1):"",this.params=this.rawQueryString?parseQueryStringToObject(this.rawQueryString):{},this.pathname=decodeURLEncodedURIComponent(~i?path.slice(0,i):path),this.hash=""}loaded||dom.addEventListener(window,"load",onWindowLoad,{once:!0}),page.start=function(options){!1!==(options=options||{}).popstate&&window.addEventListener("popstate",onpopstate,!1);let url;~location.hash.indexOf("#!")?(url=location.hash.substr(2),(options=location.href.toString()).indexOf("?")>=options.indexOf("#!")&&(url+=location.search)):url=location.pathname+location.search+location.hash,page.replace(url,null,!0)},page.show=function(path,state,dispatch,push,isBack){path=new Context(path,state);path.isBack=isBack,page.current=path.path;let promise;return!1!==dispatch&&(promise=page.dispatch(path)),!1!==path.handled&&!1!==push&&path.pushState(),promise||Promise.resolve()},page.restorePreviousState=function(){prevContext=prevPageContext,page.show(prevContext.pathname,prevContext.state,!1,!0,!1)},page.back=function(){history.back()},page.forward=function(){history.forward()},page.canGoBack=function(){return 1<history.length},page.replace=function(path,state,dispatch,isBack){path=new Context(path,state);return path.isBack=isBack,page.current=path.path,path.save(),!1!==dispatch&&page.dispatch(path),path},page.getRoute=function(path){var callbacks=page.callbacks,qsIndex=path.indexOf("?");return callbacks[(~qsIndex?path.slice(0,qsIndex):path).toUpperCase()]},page.createContext=function(path){return new Context(path)},page.dispatch=function(ctx){prevPageContext=prevContext,prevContext=ctx;var callbacks=page.callbacks,path=ctx.path,qsIndex=path.indexOf("?"),callbacks=callbacks[(~qsIndex?path.slice(0,qsIndex):path).toUpperCase()];if(callbacks)return page.handleRoute(ctx,callbacks)},Context.prototype.pushState=function(){history.pushState(this.state,"","/"!==this.path?"#!"+this.path:this.canonicalPath)},Context.prototype.save=function(){history.replaceState(this.state,"","/"!==this.path?"#!"+this.path:this.canonicalPath)};let previousPopState={};function ignorePopState(event){event=event.state||{};return!1===previousPopState.navigate?(previousPopState=event,!0):(previousPopState=event,!1)}function onclick(e){if(1===getButtonFromEvent(e)&&!(e.metaKey||e.ctrlKey||e.shiftKey||e.defaultPrevented)){let el=e.target;if((el=el&&el.closest("A"))&&"A"===el.nodeName&&!el.hasAttribute("download")&&"external"!==el.getAttribute("rel")){var link=el.getAttribute("href");if("#"===link)e.preventDefault();else if(!el.target&&sameOrigin(el.href)){let path=el.pathname+el.search+(el.hash||"");link=path="file:"===el.protocol&&3<path.length&&":"===path[2]&&link.startsWith("/")?path.substr(3):path;path=(path=0===path.indexOf(base)?path.substr(base.length):path).replace("#!",""),base&&path,e.preventDefault(),page.show(link)}}}}function getButtonFromEvent(e){let which=(e=e||window.event).which;return which=null==which?e.button:which}function sameOrigin(href){let origin=location.protocol+"//"+location.hostname;return location.port&&(origin+=":"+location.port),href&&0===href.indexOf(origin)}page.pushState=function(state,title,url){url="#!"+url,history.pushState(state,title,url),previousPopState=state},page.handleAnchorClick=onclick;export default page; |