PageRenderTime 43ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/htmlunit-2.8/src/test/resources/libraries/dojo/1.0.2/dojo/back.js

https://gitlab.com/essere.lab.public/qualitas.class-corpus
JavaScript | 389 lines | 214 code | 46 blank | 129 comment | 74 complexity | 11d1702e40e21f64d52e721cc0ec34ce MD5 | raw file
  1. if(!dojo._hasResource["dojo.back"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  2. dojo._hasResource["dojo.back"] = true;
  3. dojo.provide("dojo.back");
  4. (function() {
  5. var back = dojo.back;
  6. // everyone deals with encoding the hash slightly differently
  7. function getHash(){
  8. var h = window.location.hash;
  9. if(h.charAt(0) == "#") { h = h.substring(1); }
  10. return dojo.isMozilla ? h : decodeURIComponent(h);
  11. }
  12. function setHash(h){
  13. if(!h) { h = "" };
  14. window.location.hash = encodeURIComponent(h);
  15. historyCounter = history.length;
  16. }
  17. // if we're in the test for these methods, expose them on dojo.back. ok'd with alex.
  18. if(dojo.exists("tests.back-hash")){
  19. back.getHash = getHash;
  20. back.setHash = setHash;
  21. }
  22. var initialHref = (typeof(window) !== "undefined") ? window.location.href : "";
  23. var initialHash = (typeof(window) !== "undefined") ? getHash() : "";
  24. var initialState = null;
  25. var locationTimer = null;
  26. var bookmarkAnchor = null;
  27. var historyIframe = null;
  28. var forwardStack = [];
  29. var historyStack = [];
  30. var moveForward = false;
  31. var changingUrl = false;
  32. var historyCounter;
  33. function handleBackButton(){
  34. //summary: private method. Do not call this directly.
  35. //The "current" page is always at the top of the history stack.
  36. //console.debug("handlingBackButton");
  37. var current = historyStack.pop();
  38. if(!current){ return; }
  39. var last = historyStack[historyStack.length-1];
  40. if(!last && historyStack.length == 0){
  41. last = initialState;
  42. }
  43. if(last){
  44. if(last.kwArgs["back"]){
  45. last.kwArgs["back"]();
  46. }else if(last.kwArgs["backButton"]){
  47. last.kwArgs["backButton"]();
  48. }else if(last.kwArgs["handle"]){
  49. last.kwArgs.handle("back");
  50. }
  51. }
  52. forwardStack.push(current);
  53. //console.debug("done handling back");
  54. }
  55. back.goBack = handleBackButton;
  56. function handleForwardButton(){
  57. //summary: private method. Do not call this directly.
  58. //console.debug("handling forward");
  59. var last = forwardStack.pop();
  60. if(!last){ return; }
  61. if(last.kwArgs["forward"]){
  62. last.kwArgs.forward();
  63. }else if(last.kwArgs["forwardButton"]){
  64. last.kwArgs.forwardButton();
  65. }else if(last.kwArgs["handle"]){
  66. last.kwArgs.handle("forward");
  67. }
  68. historyStack.push(last);
  69. //console.debug("done handling forward");
  70. }
  71. back.goForward = handleForwardButton;
  72. function createState(url, args, hash){
  73. //summary: private method. Do not call this directly.
  74. return {"url": url, "kwArgs": args, "urlHash": hash}; //Object
  75. }
  76. function getUrlQuery(url){
  77. //summary: private method. Do not call this directly.
  78. var segments = url.split("?");
  79. if (segments.length < 2){
  80. return null; //null
  81. }
  82. else{
  83. return segments[1]; //String
  84. }
  85. }
  86. function loadIframeHistory(){
  87. //summary: private method. Do not call this directly.
  88. var url = (djConfig["dojoIframeHistoryUrl"] || dojo.moduleUrl("dojo", "resources/iframe_history.html")) + "?" + (new Date()).getTime();
  89. moveForward = true;
  90. if (historyIframe) {
  91. (dojo.isSafari) ? historyIframe.location = url : window.frames[historyIframe.name].location = url;
  92. } else {
  93. //console.warn("dojo.back: Not initialised. You need to call dojo.back.init() from a <script> block that lives inside the <body> tag.");
  94. }
  95. return url; //String
  96. }
  97. function checkLocation(){
  98. //console.debug("checking url");
  99. if(!changingUrl){
  100. var hsl = historyStack.length;
  101. var hash = getHash();
  102. if((hash === initialHash||window.location.href == initialHref)&&(hsl == 1)){
  103. // FIXME: could this ever be a forward button?
  104. // we can't clear it because we still need to check for forwards. Ugg.
  105. // clearInterval(this.locationTimer);
  106. handleBackButton();
  107. return;
  108. }
  109. // first check to see if we could have gone forward. We always halt on
  110. // a no-hash item.
  111. if(forwardStack.length > 0){
  112. if(forwardStack[forwardStack.length-1].urlHash === hash){
  113. handleForwardButton();
  114. return;
  115. }
  116. }
  117. // ok, that didn't work, try someplace back in the history stack
  118. if((hsl >= 2)&&(historyStack[hsl-2])){
  119. if(historyStack[hsl-2].urlHash === hash){
  120. handleBackButton();
  121. return;
  122. }
  123. }
  124. if(dojo.isSafari && dojo.isSafari < 3){
  125. var hisLen = history.length;
  126. if(hisLen > historyCounter) handleForwardButton();
  127. else if(hisLen < historyCounter) handleBackButton();
  128. historyCounter = hisLen;
  129. }
  130. }
  131. //console.debug("done checking");
  132. };
  133. back.init = function(){
  134. //summary: Initializes the undo stack. This must be called from a <script>
  135. // block that lives inside the <body> tag to prevent bugs on IE.
  136. if(dojo.byId("dj_history")){ return; } // prevent reinit
  137. var src = djConfig["dojoIframeHistoryUrl"] || dojo.moduleUrl("dojo", "resources/iframe_history.html");
  138. 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>');
  139. };
  140. back.setInitialState = function(/*Object*/args){
  141. //summary:
  142. // Sets the state object and back callback for the very first page
  143. // that is loaded.
  144. //description:
  145. // It is recommended that you call this method as part of an event
  146. // listener that is registered via dojo.addOnLoad().
  147. //args: Object
  148. // See the addToHistory() function for the list of valid args properties.
  149. initialState = createState(initialHref, args, initialHash);
  150. };
  151. //FIXME: Make these doc comments not be awful. At least they're not wrong.
  152. //FIXME: Would like to support arbitrary back/forward jumps. Have to rework iframeLoaded among other things.
  153. //FIXME: is there a slight race condition in moz using change URL with the timer check and when
  154. // the hash gets set? I think I have seen a back/forward call in quick succession, but not consistent.
  155. /*=====
  156. dojo.__backArgs = function(kwArgs){
  157. // back: Function?
  158. // A function to be called when this state is reached via the user
  159. // clicking the back button.
  160. // forward: Function?
  161. // Upon return to this state from the "back, forward" combination
  162. // of navigation steps, this function will be called. Somewhat
  163. // analgous to the semantic of an "onRedo" event handler.
  164. // changeUrl: Boolean?|String?
  165. // Boolean indicating whether or not to create a unique hash for
  166. // this state. If a string is passed instead, it is used as the
  167. // hash.
  168. }
  169. =====*/
  170. back.addToHistory = function(/*dojo.__backArgs*/ args){
  171. // summary:
  172. // adds a state object (args) to the history list.
  173. // description:
  174. // To support getting back button notifications, the object
  175. // argument should implement a function called either "back",
  176. // "backButton", or "handle". The string "back" will be passed as
  177. // the first and only argument to this callback.
  178. //
  179. // To support getting forward button notifications, the object
  180. // argument should implement a function called either "forward",
  181. // "forwardButton", or "handle". The string "forward" will be
  182. // passed as the first and only argument to this callback.
  183. //
  184. // If you want the browser location string to change, define "changeUrl" on the object. If the
  185. // value of "changeUrl" is true, then a unique number will be appended to the URL as a fragment
  186. // identifier (http://some.domain.com/path#uniquenumber). If it is any other value that does
  187. // not evaluate to false, that value will be used as the fragment identifier. For example,
  188. // if changeUrl: 'page1', then the URL will look like: http://some.domain.com/path#page1
  189. //
  190. // example:
  191. // | dojo.back.addToHistory({
  192. // | back: function(){ console.debug('back pressed'); },
  193. // | forward: function(){ console.debug('forward pressed'); },
  194. // | changeUrl: true
  195. // | });
  196. // BROWSER NOTES:
  197. // Safari 1.2:
  198. // back button "works" fine, however it's not possible to actually
  199. // DETECT that you've moved backwards by inspecting window.location.
  200. // Unless there is some other means of locating.
  201. // FIXME: perhaps we can poll on history.length?
  202. // Safari 2.0.3+ (and probably 1.3.2+):
  203. // works fine, except when changeUrl is used. When changeUrl is used,
  204. // Safari jumps all the way back to whatever page was shown before
  205. // the page that uses dojo.undo.browser support.
  206. // IE 5.5 SP2:
  207. // back button behavior is macro. It does not move back to the
  208. // previous hash value, but to the last full page load. This suggests
  209. // that the iframe is the correct way to capture the back button in
  210. // these cases.
  211. // Don't test this page using local disk for MSIE. MSIE will not create
  212. // a history list for iframe_history.html if served from a file: URL.
  213. // The XML served back from the XHR tests will also not be properly
  214. // created if served from local disk. Serve the test pages from a web
  215. // server to test in that browser.
  216. // IE 6.0:
  217. // same behavior as IE 5.5 SP2
  218. // Firefox 1.0+:
  219. // the back button will return us to the previous hash on the same
  220. // page, thereby not requiring an iframe hack, although we do then
  221. // need to run a timer to detect inter-page movement.
  222. //If addToHistory is called, then that means we prune the
  223. //forward stack -- the user went back, then wanted to
  224. //start a new forward path.
  225. forwardStack = [];
  226. var hash = null;
  227. var url = null;
  228. if(!historyIframe){
  229. if(djConfig["useXDomain"] && !djConfig["dojoIframeHistoryUrl"]){
  230. console.debug("dojo.back: When using cross-domain Dojo builds,"
  231. + " please save iframe_history.html to your domain and set djConfig.dojoIframeHistoryUrl"
  232. + " to the path on your domain to iframe_history.html");
  233. }
  234. historyIframe = window.frames["dj_history"];
  235. }
  236. if(!bookmarkAnchor){
  237. bookmarkAnchor = document.createElement("a");
  238. dojo.body().appendChild(bookmarkAnchor);
  239. bookmarkAnchor.style.display = "none";
  240. }
  241. if(args["changeUrl"]){
  242. hash = ""+ ((args["changeUrl"]!==true) ? args["changeUrl"] : (new Date()).getTime());
  243. //If the current hash matches the new one, just replace the history object with
  244. //this new one. It doesn't make sense to track different state objects for the same
  245. //logical URL. This matches the browser behavior of only putting in one history
  246. //item no matter how many times you click on the same #hash link, at least in Firefox
  247. //and Safari, and there is no reliable way in those browsers to know if a #hash link
  248. //has been clicked on multiple times. So making this the standard behavior in all browsers
  249. //so that dojo.back's behavior is the same in all browsers.
  250. if(historyStack.length == 0 && initialState.urlHash == hash){
  251. initialState = createState(url, args, hash);
  252. return;
  253. }else if(historyStack.length > 0 && historyStack[historyStack.length - 1].urlHash == hash){
  254. historyStack[historyStack.length - 1] = createState(url, args, hash);
  255. return;
  256. }
  257. changingUrl = true;
  258. setTimeout(function() {
  259. setHash(hash);
  260. changingUrl = false;
  261. }, 1);
  262. bookmarkAnchor.href = hash;
  263. if(dojo.isIE){
  264. url = loadIframeHistory();
  265. var oldCB = args["back"]||args["backButton"]||args["handle"];
  266. //The function takes handleName as a parameter, in case the
  267. //callback we are overriding was "handle". In that case,
  268. //we will need to pass the handle name to handle.
  269. var tcb = function(handleName){
  270. if(getHash() != ""){
  271. setTimeout(function() { setHash(hash); }, 1);
  272. }
  273. //Use apply to set "this" to args, and to try to avoid memory leaks.
  274. oldCB.apply(this, [handleName]);
  275. };
  276. //Set interceptor function in the right place.
  277. if(args["back"]){
  278. args.back = tcb;
  279. }else if(args["backButton"]){
  280. args.backButton = tcb;
  281. }else if(args["handle"]){
  282. args.handle = tcb;
  283. }
  284. var oldFW = args["forward"]||args["forwardButton"]||args["handle"];
  285. //The function takes handleName as a parameter, in case the
  286. //callback we are overriding was "handle". In that case,
  287. //we will need to pass the handle name to handle.
  288. var tfw = function(handleName){
  289. if(getHash() != ""){
  290. setHash(hash);
  291. }
  292. if(oldFW){ // we might not actually have one
  293. //Use apply to set "this" to args, and to try to avoid memory leaks.
  294. oldFW.apply(this, [handleName]);
  295. }
  296. };
  297. //Set interceptor function in the right place.
  298. if(args["forward"]){
  299. args.forward = tfw;
  300. }else if(args["forwardButton"]){
  301. args.forwardButton = tfw;
  302. }else if(args["handle"]){
  303. args.handle = tfw;
  304. }
  305. }else if(!dojo.isIE){
  306. // start the timer
  307. if(!locationTimer){
  308. locationTimer = setInterval(checkLocation, 200);
  309. }
  310. }
  311. }else{
  312. url = loadIframeHistory();
  313. }
  314. historyStack.push(createState(url, args, hash));
  315. };
  316. back._iframeLoaded = function(evt, ifrLoc){
  317. //summary:
  318. // private method. Do not call this directly.
  319. var query = getUrlQuery(ifrLoc.href);
  320. if(query == null){
  321. // alert("iframeLoaded");
  322. // we hit the end of the history, so we should go back
  323. if(historyStack.length == 1){
  324. handleBackButton();
  325. }
  326. return;
  327. }
  328. if(moveForward){
  329. // we were expecting it, so it's not either a forward or backward movement
  330. moveForward = false;
  331. return;
  332. }
  333. //Check the back stack first, since it is more likely.
  334. //Note that only one step back or forward is supported.
  335. if(historyStack.length >= 2 && query == getUrlQuery(historyStack[historyStack.length-2].url)){
  336. handleBackButton();
  337. }
  338. else if(forwardStack.length > 0 && query == getUrlQuery(forwardStack[forwardStack.length-1].url)){
  339. handleForwardButton();
  340. }
  341. };
  342. })();
  343. }