secret
Created

Jqm Angular adapter page loader using custom routing

  • Download Gist
PageLoader
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
// The pageloader is largely inspired by angulars ngRoute service
function $PageLoaderProvider() {
var routes = {};
 
this.when = function( path, route ) {
routes[path] = route;
 
// create redirection for trailing slashes
if ( path ) {
var redirectPath = ( path[path.length - 1] == '/' )
? path.substr( 0, path.length - 1 )
: path + '/';
 
routes[redirectPath] = { redirectTo: path };
}
 
return this;
}
 
this.otherwise = function( params ) {
this.when( null, params );
return this;
};
 
this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache',
function( $rootScope, $location, $routeParams, $q, $injector, $http, $templateCache ) {
 
var matcher = switchRouteMatcher;
var $pageLoader = {
routes: routes,
};
 
var jqmLoadPage = $.mobile.loadPage;
$.mobile.loadPage = function( url, options ) {
var match = url.match(/#(\w+)/); // match everything after the hash
if ( match ) {
var path = match[1];
 
// check whether the requested page matches on of our routes
var next = parseRoute( path, $location.search() );
 
if ( next ) {
var template;
if ( angular.isDefined( template = next.template ) || angular.isDefined( template = next.templateUrl ) ) {
url = template;
}
}
}
 
return jqmLoadPage( url, options );
};
 
return $pageLoader;
 
/////////////////////////////////////////////////////
 
function switchRouteMatcher( on, when ) {
// TODO(i): this code is convoluted and inefficient, we should construct the route matching
// regex only once and then reuse it
var regex = '^' + when.replace( /([\.\\\(\)\^\$])/g, "\\$1" ) + '$',
params = [],
dst = {};
angular.forEach( when.split( /\W/ ), function( param ) {
if ( param ) {
var paramRegExp = new RegExp( ":" + param + "([\\W])" );
if ( regex.match( paramRegExp ) ) {
regex = regex.replace( paramRegExp, "([^\\/]*)$1" );
params.push( param );
}
}
} );
var match = on.match( new RegExp( regex ) );
if ( match ) {
angular.forEach( params, function( name, index ) {
dst[name] = match[index + 1];
} );
}
return match ? dst : null;
}
 
function loadNextPage() {
var next = parseRoute( $location.path(), $location.search() ),
last = $pageLoader.current;
 
if ( next || last ) {
$pageLoader.current = next;
 
$q.when( next ).
then( function() {
if ( next ) {
var keys = [],
values = [],
template;
 
angular.forEach( next.resolve || {}, function( value, key ) {
keys.push( key );
values.push( isString( value ) ? $injector.get( value ) : $injector.invoke( value ) );
} );
 
if ( angular.isDefined( template = next.template ) ) {
} else if ( angular.isDefined( template = next.templateUrl ) ) {
template = $http.get( template, { cache: $templateCache } ).
then( function( response ) { return response.data; } );
}
if ( angular.isDefined( template ) ) {
keys.push( '$template' );
values.push( template );
}
return $q.all( values ).then( function( values ) {
var locals = {};
angular.forEach( values, function( value, index ) {
locals[keys[index]] = value;
} );
return locals;
} );
}
} ).
// after route change
then( function( locals ) {
if ( next == $pageLoader.current ) {
if ( next ) {
next.locals = locals;
angular.copy( next.params, $routeParams );
}
$rootScope.$broadcast( '$pageLoadSuccess', next, last );
}
}, function( error ) {
if ( next == $pageLoader.current ) {
$rootScope.$broadcast( '$pageLoadError', next, last, error );
}
} );
}
}
 
// copied straight from Angular.js (not exposed publicly)
function inherit( parent, extra ) {
return angular.extend( new ( angular.extend( function() { }, { prototype: parent } ) )(), extra );
}
 
/**
* @returns the current active route, by matching it against the URL
*/
function parseRoute( targetPath, targetSearch ) {
// Match a route
var params, match;
angular.forEach( routes, function( route, path ) {
if ( !match && ( params = matcher( targetPath, path ) ) ) {
match = inherit( route, {
params: angular.extend( {}, targetSearch, params ),
pathParams: params
} );
match.$pageLoader = route;
}
} );
// No route matched; fallback to "otherwise" route
return match || routes[null] && inherit( routes[null], { params: {}, pathParams: {} } );
}
 
/**
* @returns interpolation of the redirect path with the parametrs
*/
function interpolate( string, params ) {
var result = [];
angular.forEach(( string || '' ).split( ':' ), function( segment, i ) {
if ( i == 0 ) {
result.push( segment );
} else {
var segmentMatch = segment.match( /(\w+)(.*)/ );
var key = segmentMatch[1];
result.push( params[key] );
result.push( segmentMatch[2] || '' );
delete params[key];
}
} );
return result.join( '' );
}
}];
}
 
angular.module( "$pageLoader", [], function( $provide ) {
$provide.provider( {
$pageLoader: $PageLoaderProvider
} );
} );
app.js
JavaScript
1 2 3 4 5 6 7 8 9
angular.module( "...", ["$pageLoader", "logfilesServices"] )
.config( ['$pageLoaderProvider', function( $pageLoaderProvider ) {
 
$pageLoaderProvider
.when( 'logfiles', { templateUrl: 'partials/logfiles.html' } )
.when( 'logfiles/:logfileId', { templateUrl: 'partials/logfile.html' } )
.otherwise( { redirectTo: '' } )
.when( '', { templateUrl: '#index' } );
}] );

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.