text: /*
   * jQuery Address Plugin v1.5
   * http://www.asual.com/jquery/address/
   *
   * Copyright (c) 2009-2010 Rostislav Hristov
   * Dual licensed under the MIT or GPL Version 2 licenses.
   * http://jquery.org/license
   *
   * Date: 2011-09-19 23:26:02 +0300 (Mon, 19 Sep 2011)
   */
  (function ($) {
  
      $.address = (function () {
  
          var _trigger = function(name) {
                  $($.address).trigger(
                      $.extend($.Event(name), 
                          (function() {
                              var parameters = {},
                                  parameterNames = $.address.parameterNames();
                              for (var i = 0, l = parameterNames.length; i < l; i++) {
                                  parameters[parameterNames[i]] = $.address.parameter(parameterNames[i]);
                              }
                              return {
                                  value: $.address.value(),
                                  path: $.address.path(),
                                  pathNames: $.address.pathNames(),
                                  parameterNames: parameterNames,
                                  parameters: parameters,
                                  queryString: $.address.queryString()
                              };
                          }).call($.address)
                      )
                  );
              },
              _array = function(obj) {
                  return Array.prototype.slice.call(obj);
              },
              _bind = function(value, data, fn) {
                  $().bind.apply($($.address), Array.prototype.slice.call(arguments));
                  return $.address;
              },
              _supportsState = function() {
                  return (_h.pushState && _opts.state !== UNDEFINED);
              },
              _hrefState = function() {
                  return ('/' + _l.pathname.replace(new RegExp(_opts.state), '') + 
                      _l.search + (_hrefHash() ? '#' + _hrefHash() : '')).replace(_re, '/');
              },
              _hrefHash = function() {
                  var index = _l.href.indexOf('#');
                  return index != -1 ? _crawl(_l.href.substr(index + 1), FALSE) : '';
              },
              _href = function() {
                  return _supportsState() ? _hrefState() : _hrefHash();
              },
              _window = function() {
                  try {
                      return top.document !== UNDEFINED ? top : window;
                  } catch (e) { 
                      return window;
                  }
              },
              _js = function() {
                  return 'javascript';
              },
              _strict = function(value) {
                  value = value.toString();
                  return (_opts.strict && value.substr(0, 1) != '/' ? '/' : '') + value;
              },
              _crawl = function(value, direction) {
                  if (_opts.crawlable && direction) {
                      return (value !== '' ? '!' : '') + value;
                  }
                  return value.replace(/^\!/, '');
              },
              _cssint = function(el, value) {
                  return parseInt(el.css(value), 10);
              },
              _listen = function() {
                  if (!_silent) {
                      var hash = _href(),
                          diff = _value != hash;
                      if (diff) {
                          if (_msie && _version < 7) {
                              _l.reload();
                          } else {
                              if (_msie && !_hashchange && _opts.history) {
                                  _st(_html, 50);
                              }
                              _value = hash;
                              _update(FALSE);
                          }
                      }
                  }
              },
              _update = function(internal) {
                  _trigger(CHANGE);
                  _trigger(internal ? INTERNAL_CHANGE : EXTERNAL_CHANGE);
                  _st(_track, 10);
              },
              _track = function() {
                  if (_opts.tracker !== 'null' && _opts.tracker !== null) {
                      var fn = $.isFunction(_opts.tracker) ? _opts.tracker : _t[_opts.tracker],
                          value = (_l.pathname + _l.search + 
                                  ($.address && !_supportsState() ? $.address.value() : ''))
                                  .replace(/\/\//, '/').replace(/^\/$/, '');
                      if ($.isFunction(fn)) {
                          fn(value);
                      } else if ($.isFunction(_t.urchinTracker)) {
                          _t.urchinTracker(value);
                      } else if (_t.pageTracker !== UNDEFINED && $.isFunction(_t.pageTracker._trackPageview)) {
                          _t.pageTracker._trackPageview(value);
                      } else if (_t._gaq !== UNDEFINED && $.isFunction(_t._gaq.push)) {
                          _t._gaq.push(['_trackPageview', decodeURI(value)]);
                      }
                  }
              },
              _html = function() {
                  var src = _js() + ':' + FALSE + ';document.open();document.writeln(\'<html><head><title>' + 
                      _d.title.replace('\'', '\\\'') + '</title><script>var ' + ID + ' = "' + encodeURIComponent(_href()) + 
                      (_d.domain != _l.hostname ? '";document.domain="' + _d.domain : '') + 
                      '";</' + 'script></head></html>\');document.close();';
                  if (_version < 7) {
                      _frame.src = src;
                  } else {
                      _frame.contentWindow.location.replace(src);
                  }
              },
              _options = function() {
                  if (_url && _qi != -1) {
                      var param, params = _url.substr(_qi + 1).split('&');
                      for (i = 0; i < params.length; i++) {
                          param = params[i].split('=');
                          if (/^(autoUpdate|crawlable|history|strict|wrap)$/.test(param[0])) {
                              _opts[param[0]] = (isNaN(param[1]) ? /^(true|yes)$/i.test(param[1]) : (parseInt(param[1], 10) !== 0));
                          }
                          if (/^(state|tracker)$/.test(param[0])) {
                              _opts[param[0]] = param[1];
                          }
                      }
                      _url = null;
                  }
                  _value = _href();
              },
              _load = function() {
                  if (!_loaded) {
                      _loaded = TRUE;
                      _options();
                      var complete = function() {
                              _enable.call(this);
                              _unescape.call(this);
                          },
                          body = $('body').ajaxComplete(complete);
                      complete();
                      if (_opts.wrap) {
                          var wrap = $('body > *')
                              .wrapAll('<div style="padding:' + 
                                  (_cssint(body, 'marginTop') + _cssint(body, 'paddingTop')) + 'px ' + 
                                  (_cssint(body, 'marginRight') + _cssint(body, 'paddingRight')) + 'px ' + 
                                  (_cssint(body, 'marginBottom') + _cssint(body, 'paddingBottom')) + 'px ' + 
                                  (_cssint(body, 'marginLeft') + _cssint(body, 'paddingLeft')) + 'px;" />')
                              .parent()
                              .wrap('<div id="' + ID + '" style="height:100%;overflow:auto;position:relative;' + 
                                  (_webkit && !window.statusbar.visible ? 'resize:both;' : '') + '" />');
                          $('html, body')
                              .css({
                                  height: '100%',
                                  margin: 0,
                                  padding: 0,
                                  overflow: 'hidden'
                              });
                          if (_webkit) {
                              $('<style type="text/css" />')
                                  .appendTo('head')
                                  .text('#' + ID + '::-webkit-resizer { background-color: #fff; }');
                          }
                      }
                      if (_msie && !_hashchange) {
                          var frameset = _d.getElementsByTagName('frameset')[0];
                          _frame = _d.createElement((frameset ? '' : 'i') + 'frame');
                          _frame.src = _js() + ':' + FALSE;
                          if (frameset) {
                              frameset.insertAdjacentElement('beforeEnd', _frame);
                              frameset[frameset.cols ? 'cols' : 'rows'] += ',0';
                              _frame.noResize = TRUE;
                              _frame.frameBorder = _frame.frameSpacing = 0;
                          } else {
                              _frame.style.display = 'none';
                              _frame.style.width = _frame.style.height = 0;
                              _frame.tabIndex = -1;
                              _d.body.insertAdjacentElement('afterBegin', _frame);
                          }
                          _st(function() {
                              $(_frame).bind('load', function() {
                                  var win = _frame.contentWindow;
                                  _value = win[ID] !== UNDEFINED ? win[ID] : '';
                                  if (_value != _href()) {
                                      _update(FALSE);
                                      _l.hash = _crawl(_value, TRUE);
                                  }
                              });
                              if (_frame.contentWindow[ID] === UNDEFINED) {
                                  _html();
                              }
                          }, 50);
                      }
  
                      _st(function() {
                          _trigger('init');
                          _update(FALSE);
                      }, 1);
  
                      if (!_supportsState()) {
                          if (_hashchange) {
                              if (_t.addEventListener) {
                                  _t.addEventListener(HASH_CHANGE, _listen, FALSE);
                              } else if (_t.attachEvent) {
                                  _t.attachEvent('on' + HASH_CHANGE, _listen);
                              }
                          } else {
                              _si(_listen, 50);
                          }
                      }
                  }
              },
              _enable = function() {
                  var el, 
                      elements = $('a'), 
                      length = elements.size(),
                      delay = 1,
                      index = -1,
                      sel = '[rel*="address:"]',
                      fn = function() {
                          if (++index != length) {
                              el = $(elements.get(index));
                              if (el.is(sel)) {
                                  el.address(sel);
                              }
                              _st(fn, delay);
                          }
                      };
                  _st(fn, delay);
              },
              _popstate = function() {
                  if (_value != _href()) {
                      _value = _href();
                      _update(FALSE);
                  }
              },
              _unload = function() {
                  if (_t.removeEventListener) {
                      _t.removeEventListener(HASH_CHANGE, _listen, FALSE);
                  } else if (_t.detachEvent) {
                      _t.detachEvent('on' + HASH_CHANGE, _listen);
                  }
              },
              _unescape = function() {
                  if (_opts.crawlable) {
                      var base = _l.pathname.replace(/\/$/, ''),
                          fragment = '_escaped_fragment_';
                      if ($('body').html().indexOf(fragment) != -1) {
                          $('a[href]:not([href^=http]), a[href*="' + document.domain + '"]').each(function() {
                              var href = $(this).attr('href').replace(/^http:/, '').replace(new RegExp(base + '/?$'), '');
                              if (href === '' || href.indexOf(fragment) != -1) {
                                  $(this).attr('href', '#' + href.replace(new RegExp('/(.*)\\?' + fragment + '=(.*)$'), '!$2'));
                              }
                          });
                      }
                  }
              },
              UNDEFINED,
              ID = 'jQueryAddress',
              STRING = 'string',
              HASH_CHANGE = 'hashchange',
              INIT = 'init',
              CHANGE = 'change',
              INTERNAL_CHANGE = 'internalChange',
              EXTERNAL_CHANGE = 'externalChange',
              TRUE = true,
              FALSE = false,
              _opts = {
                  autoUpdate: TRUE, 
                  crawlable: FALSE,
                  history: TRUE, 
                  strict: TRUE,
                  wrap: FALSE
              },
              _browser = $.browser, 
              _version = parseFloat(_browser.version),
              _msie = !$.support.opacity,
              _webkit = _browser.webkit || _browser.safari,
              _t = _window(),
              _d = _t.document,
              _h = _t.history, 
              _l = _t.location,
              _si = setInterval,
              _st = setTimeout,
              _re = /\/{2,9}/g,
              _agent = navigator.userAgent,
              _hashchange = 'on' + HASH_CHANGE in _t,
              _frame,
              _form,
              _url = $('script:last').attr('src'),
              _qi = _url ? _url.indexOf('?') : -1,
              _title = _d.title, 
              _silent = FALSE,
              _loaded = FALSE,
              _justset = TRUE,
              _juststart = TRUE,
              _updating = FALSE,
              _listeners = {}, 
              _value = _href();
              
          if (_msie) {
              _version = parseFloat(_agent.substr(_agent.indexOf('MSIE') + 4));
              if (_d.documentMode && _d.documentMode != _version) {
                  _version = _d.documentMode != 8 ? 7 : 8;
              }
              var pc = _d.onpropertychange;
              _d.onpropertychange = function() {
                  if (pc) {
                      pc.call(_d);
                  }
                  if (_d.title != _title && _d.title.indexOf('#' + _href()) != -1) {
                      _d.title = _title;
                  }
              };
          }
          
          if (_h.navigationMode) {
              _h.navigationMode = 'compatible';
          }
          if (document.readyState == 'complete') {
              var interval = setInterval(function() {
                  if ($.address) {
                      _load();
                      clearInterval(interval);
                  }
              }, 50);
          } else {
              _options();
              $(_load);
          }
          $(window).bind('popstate', _popstate).bind('unload', _unload);
  
          return {
              bind: function(type, data, fn) {
                  return _bind.apply(this, _array(arguments));
              },
              init: function(data, fn) {
                  return _bind.apply(this, [INIT].concat(_array(arguments)));
              },
              change: function(data, fn) {
                  return _bind.apply(this, [CHANGE].concat(_array(arguments)));
              },
              internalChange: function(data, fn) {
                  return _bind.apply(this, [INTERNAL_CHANGE].concat(_array(arguments)));
              },
              externalChange: function(data, fn) {
                  return _bind.apply(this, [EXTERNAL_CHANGE].concat(_array(arguments)));
              },
              baseURL: function() {
                  var url = _l.href;
                  if (url.indexOf('#') != -1) {
                      url = url.substr(0, url.indexOf('#'));
                  }
                  if (/\/$/.test(url)) {
                      url = url.substr(0, url.length - 1);
                  }
                  return url;
              },
              autoUpdate: function(value) {
                  if (value !== UNDEFINED) {
                      _opts.autoUpdate = value;
                      return this;
                  }
                  return _opts.autoUpdate;
              },
              crawlable: function(value) {
                  if (value !== UNDEFINED) {
                      _opts.crawlable = value;
                      return this;
                  }
                  return _opts.crawlable;
              },
              history: function(value) {
                  if (value !== UNDEFINED) {
                      _opts.history = value;
                      return this;
                  }
                  return _opts.history;
              },
              state: function(value) {
                  if (value !== UNDEFINED) {
                      _opts.state = value;
                      var hrefState = _hrefState();
                      if (_opts.state !== UNDEFINED) {
                          if (_h.pushState) {
                              if (hrefState.substr(0, 3) == '/#/') {
                                  _l.replace(_opts.state.replace(/^\/$/, '') + hrefState.substr(2));
                              }
                          } else if (hrefState != '/' && hrefState.replace(/^\/#/, '') != _hrefHash()) {
                              _st(function() {
                                  _l.replace(_opts.state.replace(/^\/$/, '') + '/#' + hrefState);
                              }, 1);
                          }
                      }
                      return this;
                  }
                  return _opts.state;
              },
              strict: function(value) {
                  if (value !== UNDEFINED) {
                      _opts.strict = value;
                      return this;
                  }
                  return _opts.strict;
              },
              tracker: function(value) {
                  if (value !== UNDEFINED) {
                      _opts.tracker = value;
                      return this;
                  }
                  return _opts.tracker;
              },
              wrap: function(value) {
                  if (value !== UNDEFINED) {
                      _opts.wrap = value;
                      return this;
                  }
                  return _opts.wrap;
              },
              update: function() {
                  _updating = TRUE;
                  this.value(_value);
                  _updating = FALSE;
                  return this;
              },
              title: function(value) {
                  if (value !== UNDEFINED) {
                      _st(function() {
                          _title = _d.title = value;
                          if (_juststart && _frame && _frame.contentWindow && _frame.contentWindow.document) {
                              _frame.contentWindow.document.title = value;
                              _juststart = FALSE;
                          }
                          if (!_justset && _browser.mozilla) {
                              _l.replace(_l.href.indexOf('#') != -1 ? _l.href : _l.href + '#');
                          }
                          _justset = FALSE;
                      }, 50);
                      return this;
                  }
                  return _d.title;
              },
              value: function(value) {
                  if (value !== UNDEFINED) {
                      value = _strict(value);
                      if (value == '/') {
                          value = '';
                      }
                      if (_value == value && !_updating) {
                          return;
                      }
                      _justset = TRUE;
                      _value = value;
                      if (_opts.autoUpdate || _updating) {
                          _update(TRUE);
                          if (_supportsState()) {
                              _h[_opts.history ? 'pushState' : 'replaceState']({}, '', 
                                      _opts.state.replace(/\/$/, '') + (_value === '' ? '/' : _value));
                          } else {
                              _silent = TRUE;
                              if (_webkit) {
                                  if (_opts.history) {
                                      _l.hash = '#' + _crawl(_value, TRUE);
                                  } else {
                                      _l.replace('#' + _crawl(_value, TRUE));
                                  }
                              } else if (_value != _href()) {
                                  if (_opts.history) {
                                      _l.hash = '#' + _crawl(_value, TRUE);
                                  } else {
                                      _l.replace('#' + _crawl(_value, TRUE));
                                  }
                              }
                              if ((_msie && !_hashchange) && _opts.history) {
                                  _st(_html, 50);
                              }
                              if (_webkit) {
                                  _st(function(){ _silent = FALSE; }, 1);
                              } else {
                                  _silent = FALSE;
                              }
                          }
                      }
                      return this;
                  }
                  return _strict(_value);
              },
              path: function(value) {
                  if (value !== UNDEFINED) {
                      var qs = this.queryString(),
                          hash = this.hash();
                      this.value(value + (qs ? '?' + qs : '') + (hash ? '#' + hash : ''));
                      return this;
                  }
                  return _strict(_value).split('#')[0].split('?')[0];
              },
              pathNames: function() {
                  var path = this.path(),
                      names = path.replace(_re, '/').split('/');
                  if (path.substr(0, 1) == '/' || path.length === 0) {
                      names.splice(0, 1);
                  }
                  if (path.substr(path.length - 1, 1) == '/') {
                      names.splice(names.length - 1, 1);
                  }
                  return names;
              },
              queryString: function(value) {
                  if (value !== UNDEFINED) {
                      var hash = this.hash();
                      this.value(this.path() + (value ? '?' + value : '') + (hash ? '#' + hash : ''));
                      return this;
                  }
                  var arr = _value.split('?');
                  return arr.slice(1, arr.length).join('?').split('#')[0];
              },
              parameter: function(name, value, append) {
                  var i, params;
                  if (value !== UNDEFINED) {
                      var names = this.parameterNames();
                      params = [];
                      value = value ? value.toString() : '';
                      for (i = 0; i < names.length; i++) {
                          var n = names[i],
                              v = this.parameter(n);
                          if (typeof v == STRING) {
                              v = [v];
                          }
                          if (n == name) {
                              v = (value === null || value === '') ? [] : 
                                  (append ? v.concat([value]) : [value]);
                          }
                          for (var j = 0; j < v.length; j++) {
                              params.push(n + '=' + v[j]);
                          }
                      }
                      if ($.inArray(name, names) == -1 && value !== null && value !== '') {
                          params.push(name + '=' + value);
                      }
                      this.queryString(params.join('&'));
                      return this;
                  }
                  value = this.queryString();
                  if (value) {
                      var r = [];
                      params = value.split('&');
                      for (i = 0; i < params.length; i++) {
                          var p = params[i].split('=');
                          if (p[0] == name) {
                              r.push(p.slice(1).join('='));
                          }
                      }
                      if (r.length !== 0) {
                          return r.length != 1 ? r : r[0];
                      }
                  }
              },
              parameterNames: function() {
                  var qs = this.queryString(),
                      names = [];
                  if (qs && qs.indexOf('=') != -1) {
                      var params = qs.split('&');
                      for (var i = 0; i < params.length; i++) {
                          var name = params[i].split('=')[0];
                          if ($.inArray(name, names) == -1) {
                              names.push(name);
                          }
                      }
                  }
                  return names;
              },
              hash: function(value) {
                  if (value !== UNDEFINED) {
                      this.value(_value.split('#')[0] + (value ? '#' + value : ''));
                      return this;
                  }
                  var arr = _value.split('#');
                  return arr.slice(1, arr.length).join('#');                
              }
          };
      })();
      
      $.fn.address = function(fn) {
          var sel;
          if (typeof fn == 'string') {
              sel = fn;
              fn = undefined;
          }
          if (!$(this).attr('address')) {
              var f = function(e) {
                  if (e.shiftKey || e.ctrlKey || e.metaKey || e.which == 2) {
                      return true;
                  }
                  if ($(this).is('a')) {
                      e.preventDefault();
                      var value = fn ? fn.call(this) : 
                          /address:/.test($(this).attr('rel')) ? $(this).attr('rel').split('address:')[1].split(' ')[0] : 
                          $.address.state() !== undefined && $.address.state() != '/' ? 
                                  $(this).attr('href').replace(new RegExp('^(.*' + $.address.state() + '|\\.)'), '') : 
                                  $(this).attr('href').replace(/^(#\!?|\.)/, '');
                      $.address.value(value);
                  }
              };
              $(sel ? sel : this).live('click', f).live('submit', function(e) {
                  if ($(this).is('form')) {
                      e.preventDefault();
                      var action = $(this).attr('action'),
                          value = fn ? fn.call(this) : (action.indexOf('?') != -1 ? action.replace(/&$/, '') : action + '?') + 
                              $(this).serialize();
                      $.address.value(value);
                  }
              }).attr('address', true);
          }
          return this;
      };
      
  })(jQuery);
  