| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 /** 2 * History/Remote - jQuery plugin for enabling history support and bookmarking 3 * @requires jQuery v1.0.3 4 * 5 * http://stilbuero.de/jquery/history/ 6 * 7 * Copyright (c) 2006 Klaus Hartl (stilbuero.de) 8 * Dual licensed under the MIT and GPL licenses: 9 * http://www.opensource.org/licenses/mit-license.php 10 * http://www.gnu.org/licenses/gpl.html 11 * 12 * Version: 0.2.3 13 */ 14 15 (function($) { // block scope 16 17 /** 18 * Initialize the history manager. Subsequent calls will not result in additional history state change 19 * listeners. Should be called soonest when the DOM is ready, because in IE an iframe needs to be added 20 * to the body to enable history support. 21 * 22 * @example $.ajaxHistory.initialize(); 23 * 24 * @param Function callback A single function that will be executed in case there is no fragment 25 * identifier in the URL, for example after navigating back to the initial 26 * state. Use to restore such an initial application state. 27 * Optional. If specified it will overwrite the default action of 28 * emptying all containers that are used to load content into. 29 * @type undefined 30 * 31 * @name $.ajaxHistory.initialize() 32 * @cat Plugins/History 33 * @author Klaus Hartl/klaus.hartl@stilbuero.de 34 */ 35 $.ajaxHistory = new function() { 36 37 var RESET_EVENT = 'historyReset'; 38 39 var _currentHash = location.hash; 40 var _intervalId = null; 41 var _observeHistory; // define outside if/else required by Opera 42 43 this.update = function() { }; // empty function body for graceful degradation 44 45 // create custom event for state reset 46 var _defaultReset = function() { 47 $('.remote-output').empty(); 48 }; 49 $(document).bind(RESET_EVENT, _defaultReset); 50 51 // TODO fix for Safari 3 52 // if ($.browser.msie) 53 // else if hash != _currentHash 54 // else check history length 55 56 if ($.browser.msie) { 57 58 var _historyIframe, initialized = false; // for IE 59 60 // add hidden iframe 61 $(function() { 62 _historyIframe = $('<iframe style="display: none;"></iframe>').appendTo(document.body).get(0); 63 var iframe = _historyIframe.contentWindow.document; 64 // create initial history entry 65 iframe.open(); 66 iframe.close(); 67 if (_currentHash && _currentHash != '#') { 68 iframe.location.hash = _currentHash.replace('#', ''); 69 } 70 }); 71 72 this.update = function(hash) { 73 _currentHash = hash; 74 var iframe = _historyIframe.contentWindow.document; 75 iframe.open(); 76 iframe.close(); 77 iframe.location.hash = hash.replace('#', ''); 78 }; 79 80 _observeHistory = function() { 81 var iframe = _historyIframe.contentWindow.document; 82 var iframeHash = iframe.location.hash; 83 if (iframeHash != _currentHash) { 84 _currentHash = iframeHash; 85 if (iframeHash && iframeHash != '#') { 86 // order does matter, set location.hash after triggering the click... 87 $('a[@href$="' + iframeHash + '"]').click(); 88 location.hash = iframeHash; 89 } else if (initialized) { 90 location.hash = ''; 91 $(document).trigger(RESET_EVENT); 92 } 93 } 94 initialized = true; 95 }; 96 97 } else if ($.browser.mozilla || $.browser.opera) { 98 99 this.update = function(hash) { 100 _currentHash = hash; 101 }; 102 103 _observeHistory = function() { 104 if (location.hash) { 105 if (_currentHash != location.hash) { 106 _currentHash = location.hash; 107 $('a[@href$="' + _currentHash + '"]').click(); 108 } 109 } else if (_currentHash) { 110 _currentHash = ''; 111 $(document).trigger(RESET_EVENT); 112 } 113 }; 114 115 } else if ($.browser.safari) { 116 117 var _backStack, _forwardStack, _addHistory; // for Safari 118 119 // etablish back/forward stacks 120 $(function() { 121 _backStack = []; 122 _backStack.length = history.length; 123 _forwardStack = []; 124 125 }); 126 var isFirst = false, initialized = false; 127 _addHistory = function(hash) { 128 _backStack.push(hash); 129 _forwardStack.length = 0; // clear forwardStack (true click occured) 130 isFirst = false; 131 }; 132 133 this.update = function(hash) { 134 _currentHash = hash; 135 _addHistory(_currentHash); 136 }; 137 138 _observeHistory = function() { 139 var historyDelta = history.length - _backStack.length; 140 if (historyDelta) { // back or forward button has been pushed 141 isFirst = false; 142 if (historyDelta < 0) { // back button has been pushed 143 // move items to forward stack 144 for (var i = 0; i < Math.abs(historyDelta); i++) _forwardStack.unshift(_backStack.pop()); 145 } else { // forward button has been pushed 146 // move items to back stack 147 for (var i = 0; i < historyDelta; i++) _backStack.push(_forwardStack.shift()); 148 } 149 var cachedHash = _backStack[_backStack.length - 1]; 150 $('a[@href$="' + cachedHash + '"]').click(); 151 _currentHash = location.hash; 152 } else if (_backStack[_backStack.length - 1] == undefined && !isFirst) { 153 // back button has been pushed to beginning and URL already pointed to hash (e.g. a bookmark) 154 // document.URL doesn't change in Safari 155 if (document.URL.indexOf('#') >= 0) { 156 $('a[@href$="' + '#' + document.URL.split('#')[1] + '"]').click(); 157 } else if (initialized) { 158 $(document).trigger(RESET_EVENT); 159 } 160 isFirst = true; 161 } 162 initialized = true; 163 }; 164 165 } 166 167 this.initialize = function(callback) { 168 // custom callback to reset app state (no hash in url) 169 if (typeof callback == 'function') { 170 $(document).unbind(RESET_EVENT, _defaultReset).bind(RESET_EVENT, callback); 171 } 172 // look for hash in current URL (not Safari) 173 if (location.hash && typeof _addHistory == 'undefined') { 174 $('a[@href$="' + location.hash + '"]').trigger('click'); 175 } 176 // start observer 177 if (_observeHistory && _intervalId == null) { 178 _intervalId = setInterval(_observeHistory, 200); // Safari needs at least 200 ms 179 } 180 }; 181 182 }; 183 184 /** 185 * Implement Ajax driven links in a completely unobtrusive and accessible manner (also known as "Hijax") 186 * with support for the browser's back/forward navigation buttons and bookmarking. 187 * 188 * The link's href attribute gets altered to a fragment identifier, such as "#remote-1", so that the browser's 189 * URL gets updated on each click, whereas the former value of that attribute is used to load content via 190 * XmlHttpRequest from and update the specified element. If no target element is found, a new div element will be 191 * created and appended to the body to load the content into. The link informs the history manager of the 192 * state change on click and adds an entry to the browser's history. 193 * 194 * jQuery's Ajax implementation adds a custom request header of the form "X-Requested-With: XmlHttpRequest" 195 * to any Ajax request so that the called page can distinguish between a standard and an Ajax (XmlHttpRequest) 196 * request. 197 * 198 * @example $('a.remote').remote('#output'); 199 * @before <a class="remote" href="/path/to/content.html">Update</a> 200 * @result <a class="remote" href="#remote-1">Update</a> 201 * @desc Alter a link of the class "remote" to an Ajax-enhanced link and let it load content from 202 * "/path/to/content.html" via XmlHttpRequest into an element with the id "output". 203 * @example $('a.remote').remote('#output', {hashPrefix: 'chapter'}); 204 * @before <a class="remote" href="/path/to/content.html">Update</a> 205 * @result <a class="remote" href="#chapter-1">Update</a> 206 * @desc Alter a link of the class "remote" to an Ajax-enhanced link and let it load content from 207 * "/path/to/content.html" via XmlHttpRequest into an element with the id "output". 208 * 209 * @param String expr A string containing a CSS selector or basic XPath specifying the element to load 210 * content into via XmlHttpRequest. 211 * @param Object settings An object literal containing key/value pairs to provide optional settings. 212 * @option String hashPrefix A String that is used for constructing the hash the link's href attribute 213 * gets altered to, such as "#remote-1". Default value: "remote-". 214 * @param Function callback A single function that will be executed when the request is complete. 215 * @type jQuery 216 * 217 * @name remote 218 * @cat Plugins/Remote 219 * @author Klaus Hartl/klaus.hartl@stilbuero.de 220 */ 221 222 /** 223 * Implement Ajax driven links in a completely unobtrusive and accessible manner (also known as "Hijax") 224 * with support for the browser's back/forward navigation buttons and bookmarking. 225 * 226 * The link's href attribute gets altered to a fragment identifier, such as "#remote-1", so that the browser's 227 * URL gets updated on each click, whereas the former value of that attribute is used to load content via 228 * XmlHttpRequest from and update the specified element. If no target element is found, a new div element will be 229 * created and appended to the body to load the content into. The link informs the history manager of the 230 * state change on click and adds an entry to the browser's history. 231 * 232 * jQuery's Ajax implementation adds a custom request header of the form "X-Requested-With: XmlHttpRequest" 233 * to any Ajax request so that the called page can distinguish between a standard and an Ajax (XmlHttpRequest) 234 * request. 235 * 236 * @example $('a.remote').remote( $('#output > div')[0] ); 237 * @before <a class="remote" href="/path/to/content.html">Update</a> 238 * @result <a class="remote" href="#remote-1">Update</a> 239 * @desc Alter a link of the class "remote" to an Ajax-enhanced link and let it load content from 240 * "/path/to/content.html" via XmlHttpRequest into an element with the id "output". 241 * @example $('a.remote').remote('#output', {hashPrefix: 'chapter'}); 242 * @before <a class="remote" href="/path/to/content.html">Update</a> 243 * @result <a class="remote" href="#chapter-1">Update</a> 244 * @desc Alter a link of the class "remote" to an Ajax-enhanced link and let it load content from 245 * "/path/to/content.html" via XmlHttpRequest into an element with the id "output". 246 * 247 * @param Element elem A DOM element to load content into via XmlHttpRequest. 248 * @param Object settings An object literal containing key/value pairs to provide optional settings. 249 * @option String hashPrefix A String that is used for constructing the hash the link's href attribute 250 * gets altered to, such as "#remote-1". Default value: "remote-". 251 * @param Function callback A single function that will be executed when the request is complete. 252 * @type jQuery 253 * 254 * @name remote 255 * @cat Plugins/Remote 256 * @author Klaus Hartl/klaus.hartl@stilbuero.de 257 */ 258 $.fn.remote = function(output, settings, callback) { 259 260 callback = callback || function() {}; 261 if (typeof settings == 'function') { // shift arguments 262 callback = settings; 263 } 264 265 settings = $.extend({ 266 hashPrefix: 'remote-' 267 }, settings || {}); 268 269 var target = $(output).size() && $(output) || $('<div></div>').appendTo('body'); 270 target.addClass('remote-output'); 271 272 return this.each(function(i) { 273 var href = this.href, hash = '#' + (this.title && this.title.replace(/\s/g, '_') || settings.hashPrefix + (i + 1)), 274 a = this; 275 this.href = hash; 276 $(this).click(function(e) { 277 // lock target to prevent double loading in Firefox 278 if (!target['locked']) { 279 // add to history only if true click occured, not a triggered click 280 if (e.clientX) { 281 $.ajaxHistory.update(hash); 282 } 283 target.load(href, function() { 284 target['locked'] = null; 285 callback.apply(a); 286 }); 287 } 288 }); 289 }); 290 291 }; 292 293 /** 294 * Provides the ability to use the back/forward navigation buttons in a DHTML application. 295 * A change of the application state is reflected by a change of the URL fragment identifier. 296 * 297 * The link's href attribute needs to point to a fragment identifier within the same resource, 298 * although that fragment id does not need to exist. On click the link changes the URL fragment 299 * identifier, informs the history manager of the state change and adds an entry to the browser's 300 * history. 301 * 302 * @param Function callback A single function that will be executed as the click handler of the 303 * matched element. It will be executed on click (adding an entry to 304 * the history) as well as in case the history manager needs to trigger 305 * it depending on the value of the URL fragment identifier, e.g. if its 306 * current value matches the href attribute of the matched element. 307 * 308 * @type jQuery 309 * 310 * @name history 311 * @cat Plugins/History 312 * @author Klaus Hartl/klaus.hartl@stilbuero.de 313 */ 314 $.fn.history = function(callback) { 315 return this.click(function(e) { 316 // add to history only if true click occured, 317 // not a triggered click... 318 if (e.clientX) { 319 // ...and die if already active 320 if (this.hash == location.hash) { 321 return false; 322 } 323 $.ajaxHistory.update(this.hash); 324 } 325 if (typeof callback == 'function') { 326 callback.call(this); 327 } 328 }); 329 }; 330 331 })(jQuery); 332 333 /* 334 var logger; 335 $(function() { 336 logger = $('<div style="position: fixed; top: 0; overflow: hidden; border: 1px solid; padding: 3px; width: 120px; height: 150px; background: #fff; color: red;"></div>').appendTo(document.body); 337 }); 338 function log(m) { 339 logger.prepend(m + '<br />'); 340 }; 341 */ 342
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |