var ViewNavigator = function( target, backLinkCSS, bindToWindow ) { this.supportsBackKey = true; //phonegap on android only this.animating = false; this.animationX = 150; this.animationDuration = 350; this.history = []; this.scroller = null; this.headerPadding = 5; this.uniqueId = this.guid(); var regexp = new RegExp("Windows Phone OS 7"); this.winPhone = (navigator.userAgent.search(regexp) >= 0); this.rootElement = $('
'); this.header = $('
'); this.content = $('
'); this.rootElement.append( this.header ); this.rootElement.append( this.content ); this.parent = $( target ); this.backLinkCSS = backLinkCSS ? backLinkCSS : "viewNavigator_backButton"; var self = this; //$(window).resize( function(event){ self.resizeContent() } ); //alert( this.parent.toString() ); //this.parent.resize( function(event){ self.resizeContent() } ); if ( bindToWindow != false ) { $(window).resize( function(event){ self.resizeContent() } ); } else { this.parent.resize( function(event){ self.resizeContent() } ); } this.parent.append( this.rootElement ); if ( window.viewNavigators == null || window.viewNavigators == undefined ) { window.viewNavigators = {}; } window.viewNavigators[ this.uniqueId ] = this; } ViewNavigator.prototype.replaceView = function( viewDescriptor ) { if (this.animating) return; viewDescriptor.animation = "pushEffect" //this is a hack to mimic behavior of pushView, then pop off the "current" from the history this.history.push( viewDescriptor ); this.updateView( viewDescriptor ); this.history.pop(); this.history.pop(); this.history.push( viewDescriptor ); } ViewNavigator.prototype.pushView = function( viewDescriptor ) { if (this.animating) return; viewDescriptor.animation = "pushEffect" this.history.push( viewDescriptor ); this.updateView( viewDescriptor ); } ViewNavigator.prototype.popView = function() { if (this.animating || this.history.length <= 1 ) return; var currentViewDescriptor = this.history[ this.history.length-1]; if ( currentViewDescriptor.backCallback ) { currentViewDescriptor.backCallback(); } this.history.pop(); var viewDescriptor = this.history[ this.history.length-1 ]; viewDescriptor.animation = "popEffect" this.updateView( viewDescriptor ); } ViewNavigator.prototype.setHeaderPadding = function( amount ) { this.headerPadding = amount; if ( this.headerBacklink ) { this.headerBacklink.css("left", amount); } } ViewNavigator.prototype.updateView = function( viewDescriptor ) { this.animating = true; this.contentPendingRemove = this.contentViewHolder; this.headerContentPendingRemove = this.headerContent; this.headerContent = $('
'); this.headerTitle = $("
" + viewDescriptor.title + "
"); this.headerContent.append( this.headerTitle ); var linkGuid = this.guid(); if ( viewDescriptor.backLabel ) { this.headerBacklink = $(''); this.headerContent.append( this.headerBacklink ); //this is for proper handling in splitviewnavigator this.setHeaderPadding( this.headerPadding ); } var id = this.guid(); this.contentViewHolder = $('
'); this.contentViewHolder.append( viewDescriptor.view ); this.resizeContent(); $(this.contentPendingRemove).click(function(){ return false; }); if ( viewDescriptor.animation == "popEffect" ) { this.contentViewHolder.css( "left", -this.contentViewHolder.width() ); this.contentViewHolder.css( "opacity", 1 ); this.content.prepend( this.contentViewHolder ); this.headerContent.css( "left", -this.animationX ); this.headerContent.css( "opacity", 0 ); this.header.append( this.headerContent ); this.contentPendingRemove.animate({ left:this.contentViewHolder.width(), opacity:1, avoidTransforms:false, useTranslate3d: true }, this.animationDuration, this.animationCompleteHandler(this.contentPendingRemove, this.headerContentPendingRemove, this.headerContent, this.contentViewHolder )); //remove this to change back this.contentViewHolder.animate({ left:0, opacity:1, avoidTransforms:false, useTranslate3d: true }, this.animationDuration); this.headerContentPendingRemove.animate({ left:this.animationX, opacity:0, avoidTransforms:false, useTranslate3d: true }, this.animationDuration ); this.headerContent.animate({ left:0, opacity:1, avoidTransforms:false, useTranslate3d: true }, this.animationDuration ); } else if ( this.history.length > 1 ) { this.contentViewHolder.css( "left", this.contentViewHolder.width() ); this.contentViewHolder.css( "opacity", 1 ); this.content.append( this.contentViewHolder ); this.headerContent.css( "left", this.animationX ); this.headerContent.css( "opacity", 0 ); this.header.append( this.headerContent ); this.contentViewHolder.animate({ left:0, opacity:1, avoidTransforms:false, useTranslate3d: true }, this.animationDuration, this.animationCompleteHandler(this.contentPendingRemove, this.headerContentPendingRemove, this.headerContent, this.contentViewHolder )); this.contentPendingRemove.animate({ left:-this.contentViewHolder.width(), opacity:1, avoidTransforms:false, useTranslate3d: true }, this.animationDuration); this.headerContent.animate({ left:0, opacity:1, avoidTransforms:false, useTranslate3d: true }, this.animationDuration ); this.headerContentPendingRemove.animate({ left:-this.animationX, opacity:0, avoidTransforms:false, useTranslate3d: true }, this.animationDuration ); } else { this.contentViewHolder.css( "left", 0 ); this.contentViewHolder.css( "opacity", 1 ); this.content.append( this.contentViewHolder ); this.headerContent.css( "left", 0 ); this.headerContent.css( "opacity", 1 ); this.header.append( this.headerContent ); this.animating = false; this.resetScroller(); } if ( viewDescriptor.backLabel ) { //new NoClickDelay( this.headerBacklink.get()[0] ); } } ViewNavigator.prototype.resetScroller = function() { var id = this.contentViewHolder.attr( "id" ); if ( !this.winPhone ) { if ( this.scroller != null ) { this.scroller.destroy(); } if ( id && !(this.currentViewDescriptor && this.currentViewDescriptor.scroll == false)) { var self = this; setTimeout( function() { self.scroller = new iScroll( id ); }, 10 ); //this.scroller = new iScroll( id ); } } } ViewNavigator.prototype.refreshScroller = function() { if ( !this.winPhone ) { if ( this.scroller != null ) { this.scroller.refresh(); } } } ViewNavigator.prototype.animationCompleteHandler = function(removalTarget, headerRemovalTarget, headerView, contentView) { var self = this; return function() { self.animating = false; self.resetScroller(); if ( removalTarget ) { removalTarget.unbind( "click" ); removalTarget.remove(); } if ( headerRemovalTarget ) { headerRemovalTarget.unbind( "click" ); headerRemovalTarget.remove(); } } } ViewNavigator.prototype.resizeContent = function(event) { var targetWidth = this.parent.width(); if ( this.headerContent ) this.headerContent.width( targetWidth ); if ( this.contentViewHolder ) this.contentViewHolder.width( targetWidth ); } //GUID logic from http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript ViewNavigator.prototype.S4 = function() { return (((1+Math.random())*0x10000)|0).toString(16).substring(1); } ViewNavigator.prototype.guid = function() { return (this.S4() + this.S4() + "-" + this.S4() + "-4" + this.S4().substr(0,3) + "-" + this.S4() + "-" + this.S4() + this.S4() + this.S4()).toLowerCase(); } /* PHONEGAP INTEGRATION */ /* //android+phonegap specific back button support - will only work if phonegap is used on android (www.phonegap.com) if ( typeof PhoneGap != 'undefined' ) { document.addEventListener("deviceready", onDeviceReady, false); } function onDeviceReady() { document.addEventListener("backbutton", onBackKey, false); } function onBackKey( event ) { event.preventDefault(); window.viewNavigator.popView(); for ( var x=0; x