/*************************************************************************
 **
 ** NOTES:
 ** Path: www.site.com/path/to/page
 ** Fragment: #hash
 ** Query stuff: ?start=10
 **
 ** Dependencies:
 **   If you want to use google analytics, you must include the ga code
 ************************************************************************/

 
 
var gCurrPage           = null;
var gCurrPagePath       = null;
var gPrevPagePath       = null;
var gShowPagesTimeoutID = null;
var gShowPagesStarted   = false;
var gWaitForContent     = false;
var gFragmentRedirects  = true;
var gNormalPageHeight   = 481;
var gUtilPageHeight     = 574;
var gBlockAnimateLinks  = false;
var gAnimatingLink      = false;
var initial_fragment = "";
var initial_mask_event = 0;
var preview_mode = 0;
var pageTracker = null;

        //* check hostname
        var ruby_index = window.location.hostname.indexOf("ruby");
        if(ruby_index != -1 && ruby_index < 5){
            preview_mode = 1;
        }
//preview_mode =1;
fastRedirect(); //* we need to run early, we cannot wait for $.history to be initialized
function fastRedirect(){
        //alert("running fast redirect");
        var initial_fragment = window.location.hash.substr(1);
        if( (typeof initial_fragment == 'undefined' || initial_fragment.length ==0) && !preview_mode){
            initial_fragment = window.location.pathname; //* USE THIS ONLY IF WE WANT ALL PAGES TO START AT HOMEPAGE
            initial_mask_event = 1;
        }

        //* check if the window.location is /index.html
        var location_path = window.location.pathname;
        //if (  !(location_path == '/' || location_path == "/index.html")  && fragment && fragment.indexOf('/') == 0) { //* USE THIS IF WE DON'T WANT ALL PAGES TO START AT HOMEPAGE
        if (  !(location_path == '/' || location_path == "/index.html") && !preview_mode ) { //* USE THIS ONLY IF WE WANT ALL PAGES TO START AT HOMEPAGE
            window.location = "/#"+initial_fragment;//*TODO, change this, new tactic: redirect to /index#fragment, then have AjaxSite load content dynamically
            return 1;
        }
}

function checkRedirects(){

    if (gFragmentRedirects) {
        var fragment = $.history.getCurrent();

        initial_fragment = fragment; //* if there's a fragment, we save it to be loaded later
        if( (typeof initial_fragment == 'undefined' || initial_fragment.length ==0) && !preview_mode){
            initial_fragment = window.location.pathname; //* USE THIS ONLY IF WE WANT ALL PAGES TO START AT HOMEPAGE
            initial_mask_event = 1;
        }


        //* remove/strip x=1 argument on fresh pageload
        var var_str = initial_fragment.substr(initial_fragment.indexOf("?")+1);
        var x_index_0 = initial_fragment.indexOf("?x=1");
        var x_index_1 = -1;
        if(x_index_0 == -1){
            x_index_1 = initial_fragment.indexOf("&x=1");
        }
        if(x_index_0 != -1){
            initial_fragment = initial_fragment.substring(0,x_index_0+1) + initial_fragment.substr(x_index_0+5); 
        }
        else if(x_index_1 != -1){
            initial_fragment = initial_fragment.substring(0,x_index_1) + initial_fragment.substr(x_index_1+4); 
        }

        //* check if the window.location is /index.html
        var location_path = window.location.pathname;
        //if (  !(location_path == '/' || location_path == "/index.html")  && fragment && fragment.indexOf('/') == 0) { //* USE THIS IF WE DON'T WANT ALL PAGES TO START AT HOMEPAGE
        if (  !(location_path == '/' || location_path == "/index.html") && !preview_mode ) { //* USE THIS ONLY IF WE WANT ALL PAGES TO START AT HOMEPAGE
            window.location = "/#"+initial_fragment;//*TODO, change this, new tactic: redirect to /index#fragment, then have AjaxSite load content dynamically
            return 1;
        }
        //* remove the fragment
        $.history.add("", 1); //* clear the hash because we do not have GSDSheet and GSDObject initialized, so monitorAddressBar will flake out
    }
    return 0;
}

$( document ).ready( function () { 
//* we start off with the body hidden:
$("#list-content").hide();
    return;
    var AjaxSiteObj = new AjaxSite();
    //AjaxSiteObj.initializeLinks($("#list-overlay2"));
        
        //setup DEMO stuff for search in nav
        $(".pane-root .pane input[type='submit']").click(function(event){
            event.preventDefault();
            AjaxSiteObj.gotoPage("/sample_pages/issues-list.html");
            return false;
        });

} ); // ready

/*
    AjaxSite constructor
        Initialize content
        
        note: 
        {
        doThis : function(){
            self = this;
            something.click(function(event){
                self.doThat(event)
            });
        },
        doThat : function(evemt){

        }
*/
var initializer_count = 0;
function AjaxSite(){
    //var link = this._breakoutLinkParts((window.location.href));
    //* initialize pageTracker for google analytics

    var target_url;
        if(initial_fragment.length){
            target_url = initial_fragment;
        }
        else{
            target_url = window.location.pathname;
        }
    
    var initLink = {
        path : "/index.html",
        query: ""
    };
    var link = this._breakoutLinkParts(target_url);
    if(link.path == "/"){link.path = "/index.html";}
    if(target_url == "/index.html" || target_url == "/" ){ //* don't want to call ajax on homepage
       initial_mask_event = 1 ;
    }
    
    if( !preview_mode){
        this.monitorAddressBar();
    }
    //$.history.add(link.path+"?"+link.query+"#"+link.fragment, 1); //* initialize hash part of the url //*TODO: alphadev

    this.GSDSheet_obj = new GSDSheet(initLink); //* always initialize with the homepage
    this.GSDField_obj = new GSDField(initLink);
    console.log(this.GSDSheet_obj);

    this.GSDField_obj.GSDSheet_obj = this.GSDSheet_obj;
    //this.GSDSheet_obj.GSDField_obj = this.GSDField_obj;

    //this.GSDSheet_obj.initialize(); 
    //this.GSDField_obj.initialize();
    this.initializeLinks();

    //* set the default breadcrumb for GSDField
    //this.backupBreadcrumb();
    this.GSDField_obj.currentBreadcrumb = $("#navigator-title").clone();
    if(!initial_mask_event && !preview_mode){
    //setTimeout( function(){ $.history.add(target_url, initial_mask_event);}, 600); //* initialize hash part of the url by loading the content dynamically
        $.history.add(target_url, initial_mask_event); //* initialize hash part of the url by loading the content dynamically

        //* prevent the homepage from doing stuff //TODO
    }
    else{
        $("#list-content").show();
        this.GSDSheet_obj.initialize(); 
        this.GSDField_obj.initialize();
        initializer_count++; //* we've initialized, we don't need the ajax success to check again
    }
    //hacky, check if there's a newsfeed button and click it
    if( initial_mask_event && $("#media-menu .news-feed-btn.feed-auto").length > 0 ){ 
        //* ^-- only if we masked the history.add do we want the feed to autoload 
            setTimeout( function(){$("#media-menu .news-feed-btn").trigger("click");}, 600);
        
        
        //$("#media-menu .news-feed-btn").trigger("click");
    }

}

