topical media & game development

talk show tell print

lib-jquery-plugin-charts-include-js-lib-ycodaslider-2.0.rc2-lib-jquery.history-remote.js / js



  
History/Remote - jQuery plugin for enabling history support and bookmarking @requires jQuery v1.0.3 http://stilbuero.de/jquery/history/ Copyright (c) 2006 Klaus Hartl (stilbuero.de) Dual licensed under the MIT and GPL licenses: http://www.opensource.org/licenses/mit-license.php http://www.gnu.org/licenses/gpl.html Version: 0.2.3

  
  
  (function() { // block scope
  
  
Initialize the history manager. Subsequent calls will not result in additional history state change listeners. Should be called soonest when the DOM is ready, because in IE an iframe needs to be added to the body to enable history support. @example .ajaxHistory.initialize();
parameter: Function callback A single function that will be executed in case there is no fragment identifier in the URL, for example after navigating back to the initial state. Use to restore such an initial application state. Optional. If specified it will overwrite the default action of emptying all containers that are used to load content into. @type undefined @name .ajaxHistory.initialize() @cat Plugins/History
author: Klaus Hartl/klaus.hartl@stilbuero.de

  
  .ajaxHistory = new function() {
  
      var RESET_EVENT = 'historyReset';
  
      var _currentHash = location.hash;
      var _intervalId = null;
      var _observeHistory; // define outside if/else required by Opera
  
      this.update = function() { }; // empty function body for graceful degradation
  
      // create custom event for state reset
      var _defaultReset = function() {
          $('.remote-output').empty();
      };
      document.bind(RESET_EVENT, _defaultReset);
      
      // TODO fix for Safari 3
      // if (.browser.msie)
      // else if hash != _currentHash
      // else check history length
  
      if (.browser.msie) {
  
          var _historyIframe, initialized = false; // for IE
  
          // add hidden iframe
          $(function() {
              _historyIframe = $('<iframe style="display: none;"></iframe>').appendTo(document.body).get(0);
              var iframe = _historyIframe.contentWindow.document;
              // create initial history entry
              iframe.open();
              iframe.close();
              if (_currentHash && _currentHash != '#') {
                  iframe.location.hash = _currentHash.replace('#', '');
              }
          });
  
          this.update = function(hash) {
              _currentHash = hash;
              var iframe = _historyIframe.contentWindow.document;
              iframe.open();
              iframe.close();
              iframe.location.hash = hash.replace('#', '');
          };
  
          _observeHistory = function() {
              var iframe = _historyIframe.contentWindow.document;
              var iframeHash = iframe.location.hash;
              if (iframeHash != _currentHash) {
                  _currentHash = iframeHash;
                  if (iframeHash && iframeHash != '#') {
                      // order does matter, set location.hash after triggering the click...
                      $('a[@href="' + iframeHash + '"]').click();
                      location.hash = iframeHash;
                  } else if (initialized) {
                      location.hash = '';
                      document.trigger(RESET_EVENT);
                  }
              }
              initialized = true;
          };
  
      } else if (.browser.mozilla || .browser.opera) {
  
          this.update = function(hash) {
              _currentHash = hash;
          };
  
          _observeHistory = function() {
              if (location.hash) {
                  if (_currentHash != location.hash) {
                      _currentHash = location.hash;
                      $('a[@href="' + _currentHash + '"]').click();
                  }
              } else if (_currentHash) {
                  _currentHash = '';
                  document.trigger(RESET_EVENT);
              }
          };
  
      } else if (.browser.safari) {
  
          var _backStack, _forwardStack, _addHistory; // for Safari
  
          // etablish back/forward stacks
          $(function() {
              _backStack = [];
              _backStack.length = history.length;
              _forwardStack = [];
  
          });
          var isFirst = false, initialized = false;
          _addHistory = function(hash) {
              _backStack.push(hash);
              _forwardStack.length = 0; // clear forwardStack (true click occured)
              isFirst = false;
          };
  
          this.update = function(hash) {
              _currentHash = hash;
              _addHistory(_currentHash);
          };
  
          _observeHistory = function() {
              var historyDelta = history.length - _backStack.length;
              if (historyDelta) { // back or forward button has been pushed
                  isFirst = false;
                  if (historyDelta < 0) { // back button has been pushed
                      // move items to forward stack
                      for (var i = 0; i < Math.abs(historyDelta); i++) _forwardStack.unshift(_backStack.pop());
                  } else { // forward button has been pushed
                      // move items to back stack
                      for (var i = 0; i < historyDelta; i++) _backStack.push(_forwardStack.shift());
                  }
                  var cachedHash = _backStack[_backStack.length - 1];
                  $('a[@href="' + cachedHash + '"]').click();
                  _currentHash = location.hash;
              } else if (_backStack[_backStack.length - 1] == undefined && !isFirst) {
                  // back button has been pushed to beginning and URL already pointed to hash (e.g. a bookmark)
                  // document.URL doesn't change in Safari
                  if (document.URL.indexOf('#') >= 0) {
                      $('a[@href="' + '#' + document.URL.split('#')[1] + '"]').click();
                  } else if (initialized) {
                      document.trigger(RESET_EVENT);
                  }
                  isFirst = true;
              }
              initialized = true;
          };
  
      }
  
      this.initialize = function(callback) {
          // custom callback to reset app state (no hash in url)
          if (typeof callback == 'function') {
              document.unbind(RESET_EVENT, _defaultReset).bind(RESET_EVENT, callback);
          }
          // look for hash in current URL (not Safari)
          if (location.hash && typeof _addHistory == 'undefined') {
              $('a[@href="' + location.hash + '"]').trigger('click');
          }
          // start observer
          if (_observeHistory && _intervalId == null) {
              _intervalId = setInterval(_observeHistory, 200); // Safari needs at least 200 ms
          }
      };
  
  };
  
  
Implement Ajax driven links in a completely unobtrusive and accessible manner (also known as "Hijax") with support for the browser's back/forward navigation buttons and bookmarking. The link's href attribute gets altered to a fragment identifier, such as "#remote-1", so that the browser's URL gets updated on each click, whereas the former value of that attribute is used to load content via XmlHttpRequest from and update the specified element. If no target element is found, a new div element will be created and appended to the body to load the content into. The link informs the history manager of the state change on click and adds an entry to the browser's history. jQuery's Ajax implementation adds a custom request header of the form "X-Requested-With: XmlHttpRequest" to any Ajax request so that the called page can distinguish between a standard and an Ajax (XmlHttpRequest) request. @example $('a.remote').remote('#output'); @before <a class="remote" href="/path/to/content.html">Update</a> @result <a class="remote" href="#remote-1">Update</a> @desc Alter a link of the class "remote" to an Ajax-enhanced link and let it load content from "/path/to/content.html" via XmlHttpRequest into an element with the id "output". @example $('a.remote').remote('#output', {hashPrefix: 'chapter'}); @before <a class="remote" href="/path/to/content.html">Update</a> @result <a class="remote" href="#chapter-1">Update</a> @desc Alter a link of the class "remote" to an Ajax-enhanced link and let it load content from "/path/to/content.html" via XmlHttpRequest into an element with the id "output".
parameter: String expr A string containing a CSS selector or basic XPath specifying the element to load content into via XmlHttpRequest.
parameter: Object settings An object literal containing key/value pairs to provide optional settings. @option String hashPrefix A String that is used for constructing the hash the link's href attribute gets altered to, such as "#remote-1". Default value: "remote-".
parameter: Function callback A single function that will be executed when the request is complete. @type jQuery @name remote @cat Plugins/Remote
author: Klaus Hartl/klaus.hartl@stilbuero.de

  
  
  
Implement Ajax driven links in a completely unobtrusive and accessible manner (also known as "Hijax") with support for the browser's back/forward navigation buttons and bookmarking. The link's href attribute gets altered to a fragment identifier, such as "#remote-1", so that the browser's URL gets updated on each click, whereas the former value of that attribute is used to load content via XmlHttpRequest from and update the specified element. If no target element is found, a new div element will be created and appended to the body to load the content into. The link informs the history manager of the state change on click and adds an entry to the browser's history. jQuery's Ajax implementation adds a custom request header of the form "X-Requested-With: XmlHttpRequest" to any Ajax request so that the called page can distinguish between a standard and an Ajax (XmlHttpRequest) request. @example $('a.remote').remote( $('#output > div')[0] ); @before <a class="remote" href="/path/to/content.html">Update</a> @result <a class="remote" href="#remote-1">Update</a> @desc Alter a link of the class "remote" to an Ajax-enhanced link and let it load content from "/path/to/content.html" via XmlHttpRequest into an element with the id "output". @example $('a.remote').remote('#output', {hashPrefix: 'chapter'}); @before <a class="remote" href="/path/to/content.html">Update</a> @result <a class="remote" href="#chapter-1">Update</a> @desc Alter a link of the class "remote" to an Ajax-enhanced link and let it load content from "/path/to/content.html" via XmlHttpRequest into an element with the id "output".
parameter: Element elem A DOM element to load content into via XmlHttpRequest.
parameter: Object settings An object literal containing key/value pairs to provide optional settings. @option String hashPrefix A String that is used for constructing the hash the link's href attribute gets altered to, such as "#remote-1". Default value: "remote-".
parameter: Function callback A single function that will be executed when the request is complete. @type jQuery @name remote @cat Plugins/Remote
author: Klaus Hartl/klaus.hartl@stilbuero.de

  
  .fn.remote = function(output, settings, callback) {
  
      callback = callback || function() {};
      if (typeof settings == 'function') { // shift arguments
          callback = settings;
      }
      
      settings = .extend({
          hashPrefix: 'remote-'
      }, settings || {});
  
      var target = output.size() && output || $('<div></div>').appendTo('body');
      target.addClass('remote-output');
  
      return this.each(function(i) {
          var href = this.href, hash = '#' + (this.title && this.title.replace(/\s/g, '_') || settings.hashPrefix + (i + 1)),
              a = this;
          this.href = hash;
          this.click(function(e) {
              // lock target to prevent double loading in Firefox
              if (!target['locked']) {
                  // add to history only if true click occured, not a triggered click
                  if (e.clientX) {
                      .ajaxHistory.update(hash);
                  }
                  target.load(href, function() {
                      target['locked'] = null;
                      callback.apply(a);
                  });
              }
          });
      });
  
  };
  
  
Provides the ability to use the back/forward navigation buttons in a DHTML application. A change of the application state is reflected by a change of the URL fragment identifier. The link's href attribute needs to point to a fragment identifier within the same resource, although that fragment id does not need to exist. On click the link changes the URL fragment identifier, informs the history manager of the state change and adds an entry to the browser's history.
parameter: Function callback A single function that will be executed as the click handler of the matched element. It will be executed on click (adding an entry to the history) as well as in case the history manager needs to trigger it depending on the value of the URL fragment identifier, e.g. if its current value matches the href attribute of the matched element. @type jQuery @name history @cat Plugins/History
author: Klaus Hartl/klaus.hartl@stilbuero.de

  
  .fn.history = function(callback) {
      return this.click(function(e) {        
          // add to history only if true click occured, not a triggered click
          if (e.clientX) {
              .ajaxHistory.update(this.hash);
          }
          typeof callback == 'function' && callback();
      });
  };
  
  })(jQuery);
  
  /*
  var logger;
  $(function() {
      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);
  });
  function log(m) {    
      logger.prepend(m + '<br />');
  };
  */
  
  


(C) Æliens 20/2/2008

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.