initial commit
[CPE_learningsite] / CPEFlex / EngagementPod / html-template / history / history.js
1 BrowserHistoryUtils = {
2     addEvent: function(elm, evType, fn, useCapture) {
3         useCapture = useCapture || false;
4         if (elm.addEventListener) {
5             elm.addEventListener(evType, fn, useCapture);
6             return true;
7         }
8         else if (elm.attachEvent) {
9             var r = elm.attachEvent('on' + evType, fn);
10             return r;
11         }
12         else {
13             elm['on' + evType] = fn;
14         }
15     }
16 }
17
18 BrowserHistory = (function() {
19     // type of browser
20     var browser = {
21         ie: false, 
22         firefox: false, 
23         safari: false, 
24         opera: false, 
25         version: -1
26     };
27
28     // if setDefaultURL has been called, our first clue
29     // that the SWF is ready and listening
30     //var swfReady = false;
31
32     // the URL we'll send to the SWF once it is ready
33     //var pendingURL = '';
34
35     // Default app state URL to use when no fragment ID present
36     var defaultHash = '';
37
38     // Last-known app state URL
39     var currentHref = document.location.href;
40
41     // Initial URL (used only by IE)
42     var initialHref = document.location.href;
43
44     // Initial URL (used only by IE)
45     var initialHash = document.location.hash;
46
47     // History frame source URL prefix (used only by IE)
48     var historyFrameSourcePrefix = 'history/historyFrame.html?';
49
50     // History maintenance (used only by Safari)
51     var currentHistoryLength = -1;
52
53     var historyHash = [];
54
55     var initialState = createState(initialHref, initialHref + '#' + initialHash, initialHash);
56
57     var backStack = [];
58     var forwardStack = [];
59
60     var currentObjectId = null;
61
62     //UserAgent detection
63     var useragent = navigator.userAgent.toLowerCase();
64
65     if (useragent.indexOf("opera") != -1) {
66         browser.opera = true;
67     } else if (useragent.indexOf("msie") != -1) {
68         browser.ie = true;
69         browser.version = parseFloat(useragent.substring(useragent.indexOf('msie') + 4));
70     } else if (useragent.indexOf("safari") != -1) {
71         browser.safari = true;
72         browser.version = parseFloat(useragent.substring(useragent.indexOf('safari') + 7));
73     } else if (useragent.indexOf("gecko") != -1) {
74         browser.firefox = true;
75     }
76
77     if (browser.ie == true && browser.version == 7) {
78         window["_ie_firstload"] = false;
79     }
80
81     // Accessor functions for obtaining specific elements of the page.
82     function getHistoryFrame()
83     {
84         return document.getElementById('ie_historyFrame');
85     }
86
87     function getAnchorElement()
88     {
89         return document.getElementById('firefox_anchorDiv');
90     }
91
92     function getFormElement()
93     {
94         return document.getElementById('safari_formDiv');
95     }
96
97     function getRememberElement()
98     {
99         return document.getElementById("safari_remember_field");
100     }
101
102     // Get the Flash player object for performing ExternalInterface callbacks.
103     // Updated for changes to SWFObject2.
104     function getPlayer(id) {
105                 if (id && document.getElementById(id)) {
106                         var r = document.getElementById(id);
107                         if (typeof r.SetVariable != "undefined") {
108                                 return r;
109                         }
110                         else {
111                                 var o = r.getElementsByTagName("object");
112                                 var e = r.getElementsByTagName("embed");
113                                 if (o.length > 0 && typeof o[0].SetVariable != "undefined") {
114                                         return o[0];
115                                 }
116                                 else if (e.length > 0 && typeof e[0].SetVariable != "undefined") {
117                                         return e[0];
118                                 }
119                         }
120                 }
121                 else {
122                         var o = document.getElementsByTagName("object");
123                         var e = document.getElementsByTagName("embed");
124                         if (e.length > 0 && typeof e[0].SetVariable != "undefined") {
125                                 return e[0];
126                         }
127                         else if (o.length > 0 && typeof o[0].SetVariable != "undefined") {
128                                 return o[0];
129                         }
130                         else if (o.length > 1 && typeof o[1].SetVariable != "undefined") {
131                                 return o[1];
132                         }
133                 }
134                 return undefined;
135         }
136     
137     function getPlayers() {
138         var players = [];
139         if (players.length == 0) {
140             var tmp = document.getElementsByTagName('object');
141             players = tmp;
142         }
143         
144         if (players.length == 0 || players[0].object == null) {
145             var tmp = document.getElementsByTagName('embed');
146             players = tmp;
147         }
148         return players;
149     }
150
151         function getIframeHash() {
152                 var doc = getHistoryFrame().contentWindow.document;
153                 var hash = String(doc.location.search);
154                 if (hash.length == 1 && hash.charAt(0) == "?") {
155                         hash = "";
156                 }
157                 else if (hash.length >= 2 && hash.charAt(0) == "?") {
158                         hash = hash.substring(1);
159                 }
160                 return hash;
161         }
162
163     /* Get the current location hash excluding the '#' symbol. */
164     function getHash() {
165        // It would be nice if we could use document.location.hash here,
166        // but it's faulty sometimes.
167        var idx = document.location.href.indexOf('#');
168        return (idx >= 0) ? document.location.href.substr(idx+1) : '';
169     }
170
171     /* Get the current location hash excluding the '#' symbol. */
172     function setHash(hash) {
173        // It would be nice if we could use document.location.hash here,
174        // but it's faulty sometimes.
175        if (hash == '') hash = '#'
176        document.location.hash = hash;
177     }
178
179     function createState(baseUrl, newUrl, flexAppUrl) {
180         return { 'baseUrl': baseUrl, 'newUrl': newUrl, 'flexAppUrl': flexAppUrl, 'title': null };
181     }
182
183     /* Add a history entry to the browser.
184      *   baseUrl: the portion of the location prior to the '#'
185      *   newUrl: the entire new URL, including '#' and following fragment
186      *   flexAppUrl: the portion of the location following the '#' only
187      */
188     function addHistoryEntry(baseUrl, newUrl, flexAppUrl) {
189
190         //delete all the history entries
191         forwardStack = [];
192
193         if (browser.ie) {
194             //Check to see if we are being asked to do a navigate for the first
195             //history entry, and if so ignore, because it's coming from the creation
196             //of the history iframe
197             if (flexAppUrl == defaultHash && document.location.href == initialHref && window['_ie_firstload']) {
198                 currentHref = initialHref;
199                 return;
200             }
201             if ((!flexAppUrl || flexAppUrl == defaultHash) && window['_ie_firstload']) {
202                 newUrl = baseUrl + '#' + defaultHash;
203                 flexAppUrl = defaultHash;
204             } else {
205                 // for IE, tell the history frame to go somewhere without a '#'
206                 // in order to get this entry into the browser history.
207                 getHistoryFrame().src = historyFrameSourcePrefix + flexAppUrl;
208             }
209             setHash(flexAppUrl);
210         } else {
211
212             //ADR
213             if (backStack.length == 0 && initialState.flexAppUrl == flexAppUrl) {
214                 initialState = createState(baseUrl, newUrl, flexAppUrl);
215             } else if(backStack.length > 0 && backStack[backStack.length - 1].flexAppUrl == flexAppUrl) {
216                 backStack[backStack.length - 1] = createState(baseUrl, newUrl, flexAppUrl);
217             }
218
219             if (browser.safari) {
220                 // for Safari, submit a form whose action points to the desired URL
221                 if (browser.version <= 419.3) {
222                     var file = window.location.pathname.toString();
223                     file = file.substring(file.lastIndexOf("/")+1);
224                     getFormElement().innerHTML = '<form name="historyForm" action="'+file+'#' + flexAppUrl + '" method="GET"></form>';
225                     //get the current elements and add them to the form
226                     var qs = window.location.search.substring(1);
227                     var qs_arr = qs.split("&");
228                     for (var i = 0; i < qs_arr.length; i++) {
229                         var tmp = qs_arr[i].split("=");
230                         var elem = document.createElement("input");
231                         elem.type = "hidden";
232                         elem.name = tmp[0];
233                         elem.value = tmp[1];
234                         document.forms.historyForm.appendChild(elem);
235                     }
236                     document.forms.historyForm.submit();
237                 } else {
238                     top.location.hash = flexAppUrl;
239                 }
240                 // We also have to maintain the history by hand for Safari
241                 historyHash[history.length] = flexAppUrl;
242                 _storeStates();
243             } else {
244                 // Otherwise, write an anchor into the page and tell the browser to go there
245                 addAnchor(flexAppUrl);
246                 setHash(flexAppUrl);
247             }
248         }
249         backStack.push(createState(baseUrl, newUrl, flexAppUrl));
250     }
251
252     function _storeStates() {
253         if (browser.safari) {
254             getRememberElement().value = historyHash.join(",");
255         }
256     }
257
258     function handleBackButton() {
259         //The "current" page is always at the top of the history stack.
260         var current = backStack.pop();
261         if (!current) { return; }
262         var last = backStack[backStack.length - 1];
263         if (!last && backStack.length == 0){
264             last = initialState;
265         }
266         forwardStack.push(current);
267     }
268
269     function handleForwardButton() {
270         //summary: private method. Do not call this directly.
271
272         var last = forwardStack.pop();
273         if (!last) { return; }
274         backStack.push(last);
275     }
276
277     function handleArbitraryUrl() {
278         //delete all the history entries
279         forwardStack = [];
280     }
281
282     /* Called periodically to poll to see if we need to detect navigation that has occurred */
283     function checkForUrlChange() {
284
285         if (browser.ie) {
286             if (currentHref != document.location.href && currentHref + '#' != document.location.href) {
287                 //This occurs when the user has navigated to a specific URL
288                 //within the app, and didn't use browser back/forward
289                 //IE seems to have a bug where it stops updating the URL it
290                 //shows the end-user at this point, but programatically it
291                 //appears to be correct.  Do a full app reload to get around
292                 //this issue.
293                 if (browser.version < 7) {
294                     currentHref = document.location.href;
295                     document.location.reload();
296                 } else {
297                                         if (getHash() != getIframeHash()) {
298                                                 // this.iframe.src = this.blankURL + hash;
299                                                 var sourceToSet = historyFrameSourcePrefix + getHash();
300                                                 getHistoryFrame().src = sourceToSet;
301                                         }
302                 }
303             }
304         }
305
306         if (browser.safari) {
307             // For Safari, we have to check to see if history.length changed.
308             if (currentHistoryLength >= 0 && history.length != currentHistoryLength) {
309                 //alert("did change: " + history.length + ", " + historyHash.length + "|" + historyHash[history.length] + "|>" + historyHash.join("|"));
310                 var flexAppUrl = getHash();
311                 if (browser.version < 528.16 /* Anything earlier than Safari 4.0 */)
312                 {    
313                     // If it did change and we're running Safari 3.x or earlier, 
314                     // then we have to look the old state up in our hand-maintained 
315                     // array since document.location.hash won't have changed, 
316                     // then call back into BrowserManager.
317                     currentHistoryLength = history.length;
318                     flexAppUrl = historyHash[currentHistoryLength];
319                 }
320
321                 //ADR: to fix multiple
322                 if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
323                     var pl = getPlayers();
324                     for (var i = 0; i < pl.length; i++) {
325                         pl[i].browserURLChange(flexAppUrl);
326                     }
327                 } else {
328                     getPlayer().browserURLChange(flexAppUrl);
329                 }
330                 _storeStates();
331             }
332         }
333         if (browser.firefox) {
334             if (currentHref != document.location.href) {
335                 var bsl = backStack.length;
336
337                 var urlActions = {
338                     back: false, 
339                     forward: false, 
340                     set: false
341                 }
342
343                 if ((window.location.hash == initialHash || window.location.href == initialHref) && (bsl == 1)) {
344                     urlActions.back = true;
345                     // FIXME: could this ever be a forward button?
346                     // we can't clear it because we still need to check for forwards. Ugg.
347                     // clearInterval(this.locationTimer);
348                     handleBackButton();
349                 }
350                 
351                 // first check to see if we could have gone forward. We always halt on
352                 // a no-hash item.
353                 if (forwardStack.length > 0) {
354                     if (forwardStack[forwardStack.length-1].flexAppUrl == getHash()) {
355                         urlActions.forward = true;
356                         handleForwardButton();
357                     }
358                 }
359
360                 // ok, that didn't work, try someplace back in the history stack
361                 if ((bsl >= 2) && (backStack[bsl - 2])) {
362                     if (backStack[bsl - 2].flexAppUrl == getHash()) {
363                         urlActions.back = true;
364                         handleBackButton();
365                     }
366                 }
367                 
368                 if (!urlActions.back && !urlActions.forward) {
369                     var foundInStacks = {
370                         back: -1, 
371                         forward: -1
372                     }
373
374                     for (var i = 0; i < backStack.length; i++) {
375                         if (backStack[i].flexAppUrl == getHash() && i != (bsl - 2)) {
376                             arbitraryUrl = true;
377                             foundInStacks.back = i;
378                         }
379                     }
380                     for (var i = 0; i < forwardStack.length; i++) {
381                         if (forwardStack[i].flexAppUrl == getHash() && i != (bsl - 2)) {
382                             arbitraryUrl = true;
383                             foundInStacks.forward = i;
384                         }
385                     }
386                     handleArbitraryUrl();
387                 }
388
389                 // Firefox changed; do a callback into BrowserManager to tell it.
390                 currentHref = document.location.href;
391                 var flexAppUrl = getHash();
392                 if (flexAppUrl == '') {
393                     //flexAppUrl = defaultHash;
394                 }
395                 //ADR: to fix multiple
396                 if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
397                     var pl = getPlayers();
398                     for (var i = 0; i < pl.length; i++) {
399                         pl[i].browserURLChange(flexAppUrl);
400                     }
401                 } else {
402                     getPlayer().browserURLChange(flexAppUrl);
403                 }
404             }
405         }
406         //setTimeout(checkForUrlChange, 50);
407     }
408
409     /* Write an anchor into the page to legitimize it as a URL for Firefox et al. */
410     function addAnchor(flexAppUrl)
411     {
412        if (document.getElementsByName(flexAppUrl).length == 0) {
413            getAnchorElement().innerHTML += "<a name='" + flexAppUrl + "'>" + flexAppUrl + "</a>";
414        }
415     }
416
417     var _initialize = function () {
418         if (browser.ie)
419         {
420             var scripts = document.getElementsByTagName('script');
421             for (var i = 0, s; s = scripts[i]; i++) {
422                 if (s.src.indexOf("history.js") > -1) {
423                     var iframe_location = (new String(s.src)).replace("history.js", "historyFrame.html");
424                 }
425             }
426             historyFrameSourcePrefix = iframe_location + "?";
427             var src = historyFrameSourcePrefix;
428
429             var iframe = document.createElement("iframe");
430             iframe.id = 'ie_historyFrame';
431             iframe.name = 'ie_historyFrame';
432             //iframe.src = historyFrameSourcePrefix;
433             try {
434                 document.body.appendChild(iframe);
435             } catch(e) {
436                 setTimeout(function() {
437                     document.body.appendChild(iframe);
438                 }, 0);
439             }
440         }
441
442         if (browser.safari)
443         {
444             var rememberDiv = document.createElement("div");
445             rememberDiv.id = 'safari_rememberDiv';
446             document.body.appendChild(rememberDiv);
447             rememberDiv.innerHTML = '<input type="text" id="safari_remember_field" style="width: 500px;">';
448
449             var formDiv = document.createElement("div");
450             formDiv.id = 'safari_formDiv';
451             document.body.appendChild(formDiv);
452
453             var reloader_content = document.createElement('div');
454             reloader_content.id = 'safarireloader';
455             var scripts = document.getElementsByTagName('script');
456             for (var i = 0, s; s = scripts[i]; i++) {
457                 if (s.src.indexOf("history.js") > -1) {
458                     html = (new String(s.src)).replace(".js", ".html");
459                 }
460             }
461             reloader_content.innerHTML = '<iframe id="safarireloader-iframe" src="about:blank" frameborder="no" scrolling="no"></iframe>';
462             document.body.appendChild(reloader_content);
463             reloader_content.style.position = 'absolute';
464             reloader_content.style.left = reloader_content.style.top = '-9999px';
465             iframe = reloader_content.getElementsByTagName('iframe')[0];
466
467             if (document.getElementById("safari_remember_field").value != "" ) {
468                 historyHash = document.getElementById("safari_remember_field").value.split(",");
469             }
470
471         }
472
473         if (browser.firefox)
474         {
475             var anchorDiv = document.createElement("div");
476             anchorDiv.id = 'firefox_anchorDiv';
477             document.body.appendChild(anchorDiv);
478         }
479         
480         //setTimeout(checkForUrlChange, 50);
481     }
482
483     return {
484         historyHash: historyHash, 
485         backStack: function() { return backStack; }, 
486         forwardStack: function() { return forwardStack }, 
487         getPlayer: getPlayer, 
488         initialize: function(src) {
489             _initialize(src);
490         }, 
491         setURL: function(url) {
492             document.location.href = url;
493         }, 
494         getURL: function() {
495             return document.location.href;
496         }, 
497         getTitle: function() {
498             return document.title;
499         }, 
500         setTitle: function(title) {
501             try {
502                 backStack[backStack.length - 1].title = title;
503             } catch(e) { }
504             //if on safari, set the title to be the empty string. 
505             if (browser.safari) {
506                 if (title == "") {
507                     try {
508                     var tmp = window.location.href.toString();
509                     title = tmp.substring((tmp.lastIndexOf("/")+1), tmp.lastIndexOf("#"));
510                     } catch(e) {
511                         title = "";
512                     }
513                 }
514             }
515             document.title = title;
516         }, 
517         setDefaultURL: function(def)
518         {
519             defaultHash = def;
520             def = getHash();
521             //trailing ? is important else an extra frame gets added to the history
522             //when navigating back to the first page.  Alternatively could check
523             //in history frame navigation to compare # and ?.
524             if (browser.ie)
525             {
526                 window['_ie_firstload'] = true;
527                 var sourceToSet = historyFrameSourcePrefix + def;
528                 var func = function() {
529                     getHistoryFrame().src = sourceToSet;
530                     window.location.replace("#" + def);
531                     setInterval(checkForUrlChange, 50);
532                 }
533                 try {
534                     func();
535                 } catch(e) {
536                     window.setTimeout(function() { func(); }, 0);
537                 }
538             }
539
540             if (browser.safari)
541             {
542                 currentHistoryLength = history.length;
543                 if (historyHash.length == 0) {
544                     historyHash[currentHistoryLength] = def;
545                     var newloc = "#" + def;
546                     window.location.replace(newloc);
547                 } else {
548                     //alert(historyHash[historyHash.length-1]);
549                 }
550                 //setHash(def);
551                 setInterval(checkForUrlChange, 50);
552             }
553             
554             
555             if (browser.firefox || browser.opera)
556             {
557                 var reg = new RegExp("#" + def + "$");
558                 if (window.location.toString().match(reg)) {
559                 } else {
560                     var newloc ="#" + def;
561                     window.location.replace(newloc);
562                 }
563                 setInterval(checkForUrlChange, 50);
564                 //setHash(def);
565             }
566
567         }, 
568
569         /* Set the current browser URL; called from inside BrowserManager to propagate
570          * the application state out to the container.
571          */
572         setBrowserURL: function(flexAppUrl, objectId) {
573             if (browser.ie && typeof objectId != "undefined") {
574                 currentObjectId = objectId;
575             }
576            //fromIframe = fromIframe || false;
577            //fromFlex = fromFlex || false;
578            //alert("setBrowserURL: " + flexAppUrl);
579            //flexAppUrl = (flexAppUrl == "") ? defaultHash : flexAppUrl ;
580
581            var pos = document.location.href.indexOf('#');
582            var baseUrl = pos != -1 ? document.location.href.substr(0, pos) : document.location.href;
583            var newUrl = baseUrl + '#' + flexAppUrl;
584
585            if (document.location.href != newUrl && document.location.href + '#' != newUrl) {
586                currentHref = newUrl;
587                addHistoryEntry(baseUrl, newUrl, flexAppUrl);
588                currentHistoryLength = history.length;
589            }
590         }, 
591
592         browserURLChange: function(flexAppUrl) {
593             var objectId = null;
594             if (browser.ie && currentObjectId != null) {
595                 objectId = currentObjectId;
596             }
597             pendingURL = '';
598             
599             if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
600                 var pl = getPlayers();
601                 for (var i = 0; i < pl.length; i++) {
602                     try {
603                         pl[i].browserURLChange(flexAppUrl);
604                     } catch(e) { }
605                 }
606             } else {
607                 try {
608                     getPlayer(objectId).browserURLChange(flexAppUrl);
609                 } catch(e) { }
610             }
611
612             currentObjectId = null;
613         },
614         getUserAgent: function() {
615             return navigator.userAgent;
616         },
617         getPlatform: function() {
618             return navigator.platform;
619         }
620
621     }
622
623 })();
624
625 // Initialization
626
627 // Automated unit testing and other diagnostics
628
629 function setURL(url)
630 {
631     document.location.href = url;
632 }
633
634 function backButton()
635 {
636     history.back();
637 }
638
639 function forwardButton()
640 {
641     history.forward();
642 }
643
644 function goForwardOrBackInHistory(step)
645 {
646     history.go(step);
647 }
648
649 //BrowserHistoryUtils.addEvent(window, "load", function() { BrowserHistory.initialize(); });
650 (function(i) {
651     var u =navigator.userAgent;var e=/*@cc_on!@*/false; 
652     var st = setTimeout;
653     if(/webkit/i.test(u)){
654         st(function(){
655             var dr=document.readyState;
656             if(dr=="loaded"||dr=="complete"){i()}
657             else{st(arguments.callee,10);}},10);
658     } else if((/mozilla/i.test(u)&&!/(compati)/.test(u)) || (/opera/i.test(u))){
659         document.addEventListener("DOMContentLoaded",i,false);
660     } else if(e){
661     (function(){
662         var t=document.createElement('doc:rdy');
663         try{t.doScroll('left');
664             i();t=null;
665         }catch(e){st(arguments.callee,0);}})();
666     } else{
667         window.onload=i;
668     }
669 })( function() {BrowserHistory.initialize();} );