Page Menu
Home
Code
Search
Configure Global Search
Log In
Files
F884657
back.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
13 KB
Subscribers
None
back.js
View Options
if
(
!
dojo
.
_hasResource
[
"dojo.back"
]){
//_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo
.
_hasResource
[
"dojo.back"
]
=
true
;
dojo
.
provide
(
"dojo.back"
);
(
function
()
{
var
back
=
dojo
.
back
;
// everyone deals with encoding the hash slightly differently
function
getHash
(){
var
h
=
window
.
location
.
hash
;
if
(
h
.
charAt
(
0
)
==
"#"
)
{
h
=
h
.
substring
(
1
);
}
return
dojo
.
isMozilla
?
h
:
decodeURIComponent
(
h
);
}
function
setHash
(
h
){
if
(
!
h
)
{
h
=
""
};
window
.
location
.
hash
=
encodeURIComponent
(
h
);
historyCounter
=
history
.
length
;
}
// if we're in the test for these methods, expose them on dojo.back. ok'd with alex.
if
(
dojo
.
exists
(
"tests.back-hash"
)){
back
.
getHash
=
getHash
;
back
.
setHash
=
setHash
;
}
var
initialHref
=
(
typeof
(
window
)
!==
"undefined"
)
?
window
.
location
.
href
:
""
;
var
initialHash
=
(
typeof
(
window
)
!==
"undefined"
)
?
getHash
()
:
""
;
var
initialState
=
null
;
var
locationTimer
=
null
;
var
bookmarkAnchor
=
null
;
var
historyIframe
=
null
;
var
forwardStack
=
[];
var
historyStack
=
[];
var
moveForward
=
false
;
var
changingUrl
=
false
;
var
historyCounter
;
function
handleBackButton
(){
//summary: private method. Do not call this directly.
//The "current" page is always at the top of the history stack.
//console.debug("handlingBackButton");
var
current
=
historyStack
.
pop
();
if
(
!
current
){
return
;
}
var
last
=
historyStack
[
historyStack
.
length
-
1
];
if
(
!
last
&&
historyStack
.
length
==
0
){
last
=
initialState
;
}
if
(
last
){
if
(
last
.
kwArgs
[
"back"
]){
last
.
kwArgs
[
"back"
]();
}
else
if
(
last
.
kwArgs
[
"backButton"
]){
last
.
kwArgs
[
"backButton"
]();
}
else
if
(
last
.
kwArgs
[
"handle"
]){
last
.
kwArgs
.
handle
(
"back"
);
}
}
forwardStack
.
push
(
current
);
//console.debug("done handling back");
}
back
.
goBack
=
handleBackButton
;
function
handleForwardButton
(){
//summary: private method. Do not call this directly.
//console.debug("handling forward");
var
last
=
forwardStack
.
pop
();
if
(
!
last
){
return
;
}
if
(
last
.
kwArgs
[
"forward"
]){
last
.
kwArgs
.
forward
();
}
else
if
(
last
.
kwArgs
[
"forwardButton"
]){
last
.
kwArgs
.
forwardButton
();
}
else
if
(
last
.
kwArgs
[
"handle"
]){
last
.
kwArgs
.
handle
(
"forward"
);
}
historyStack
.
push
(
last
);
//console.debug("done handling forward");
}
back
.
goForward
=
handleForwardButton
;
function
createState
(
url
,
args
,
hash
){
//summary: private method. Do not call this directly.
return
{
"url"
:
url
,
"kwArgs"
:
args
,
"urlHash"
:
hash
};
//Object
}
function
getUrlQuery
(
url
){
//summary: private method. Do not call this directly.
var
segments
=
url
.
split
(
"?"
);
if
(
segments
.
length
<
2
){
return
null
;
//null
}
else
{
return
segments
[
1
];
//String
}
}
function
loadIframeHistory
(){
//summary: private method. Do not call this directly.
var
url
=
(
djConfig
[
"dojoIframeHistoryUrl"
]
||
dojo
.
moduleUrl
(
"dojo"
,
"resources/iframe_history.html"
))
+
"?"
+
(
new
Date
()).
getTime
();
moveForward
=
true
;
if
(
historyIframe
)
{
(
dojo
.
isSafari
)
?
historyIframe
.
location
=
url
:
window
.
frames
[
historyIframe
.
name
].
location
=
url
;
}
else
{
//console.warn("dojo.back: Not initialised. You need to call dojo.back.init() from a <script> block that lives inside the <body> tag.");
}
return
url
;
//String
}
function
checkLocation
(){
//console.debug("checking url");
if
(
!
changingUrl
){
var
hsl
=
historyStack
.
length
;
var
hash
=
getHash
();
if
((
hash
===
initialHash
||
window
.
location
.
href
==
initialHref
)
&&
(
hsl
==
1
)){
// FIXME: could this ever be a forward button?
// we can't clear it because we still need to check for forwards. Ugg.
// clearInterval(this.locationTimer);
handleBackButton
();
return
;
}
// first check to see if we could have gone forward. We always halt on
// a no-hash item.
if
(
forwardStack
.
length
>
0
){
if
(
forwardStack
[
forwardStack
.
length
-
1
].
urlHash
===
hash
){
handleForwardButton
();
return
;
}
}
// ok, that didn't work, try someplace back in the history stack
if
((
hsl
>=
2
)
&&
(
historyStack
[
hsl
-
2
])){
if
(
historyStack
[
hsl
-
2
].
urlHash
===
hash
){
handleBackButton
();
return
;
}
}
if
(
dojo
.
isSafari
&&
dojo
.
isSafari
<
3
){
var
hisLen
=
history
.
length
;
if
(
hisLen
>
historyCounter
)
handleForwardButton
();
else
if
(
hisLen
<
historyCounter
)
handleBackButton
();
historyCounter
=
hisLen
;
}
}
//console.debug("done checking");
};
back
.
init
=
function
(){
//summary: Initializes the undo stack. This must be called from a <script>
// block that lives inside the <body> tag to prevent bugs on IE.
if
(
dojo
.
byId
(
"dj_history"
)){
return
;
}
// prevent reinit
var
src
=
djConfig
[
"dojoIframeHistoryUrl"
]
||
dojo
.
moduleUrl
(
"dojo"
,
"resources/iframe_history.html"
);
document
.
write
(
'<iframe style="border:0;width:1px;height:1px;position:absolute;visibility:hidden;bottom:0;right:0;" name="dj_history" id="dj_history" src="'
+
src
+
'"></iframe>'
);
};
back
.
setInitialState
=
function
(
/*Object*/
args
){
//summary:
// Sets the state object and back callback for the very first page
// that is loaded.
//description:
// It is recommended that you call this method as part of an event
// listener that is registered via dojo.addOnLoad().
//args: Object
// See the addToHistory() function for the list of valid args properties.
initialState
=
createState
(
initialHref
,
args
,
initialHash
);
};
//FIXME: Make these doc comments not be awful. At least they're not wrong.
//FIXME: Would like to support arbitrary back/forward jumps. Have to rework iframeLoaded among other things.
//FIXME: is there a slight race condition in moz using change URL with the timer check and when
// the hash gets set? I think I have seen a back/forward call in quick succession, but not consistent.
/*=====
dojo.__backArgs = function(kwArgs){
// back: Function?
// A function to be called when this state is reached via the user
// clicking the back button.
// forward: Function?
// Upon return to this state from the "back, forward" combination
// of navigation steps, this function will be called. Somewhat
// analgous to the semantic of an "onRedo" event handler.
// changeUrl: Boolean?|String?
// Boolean indicating whether or not to create a unique hash for
// this state. If a string is passed instead, it is used as the
// hash.
}
=====*/
back
.
addToHistory
=
function
(
/*dojo.__backArgs*/
args
){
// summary:
// adds a state object (args) to the history list.
// description:
// To support getting back button notifications, the object
// argument should implement a function called either "back",
// "backButton", or "handle". The string "back" will be passed as
// the first and only argument to this callback.
//
// To support getting forward button notifications, the object
// argument should implement a function called either "forward",
// "forwardButton", or "handle". The string "forward" will be
// passed as the first and only argument to this callback.
//
// If you want the browser location string to change, define "changeUrl" on the object. If the
// value of "changeUrl" is true, then a unique number will be appended to the URL as a fragment
// identifier (http://some.domain.com/path#uniquenumber). If it is any other value that does
// not evaluate to false, that value will be used as the fragment identifier. For example,
// if changeUrl: 'page1', then the URL will look like: http://some.domain.com/path#page1
//
// example:
// | dojo.back.addToHistory({
// | back: function(){ console.debug('back pressed'); },
// | forward: function(){ console.debug('forward pressed'); },
// | changeUrl: true
// | });
// BROWSER NOTES:
// Safari 1.2:
// back button "works" fine, however it's not possible to actually
// DETECT that you've moved backwards by inspecting window.location.
// Unless there is some other means of locating.
// FIXME: perhaps we can poll on history.length?
// Safari 2.0.3+ (and probably 1.3.2+):
// works fine, except when changeUrl is used. When changeUrl is used,
// Safari jumps all the way back to whatever page was shown before
// the page that uses dojo.undo.browser support.
// IE 5.5 SP2:
// back button behavior is macro. It does not move back to the
// previous hash value, but to the last full page load. This suggests
// that the iframe is the correct way to capture the back button in
// these cases.
// Don't test this page using local disk for MSIE. MSIE will not create
// a history list for iframe_history.html if served from a file: URL.
// The XML served back from the XHR tests will also not be properly
// created if served from local disk. Serve the test pages from a web
// server to test in that browser.
// IE 6.0:
// same behavior as IE 5.5 SP2
// Firefox 1.0+:
// the back button will return us to the previous hash on the same
// page, thereby not requiring an iframe hack, although we do then
// need to run a timer to detect inter-page movement.
//If addToHistory is called, then that means we prune the
//forward stack -- the user went back, then wanted to
//start a new forward path.
forwardStack
=
[];
var
hash
=
null
;
var
url
=
null
;
if
(
!
historyIframe
){
if
(
djConfig
[
"useXDomain"
]
&&
!
djConfig
[
"dojoIframeHistoryUrl"
]){
console
.
debug
(
"dojo.back: When using cross-domain Dojo builds,"
+
" please save iframe_history.html to your domain and set djConfig.dojoIframeHistoryUrl"
+
" to the path on your domain to iframe_history.html"
);
}
historyIframe
=
window
.
frames
[
"dj_history"
];
}
if
(
!
bookmarkAnchor
){
bookmarkAnchor
=
document
.
createElement
(
"a"
);
dojo
.
body
().
appendChild
(
bookmarkAnchor
);
bookmarkAnchor
.
style
.
display
=
"none"
;
}
if
(
args
[
"changeUrl"
]){
hash
=
""
+
((
args
[
"changeUrl"
]
!==
true
)
?
args
[
"changeUrl"
]
:
(
new
Date
()).
getTime
());
//If the current hash matches the new one, just replace the history object with
//this new one. It doesn't make sense to track different state objects for the same
//logical URL. This matches the browser behavior of only putting in one history
//item no matter how many times you click on the same #hash link, at least in Firefox
//and Safari, and there is no reliable way in those browsers to know if a #hash link
//has been clicked on multiple times. So making this the standard behavior in all browsers
//so that dojo.back's behavior is the same in all browsers.
if
(
historyStack
.
length
==
0
&&
initialState
.
urlHash
==
hash
){
initialState
=
createState
(
url
,
args
,
hash
);
return
;
}
else
if
(
historyStack
.
length
>
0
&&
historyStack
[
historyStack
.
length
-
1
].
urlHash
==
hash
){
historyStack
[
historyStack
.
length
-
1
]
=
createState
(
url
,
args
,
hash
);
return
;
}
changingUrl
=
true
;
setTimeout
(
function
()
{
setHash
(
hash
);
changingUrl
=
false
;
},
1
);
bookmarkAnchor
.
href
=
hash
;
if
(
dojo
.
isIE
){
url
=
loadIframeHistory
();
var
oldCB
=
args
[
"back"
]
||
args
[
"backButton"
]
||
args
[
"handle"
];
//The function takes handleName as a parameter, in case the
//callback we are overriding was "handle". In that case,
//we will need to pass the handle name to handle.
var
tcb
=
function
(
handleName
){
if
(
getHash
()
!=
""
){
setTimeout
(
function
()
{
setHash
(
hash
);
},
1
);
}
//Use apply to set "this" to args, and to try to avoid memory leaks.
oldCB
.
apply
(
this
,
[
handleName
]);
};
//Set interceptor function in the right place.
if
(
args
[
"back"
]){
args
.
back
=
tcb
;
}
else
if
(
args
[
"backButton"
]){
args
.
backButton
=
tcb
;
}
else
if
(
args
[
"handle"
]){
args
.
handle
=
tcb
;
}
var
oldFW
=
args
[
"forward"
]
||
args
[
"forwardButton"
]
||
args
[
"handle"
];
//The function takes handleName as a parameter, in case the
//callback we are overriding was "handle". In that case,
//we will need to pass the handle name to handle.
var
tfw
=
function
(
handleName
){
if
(
getHash
()
!=
""
){
setHash
(
hash
);
}
if
(
oldFW
){
// we might not actually have one
//Use apply to set "this" to args, and to try to avoid memory leaks.
oldFW
.
apply
(
this
,
[
handleName
]);
}
};
//Set interceptor function in the right place.
if
(
args
[
"forward"
]){
args
.
forward
=
tfw
;
}
else
if
(
args
[
"forwardButton"
]){
args
.
forwardButton
=
tfw
;
}
else
if
(
args
[
"handle"
]){
args
.
handle
=
tfw
;
}
}
else
if
(
!
dojo
.
isIE
){
// start the timer
if
(
!
locationTimer
){
locationTimer
=
setInterval
(
checkLocation
,
200
);
}
}
}
else
{
url
=
loadIframeHistory
();
}
historyStack
.
push
(
createState
(
url
,
args
,
hash
));
};
back
.
_iframeLoaded
=
function
(
evt
,
ifrLoc
){
//summary:
// private method. Do not call this directly.
var
query
=
getUrlQuery
(
ifrLoc
.
href
);
if
(
query
==
null
){
// alert("iframeLoaded");
// we hit the end of the history, so we should go back
if
(
historyStack
.
length
==
1
){
handleBackButton
();
}
return
;
}
if
(
moveForward
){
// we were expecting it, so it's not either a forward or backward movement
moveForward
=
false
;
return
;
}
//Check the back stack first, since it is more likely.
//Note that only one step back or forward is supported.
if
(
historyStack
.
length
>=
2
&&
query
==
getUrlQuery
(
historyStack
[
historyStack
.
length
-
2
].
url
)){
handleBackButton
();
}
else
if
(
forwardStack
.
length
>
0
&&
query
==
getUrlQuery
(
forwardStack
[
forwardStack
.
length
-
1
].
url
)){
handleForwardButton
();
}
};
})();
}
File Metadata
Details
Attached
Mime Type
text/html
Expires
Sun, Apr 6, 10:53 (2 w, 13 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24559
Default Alt Text
back.js (13 KB)
Attached To
rZEDHG ZedLegacy
Event Timeline
Log In to Comment