AjaxSite.prototype = {
    //some options

    gCurrPage           : null,
    gCurrPagePath       : null,
    gPrevPagePath       : null,
    gShowPagesTimeoutID : null,
    gShowPagesStarted   : false,
    gWaitForContent     : false,
    gFragmentRedirects  : true,
    gNormalPageHeight   : 481,
    gUtilPageHeight     : 574,
    gBlockAnimateLinks  : false,
    gAnimatingLink      : false,
    GSDSheet_obj        : '',   //CUSTOM
    GSDField_obj        : '',    //CUSTOM
    printCSS            : undefined,

    backupBreadcrumb: function(){
        var self = this;
        console.log("backupBreadcrumb self", self, $("#navigator-title").html());
        //* after breadcrumb has been updated, we check if its a field crumb or a sheet crumb
        if($("#navigator-title span.sheet-tag").length > 0){
            //* it's a sheet nav, we should backup the sheet
            self.GSDSheet_obj.currentBreadcrumb = $("#navigator-title").clone();
        }
        else{ //* we assume it's a field nav
            self.GSDField_obj.currentBreadcrumb = $("#navigator-title").clone();
        }
    },
    pageChange :    function(html,query, suppress_hide){ //CUSTOM
        var self = this;
        //console.log("Page Changing... ", html);

        var content = $(html);
        if(typeof suppress_hide == "undefined" || !suppress_hide){
            //* replace header title and meta data
            if($("#head-title", content).length > 0 ){ 
                //$("title").replaceWith( "<title>"+$("#head-title", content).text()+"</title>" );
                document.title = $("#head-title", content).text();
            }
            if($("#head-keywords",content).length > 0 ){ $("meta[name='keywords']").attr("content", $("#head-keywords",content).text() ); }
            if($("#head-description",content).length > 0 ){ $("meta[name='description']").attr("content", $("#head-description",content).text() ); }

            //* load new nav label
            //* Do some smart  navigator crumb jumbling
            if( $(content).find("#navigator-title").length > 0){
                var span_backup;
                var tag_selector = null;
                //* first we remove unwanted tags
                $("#navigator-title span.remove-tag", content ).remove();
                //$("#navigator-title span").removeClass("hide");
                //$("#navigator-title").replaceWith($(content).find("#navigator-title"));

                //* first we check if the parent tag of the new breadcrumb matches any of the tags
                //* in the current breadcrumb
                //* and find out whether it's a sheet or field
                    var match_tag_type = null;
                    var short_circuit = 0;
                    var next_idx = -1;
                        //* we extract the id_#-tag selectors
                    $("#navigator-title span", content).each(function(i,e){
                        //* rt#11814: removing : if its the last character in the name
                            var temp_name = $(e).text();
                            temp_name = jQuery.trim(temp_name); 
                            if(temp_name.lastIndexOf(':') == temp_name.length -1){
                               $(e).text(temp_name.substr(0, temp_name.length - 1));  
                            }
                        //* END rt#11814
                        console.log("testing tag match: ", $(e).html(), i, next_idx, "has field class?",$(e).hasClass('field-tag'));
                        var temp_selector = $(e).attr("class");
                        var temp_idx = temp_selector.indexOf("id_");

        
                        if(temp_idx != -1 && tag_selector == null){ //* while it's still null
                            temp_selector = temp_selector.substring(temp_idx);
                            var temp_selector_arr = temp_selector.split(" ");
                            temp_selector = "."+temp_selector_arr[0];
                            console.log("current selector array:", temp_selector_arr, temp_selector );
                            //* we found a tag selector, now check if it's avail, then find its tag type
                            if($("#navigator-title "+ temp_selector).length > 0){
                                console.log("found tag selector:", temp_selector);
                                tag_selector = temp_selector;
                                next_idx = i;
                                //* tag type?
                                if($($("#navigator-title "+ tag_selector)[0]).hasClass('field-tag')){
                                    match_tag_type = 'field-tag';
                                }else{
                                    //* we assume it's a sheet
                                    match_tag_type = 'sheet-tag';
                                }
                            }
                        }
                        else if(i == next_idx+1){ //* the element immediately to the right
                            if( (match_tag_type == 'field-tag' && $(e).hasClass('field-tag')) || (match_tag_type == 'sheet-tag' && $(e).hasClass('sheet-tag'))){
                                short_circuit = 1; //if its the same field tag, then we're not doing the smart breadcrumb hack of tacking stuff on.
                            }
                        }
                        
                        //if($("#navigator-title "+))
                    });
                    console.log("final tag selector: ", tag_selector, match_tag_type);
                if( tag_selector != null && !short_circuit){
                        console.log("replacing/tacking on tags", match_tag_type == 'field-tag');
                        var list_of_tags;
                        if( match_tag_type == 'field-tag' ){
                            list_of_tags  = '.field-tag';
                        }
                        else{
                            list_of_tags = '.field-tag, .sheet-tag, .misc-tag';
                        }
                        //* if one of the field tags in new matches old, then we don't replace field
                        console.log(":not", list_of_tags ,$("#navigator-title span:not("+ list_of_tags +")"));
                        console.log(":has",$("#navigator-title :has("+ list_of_tags +")", content));
                        $("#navigator-title span:not("+ list_of_tags +")").remove();
                        $(list_of_tags, $("#navigator-title", content) ).remove();
                        $("#navigator-title").append($("#navigator-title span", content));
                        console.log("page has" + match_tag_type + " as  parents",tag_selector);
                        /*
                        $("#navigator-title span:not(.field-tag)").remove();
                        $("#navigator-title span.field-tag", content).remove();
                        $("#navigator-title").append($("#navigator-title span", content));
                        */
                }
                else if($("#navigator-title .field-tag", content).length > 0){
                        //* else we replace everything
                    console.log("replace all");
                        $("#navigator-title").replaceWith($(content).find("#navigator-title"));
                        //$("#navigator-title span.field-tag").remove();
                        //$("#navigator-title").prepend($("#navigator-title span", content));
                }
                else if($("#navigator-title .sheet-tag", content).length > 0){
                    console.log("replace sheet", $("#navigator-title span:not(.field-tag)"));

                        //* also replace everything
                        $("#navigator-title").replaceWith($(content).find("#navigator-title"));
                    //* if there are no fields in the new breadcrumb, 
                    //* we strip out every other tag except the fields in the current breadcrumb
                    //* then we append the new non-field tags;
                    

                        //$("#navigator-title span:not(.field-tag)").remove();
                        //$("#navigator-title span.field-tag").addClass("hide");
                        //$("#navigator-title").append($("#navigator-title span", content));
                        // TODO
                        //* for sheets associated with field, the parent field tag and the previous logic
                        //* check should've taken care of it.
                        //* this is called only when the sheets are not associated with fields 
                        //* ( basically sitemap sheets)
                        //* if this is called, we shouldn't replace the nav, but hide all field items 
                        //* (because the field is still visible)
                        //* that way, if the sheet is closed, we can show the field breadcrumb
                        //$("#navigator-title").replaceWith($(content).find("#navigator-title"));
                }
                else if($("#navigator-title .subtype-tag", content).length > 0){
                    //* this should only get called if the subtype doesn't have the parent page that's
                    //* either a field or sheet
                    //* else the other two logic checks should've kicked in
                    $("#navigator-title span:not(.field-tag, .sheet-tag, .misc-tag)").remove();
                    span_backup = $("#navigator-title span").detach();
                    $("#navigator-title").empty().append(span_backup);
                    $("#navigator-title").append($("#navigator-title span", content));
                }
                //* re-insert ':'
                    //* we first clear it
                    span_backup = $("#navigator-title span").detach();
                    $("#navigator-title").empty().append(span_backup);
                    //* then we insert it a different way
                //$("#navigator-title span:not(:first)").each(function(i,e){
                var not_arr = $("#navigator-title span:not(.hide)");
                for(var i=0; i< not_arr.length-1; i++){
                    $(not_arr[i]).after(": ");
                }
                /*
                $("#navigator-title span:not(:last)").each(function(i,e){
                    if($(e).text().lastIndexOf(':') != $(e).text().length-2){
                        //$(e).prepend(": ");
                        //$(e).append(": ");
                        $(e).after(": ");
                    }
                });
                */
                
                self.backupBreadcrumb();
                //$("#navigator-title span:not(:last)").after(": ");
                //$("#navigator-title span:not(:first)").before(": ");
            }
            //* load new menu label
            //* no longer used
            
    //        if($(content).find("#navigator-opener img").length > 0){
    //			$("#navigator-opener img").replaceWith($(content).find("#navigator-opener img"));
    //        }
        }
		//new GSDSheet().setContent(html);
        //we want to load content for GSDSheet second because if the content
        //contains both, we want GSDSheet to reshow the sheet
        self.GSDSheet_obj.setContent(html, query, suppress_hide);
        self.GSDField_obj.setContent(html, query, suppress_hide);
    },
    
    externalLinkInit: function(){
	//console.log(location.protocol+"//"+location.host);
	//$('a:regex(href, (?<!'+location.host+').* )').each(function(index, element){

	$('a:not(.target-blank, .exclude, .fb-btn, .twitter-btn, .print-btn, .back-button)').each(function(index, element){

		var temp_str = $(element).attr('href');
		if(temp_str == undefined){return;}
        //* extract the filetype
        var file_type_idx = temp_str.lastIndexOf(".");
        var has_html = -1;
        if(file_type_idx > -1){
            has_html = temp_str.lastIndexOf(".html");
        }
        
		if( !$(element).data("link_set") &&
            ((temp_str.charAt(0)!= "#" &&  
                (!temp_str.match(location.host) || temp_str.indexOf(location.host)>15) && 
            temp_str.charAt(0)!="/" && !temp_str.match("mailto:")) || 
            temp_str.match(".pdf") ||
            (file_type_idx > -1 && has_html == -1)
            ) ){
            //$(element).unbind("click.ext");
                $(element).data("link_set", true);
			    $(element).bind("click.ext", function(){window.open(temp_str); return false;});
		}
	});

        // Look for links that need to open in a new window
        $('a.target-blank, a.add-to-cal-btn').each( function(index, element) {
            $( element )
                .data("link_set", true)
                .unbind( '.ext' ) // unbind any previously set handler
                .bind( 'click.ext', function() {
                    window.open( this.href ); // show in new window
                    return false;
                })
            ;
        }); // for each link that needs to open in a new window
        
    //console.log($('a.fb-btn, a.twitter-btn'));
    $('#media-menu a.fb-btn, #media-menu a.twitter-btn, .sheet-media-menu a.fb-btn, .sheet-media-menu a.twitter-btn').each(function(index, element){
            if(!$(element).data("link_set") ){
                $(element).data("link_set", true);
            }
            else{
                return;
            }
            if(isIphone()){
			    $(element).bind("click.ext", function(){window.open($(element).attr("href")); return false;});
            }   
            else{
           
    			$(element).bind("click.ext",function(){window.open($(element).attr("href"), "_blank" ,'width=560,height=360'); return false;});
            }
		
	});
    $(".footer-social-buttons a.fb-btn, .footer-social-buttons a.twitter-btn").each(function(index, element){
            if(!$(element).data("link_set") ){
                $(element).data("link_set", true);
            }
            else{
                return;
            }
			$(element).bind("click.ext", function(){window.open($(element).attr("href")); return false;});
    });


    },
    initializeLinks : function(root){
        var self = this;
        root = typeof(root) != 'undefined' ? root : $("body");
        var count = 0;
        self.externalLinkInit();
        $(root).find("a:not(.btn-full, .print-btn, .ui-state-default, .ui-datepicker-prev, .ui-datepicker-next, .exclude, .switcher .btn-next, .switcher .btn-prev)").each(function(i, e){
            //console.log($(e).data("link_set"));
            //if(count < 100){
            if(!$(e).data("link_set") ){
                self._linkSetup($(e));
                $(e).data("link_set", true);
            }
            //}
            count++;

        });
        //* initialize special nav buttons like print
        $("#media-menu .print-btn").each(function(i,e) {
            e = $(e);
            //* store whether the link as been set a jquery data object
            if(!$(e).data("link_set") ){
                $(e).data("link_set", true);
            }
            else{
                return;
            }
            //e.unbind("click");
            e.click(function(){  
                //console.log(self.printCSS);
                /*
                if(self.printCSS != undefined){
                    $(self.printCSS).remove();
                    self.printCSS = undefined;
                }*/
                $('link.js-print').remove();
                if($("#list-content .cell-hover img").length > 0){
                    $.getCSS('/styles/img-print.css',{
                        media : 'print'
                        } ,function(e){
                        //console.log(e);
                        $(e).addClass("js-print");
                        self.printCSS = e;
                        window.print();
                    });
                }
                else{
                    $.getCSS('/styles/field-print.css',{
                        media : 'print'
                        } ,function(e){
                        $(e).addClass("js-print");
                        self.printCSS = e;
                        window.print();
                    });
                }
                return false;
            });
        });
        $(".sheet-media-menu .print-btn").each(function(i,e) {
            e = $(e);
            //* store whether the link as been set a jquery data object
            if(!$(e).data("link_set") ){
                $(e).data("link_set", true);
            }
            else{
                return;
            }
            //e.unbind("click");
            e.click(function(){  
                /*
                if(self.printCSS != undefined){
                    $(self.printCSS).remove();
                    self.printCSS = undefined;
                }
                */              
                $('link.js-print').remove();
                    $.getCSS('/styles/sheet-print.css',{
                        media : 'print'
                        } ,function(e){ 
                        //console.log(e);
                        $(e).addClass("js-print");
                        self.printCSS = e;
                        window.print();
                    });
                return false;
            });
        });
            //* loading the sheet-print as the initial css 
                    $.getCSS('/styles/sheet-print.css',{
                        media : 'print'
                        } ,function(e){ 
                        $(e).addClass("js-print");
                        self.printCSS =e ;
                    });
            // ------------------------------------------- //
        
        //DEBUG search button
        /*
        $("input[type=submit]").click(function(){
            self.gotoPage("/sample_pages/search-results.html");
            return false;
        });
        */
    },
    _breakoutUrlVars: function(query){
        var vars = [], hash;
        var hashes = query.split('&');
        for(var i = 0; i < hashes.length; i++)
        {
            hash = hashes[i].split('=');
            vars.push(hash[0]);
            vars[hash[0]] = hash[1];
        }
        return vars;
    },
	_breakoutLinkParts : function(link){
        if(typeof link == 'undefined'){
            return {
                path:'',
                query: '',
                query_hash : {},
                fragment : ''
            };
        }
        //console.log(link);
		var origin = window.location.protocol + '//' + window.location.host;
        var path;
        var query = '';
        var query_hash = {};
        var fragment = '';
		
        if ( link.indexOf(origin) == 0 ){
            path = link.substr( origin.length );
		}
        else if ( link.indexOf("/") == 0 ){
            path = link;
		}

        // Link must be site-relative or same origin to animate
		// If it's just "href='#top'" then we dont care
        if ( path == null)
            return;

        // Further uri parsing - separate path, query and fragment
        var i;

        if ( (i = path.indexOf('#')) >= 0 ) {
            fragment = path.substr( i+1 );
            path = path.substr( 0, i );
        }

        if ( (i = path.indexOf('?')) >= 0 ) {
            query = path.substr( i+1 );
            path = path.substr( 0, i );
            query_hash = this._breakoutUrlVars(query);
        }

        // Link with path in fragment, e.g. #/home.html - use fragment as target
        if ( fragment.indexOf('/') == 0 ) {
            path = fragment;
            fragment = '';
        }
		return {
			'path': path,
			'fragment': fragment,
			'query': query,
            'query_hash': query_hash
		};
	},
    _linkSetup : function(clickable) {
        clickable = $(clickable);
        var self = this;
        // Allow "fast" links for BUTTON or A tags.  If it is a BUTTON tag
        // then it is assumed that that button contains an A tag, which is where
        // the link is grabbed from.  SideNote: We need to put the class="fast" on
        // the BUTTON tag because the A tag's onclick will not execute when the A
        // tag resides within a BUTTON tag and the button is clicked (FF3).
        //var tagName = clickable.tagName.toUpperCase();
        /*
        var link    = tagName == "BUTTON" ? $( 'a', clickable )[0]
            : tagName == "A"      ? clickable
            :                       null
            ;
        */
        var link = clickable;
        if ( link == null ) 
            return;

        var origin = window.location.protocol + '//' + window.location.host;
        var path;
        var query = '';
        var fragment = '';

        //* setup nav links

        //* do these immediately cause we dont need to parse anything else
        //* Setting up back button clicks
        if(link.hasClass("back-button")){

            //$(clickable).unbind( 'click.ajax' );
            //$(clickable).unbind( 'keypress.ajax' );
            $(clickable).bind("click.ajax",function(event){ 
				self.backlinkClicked(event, self);
				return false;
			} );
            $(clickable).bind("keypress.ajax",function(event){
				self.backlinkClicked(event, self);
				return false;
			});
            return;
        }
        //* setting up click action for closing sheet
        if(link.hasClass("close-button")){

            //$(clickable).unbind( 'click.ajax' );
            //$(clickable).unbind( 'keypress.ajax' );
            $(clickable).bind("click.ajax",function(event){ 
				self.closelinkClicked(event, self);
				return false;
			} );
            $(clickable).bind("keypress.ajax",function(event){
				self.closelinkClicked(event, self);
				return false;
			});
            return;
        }


		if(link.attr("href") && link.attr("href").indexOf("#") == 0) {
            if(link.attr("href").length == 1){//only a hash, ie, we're not using it as a link
                //console.log("return due to: "+ link.attr("href"));
                //console.log(link);
				link.bind("click.ajax",function(event){ //necessary to stop hash links from triggering address bar
					event.preventDefault();
					return false;
				});
        /*
                link.bind("click.ajax",function(){
 
        var previous = $.history.getPrevious();

        if (previous == null)
          window.history.go(-1);
        else
          $.history.add(previous);
                    alert(previous);
                
                    event.preventDefault();
                    event.stopPropagation();
                    return false;
                    
                });
        */
                return;
            }
			//alert(link.attr("href") + " href is a same page hash anchor jump");
			var temp_base_path = self.currentBasePath();
			
			//alert(window.location);
			link.attr("href", temp_base_path+link.attr("href"));
		}
        if (link.attr("href") && link.attr("href").indexOf(origin) == 0 ){
            path = link.attr("href").substr( origin.length );
		}
        else if ( link.attr("href") && link.attr("href").indexOf("/") == 0 ){
            path = link.attr("href");
		}

        // Link must be site-relative or same origin to animate
		// If it's just "href='#top'" then we dont care
        if ( path == null)
            return;

        // Further uri parsing - separate path, query and fragment
        var i;

        if ( (i = path.indexOf('#')) >= 0 ) {
            fragment = path.substr( i+1 );
            path = path.substr( 0, i );
        }

        if ( (i = path.indexOf('?')) >= 0 ) {
            query = path.substr( i+1 );
            path = path.substr( 0, i );
        }

        // Link with path in fragment, e.g. #/home.html - use fragment as target
        if ( fragment.indexOf('/') == 0 ) {
            path = fragment;
            fragment = '';
        }

        // Compute file extension
        var parts = path.split('/');
        var last = parts.length > 0 ? parts.pop() : '';
        parts = last.split('.');
        last = parts.length > 0 ? parts.pop() : '';

        // Exclude links with non-.html file extensions from animation 
            //TODO, dunno if we want to exclude the links, we should just let pageChange handle it
        
        //if ( last != '' && last != 'html')
        //    return;

			//console.log(link);
            //console.log("query stuff");
            //console.log(query);
            //console.log("path");
            //console.log(path);
            //console.log("fragment");
            //console.log(fragment);
            //return;
        
        var onclick = self.pagelinkClicked;

        var cpath = self.currentPagePath();
		//console.log("CPATH");
		//console.log(cpath);
        // If a link references a named anchor on this page, simulate browser scroll.
        // If it references a named anchor on another page, don't animate at all.
        if ( fragment.length > 0 ){
			// NOTE: in this case we want to respond to ANY path that passes inspect (ie, its a valid link to animate)
			// We will parse the ACTION of the namedAnchor depending on wither its the same as the current page OR an anchor on a NEW page
            //if ( path == cpath ){

    			var target = $('a[name="' + fragment + '"]');

					if (target.length > 0) {
                        onclick = self.namedAnchorClicked;
					}
				//console.log("namedAnchorClicked");
			//}
            //else
            //    return;
        }
		//DEBUG
		//onclick = self.pagelinkClicked;
        // If a link is a "back" button, it should simulate a browser back button click
            //console.log(clickable);
			//console.log($(clickable.hasClass("back-button")));
        if ($(clickable).hasClass('back-button')){
            onclick = self.backlinkClicked;
		}
		////console.log(onclick);
			//* unbind so that we dont get link conflicts
        //$(clickable).unbind( 'click.ajax' );
        //$(clickable).unbind( 'keypress.ajax' );
        $(clickable).bind("click.ajax",function(event){
            if(clickable.hasClass("toggle")){
                if(clickable.hasClass("active")){
                    clickable.removeClass("active");
                    //self.GSDSheet_obj.hide(); //TODO, a kludge here cause we dont know whether it is a sheet obj
                    //* ^-- must also update url
                    self.closelinkClicked(event,self);
                }
                else{
                    onclick(event, self); 
                    clickable.addClass("active");
                }

            }
            else{
                    onclick(event, self); 
            }
            return false;

        });
        $(clickable).bind("keypress.ajax",function(event){onclick(event, self); return false;});
    },

// Simulate a browser back button click

    backlinkClicked : function(event, self) {
        event.preventDefault();
        var previous = $.history.getPrevious();
        //console.log("previous:", previous);
        //console.log("bbackbuttonclicked");
        //console.log(event);

            //console.log($(event.currentTarget).parents(".close-btn"));
        maskEvent = 0;
        if($(event.currentTarget).hasClass("close-btn") || $(event.currentTarget).parents(".close-btn").length>0 ){
            self.closelinkClicked(event, self);
            /*
            //previous = "";
            maskEvent = 1;
            this.GSDSheet_obj.hide();
            var current = $.history.getCurrent();
            //console.log("current", current);
            $.history.add(current+"?x=1", maskEvent); //force it close
            */
            return false;
        }

        if (previous == null){
          window.history.go(-1);

        }
        else{
          $.history.add(previous, maskEvent);

        }

        //event.stopPropagation();
        return false;
    },
    refreshBreadcrumb : function (option){
        var self = this;
        if(option == 'close-sheet'){
            //* reinsert crumb from field's backup
            
            $("#navigator-breadcrumb-wrapper").empty().append(self.GSDField_obj.currentBreadcrumb);
        }
        else if(option == 'reopen-sheet'){
            //$("#navigator-title .field-tag.active").addClass("hide");
            //$("#navigator-title .field-tag.active").removeClass("active");
            //$("#navigator-title span:not(.field-tag)").removeClass("hide");

            $("#navigator-breadcrumb-wrapper").empty().append(self.GSDSheet_obj.currentBreadcrumb);
        }
    
        return;
        var span_backup = $("#navigator-title span").detach();
        $("#navigator-title").empty().append(span_backup);
        //$("#navigator-title span:not(.hide):not(:last)").after(": ");
            var not_arr = $("#navigator-title span:not(.hide)");
            for(var i=0; i< not_arr.length-1; i++){
                $(not_arr[i]).after(": ");
            }
    },
    closelinkClicked : function(event, self) {
            //previous = "";
            maskEvent = 1;
            this.GSDSheet_obj.hide();
            //* when closing the sheet (cause closelink only calls on sheet, we do some smart stuff to the breadcrumb
            self.refreshBreadcrumb("close-sheet");
            var current = $.history.getCurrent();
            //console.log("current", current);
            $.history.add(current+"?x=1", maskEvent); //force it close
        /*
        event.preventDefault();
        var previous = "";
        var maskEvent = 1;

        if (previous == null){
          window.history.go(-1);

        }
        else{
          $.history.add(previous, maskEvent);

        } 
        */
        //event.stopPropagation();
        return false;
    },

// Simulate browser scroll to named anchor

    namedAnchorClicked : function(event, AjaxSiteObj) {
        event.preventDefault();
		//console.log(event);
		var target = event.target;
		var self = AjaxSiteObj;
		//alert("namedAnchorClicked");
        // Clicked link must reference named anchor on current page

        var origin = window.location.protocol + '//' + window.location.host;
		//console.log("current page path: " + self.currentPagePath());
        var cpath = origin + (self.currentPagePath());
		
        //var href = this.href;
        var href = $(target).attr("href");

        //if (href.indexOf(cpath+'#') != 0)
        //  return true;
        var index = href.indexOf('#');
        
        //href = href.substr(cpath.length+1);
        href = href.substr(index+1);
        //* add the href to the end of the hash
 
        //window.location.hash = window.location.hash+"#"+href;
        var current_link = window.location.hash;
        if(current_link[0] == '#'){
            current_link = current_link.substr(1);
        }
        var hash_index = current_link.indexOf('#');
        if(hash_index > 0){
            current_link = current_link.substr(0,hash_index);
        }
        $.history.add( current_link+"#"+href, 1); //TODO: need to deal with the initial page load
        // Find target anchor and scroll there

        var target = $('a[name="' + href + '"]');
        if (target.length > 0) {
          var pos = $(target[0]).offset();
          window.scrollTo(pos.left, pos.top);
        }
		//just add to history. we'll let the monitor address bar deal with parsing it

        return false;
    },

// client-side navigation via url fragment (aka "hash").
// #include jquery.history.js

    pagelinkClicked : function(event, AjaxSiteObj) {
        event.preventDefault();
		var target = event.target;
        if(!$(target).is("a")){
            target = event.currentTarget;
        }
		var self = AjaxSiteObj;
        // mimic same origin policy to determine whether or not
        // we should do client-side navigation on this link click.

        var origin = window.location.protocol + '//' + window.location.host;
        ////console.log("origin");
        ////console.log(origin);
        // Allow "fast" links for BUTTON or A tags.  If it is a BUTTON tag
        // then it is assumed that that button contains an A tag, which is where
        // the link is grabbed from.  SideNote: We need to put the class="fast" on
        // the BUTTON tag because the A tag's onclick will not execute when the A
        // tag resides within a BUTTON tag and the button is clicked (FF3).  Using
        // an A tag within the BUTTON tag is beneficial because it will make 
        // relative links absolute when accessed via the A tag's href attribute
        // (although, not true in IE7)0
        /*
        var tagName = this.tagName.toUpperCase();
        var url     = tagName == "BUTTON" ? $( 'a', this )[0].href
            : tagName == "A"      ? this.href
            :                       ""
            ;
        */
        //alert(target);
        //console.log(event);
        var url = $(target).attr("href");

        // A tag within BUTTON tag in IE7 will not make links absolute
        if( url.indexOf( '/' ) == 0 ) { //check if the path is absolute
            url = origin + url;
        }

        if (0 == url.indexOf(origin)) {

            /*
            if (self.gBlockAnimateLinks) //prevent animation
                return false;
            */

            var url_relative = url.substr(origin.length);
			//alert("page click url relative");
            //console.log(url_relative) ;
            //console.log("history current");
            //console.log($.history.getCurrent());

            // HACK: short-circuit animated link if it matches current url - // 2011-08-08: GSDSheet and GSDField is handling this - howard
            // jquery.history will not fire an event otherwise, and gBlockAnimateLinks
            // will end up stuck in the on position
            if (url_relative == $.history.getCurrent()){
                //self.GSDSheet_obj.show();//TODO
                //self.GSDField_obj.show();
                return false;
            }

            // block animated links; cleared when transition is finished
            self.gBlockAnimateLinks = true;
			//console.log("addingto history");
            $.history.add(url_relative);
            

            // track new location with google analytics
            if (typeof(pageTracker) != 'undefined' && pageTracker != null)
                pageTracker._trackPageview(url_relative);

            return false;
        }
        return false;
        //return true;
    },
    gotoPage : function(link) {
		var self = this;
        // mimic same origin policy to determine whether or not
        // we should do client-side navigation on this link click.

        var origin = window.location.protocol + '//' + window.location.host;
        var url = link;

        // A tag within BUTTON tag in IE7 will not make links absolute
        if( url.indexOf( '/' ) == 0 ) { //check if the path is absolute
            url = origin + url;
        }

        if (0 == url.indexOf(origin)) {

            /*
            if (self.gBlockAnimateLinks) //prevent animation
                return false;
            */

            var url_relative = url.substr(origin.length);
			//alert("page click url relative");
            //console.log(url_relative) ;
            //console.log("history current");
            //console.log($.history.getCurrent());

            // HACK: short-circuit animated link if it matches current url -
            // jquery.history will not fire an event otherwise, and gBlockAnimateLinks
            // will end up stuck in the on position
            if (url_relative == $.history.getCurrent()){
                self.GSDSheet_obj.show();//TODO
                self.GSDField_obj.show();
                return false;
            }

            // block animated links; cleared when transition is finished
            self.gBlockAnimateLinks = true;
			//console.log("addingto history");
            $.history.add(url_relative);
            

            // track new location with google analytics
            if (typeof(pageTracker) != 'undefined' && pageTracker != null)
                pageTracker._trackPageview(url_relative);

            return false;
        }
        return false;
        //return true;
    },

    monitorAddressBar : function( ) {
        var self = this;
        // initially, set current page to base uri, ignoring any url fragment.
        // but see [1] below.

        self.gCurrPagePath = self.currentBasePath();
    
        //$.history.add("/", true);
        
        
        // event: programmatic history changes ($.history.add)

        $(window).historyadd(function(e, currentHash, previousHash) {
                self.addressBarChanged( previousHash, currentHash );
                });

        // event: browser history changes (back & forward buttons)

        $(window).history(function(e, currentHash, previousHash) {
                self.addressBarChanged( previousHash, currentHash );
                });

        // [1] initially, if there is a fragment and it doesn't match the
        // base uri path, transition to the page given by the fragment.
        // NOTE: this code only takes effect if gFragmentRedirects is false.

        var hash = $.history.getCurrent();

        if (hash && self.gCurrPagePath != hash) {
            self.addressBarChanged( self.gCurrPagePath, hash);
        }
    },

    addressBarChanged: function(oldPagePath, newPagePath ) {
        var self = this;
		//alert("page changing");
        // If it's a named anchor hash like #foo, the browser has scrolled now.
        // Restore the old hash without firing another event. FIXME: this has
        // the side effect of leaving #foo in the history, preventing browser back.
        //console.log("address bar changes:: oldpath:", oldPagePath,"new page:", newPagePath);

        if (newPagePath.length > 0 && newPagePath.indexOf('/') < 0) {
            console.log("not a path", newPagePath.indexOf('/'));
            var maskevent = 1;
            $.history.add(self.gCurrPagePath, maskevent);
            return;
        }

        if (oldPagePath == '' || oldPagePath == '#') {
            //oldPagePath = self.currentBasePath();    
            oldPagePath = "/index.html";
        }

        if (newPagePath == '' || newPagePath == '#') {
            newPagePath = self.currentBasePath();    
        }

        self.gPrevPagePath = oldPagePath;
        self.gCurrPagePath = newPagePath;

        /*
        var oldFolder = siteFolder( self.gPrevPagePath );
        var newFolder = siteFolder( self.gCurrPagePath );

        //gAnimatingLink = true; //used to check if it's still animation, not necessary
    
        if ( newFolder == 'util' ) {
            showUtilityPage( 1000, self.gCurrPagePath );
        }
        else if ( newFolder == 'intro' ) {
            showIntro( 1000 );
        }
        else {
            // dynamically transition to regular content page
            $( '#pages #'+newFolder ).each(
                    function() {
                    showPage( 1000, $( this ), self.gCurrPagePath );
                    }
                    );
        }
        */
		//do scrollTo here if the path hasn't changed, else let pageChange deal with it.
		//strip hashes and ?
		
		var temp_newPage = self._breakoutLinkParts(newPagePath);
		var temp_oldPage = self._breakoutLinkParts(oldPagePath);
		//console.log(temp_newPage);
        
		if(typeof $temp_oldPage != "undefined" &&  (temp_newPage.path == temp_oldPage.path && temp_newPage.fragment != "") ){
			//console.log("new page is still current page, scrollto");
			//do scrollto since it's the current page
			var target = $('a[name="' + temp_newPage.fragment + '"]');

			if (target.length > 0) {
			  var pos = $(target[0]).offset();
			  window.scrollTo(pos.left, pos.top);
			}
		}
		else{ //* newPagePath may or maynot havea  query, 
			//* we need to retrieve a new page
			self.getPageContent(newPagePath); 
		}
    },




// get the current effective uri path -
// a path in the fragment overrides any uri path component. 

    currentPagePath : function(){
        var self = this;
        var path = self.currentFragmentPath();
		//console.log("path");
		//console.log(path);
        if (path != null)
            return path;

        return self.currentBasePath();
    },


// get the absolute path component from the current url

    currentBasePath : function(){
        var self = this;
        var loc = window.location;

        // extract uri path component + query string

        if (loc.search.length > 0)
            return loc.pathname + loc.search;

        return loc.pathname;
    },


// get fragment component ('#' and beyond) from the current url

    currentFragmentPath : function() {
        var self = this;
        var fragment = window.location.hash;

        if (fragment.indexOf('#') == 0)
            fragment = fragment.substr(1);

        if (fragment.length > 0)
            return fragment;

        return null;
    },
	getPageContent: function( link,suppress_hide, callback ){
		var self = this;
		/*
		var path = getPageURL( link );
		path     = path.replace( /\.html(\?.*)?$/, '.xml$1' );
		
		preparePageForContent( jqPage );
		*/
		//format link, add the ajax parameter
		
		var link_parts = self._breakoutLinkParts(link);
		var original_query = link_parts.query;
        var original_link = {
                path : link_parts.path,
                query : original_query, 
                query_hash : link_parts.query_hash,
                fragment : link_parts.fragment
        };
        //* run checkContent to see if we need to load
        var checkContent_sheet = 0;
        var checkContent_field = 0;
        checkContent_sheet = self.GSDSheet_obj.checkContent(original_link);
        if(checkContent_sheet){
            //* reopen sheet
            self.refreshBreadcrumb("reopen-sheet");
        }
        checkContent_field = self.GSDField_obj.checkContent(original_link);
        if(checkContent_field){
            //* reopen field
            self.refreshBreadcrumb("close-sheet");
        }

    //checkContent : function(query){ 
        //* we only load a sheet or field during every ajax call, not both
	    if(checkContent_sheet || checkContent_field){return;} //* we already did what we needed for page load

		if(link_parts.query == ""){
			link_parts.query = "ajax=1";
		}
		else{
			link_parts.query += "&ajax=1";
		}
		var successCallback = callback;
		if( successCallback ==  null ) {
			successCallback = function (html) { 
                console.log(html);
                //Content was grabbed, hit google analytics and tell it that
                //
                if(typeof pageTracker != "undefined" && pageTracker != null){
                    pageTracker._trackPageview(link);
                }
				//pageChange( html, link.query   ); //let GSDSheet deal with the query
				self.pageChange(html, original_link, suppress_hide);
                    //* note: for we probably want GSDSheet to re-href the sheetclose button
				self.initializeLinks();//reinit links after pageChange
				//* After the page loads, if there's a scrollto, do it
				if(link_parts.fragment != ""){
						
					var target = $('a[name="' + link_parts.fragment + '"]');

					if (target.length > 0) {
					  var pos = $(target[0]).offset();
					  window.scrollTo(pos.left, pos.top);
					}
				}
                var parentifier_url = $(html).find("#parentifier-link").attr("href");
                //* clean up parentifier
                if(typeof parentifier_url != 'undefined'){
                    var parentifier_hash = self._breakoutLinkParts(parentifier_url);
                    parentifier_url = parentifier_hash.path;
                }

                if(typeof parentifier_url != 'undefined' && initializer_count == 0 && self.GSDField_obj.currentLink.path == "/index.html" && !(parentifier_url == "/index.html") ){
                    self.getPageContent(parentifier_url, 1); //* load semi-correct field dynamically, but we don't include it in the history
                }else if(initializer_count == 0){
                    //* no field to load, so we finally load the homepage
                    $("#list-content").show();
                    self.GSDSheet_obj.initialize(); 
                    self.GSDField_obj.initialize();
                    $("#ajax-loader").fadeOut();
                }
                else{
                    $("#ajax-loader").fadeOut();
                }
                    initializer_count ++;
			}
		}
        if( $("#list-overlay.homepage-feed-override").length > 0 && link_parts.path.indexOf("all-news/feed") > 0){
            //* custom page load for the homepage since the news feed is already on the homepage
            //$("#list-overlay.homepage-feed-override").fadeIn();
            //$("#list-content:not(:visible)").fadeIn();
            //* replace nav title with the newsfeed one
            $("#list-overlay.homepage-feed-override .back-button").click(function(){
                $(".news-feed-btn.toggle").removeClass("active");
            });
            var temp_el = $("<div></div>");
            var temp_sheet = $("#list-overlay.homepage-feed-override").clone();
            successCallback($("<div></div>").append( temp_el.append( temp_sheet ) ).html() );

            $("#navigator-title").replaceWith('<div id="navigator-title"><span class="sheet-tag id_8026-tag">All News</span>: <span class="subtype-tag id_8026-tag">Feed</span></div>');
            self.GSDSheet_obj.currentBreadcrumb = $("#navigator-title").clone();// still have to manually call this since this is not the typical call to successCallback;  
            return;
        }
	    //* show ajax loader
        $("#ajax-loader").fadeIn();
		$.ajax( {
		url      : link_parts.path + "?"+link_parts.query,
		type     : 'GET',
		//type     : 'POST', //shouldn't it be POST? 
		error    : function (res) { 
            //return self.getPageContent('/error.html', callback) 
            //alert(res);
            //console.log(res);
            //console.log(res.responseText);
            //successCallback($(res.responseText));
            var responseText = res.responseText;
            var idx = responseText.indexOf("<!--sheet-handler-->"); //* hacky but necessary for the 404 page
            responseText = responseText.substr(idx+20 );
            idx = responseText.indexOf("<!--sheet-handler-end-->");
            responseText = responseText.substr(0, idx);
            //console.log(responseText);
            
            successCallback(responseText);
            $("#ajax-loader").fadeOut();
            return;
        },
		success  : successCallback
		} );
		
		return true;
	} // getPageContent





}






/*


// OLD CODE FOR REFERENCE

function animateLink(clickable) {

    // Do not animate links in preview mode
    if ($('body').hasClass('preview'))
      return;

    // Allow "fast" links for BUTTON or A tags.  If it is a BUTTON tag
    // then it is assumed that that button contains an A tag, which is where
    // the link is grabbed from.  SideNote: We need to put the class="fast" on
    // the BUTTON tag because the A tag's onclick will not execute when the A
    // tag resides within a BUTTON tag and the button is clicked (FF3).
    var tagName = clickable.tagName.toUpperCase();
    var link    = tagName == "BUTTON" ? $( 'a', clickable )[0]
                : tagName == "A"      ? clickable
                :                       null
                ;

    if ( link == null ) 
      return;

    var origin = window.location.protocol + '//' + window.location.host;
    var path;
    var query = '';
    var fragment = '';

    if ( link.href.indexOf(origin) == 0 )
      path = link.href.substr( origin.length );
    else if ( link.href.indexOf("/") == 0 )
      path = link.href;

    // Link must be site-relative or same origin to animate
    if ( path == null ) 
      return;

    // Further uri parsing - separate path, query and fragment
    var i;

    if ( (i = path.indexOf('#')) >= 0 ) {
      fragment = path.substr( i+1 );
      path = path.substr( 0, i );
    }

    if ( (i = path.indexOf('?')) >= 0 ) {
      query = path.substr( i+1 );
      path = path.substr( 0, i );
    }

    // Link with path in fragment, e.g. #/home.html - use fragment as target
    if ( fragment.indexOf('/') == 0 ) {
      path = fragment;
      fragment = '';
    }

    // Site-relative link that's not in sitemap - don't animate.
    // The most common case is an uninitialized ruby link ("/content/").
    if ( siteFolder(path) == null )
      return;

    // Of the shop section pages, only /shop/index.html can be animated to
    if ( path.indexOf('/shop/') == 0 && path != '/shop/' && path != '/shop/index.html' )
      return;

    // Conversely, if we're in the shop section but not /shop/index.html,
    // nothing should animate
    var cpath = currentPagePath();
    if ( cpath.indexOf('/shop/') == 0 && cpath != '/shop/' && cpath != '/shop/index.html' )
      return;

    // Can't animate to members area links from non-ssl pages - members area is requiressl
    if ( path.indexOf('/members-area/') == 0 && window.location.protocol != 'https:' )
      return;

    // Compute file extension
    var parts = path.split('/');
    var last = parts.length > 0 ? parts.pop() : '';
    parts = last.split('.');
    last = parts.length > 0 ? parts.pop() : '';

    // Exclude links with non-.html file extensions from animation
    if ( last != '' && last != 'html')
      return;

    var onclick = pagelinkClicked;

    // If a link references a named anchor on this page, simulate browser scroll.
    // If it references a named anchor on another page, don't animate at all.
    if ( fragment.length > 0 )
      if ( path == cpath )
        onclick = namedAnchorClicked;
      else
        return;

    // If a link is a "back" button, it should simulate a browser back button click
    if ($(clickable).hasClass('back-button'))
      onclick = backlinkClicked;

    $(clickable).unbind( 'click' );
    $(clickable).unbind( 'keypress' );
    $(clickable).click( onclick );
    $(clickable).keypress( onclick );
}

// Simulate a browser back button click

function backlinkClicked() {

    var previous = $.history.getPrevious();

    if (previous == null)
      window.history.go(-1);
    else
      $.history.add(previous);

    return false;
}

// Simulate browser scroll to named anchor

function namedAnchorClicked() {

    // Clicked link must reference named anchor on current page

    var origin = window.location.protocol + '//' + window.location.host;
    var cpath = origin + currentPagePath();
    var href = this.href;

    if (href.indexOf(cpath+'#') != 0)
      return true;

    href = href.substr(cpath.length+1);

    // Find target anchor and scroll there

    var target = $('a[name="' + href + '"]');

    if (target.length > 0) {
      var pos = $(target[0]).offset();
      window.scrollTo(pos.left, pos.top);
    }

    return false;
}

// client-side navigation via url fragment (aka "hash").
// #include jquery.history.js

function pagelinkClicked() {

    // mimic same origin policy to determine whether or not
    // we should do client-side navigation on this link click.

    var origin = window.location.protocol + '//' + window.location.host;

    // Allow "fast" links for BUTTON or A tags.  If it is a BUTTON tag
    // then it is assumed that that button contains an A tag, which is where
    // the link is grabbed from.  SideNote: We need to put the class="fast" on
    // the BUTTON tag because the A tag's onclick will not execute when the A
    // tag resides within a BUTTON tag and the button is clicked (FF3).  Using
    // an A tag within the BUTTON tag is beneficial because it will make 
    // relative links absolute when accessed via the A tag's href attribute
    // (although, not true in IE7)0
    var tagName = this.tagName.toUpperCase();
    var url     = tagName == "BUTTON" ? $( 'a', this )[0].href
                : tagName == "A"      ? this.href
                :                       ""
                ;

    // A tag within BUTTON tag in IE7 will not make links absolute
    if( url.indexOf( '/' ) == 0 ) {
	url = origin + url;
    }

    if (0 == url.indexOf(origin)) {

        if (gBlockAnimateLinks)
          return false;
 
        var url_relative = url.substr(origin.length);

        // HACK: short-circuit animated link if it matches current url -
        // jquery.history will not fire an event otherwise, and gBlockAnimateLinks
        // will end up stuck in the on position

        if (url_relative == $.history.getCurrent())
          return false;

        // block animated links; cleared when transition is finished
        gBlockAnimateLinks = true;

        $.history.add(url_relative);

        // track new location with google analytics
        if (typeof(pageTracker) != 'undefined')
          pageTracker._trackPageview(url_relative);

        return false;
    }

    return true;
}

function monitorAddressBar() {

  // initially, set current page to base uri, ignoring any url fragment.
  // but see [1] below.

  self.gCurrPagePath = currentBasePath();

  // event: programmatic history changes ($.history.add)

  $(window).historyadd(function(e, currentHash, previousHash) {
    addressBarChanged( previousHash, currentHash );
  });

  // event: browser history changes (back & forward buttons)

  $(window).history(function(e, currentHash, previousHash) {
    addressBarChanged( previousHash, currentHash );
  });

  // [1] initially, if there is a fragment and it doesn't match the
  // base uri path, transition to the page given by the fragment.
  // NOTE: this code only takes effect if gFragmentRedirects is false.

  var hash = $.history.getCurrent();

  if (hash && self.gCurrPagePath != hash) {
    addressBarChanged( self.gCurrPagePath, hash );
  }
}

function addressBarChanged( oldPagePath, newPagePath ) {

  if (gAnimatingLink)
    return;

  // If it's a named anchor hash like #foo, the browser has scrolled now.
  // Restore the old hash without firing another event. FIXME: this has
  // the side effect of leaving #foo in the history, preventing browser back.

  if (newPagePath.length > 0 && newPagePath.indexOf('/') < 0) {
    var maskevent = 1;
    $.history.add(self.gCurrPagePath, maskevent);
    return;
  }

  if (oldPagePath == '' || oldPagePath == '#') {
    oldPagePath = currentBasePath();    
  }

  if (newPagePath == '' || newPagePath == '#') {
    newPagePath = currentBasePath();    
  }

  gPrevPagePath = oldPagePath;
  self.gCurrPagePath = newPagePath;

  var oldFolder = siteFolder( gPrevPagePath );
  var newFolder = siteFolder( self.gCurrPagePath );

  gAnimatingLink = true;

  if ($.browser.msie && $.browser.version < 7)
    dehoverizeAll();

  if ( newFolder == 'util' ) {
    showUtilityPage( 1000, self.gCurrPagePath );
  }
  else if ( newFolder == 'intro' ) {
    showIntro( 1000 );
  }
  else {
    // dynamically transition to regular content page
    $( '#pages #'+newFolder ).each(
      function() {
        showPage( 1000, $( this ), self.gCurrPagePath );
      }
    );
  }
}


function getPageContent( link, jqPage, cback )
{
    var path = getPageURL( link );
    path     = path.replace( /\.html(\?.*)?$/, '.xml$1' );
    
    preparePageForContent( jqPage );

    var successCallback = cback;

    if( successCallback ==  null ) 
	successCallback = function (html) { 
	    showPageContent( jqPage, { 'html' : html } );
	}

    $.ajax( {
	url      : "/services/content" + path,
	type     : 'GET',
	error    : function (res) { return getPageContent('/error.html', jqPage, cback) },
	success  : successCallback
    } );

    return true;
} // getPageContent




*/

