Skip to content

Instantly share code, notes, and snippets.

@JohannesRudolph
Created November 7, 2012 15:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JohannesRudolph/47e5c58128c0ff31bccc to your computer and use it in GitHub Desktop.
Save JohannesRudolph/47e5c58128c0ff31bccc to your computer and use it in GitHub Desktop.
Jqm Angular adapter page loader using custom routing
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' } );
}] );
// 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
} );
} );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment