From 686f1019256822f434aa7cd55a4425758d44016f Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Fri, 13 May 2011 13:30:49 +1200 Subject: [PATCH 01/24] ENHANCEMENT Toggleable panels in CMS --- admin/code/LeftAndMain.php | 4 + admin/css/layout.css | 7 +- admin/css/screen.css | 47 +++++--- admin/javascript/LeftAndMain.Panel.js | 108 ++++++++++++++++++ admin/javascript/LeftAndMain.js | 27 +++-- admin/scss/_menu.scss | 39 +++++++ admin/scss/_style.scss | 59 +++++++++- admin/templates/Includes/LeftAndMain_Menu.ss | 96 ++++++++-------- .../templates/Includes/ModelAdmin_Content.ss | 53 +++++---- 9 files changed, 341 insertions(+), 99 deletions(-) create mode 100644 admin/javascript/LeftAndMain.Panel.js diff --git a/admin/code/LeftAndMain.php b/admin/code/LeftAndMain.php index 20cb96b4c..df50f0fd5 100755 --- a/admin/code/LeftAndMain.php +++ b/admin/code/LeftAndMain.php @@ -254,8 +254,10 @@ class LeftAndMain extends Controller { Requirements::css(THIRDPARTY_DIR . '/jstree/themes/apple/style.css'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.js'); + Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Panel.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Tree.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.EditForm.js'); + Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Menu.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.AddForm.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Preview.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.BatchActions.js'); @@ -310,8 +312,10 @@ class LeftAndMain extends Controller { 'leftandmain.js', array( SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.js', + SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Panel.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Tree.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.EditForm.js', + SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Menu.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.AddForm.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Preview.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.BatchActions.js', diff --git a/admin/css/layout.css b/admin/css/layout.css index 4a4136147..bae19c120 100755 --- a/admin/css/layout.css +++ b/admin/css/layout.css @@ -24,11 +24,14 @@ html, body { width: 100%; height: 100%; padding: 0; margin: 0; overflow: hidden; .cms-container { height: 100%; } .cms-menu { width: 250px; overflow: auto; } +.cms-menu .cms-panel-content { width: 250px; } +.cms-menu.collapsed { width: 40px; } .cms-preview, .cms-menu, .cms-content, .cms-content-header, .cms-content-tools, .cms-content-form { display: -moz-inline-box; -moz-box-orient: vertical; display: inline-block; vertical-align: middle; *vertical-align: auto; } .cms-preview, .cms-menu, .cms-content, .cms-content-header, .cms-content-tools, .cms-content-form { *display: inline; } -.cms-content-tools { width: 230px; padding: 10px; overflow: auto; } +.cms-content-tools { width: 230px; overflow: auto; } +.cms-content-tools .cms-panel-header, .cms-content-tools .cms-panel-content { padding: 10px; } .cms-content-form { overflow: auto; } @@ -38,6 +41,8 @@ html, body { width: 100%; height: 100%; padding: 0; margin: 0; overflow: hidden; .cms-content-actions { padding: 10px; } +.cms-header { padding: 7px 0 7px 7px; } + .cms-logo { height: 30px; overflow: hidden; vertical-align: middle; } .cms-login-status { height: 30px; overflow: hidden; vertical-align: middle; } diff --git a/admin/css/screen.css b/admin/css/screen.css index 119229857..3d19ab669 100755 --- a/admin/css/screen.css +++ b/admin/css/screen.css @@ -137,20 +137,27 @@ li.jstree-closed > ul { display: none; } @charset "UTF-8"; .cms-menu { z-index: 10; background: #c6d7df; border-right: 1px solid #8c99a1; width: 250px; overflow: auto; -moz-box-shadow: rgba(107, 120, 123, 0.5) 2px 0 6px 0; -webkit-box-shadow: rgba(107, 120, 123, 0.5) 2px 0 6px 0; -o-box-shadow: rgba(107, 120, 123, 0.5) 2px 0 6px 0; box-shadow: rgba(107, 120, 123, 0.5) 2px 0 6px 0; } .cms-menu a { text-decoration: none; } +.cms-menu.collapsed { cursor: auto; } +.cms-menu.collapsed .cms-menu-list li span.text { display: none; } +.cms-menu.collapsed .cms-menu-list li ul { display: none; } +.cms-menu.collapsed.cms-panel .cms-panel-content { display: block; } -.cms-menu-list li a { display: block; height: 30px; line-height: 30px; vertical-align: middle; font-size: 13px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; text-shadow: #ced7dc 1px 1px 0; color: #1f1f1f; padding: 5px; background-color: #b0bec7; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #b0bec7), color-stop(100%, #98aab6)); background-image: -moz-linear-gradient(top, #b0bec7 0%, #98aab6 100%); background-image: linear-gradient(top, #b0bec7 0%, #98aab6 100%); border-top: 1px solid #ced7dc; border-bottom: 1px solid #748d9d; } -.cms-menu-list li a:hover { text-decoration: none; background-color: #b6c3cb; border-bottom: 1px solid #8399a7; color: #2c2c2c; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #bfcad2), color-stop(100%, #b0bec7)); background-image: -moz-linear-gradient(top, #bfcad2 0%, #b0bec7 100%); background-image: linear-gradient(top, #bfcad2 0%, #b0bec7 100%); } -.cms-menu-list li a:focus { border-top: 1px solid #a1b2bc; text-decoration: none; background-color: #a1b2bc; color: #393939; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #92a5b2), color-stop(100%, #a1b2bc)); background-image: -moz-linear-gradient(top, #92a5b2 0%, #a1b2bc 100%); background-image: linear-gradient(top, #92a5b2 0%, #a1b2bc 100%); } -.cms-menu-list li a .icon { display: block; float: left; margin-right: 4px; background: url('../images/icons-32.png') no-repeat; width: 32px; height: 32px; overflow: hidden; background-position: 0px 0px; } -.cms-menu-list li a .text { display: block; } -.cms-menu-list li.current a { color: white; text-shadow: #1e5270 0 -1px 0; border-top: 1px solid #55a4d2; border-bottom: 1px solid #1e5270; background-color: #338dc1; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #338dc1), color-stop(100%, #287099)); background-image: -moz-linear-gradient(top, #338dc1 0%, #287099 100%); background-image: linear-gradient(top, #338dc1 0%, #287099 100%); } -.cms-menu-list li.current ul { border-top: 1px solid #1e5270; } -.cms-menu-list li.current li { background-color: #287099; } -.cms-menu-list li.current li a { font-size: 11px; padding: 0 10px 0 36px; height: 32px; line-height: 32px; color: #e2f0f7; background: none; border-top: 1px solid #338dc1; border-bottom: 1px solid #1e5270; } -.cms-menu-list li.current li a.current, .cms-menu-list li.current li a:hover { background: #2e7ead; border-top: 1px solid #2e7ead; color: white; } -.cms-menu-list li.current li a:focus { background: #236184; border-top: 1px solid #1e5270; color: white; } -.cms-menu-list li.current li.current a { font-weight: bold; color: white; } -.cms-menu-list li.current li.first a { border-top: none; } +.cms-menu-list li { background-color: #b0bfc6; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #b0bfc6), color-stop(100%, #758f9b)); background-image: -moz-linear-gradient(top, #b0bfc6 0%, #758f9b 100%); background-image: linear-gradient(top, #b0bfc6 0%, #758f9b 100%); border-bottom: 1px solid #aaaaaa; } +.cms-menu-list li a { display: block; height: 32px; vertical-align: middle; font-size: 14px; text-shadow: #aaaaaa 1px 1px 1px; color: #333333; padding: 5px; } +.cms-menu-list li a .icon { display: block; float: left; margin-right: 5px; background: url('../images/icons-32.png?1305180670') no-repeat; width: 32px; height: 32px; overflow: hidden; background-position: 0px 0px; } +.cms-menu-list li a .text { display: block; padding-top: 10px; } +.cms-menu-list li.current { background-color: #338dc1; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #338dc1), color-stop(100%, #1e5270)); background-image: -moz-linear-gradient(top, #338dc1 0%, #1e5270 100%); background-image: linear-gradient(top, #338dc1 0%, #1e5270 100%); } +.cms-menu-list li.current li { background-color: #2e7ead; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #2e7ead), color-stop(100%, #287099)); background-image: -moz-linear-gradient(top, #2e7ead 0%, #287099 100%); background-image: linear-gradient(top, #2e7ead 0%, #287099 100%); } +.cms-menu-list li.current a { color: white; text-shadow: #333333 1px 1px 1px; } +.cms-menu-list li li:first { -moz-box-shadow: #333333 0 4px 4px 0; -webkit-box-shadow: #333333 0 4px 4px 0; -o-box-shadow: #333333 0 4px 4px 0; box-shadow: #333333 0 4px 4px 0; } +.cms-menu-list li li a { font-size: 12px; text-shadow: #333333 1px 1px 1px; margin: 0; padding-left: 30px; color: white; } +.cms-menu-list li li.current a { font-weight: bold; } +.cms-menu-list li#Menu-CMSMain a .icon { background-position: 0px 0px; } +.cms-menu-list li#Menu-CMSMain.current a .icon, .cms-menu-list li#Menu-CMSMain a:hover .icon { background-position: -32px 0px; } +.cms-menu-list li#Menu-AssetAdmin a .icon { background-position: 0px -32px; } +.cms-menu-list li#Menu-AssetAdmin.current a .icon, .cms-menu-list li#Menu-AssetAdmin a:hover .icon { background-position: -32px -32px; } +.cms-menu-list.collapsed li .text { display: none; } +.cms-menu-list.collapsed li > li { display: none; } /** This file defines common styles for form elements used throughout the CMS interface. It is an addition to the base styles defined in sapphire/css/Form.css. */ .field { display: block; padding: 10px 0; border-bottom: 1px solid rgba(201, 205, 206, 0.8); } @@ -225,7 +232,7 @@ strong { font-weight: bold; } .ui-tabs .cms-content-header .ui-state-default, .ui-tabs .cms-content-header .ui-widget-content .ui-state-default, .ui-tabs .cms-content-header .ui-widget-header .ui-state-default { background-color: #feffff; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #feffff), color-stop(100%, #d6d9da)); background-image: -moz-linear-gradient(top, #feffff 0%, #d6d9da 100%); background-image: linear-gradient(top, #feffff 0%, #d6d9da 100%); } .ui-tabs .cms-content-header .ui-state-active, .ui-tabs .cms-content-header .ui-widget-content .ui-state-active, .ui-tabs .cms-content-header .ui-widget-header .ui-state-active { background: #eceff1; } -.cms-content-tools { background-color: #dde3e6; padding: 10px; width: 230px; overflow: auto; } +.cms-content-tools { background-color: #dce3e6; } /** ------------------------------------------------------- Top Left Header and logo area -------------------------------------------------------- */ .cms-header { background-color: #00111d; position: relative; padding: 16px 8px 8px; line-height: 24px; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #00111d), color-stop(50%, #003050), color-stop(100%, #00111d)); background-image: -moz-linear-gradient(top, #00111d 0%, #003050 50%, #00111d 100%); background-image: linear-gradient(top, #00111d 0%, #003050 50%, #00111d 100%); } @@ -283,9 +290,17 @@ form.member-profile-form .formattingHelpText { margin: 5px auto; color: #333; pa form.member-profile-form .formattingHelpText ul { padding: 0; } form.member-profile-form .formattingHelpText li { font-size: 11px; color: #333; margin-bottom: 2px; } -.cms-content-form { overflow: auto; } +.cms-panel { overflow: hidden; } +.cms-panel .toggle-expand, .cms-panel .toggle-collapse { display: block; position: absolute; bottom: 0; text-align: right; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #afbfc7), color-stop(100%, #91a7b2)); background-image: -moz-linear-gradient(top, #afbfc7 0%, #91a7b2 100%); background-image: linear-gradient(top, #afbfc7 0%, #91a7b2 100%); } +.cms-panel .toggle-expand span, .cms-panel .toggle-collapse span { display: inline-block; margin: 5px; color: #333333; font-size: 16px; } +.cms-panel .toggle-collapse { width: 100%; } +.cms-panel .toggle-expand { width: 40px; } +.cms-panel.collapsed .cms-panel-content { display: none; } +.cms-panel.collapsed .cms-panel-header { -moz-transform: rotate(-90deg); -webkit-transform: rotate(-90deg); -o-transform: rotate(-90deg); transform: rotate(-90deg); position: relative; top: 100px; } -.cms-preview { background-color: #b0bec7; } +.cms-content .cms-panel.collapsed { cursor: pointer; } + +.cms-preview { background-color: #b0bfc6; } .cms-preview .cms-preview-toggle { cursor: pointer; } .cms-preview .cms-preview-toggle a { color: white; font-weight: bold; text-decoration: none; } diff --git a/admin/javascript/LeftAndMain.Panel.js b/admin/javascript/LeftAndMain.Panel.js new file mode 100644 index 000000000..b4d12f878 --- /dev/null +++ b/admin/javascript/LeftAndMain.Panel.js @@ -0,0 +1,108 @@ +(function($) { + + $.entwine('ss', function($){ + + // setup jquery.entwine + $.entwine.warningLevel = $.entwine.WARN_LEVEL_BESTPRACTISE; + + /** + * Vertically collapsible panel. Generic enough to work with CMS menu as well as various "filter" panels. + * + * A panel consists of the following parts: + * - Container div: The outer element, with class ".cms-panel" + * - Header (optional) + * - Content + * - Expand and collapse toggle anchors (optional) + * + * Sample HTML: + *
+ *
your header
+ *
your content here
+ * your toggle text + * your toggle text + *
+ */ + $('.cms-panel').entwine({ + + WidthExpanded: null, + + WidthCollapsed: null, + + onmatch: function() { + if(!this.find('.cms-panel-content').length) throw new Exception('Content panel for ".cms-panel" not found'); + + // Create default controls unless they already exist + if(!this.find('.toggle-expand').length) this.append('»'); + if(!this.find('.toggle-collapse').length) this.append('«'); + + // Set panel width same as the content panel it contains. Assumes the panel has overflow: hidden. + this.setWidthExpanded(this.find('.cms-panel-content').width()); + + // Assumes the collasped width is indicated by the toggle, or by an optional collapsed view + var collapsedContent = this.find('.cms-panel-content-collapsed'); + this.setWidthCollapsed(collapsedContent.length ? collapsedContent.widht() : this.find('.toggle-expand').width()); + + this.togglePanel(!jQuery(this).hasClass('collapsed')); + + this._super(); + }, + + onclick: function(e) { + // By default, the whole collapsed area serves as a trigger + if(this.data('expandOnClick') && jQuery(this).hasClass('collapsed')) { + e.preventDefault(); + this.expandPanel(); + } + }, + + togglePanel: function(bool) { + // if((!bool && this.hasClass('collapsed')) || (bool && !this.hasClass('collapsed'))) return; + + this.toggleClass('collapsed', !bool); + var newWidth = bool ? this.getWidthExpanded() : this.getWidthCollapsed(); + + this.trigger('beforetoggle'); + this.width(newWidth); // the content panel width always stays in "expanded state" to avoid floating elements + this.find('.toggle-collapse')[bool ? 'show' : 'hide'](); + this.find('.toggle-expand')[bool ? 'hide' : 'show'](); + + // If an alternative collapsed view exists, toggle it as well + var collapsedContent = this.find('.cms-panel-content-collapsed'); + if(collapsedContent.length) { + this.find('.cms-panel-content')[bool ? 'show' : 'hide'](); + this.find('.cms-panel-content-collapsed')[bool ? 'hide' : 'show'](); + } + + this.trigger('toggle'); + }, + + expandPanel: function() { + this.togglePanel(true); + }, + + collapsePanel: function() { + this.togglePanel(false); + } + }); + + $('.cms-panel *').entwine({ + getPanel: function() { + return this.parents('.cms-panel:first'); + } + }); + + $('.cms-panel .toggle-expand').entwine({ + onclick: function(e) { + e.preventDefault(); + this.getPanel().expandPanel(); + } + }); + + $('.cms-panel .toggle-collapse').entwine({ + onclick: function(e) { + this.getPanel().collapsePanel(); + return false; + } + }); + }); +}(jQuery)); \ No newline at end of file diff --git a/admin/javascript/LeftAndMain.js b/admin/javascript/LeftAndMain.js index 16345f309..ef57b1c28 100755 --- a/admin/javascript/LeftAndMain.js +++ b/admin/javascript/LeftAndMain.js @@ -65,12 +65,8 @@ } // Initialize layouts, inner to outer - var doInnerLayout = function() {$('.cms-content').layout();} - var outer = $('.cms-container'); - var doOuterLayout = function() {outer.layout({resize: false});} - doInnerLayout(); - doOuterLayout(); - $(window).resize(doOuterLayout); + this.updateLayout(); + $(window).resize(function() {self.updateLayout()}); // Remove loading screen $('.ss-loading-screen').hide(); @@ -79,13 +75,15 @@ this._setupPinging(); - $('.cms-edit-form').live('loadnewpage', function() { - doInnerLayout(); - doOuterLayout(); - }); + $('.cms-edit-form').live('loadnewpage', function() {self.updateLayout()}); this._super(); }, + + updateLayout: function() { + $('.cms-content').layout(); + $('.cms-container').layout({resize: false}) + }, /** * Function: _setupPinging @@ -116,6 +114,15 @@ }, this.getPingIntervalSeconds() * 1000); } }); + + /** + * Monitor all panels for layout changes + */ + $('.LeftAndMain .cms-panel').entwine({ + ontoggle: function(e) { + this.parents('.LeftAndMain').updateLayout(); + } + }); /** * Class: .LeftAndMain :submit, .LeftAndMain button, .LeftAndMain :reset diff --git a/admin/scss/_menu.scss b/admin/scss/_menu.scss index 9d3b88792..101b5c76c 100755 --- a/admin/scss/_menu.scss +++ b/admin/scss/_menu.scss @@ -21,6 +21,30 @@ a { text-decoration: none; } + + .cms-panel-content { + width: 250px; // avoids floating of elements when collapsed + } + + // toggled via JS + &.collapsed { + + width: 40px; + cursor: auto; + + .cms-menu-list { + li span.text { + display: none; + } + li ul { + display: none; + } + } + + &.cms-panel .cms-panel-content { + display: block; // override panel defaults + } + } } .cms-menu-list { @@ -140,4 +164,19 @@ } } } + + li#Menu-CMSMain a .icon {@include sprite-position(1, 1);} + li#Menu-CMSMain.current a .icon, li#Menu-CMSMain a:hover .icon {@include sprite-position(2, 1);} + li#Menu-AssetAdmin a .icon {@include sprite-position(1, 2);} + li#Menu-AssetAdmin.current a .icon, li#Menu-AssetAdmin a:hover .icon {@include sprite-position(2, 2);} + + &.collapsed { + li .text { + display: none; + } + + li > li { + display: none; + } + } } \ No newline at end of file diff --git a/admin/scss/_style.scss b/admin/scss/_style.scss index 1e0fd04c0..656e262ec 100755 --- a/admin/scss/_style.scss +++ b/admin/scss/_style.scss @@ -121,9 +121,13 @@ strong { .cms-content-tools { background-color: darken($color-widget-bg, 5%); - padding: 10px; width: 230px; overflow: auto; + + .cms-panel-header, + .cms-panel-content { + padding: 10px; + } } @@ -405,6 +409,59 @@ form.member-profile-form { overflow: auto; } +// ######################### Panels ######################### +.cms-panel { + + overflow: hidden; + + .toggle-expand, + .toggle-collapse { + display: block; + position: absolute; + bottom: 0; + text-align: right; + @include linear-gradient(color-stops( + darken($color-widget-bg, 20%), + darken($color-widget-bg, 30%) + )); + + span { + display: inline-block; + margin: 5px; + color: $color-text-dark; + font-size: 16px; + } + } + + .toggle-collapse { + width: 100%; + } + + .toggle-expand { + width: 40px; // will set the collapsed width + } + + &.collapsed { + + .cms-panel-content { + display: none; + } + + .cms-panel-header { + @include rotate(-90deg); + // TODO How to reflow container to correct height? + position: relative; + top: 100px; + } + } + +} + +.cms-content .cms-panel.collapsed { + cursor: pointer; +} + +// ######################### Other ######################### .cms-preview { background-color: $color-base; diff --git a/admin/templates/Includes/LeftAndMain_Menu.ss b/admin/templates/Includes/LeftAndMain_Menu.ss index da5537edd..383488c8f 100755 --- a/admin/templates/Includes/LeftAndMain_Menu.ss +++ b/admin/templates/Includes/LeftAndMain_Menu.ss @@ -1,50 +1,54 @@ -
+
+ +
-
- - - - - +
\ No newline at end of file diff --git a/admin/templates/Includes/ModelAdmin_Content.ss b/admin/templates/Includes/ModelAdmin_Content.ss index c8643d761..1f79725be 100755 --- a/admin/templates/Includes/ModelAdmin_Content.ss +++ b/admin/templates/Includes/ModelAdmin_Content.ss @@ -6,34 +6,37 @@
- -
- -
- <% if SearchClassSelector = tabs %> -
    - <% control ModelForms %> -
  • $Title
  • - <% end_control %> -
- <% end_if %> - - <% if SearchClassSelector = dropdown %> -
- Search for: - -
- <% end_if %> + + <% end_if %> - <% control ModelForms %> -
- $Content -
- <% end_control %> + <% if SearchClassSelector = dropdown %> +
+ Search for: + +
+ <% end_if %> + + <% control ModelForms %> +
+ $Content +
+ <% end_control %> +
From 6649d69b397aca3d4d4e3ed7c477f99eeae5924a Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Fri, 13 May 2011 17:10:50 +1200 Subject: [PATCH 02/24] MINOR Updated menu icons --- admin/css/screen.css | 12 +++++++++--- admin/scss/_menu.scss | 21 +++++++++++++++++++-- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/admin/css/screen.css b/admin/css/screen.css index 3d19ab669..2a0c09228 100755 --- a/admin/css/screen.css +++ b/admin/css/screen.css @@ -144,18 +144,24 @@ li.jstree-closed > ul { display: none; } .cms-menu-list li { background-color: #b0bfc6; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #b0bfc6), color-stop(100%, #758f9b)); background-image: -moz-linear-gradient(top, #b0bfc6 0%, #758f9b 100%); background-image: linear-gradient(top, #b0bfc6 0%, #758f9b 100%); border-bottom: 1px solid #aaaaaa; } .cms-menu-list li a { display: block; height: 32px; vertical-align: middle; font-size: 14px; text-shadow: #aaaaaa 1px 1px 1px; color: #333333; padding: 5px; } -.cms-menu-list li a .icon { display: block; float: left; margin-right: 5px; background: url('../images/icons-32.png?1305180670') no-repeat; width: 32px; height: 32px; overflow: hidden; background-position: 0px 0px; } +.cms-menu-list li a .icon { display: block; float: left; margin-right: 5px; background: url('../images/icons-32.png?1305262748') no-repeat; width: 32px; height: 32px; overflow: hidden; background-position: 0px 0px; } +.cms-menu-list li a:hover .icon { background-position: -32px 0px; } .cms-menu-list li a .text { display: block; padding-top: 10px; } .cms-menu-list li.current { background-color: #338dc1; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #338dc1), color-stop(100%, #1e5270)); background-image: -moz-linear-gradient(top, #338dc1 0%, #1e5270 100%); background-image: linear-gradient(top, #338dc1 0%, #1e5270 100%); } .cms-menu-list li.current li { background-color: #2e7ead; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #2e7ead), color-stop(100%, #287099)); background-image: -moz-linear-gradient(top, #2e7ead 0%, #287099 100%); background-image: linear-gradient(top, #2e7ead 0%, #287099 100%); } .cms-menu-list li.current a { color: white; text-shadow: #333333 1px 1px 1px; } +.cms-menu-list li.current a .icon { background-position: -32px 0px; } .cms-menu-list li li:first { -moz-box-shadow: #333333 0 4px 4px 0; -webkit-box-shadow: #333333 0 4px 4px 0; -o-box-shadow: #333333 0 4px 4px 0; box-shadow: #333333 0 4px 4px 0; } .cms-menu-list li li a { font-size: 12px; text-shadow: #333333 1px 1px 1px; margin: 0; padding-left: 30px; color: white; } .cms-menu-list li li.current a { font-weight: bold; } .cms-menu-list li#Menu-CMSMain a .icon { background-position: 0px 0px; } .cms-menu-list li#Menu-CMSMain.current a .icon, .cms-menu-list li#Menu-CMSMain a:hover .icon { background-position: -32px 0px; } -.cms-menu-list li#Menu-AssetAdmin a .icon { background-position: 0px -32px; } -.cms-menu-list li#Menu-AssetAdmin.current a .icon, .cms-menu-list li#Menu-AssetAdmin a:hover .icon { background-position: -32px -32px; } +.cms-menu-list li#Menu-AssetAdmin a .icon { background-position: 0px -96px; } +.cms-menu-list li#Menu-AssetAdmin.current a .icon, .cms-menu-list li#Menu-AssetAdmin a:hover .icon { background-position: -32px -96px; } +.cms-menu-list li#Menu-SecurityAdmin a .icon { background-position: 0px -128px; } +.cms-menu-list li#Menu-SecurityAdmin.current a .icon, .cms-menu-list li#Menu-SecurityAdmin a:hover .icon { background-position: -32px -128px; } +.cms-menu-list li#Menu-CMSPagesController a .icon { background-position: 0px -32px; } +.cms-menu-list li#Menu-CMSPagesController.current a .icon, .cms-menu-list li#Menu-CMSPagesController a:hover .icon { background-position: -32px -32px; } .cms-menu-list.collapsed li .text { display: none; } .cms-menu-list.collapsed li > li { display: none; } diff --git a/admin/scss/_menu.scss b/admin/scss/_menu.scss index 101b5c76c..9b75e516b 100755 --- a/admin/scss/_menu.scss +++ b/admin/scss/_menu.scss @@ -103,6 +103,10 @@ @include sprite-position(1, 1); } + &:hover .icon { + @include sprite-position(2, 1); + } + .text { display: block; } @@ -125,6 +129,15 @@ border-top: 1px solid darken($color-menu-button, 20%); } + a .icon { + @include sprite-position(2, 1); + } + } + + // nested elements + li { + + li { background-color: darken($color-menu-button, 10%); @@ -167,8 +180,12 @@ li#Menu-CMSMain a .icon {@include sprite-position(1, 1);} li#Menu-CMSMain.current a .icon, li#Menu-CMSMain a:hover .icon {@include sprite-position(2, 1);} - li#Menu-AssetAdmin a .icon {@include sprite-position(1, 2);} - li#Menu-AssetAdmin.current a .icon, li#Menu-AssetAdmin a:hover .icon {@include sprite-position(2, 2);} + li#Menu-AssetAdmin a .icon {@include sprite-position(1, 4);} + li#Menu-AssetAdmin.current a .icon, li#Menu-AssetAdmin a:hover .icon {@include sprite-position(2, 4);} + li#Menu-SecurityAdmin a .icon {@include sprite-position(1, 5);} + li#Menu-SecurityAdmin.current a .icon, li#Menu-SecurityAdmin a:hover .icon {@include sprite-position(2, 5);} + li#Menu-CMSPagesController a .icon {@include sprite-position(1, 2);} + li#Menu-CMSPagesController.current a .icon, li#Menu-CMSPagesController a:hover .icon {@include sprite-position(2, 2);} &.collapsed { li .text { From 2b56d2a8d864c00c9e7b9777e914e6d0f0198dd1 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Sun, 15 May 2011 15:43:21 +1200 Subject: [PATCH 03/24] FEATURE Preview panel to show CMS changes on actual website. Navigating in preview loads new page for editing in CMS. --- admin/code/LeftAndMain.php | 19 +++-- admin/css/layout.css | 2 +- admin/css/screen.css | 5 +- admin/javascript/LeftAndMain.Menu.js | 17 ++++ admin/javascript/LeftAndMain.Preview.js | 100 ++++++++++++++++-------- admin/javascript/LeftAndMain.js | 10 +-- admin/scss/_style.scss | 18 ++++- admin/templates/LeftAndMain.ss | 6 +- 8 files changed, 125 insertions(+), 52 deletions(-) create mode 100644 admin/javascript/LeftAndMain.Menu.js diff --git a/admin/code/LeftAndMain.php b/admin/code/LeftAndMain.php index df50f0fd5..79241a516 100755 --- a/admin/code/LeftAndMain.php +++ b/admin/code/LeftAndMain.php @@ -1074,12 +1074,17 @@ class LeftAndMain extends Controller { } /** - * Get the staus of a certain page and version. - * - * This function is used for concurrent editing, and providing alerts - * when multiple users are editing a single page. It echoes a json - * encoded string to the UA. + * URL to a previewable record which is shown through this controller. + * The controller might not have any previewable content, in which case + * this method returns FALSE. + * + * @return String|boolean */ + public function PreviewLink() { + $record = $this->getRecord($this->currentPageID()); + $baseLink = ($record && $record instanceof Page) ? $record->Link('?stage=Stage') : Director::absoluteBaseURL(); + return Controller::join_links($baseLink, '?cms-preview-disabled=1'); + } /** * Return the version number of this application. @@ -1166,6 +1171,10 @@ class LeftAndMain extends Controller { return MCE_ROOT; } + function IsPreviewExpanded() { + return ($this->request->getVar('cms-preview-expanded')); + } + /** * Register the given javascript file as required in the CMS. * Filenames should be relative to the base, eg, SAPPHIRE_DIR . '/javascript/loader.js' diff --git a/admin/css/layout.css b/admin/css/layout.css index bae19c120..de4a5a1c4 100755 --- a/admin/css/layout.css +++ b/admin/css/layout.css @@ -17,7 +17,7 @@ a img { border: none; } @charset "UTF-8"; html, body { width: 100%; height: 100%; padding: 0; margin: 0; overflow: hidden; } -.cms-preview { width: 1px; overflow: hidden; } +.cms-preview { width: 1px; } .cms-preview .cms-preview-toggle { width: 10px; } .cms-preview iframe { width: 100%; height: 100%; } diff --git a/admin/css/screen.css b/admin/css/screen.css index 2a0c09228..06e3d7c45 100755 --- a/admin/css/screen.css +++ b/admin/css/screen.css @@ -297,7 +297,7 @@ form.member-profile-form .formattingHelpText ul { padding: 0; } form.member-profile-form .formattingHelpText li { font-size: 11px; color: #333; margin-bottom: 2px; } .cms-panel { overflow: hidden; } -.cms-panel .toggle-expand, .cms-panel .toggle-collapse { display: block; position: absolute; bottom: 0; text-align: right; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #afbfc7), color-stop(100%, #91a7b2)); background-image: -moz-linear-gradient(top, #afbfc7 0%, #91a7b2 100%); background-image: linear-gradient(top, #afbfc7 0%, #91a7b2 100%); } +.cms-panel .toggle-expand, .cms-panel .toggle-collapse { display: block; position: absolute; bottom: 0; text-align: right; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #afbfc7), color-stop(100%, #91a7b2)); background-image: -moz-linear-gradient(top, #afbfc7 0%, #91a7b2 100%); background-image: linear-gradient(top, #afbfc7 0%, #91a7b2 100%); text-decoration: none; } .cms-panel .toggle-expand span, .cms-panel .toggle-collapse span { display: inline-block; margin: 5px; color: #333333; font-size: 16px; } .cms-panel .toggle-collapse { width: 100%; } .cms-panel .toggle-expand { width: 40px; } @@ -308,6 +308,7 @@ form.member-profile-form .formattingHelpText li { font-size: 11px; color: #333; .cms-preview { background-color: #b0bfc6; } .cms-preview .cms-preview-toggle { cursor: pointer; } -.cms-preview .cms-preview-toggle a { color: white; font-weight: bold; text-decoration: none; } +.cms-preview .cms-preview-toggle a { display: block; width: 15px; height: 15px; position: relative; left: 10px; top: 48%; background-color: #b0bfc6; color: white; font-weight: bold; text-decoration: none; z-index: 2000; } +.cms-preview.is-collapsed .cms-preview-toggle a { left: -15px; } .cms-switch-view a { padding-right: 1em; } diff --git a/admin/javascript/LeftAndMain.Menu.js b/admin/javascript/LeftAndMain.Menu.js new file mode 100644 index 000000000..401c71b6f --- /dev/null +++ b/admin/javascript/LeftAndMain.Menu.js @@ -0,0 +1,17 @@ +(function($) { + + $.entwine('ss', function($){ + + $('.cms-menu').entwine({ + + }); + + $('.cms-menu.collapsed li').entwine({ + onclick: function() { + // the container is overflow: hidden, so we need to break the subnavigation out of it + // return false; + } + }); + + }); +}(jQuery)); \ No newline at end of file diff --git a/admin/javascript/LeftAndMain.Preview.js b/admin/javascript/LeftAndMain.Preview.js index a6ab43c28..c4507a300 100755 --- a/admin/javascript/LeftAndMain.Preview.js +++ b/admin/javascript/LeftAndMain.Preview.js @@ -1,7 +1,10 @@ (function($) { + $.entwine('ss', function($){ + $('.LeftAndMain .cms-preview').entwine({ + // Minimum width to keep the CMS operational SharedWidth: null, onmatch: function() { @@ -17,18 +20,25 @@ this.setSharedWidth(500); // Create layout and controls - this.prepend(''); + this.prepend(''); this.find('iframe').addClass('center'); this.layout({type: 'border'}); - this.find('iframe').bind('load', function() {self._fixIframeLinks();}); + this.find('iframe').bind('load', function() { + self._fixIframeLinks(); + self.loadCurrentPage(); + }); self._fixIframeLinks(); - $('.cms-edit-form').bind('loadnewpage', function(e, ui) { + // Limit to CMS forms for the moment + $('.CMSMain .cms-edit-form').bind('loadnewpage', function(e, ui) { // var url = ui.xmlhttp.getResponseHeader('x-frontend-url'); var url = $(this).find(':input[name=StageURLSegment]').val(); - if(url) self.loadUrl(url); + if(url) self.loadUrl(url + '&cms-preview-disabled=1'); }); + + if(this.hasClass('is-expanded')) this.expand(); + else this.collapse(); this._super(); }, @@ -37,6 +47,18 @@ this.find('iframe').attr('src', url); }, + loadCurrentPage: function() { + var doc = this.find('iframe')[0].contentDocument, container = this.getLayoutContainer(); + + // Only load if we're in the "edit page" view + if(!container.hasClass('CMSMain')) return; + + // Load this page in the admin interface if appropriate + var id = $(doc).find('meta[name=x-page-id]').attr('content'), form = $('.cms-edit-form'); + // TODO Remove hardcoding + if(id && form.find(':input[name=ID]').val() != id) form.loadForm('admin/page/edit/show/' + id); + }, + _fixIframeLinks: function() { var doc = this.find('iframe')[0].contentDocument; @@ -46,41 +68,40 @@ var href = links[i].getAttribute('href'); if (href && href.match(/^http:\/\//)) { links[i].setAttribute('href', 'javascript:false'); + } else { + links[i].setAttribute('href', href + '?cms-preview=1'); } } - - // Load this page in the admin interface if appropriate - var id = $(doc).find('meta[name=x-page-id]').attr('content'), form = $('.cms-edit-form'); - // TODO Remove hardcoding - if(id && form.find(':input[name=ID]').val() != id) form.loadForm('admin/page/edit/show/' + id); + }, + + expand: function() { + var self = this, containerEl = this.getLayoutContainer(), contentEl = containerEl.find('.cms-content'); + this.removeClass('east').addClass('center').removeClass('is-collapsed'); + // this.css('overflow', 'auto'); + contentEl.removeClass('center').hide(); + this.find('iframe').show(); + containerEl.find('.cms-menu').collapsePanel(); + this.find('.cms-preview-toggle a').html('»'); + containerEl.redraw(); + }, + + collapse: function() { + var self = this, containerEl = this.getLayoutContainer(), contentEl = containerEl.find('.cms-content'); + this.addClass('east').removeClass('center').addClass('is-collapsed').width(10); + // this.css('overflow', 'hidden'); + contentEl.addClass('center').show(); + this.find('iframe').hide(); + containerEl.find('.cms-menu').expandPanel(); + this.find('.cms-preview-toggle a').html('«'); + containerEl.redraw(); + }, + + getLayoutContainer: function() { + return this.parents('.LeftAndMain'); }, toggle: function(bool) { - var self = this, - width = this.width(), - relayout = function() {$('.cms-container').layout({resize: false});}, - minWidth = this.find('.cms-preview-toggle').width(), - wasCollapsed = (bool === true || bool === false) ? bool : (width <= minWidth), - newWidth = wasCollapsed ? this.getSharedWidth() : minWidth, - newOverflow = wasCollapsed ? 'auto' : 'hidden'; - - this.css('overflow', newOverflow).width(newWidth); - this.toggleClass('collapsed', !wasCollapsed).toggleClass('expanded', wasCollapsed); - this.find('iframe').toggle(wasCollapsed); - relayout(); - - // this.css('overflow', newOverflow).animate( - // {width: newWidth+'px'}, - // { - // duration: 500, - // complete: function() { - // relayout(); - // self.toggleClass('collapsed', !wasCollapsed).toggleClass('expanded', wasCollapsed); - // self.find('iframe').toggle(wasCollapsed); - // }, - // step: relayout - // } - // ); + this[this.hasClass('is-collapsed') ? 'expand' : 'collapse'](); } }); @@ -111,5 +132,16 @@ preview.loadUrl($(e.target).attr('href')); } }); + + $('.LeftAndMain .cms-menu li').entwine({ + onclick: function(e) { + // Prevent reloading of interface when opening the edit panel + if(this.hasClass('Menu-CMSMain')) { + var preview = $('.cms-preview'); + preview.toggle(true); + e.preventDefault(); + } + } + }); }); }(jQuery)); \ No newline at end of file diff --git a/admin/javascript/LeftAndMain.js b/admin/javascript/LeftAndMain.js index ef57b1c28..868d4606b 100755 --- a/admin/javascript/LeftAndMain.js +++ b/admin/javascript/LeftAndMain.js @@ -65,8 +65,8 @@ } // Initialize layouts, inner to outer - this.updateLayout(); - $(window).resize(function() {self.updateLayout()}); + this.redraw(); + $(window).resize(function() {self.redraw()}); // Remove loading screen $('.ss-loading-screen').hide(); @@ -75,12 +75,12 @@ this._setupPinging(); - $('.cms-edit-form').live('loadnewpage', function() {self.updateLayout()}); + $('.cms-edit-form').live('loadnewpage', function() {self.redraw()}); this._super(); }, - updateLayout: function() { + redraw: function() { $('.cms-content').layout(); $('.cms-container').layout({resize: false}) }, @@ -120,7 +120,7 @@ */ $('.LeftAndMain .cms-panel').entwine({ ontoggle: function(e) { - this.parents('.LeftAndMain').updateLayout(); + this.parents('.LeftAndMain').redraw(); } }); diff --git a/admin/scss/_style.scss b/admin/scss/_style.scss index 656e262ec..bfae6200b 100755 --- a/admin/scss/_style.scss +++ b/admin/scss/_style.scss @@ -342,7 +342,6 @@ strong { // ######################### Preview header (remove before release) ######################### .cms-preview { width: 1px; // collapsed by default - overflow: hidden; .cms-preview-toggle { width: 10px; @@ -424,6 +423,7 @@ form.member-profile-form { darken($color-widget-bg, 20%), darken($color-widget-bg, 30%) )); + text-decoration: none; span { display: inline-block; @@ -469,9 +469,25 @@ form.member-profile-form { cursor: pointer; a { + display: block; + width: 15px; + height: 15px; + position: relative; + left: 10px; // point right (width of toggle) + top: 48%; + background-color: $color-base; color: $color-text-light; font-weight: bold; text-decoration: none; + z-index: 2000; + } + } + + &.is-collapsed { + .cms-preview-toggle { + a { + left: -15px; // point left + } } } } diff --git a/admin/templates/LeftAndMain.ss b/admin/templates/LeftAndMain.ss index 165b9938a..cdfbc5ba1 100755 --- a/admin/templates/LeftAndMain.ss +++ b/admin/templates/LeftAndMain.ss @@ -25,11 +25,9 @@ $Content - <% if currentPage %> -
- +
+
- <% end_if %>
From 4e0949f565144706cd5ea3742a6a58344ff75dec Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Fri, 20 May 2011 11:38:36 +1200 Subject: [PATCH 04/24] ENHANCEMENT Consistently wrapping CMS forms in
, added LeftAndMain.Content.js to reload panels via ajax, hooking into preview logic --- admin/code/LeftAndMain.php | 2 + admin/css/screen.css | 10 +-- admin/javascript/LeftAndMain.Content.js | 40 +++++++++++ admin/javascript/LeftAndMain.Menu.js | 8 ++- admin/javascript/LeftAndMain.Preview.js | 4 +- admin/scss/_style.scss | 7 ++ .../templates/Includes/LeftAndMain_Content.ss | 4 +- .../Includes/LeftAndMain_EditForm.ss | 72 ++++++++++--------- 8 files changed, 103 insertions(+), 44 deletions(-) create mode 100644 admin/javascript/LeftAndMain.Content.js diff --git a/admin/code/LeftAndMain.php b/admin/code/LeftAndMain.php index 79241a516..55a5e9605 100755 --- a/admin/code/LeftAndMain.php +++ b/admin/code/LeftAndMain.php @@ -256,6 +256,7 @@ class LeftAndMain extends Controller { Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Panel.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Tree.js'); + Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Content.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.EditForm.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Menu.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.AddForm.js'); @@ -314,6 +315,7 @@ class LeftAndMain extends Controller { SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Panel.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Tree.js', + SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Content.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.EditForm.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Menu.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.AddForm.js', diff --git a/admin/css/screen.css b/admin/css/screen.css index 06e3d7c45..ed8e576c8 100755 --- a/admin/css/screen.css +++ b/admin/css/screen.css @@ -144,7 +144,7 @@ li.jstree-closed > ul { display: none; } .cms-menu-list li { background-color: #b0bfc6; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #b0bfc6), color-stop(100%, #758f9b)); background-image: -moz-linear-gradient(top, #b0bfc6 0%, #758f9b 100%); background-image: linear-gradient(top, #b0bfc6 0%, #758f9b 100%); border-bottom: 1px solid #aaaaaa; } .cms-menu-list li a { display: block; height: 32px; vertical-align: middle; font-size: 14px; text-shadow: #aaaaaa 1px 1px 1px; color: #333333; padding: 5px; } -.cms-menu-list li a .icon { display: block; float: left; margin-right: 5px; background: url('../images/icons-32.png?1305262748') no-repeat; width: 32px; height: 32px; overflow: hidden; background-position: 0px 0px; } +.cms-menu-list li a .icon { display: block; float: left; margin-right: 5px; background: url('../images/icons-32.png?1305837920') no-repeat; width: 32px; height: 32px; overflow: hidden; background-position: 0px 0px; } .cms-menu-list li a:hover .icon { background-position: -32px 0px; } .cms-menu-list li a .text { display: block; padding-top: 10px; } .cms-menu-list li.current { background-color: #338dc1; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #338dc1), color-stop(100%, #1e5270)); background-image: -moz-linear-gradient(top, #338dc1 0%, #1e5270 100%); background-image: linear-gradient(top, #338dc1 0%, #1e5270 100%); } @@ -240,10 +240,10 @@ strong { font-weight: bold; } .cms-content-tools { background-color: #dce3e6; } -/** ------------------------------------------------------- Top Left Header and logo area -------------------------------------------------------- */ -.cms-header { background-color: #00111d; position: relative; padding: 16px 8px 8px; line-height: 24px; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #00111d), color-stop(50%, #003050), color-stop(100%, #00111d)); background-image: -moz-linear-gradient(top, #00111d 0%, #003050 50%, #00111d 100%); background-image: linear-gradient(top, #00111d 0%, #003050 50%, #00111d 100%); } -.cms-header span { color: white; white-space: no-wrap; text-overflow: ellipsis; display: block; } -.cms-header span a { color: #3ebae0; display: inline; } +.cms-content.loading { background: url(../images/spinner.gif) no-repeat 50% 50%; } + +.cms-header { background-color: #00111d; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #00111d), color-stop(50%, #003050), color-stop(100%, #00111d)); background-image: -moz-linear-gradient(top, #00111d 0%, #003050 50%, #00111d 100%); background-image: linear-gradient(top, #00111d 0%, #003050 50%, #00111d 100%); } +.cms-header * { color: white; } .cms-logo { border-bottom: 1px solid #03090c; height: 31px; overflow: hidden; padding: 0 4px; vertical-align: middle; } .cms-logo .version { display: none; } diff --git a/admin/javascript/LeftAndMain.Content.js b/admin/javascript/LeftAndMain.Content.js new file mode 100644 index 000000000..529dedd87 --- /dev/null +++ b/admin/javascript/LeftAndMain.Content.js @@ -0,0 +1,40 @@ +(function($) { + + $.entwine('ss', function($){ + + $('.LeftAndMain .cms-content').entwine({ + + redraw: function() { + }, + + cleanup: function() { + this.empty(); + }, + + loadPanel: function(url, callback, ajaxOptions) { + var self = this; + + this.trigger('load', {url: url, args: arguments}); + + this.cleanup(); + + // TODO Add browser history support + return $.ajax($.extend({ + url: url, + complete: function(xmlhttp, status) { + self.loadPanel_onSuccess(xmlhttp.responseText, status, xmlhttp); + self.removeClass('loading'); + + if(callback) callback.apply(self, arguments); + }, + dataType: 'html' + }, ajaxOptions)); + }, + + loadPanel_onSuccess: function(html, status, xmlhttp) { + this.html(html); + this.redraw(); + } + }); + }); +})(jQuery); \ No newline at end of file diff --git a/admin/javascript/LeftAndMain.Menu.js b/admin/javascript/LeftAndMain.Menu.js index 401c71b6f..04af4cd52 100644 --- a/admin/javascript/LeftAndMain.Menu.js +++ b/admin/javascript/LeftAndMain.Menu.js @@ -2,8 +2,12 @@ $.entwine('ss', function($){ - $('.cms-menu').entwine({ - + $('.cms-menu li a').entwine({ + onclick: function(e) { + e.preventDefault(); + console.debug($('.LeftAndMain .cms-content')); + $('.LeftAndMain .cms-content').entwine('ss').loadPanel(this.attr('href')); + } }); $('.cms-menu.collapsed li').entwine({ diff --git a/admin/javascript/LeftAndMain.Preview.js b/admin/javascript/LeftAndMain.Preview.js index c4507a300..d4423c8d3 100755 --- a/admin/javascript/LeftAndMain.Preview.js +++ b/admin/javascript/LeftAndMain.Preview.js @@ -54,9 +54,9 @@ if(!container.hasClass('CMSMain')) return; // Load this page in the admin interface if appropriate - var id = $(doc).find('meta[name=x-page-id]').attr('content'), form = $('.cms-edit-form'); + var id = $(doc).find('meta[name=x-page-id]').attr('content'), contentPanel = $('.cms-content'); // TODO Remove hardcoding - if(id && form.find(':input[name=ID]').val() != id) form.loadForm('admin/page/edit/show/' + id); + if(id && contentPanel.find(':input[name=ID]').val() != id) contentPanel.loadPanel('admin/page/edit/show/' + id); }, _fixIframeLinks: function() { diff --git a/admin/scss/_style.scss b/admin/scss/_style.scss index bfae6200b..c36c6411c 100755 --- a/admin/scss/_style.scss +++ b/admin/scss/_style.scss @@ -130,6 +130,13 @@ strong { } } +.cms-content { + &.loading { + background: url(../images/spinner.gif) no-repeat 50% 50%; + } +} + +// ######################### Header and Logo ######################### /** ------------------------------------------------------- * Top Left Header and logo area diff --git a/admin/templates/Includes/LeftAndMain_Content.ss b/admin/templates/Includes/LeftAndMain_Content.ss index 40443e046..c74f54b0a 100755 --- a/admin/templates/Includes/LeftAndMain_Content.ss +++ b/admin/templates/Includes/LeftAndMain_Content.ss @@ -1 +1,3 @@ -$EditForm \ No newline at end of file +
+$EditForm +
\ No newline at end of file diff --git a/admin/templates/Includes/LeftAndMain_EditForm.ss b/admin/templates/Includes/LeftAndMain_EditForm.ss index d42c8bca2..93c09d44d 100755 --- a/admin/templates/Includes/LeftAndMain_EditForm.ss +++ b/admin/templates/Includes/LeftAndMain_EditForm.ss @@ -1,10 +1,6 @@ -<% if IncludeFormTag %> -
-<% end_if %> -
-

My Page Title

+

My Page Title

<% if Fields.hasTabset %> <% with Fields.fieldByName('Root') %>
@@ -21,38 +17,46 @@
- -
- - <% if Message %> -

$Message

- <% else %> - + + <% if IncludeFormTag %> + <% end_if %> -
- <% if Legend %>$Legend<% end_if %> - <% control Fields %> - $FieldHolder - <% end_control %> -
-
- -
+ -
- <% if Actions %> -
- <% control Actions %> - $Field - <% end_control %> +
+ + <% if Message %> +

$Message

+ <% else %> + + <% end_if %> + +
+ <% if Legend %>$Legend<% end_if %> + <% control Fields %> + $FieldHolder + <% end_control %> +
+
+
- <% end_if %> -
-<% if IncludeFormTag %> - -<% end_if %> \ No newline at end of file +
+ <% if Actions %> +
+ <% control Actions %> + $Field + <% end_control %> +
+ <% end_if %> +
+ + <% if IncludeFormTag %> + + <% end_if %> + +
\ No newline at end of file From 8378a9d56152f0973093a53588147fa9827010a5 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Fri, 20 May 2011 11:39:44 +1200 Subject: [PATCH 05/24] MINOR Moved "pinging" logic for CMS into new LeftAndMain.Ping.js container --- admin/code/LeftAndMain.php | 2 ++ admin/javascript/LeftAndMain.Ping.js | 50 ++++++++++++++++++++++++++++ admin/javascript/LeftAndMain.js | 41 ++--------------------- 3 files changed, 54 insertions(+), 39 deletions(-) create mode 100644 admin/javascript/LeftAndMain.Ping.js diff --git a/admin/code/LeftAndMain.php b/admin/code/LeftAndMain.php index 55a5e9605..7bd961fbc 100755 --- a/admin/code/LeftAndMain.php +++ b/admin/code/LeftAndMain.php @@ -256,6 +256,7 @@ class LeftAndMain extends Controller { Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Panel.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Tree.js'); + Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Ping.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Content.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.EditForm.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Menu.js'); @@ -315,6 +316,7 @@ class LeftAndMain extends Controller { SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Panel.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Tree.js', + SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Ping.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Content.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.EditForm.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Menu.js', diff --git a/admin/javascript/LeftAndMain.Ping.js b/admin/javascript/LeftAndMain.Ping.js new file mode 100644 index 000000000..f35313922 --- /dev/null +++ b/admin/javascript/LeftAndMain.Ping.js @@ -0,0 +1,50 @@ +/** + * File: LeftAndMain.EditForm.js + */ +(function($) { + $.entwine('ss', function($){ + + $('.LeftAndMain').entwine(/** @lends ss.Form_EditForm */{ + /** + * Variable: PingIntervalSeconds + * (Number) Interval in which /Security/ping will be checked for a valid login session. + */ + PingIntervalSeconds: 5*60, + + onmatch: function() { + this._super(); + + this._setupPinging(); + }, + + /** + * Function: _setupPinging + * + * This function is called by prototype when it receives notification that the user was logged out. + * It uses /Security/ping for this purpose, which should return '1' if a valid user session exists. + * It redirects back to the login form if the URL is either unreachable, or returns '0'. + */ + _setupPinging: function() { + var onSessionLost = function(xmlhttp, status) { + if(xmlhttp.status > 400 || xmlhttp.responseText == 0) { + // TODO will pile up additional alerts when left unattended + if(window.open('Security/login')) { + alert("Please log in and then try again"); + } else { + alert("Please enable pop-ups for this site"); + } + } + }; + + // setup pinging for login expiry + setInterval(function() { + jQuery.ajax({ + url: "Security/ping", + global: false, + complete: onSessionLost + }); + }, this.getPingIntervalSeconds() * 1000); + } + }); + }); +}(jQuery)); \ No newline at end of file diff --git a/admin/javascript/LeftAndMain.js b/admin/javascript/LeftAndMain.js index 868d4606b..9576164d9 100755 --- a/admin/javascript/LeftAndMain.js +++ b/admin/javascript/LeftAndMain.js @@ -42,12 +42,6 @@ */ $('.LeftAndMain').entwine({ - /** - * Variable: PingIntervalSeconds - * (Number) Interval in which /Security/ping will be checked for a valid login session. - */ - PingIntervalSeconds: 5*60, - /** * Constructor: onmatch */ @@ -73,45 +67,14 @@ $('body').removeClass('loading'); $(window).unbind('resize', positionLoadingSpinner); - this._setupPinging(); - $('.cms-edit-form').live('loadnewpage', function() {self.redraw()}); this._super(); }, redraw: function() { - $('.cms-content').layout(); - $('.cms-container').layout({resize: false}) - }, - - /** - * Function: _setupPinging - * - * This function is called by prototype when it receives notification that the user was logged out. - * It uses /Security/ping for this purpose, which should return '1' if a valid user session exists. - * It redirects back to the login form if the URL is either unreachable, or returns '0'. - */ - _setupPinging: function() { - var onSessionLost = function(xmlhttp, status) { - if(xmlhttp.status > 400 || xmlhttp.responseText == 0) { - // TODO will pile up additional alerts when left unattended - if(window.open('Security/login')) { - alert("Please log in and then try again"); - } else { - alert("Please enable pop-ups for this site"); - } - } - }; - - // setup pinging for login expiry - setInterval(function() { - jQuery.ajax({ - url: "Security/ping", - global: false, - complete: onSessionLost - }); - }, this.getPingIntervalSeconds() * 1000); + this.find('.cms-content').layout(); + this.find('.cms-container').layout({resize: false}) } }); From a5f841764de94d768990f4776c905ecfe8daf201 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Fri, 20 May 2011 15:49:30 +1200 Subject: [PATCH 06/24] MINOR Added history.js dependency --- admin/thirdparty/history-js/.piston.yml | 8 + admin/thirdparty/history-js/README.md | 311 + admin/thirdparty/history-js/cli | 351 + .../history-js/demo/bcherry-orig.html | 58 + admin/thirdparty/history-js/demo/bcherry.html | 62 + admin/thirdparty/history-js/demo/chrome.html | 37 + admin/thirdparty/history-js/demo/index.html | 101 + .../history-js/demo/native-auto.html | 43 + admin/thirdparty/history-js/demo/native.html | 62 + .../thirdparty/history-js/demo/navigator.html | 23 + admin/thirdparty/history-js/demo/safari.html | 61 + admin/thirdparty/history-js/license.txt | 10 + admin/thirdparty/history-js/package.json | 74 + .../scripts/compressed/amplify.store.js | 1 + .../compressed/history.adapter.dojo.js | 0 .../compressed/history.adapter.jquery.js | 1 + .../compressed/history.adapter.mootools.js | 1 + .../compressed/history.adapter.prototype.js | 1 + .../scripts/compressed/history.adapter.yui.js | 1 + .../compressed/history.adapter.zepto.js | 1 + .../scripts/compressed/history.html4.js | 1 + .../history-js/scripts/compressed/history.js | 1 + .../history-js/scripts/compressed/json2.js | 1 + .../scripts/uncompressed/amplify.store.js | 247 + .../uncompressed/history.adapter.dojo.js | 1 + .../uncompressed/history.adapter.jquery.js | 58 + .../uncompressed/history.adapter.mootools.js | 66 + .../uncompressed/history.adapter.prototype.js | 197 + .../uncompressed/history.adapter.yui.js | 64 + .../uncompressed/history.adapter.zepto.js | 58 + .../scripts/uncompressed/history.html4.js | 606 ++ .../scripts/uncompressed/history.js | 1867 ++++ .../history-js/scripts/uncompressed/json2.js | 480 + .../history-js/tests.src/_header.php | 28 + admin/thirdparty/history-js/tests.src/all.php | 59 + .../thirdparty/history-js/tests.src/each.php | 62 + .../thirdparty/history-js/tests.src/index.php | 25 + admin/thirdparty/history-js/tests/.htaccess | 13 + ...compressed-html4-nonpersistant-jquery.html | 47 + ...mpressed-html4-nonpersistant-mootools.html | 47 + ...pressed-html4-nonpersistant-prototype.html | 47 + .../compressed-html4-nonpersistant-zepto.html | 47 + .../compressed-html4-persistant-jquery.html | 48 + .../compressed-html4-persistant-mootools.html | 48 + ...compressed-html4-persistant-prototype.html | 48 + .../compressed-html4-persistant-zepto.html | 48 + ...compressed-html5-nonpersistant-jquery.html | 46 + ...mpressed-html5-nonpersistant-mootools.html | 46 + ...pressed-html5-nonpersistant-prototype.html | 46 + .../compressed-html5-nonpersistant-zepto.html | 46 + .../compressed-html5-persistant-jquery.html | 47 + .../compressed-html5-persistant-mootools.html | 47 + ...compressed-html5-persistant-prototype.html | 47 + .../compressed-html5-persistant-zepto.html | 47 + admin/thirdparty/history-js/tests/image.php | 3 + admin/thirdparty/history-js/tests/index.html | 28 + admin/thirdparty/history-js/tests/tests.js | 254 + ...compressed-html4-nonpersistant-jquery.html | 47 + ...mpressed-html4-nonpersistant-mootools.html | 47 + ...pressed-html4-nonpersistant-prototype.html | 47 + ...ncompressed-html4-nonpersistant-zepto.html | 47 + .../uncompressed-html4-persistant-jquery.html | 48 + ...ncompressed-html4-persistant-mootools.html | 48 + ...compressed-html4-persistant-prototype.html | 48 + .../uncompressed-html4-persistant-zepto.html | 48 + ...compressed-html5-nonpersistant-jquery.html | 46 + ...mpressed-html5-nonpersistant-mootools.html | 46 + ...pressed-html5-nonpersistant-prototype.html | 46 + ...ncompressed-html5-nonpersistant-zepto.html | 46 + .../uncompressed-html5-persistant-jquery.html | 47 + ...ncompressed-html5-persistant-mootools.html | 47 + ...compressed-html5-persistant-prototype.html | 47 + .../uncompressed-html5-persistant-zepto.html | 47 + admin/thirdparty/history-js/vendor/jquery.js | 8316 +++++++++++++++++ .../thirdparty/history-js/vendor/mootools.js | 5491 +++++++++++ .../thirdparty/history-js/vendor/prototype.js | 6082 ++++++++++++ admin/thirdparty/history-js/vendor/yui.js | 13 + admin/thirdparty/history-js/vendor/zepto.js | 576 ++ 78 files changed, 27308 insertions(+) create mode 100644 admin/thirdparty/history-js/.piston.yml create mode 100644 admin/thirdparty/history-js/README.md create mode 100755 admin/thirdparty/history-js/cli create mode 100644 admin/thirdparty/history-js/demo/bcherry-orig.html create mode 100644 admin/thirdparty/history-js/demo/bcherry.html create mode 100644 admin/thirdparty/history-js/demo/chrome.html create mode 100644 admin/thirdparty/history-js/demo/index.html create mode 100644 admin/thirdparty/history-js/demo/native-auto.html create mode 100644 admin/thirdparty/history-js/demo/native.html create mode 100644 admin/thirdparty/history-js/demo/navigator.html create mode 100644 admin/thirdparty/history-js/demo/safari.html create mode 100644 admin/thirdparty/history-js/license.txt create mode 100644 admin/thirdparty/history-js/package.json create mode 100644 admin/thirdparty/history-js/scripts/compressed/amplify.store.js create mode 100644 admin/thirdparty/history-js/scripts/compressed/history.adapter.dojo.js create mode 100644 admin/thirdparty/history-js/scripts/compressed/history.adapter.jquery.js create mode 100644 admin/thirdparty/history-js/scripts/compressed/history.adapter.mootools.js create mode 100644 admin/thirdparty/history-js/scripts/compressed/history.adapter.prototype.js create mode 100644 admin/thirdparty/history-js/scripts/compressed/history.adapter.yui.js create mode 100644 admin/thirdparty/history-js/scripts/compressed/history.adapter.zepto.js create mode 100644 admin/thirdparty/history-js/scripts/compressed/history.html4.js create mode 100644 admin/thirdparty/history-js/scripts/compressed/history.js create mode 100644 admin/thirdparty/history-js/scripts/compressed/json2.js create mode 100644 admin/thirdparty/history-js/scripts/uncompressed/amplify.store.js create mode 100644 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.dojo.js create mode 100644 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.jquery.js create mode 100644 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.mootools.js create mode 100644 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.prototype.js create mode 100644 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.yui.js create mode 100644 admin/thirdparty/history-js/scripts/uncompressed/history.adapter.zepto.js create mode 100644 admin/thirdparty/history-js/scripts/uncompressed/history.html4.js create mode 100644 admin/thirdparty/history-js/scripts/uncompressed/history.js create mode 100644 admin/thirdparty/history-js/scripts/uncompressed/json2.js create mode 100644 admin/thirdparty/history-js/tests.src/_header.php create mode 100644 admin/thirdparty/history-js/tests.src/all.php create mode 100644 admin/thirdparty/history-js/tests.src/each.php create mode 100644 admin/thirdparty/history-js/tests.src/index.php create mode 100644 admin/thirdparty/history-js/tests/.htaccess create mode 100644 admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-jquery.html create mode 100644 admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-mootools.html create mode 100644 admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-prototype.html create mode 100644 admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-zepto.html create mode 100644 admin/thirdparty/history-js/tests/compressed-html4-persistant-jquery.html create mode 100644 admin/thirdparty/history-js/tests/compressed-html4-persistant-mootools.html create mode 100644 admin/thirdparty/history-js/tests/compressed-html4-persistant-prototype.html create mode 100644 admin/thirdparty/history-js/tests/compressed-html4-persistant-zepto.html create mode 100644 admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-jquery.html create mode 100644 admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-mootools.html create mode 100644 admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-prototype.html create mode 100644 admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-zepto.html create mode 100644 admin/thirdparty/history-js/tests/compressed-html5-persistant-jquery.html create mode 100644 admin/thirdparty/history-js/tests/compressed-html5-persistant-mootools.html create mode 100644 admin/thirdparty/history-js/tests/compressed-html5-persistant-prototype.html create mode 100644 admin/thirdparty/history-js/tests/compressed-html5-persistant-zepto.html create mode 100644 admin/thirdparty/history-js/tests/image.php create mode 100644 admin/thirdparty/history-js/tests/index.html create mode 100644 admin/thirdparty/history-js/tests/tests.js create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-jquery.html create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-mootools.html create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-prototype.html create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-zepto.html create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html4-persistant-jquery.html create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html4-persistant-mootools.html create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html4-persistant-prototype.html create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html4-persistant-zepto.html create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-jquery.html create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-mootools.html create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-prototype.html create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-zepto.html create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html5-persistant-jquery.html create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html5-persistant-mootools.html create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html5-persistant-prototype.html create mode 100644 admin/thirdparty/history-js/tests/uncompressed-html5-persistant-zepto.html create mode 100644 admin/thirdparty/history-js/vendor/jquery.js create mode 100644 admin/thirdparty/history-js/vendor/mootools.js create mode 100644 admin/thirdparty/history-js/vendor/prototype.js create mode 100644 admin/thirdparty/history-js/vendor/yui.js create mode 100644 admin/thirdparty/history-js/vendor/zepto.js diff --git a/admin/thirdparty/history-js/.piston.yml b/admin/thirdparty/history-js/.piston.yml new file mode 100644 index 000000000..480cb6a25 --- /dev/null +++ b/admin/thirdparty/history-js/.piston.yml @@ -0,0 +1,8 @@ +--- +format: 1 +handler: + commit: 861b4b1f7240b9d5e50d560ba5b94de78aa439e5 + branch: master +lock: false +repository_class: Piston::Git::Repository +repository_url: https://github.com/balupton/history.js.git diff --git a/admin/thirdparty/history-js/README.md b/admin/thirdparty/history-js/README.md new file mode 100644 index 000000000..5eeee3286 --- /dev/null +++ b/admin/thirdparty/history-js/README.md @@ -0,0 +1,311 @@ +Welcome to History.js (v1.7.0 - April 01 2011) +================== + + +This project is the successor of [jQuery History](http://balupton.com/projects/jquery-history), it aims to: + +- Follow the [HTML5 History API](https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history) as much as possible +- Provide a cross-compatible experience for all HTML5 Browsers (they all implement the HTML5 History API a little bit differently causing different behaviours and sometimes bugs - History.js fixes this ensuring the experience is as expected / the same / great throughout the HTML5 browsers) +- Provide a backwards-compatible experience for all HTML4 Browsers using a hash-fallback (including continued support for the HTML5 History API's `data`, `title`, `pushState` and `replaceState`) with the option to [remove HTML4 support if it is not right for your application](https://github.com/balupton/History.js/wiki/Intelligent-State-Handling) +- Provide a forwards-compatible experience for HTML4 States to HTML5 States (so if a hash-fallbacked url is accessed by a HTML5 browser it is naturally transformed into its non-hashed url equivalent) +- Provide support for as many javascript frameworks as possible via adapters; especially [jQuery](http://jquery.com/), [MooTools](http://mootools.net/), [Prototype](http://www.prototypejs.org/) and [Zepto](http://zeptojs.com/) + +Licensed under the [New BSD License](http://creativecommons.org/licenses/BSD/) +Copyright 2011 [Benjamin Arthur Lupton](http://balupton.com) + + +## Usage + +### Working with History.js: + + (function(window,undefined){ + + // Prepare + var History = window.History; // Note: We are using a capital H instead of a lower h + if ( !History.enabled ) { + // History.js is disabled for this browser. + // This is because we can optionally choose to support HTML4 browsers or not. + return false; + } + + // Bind to StateChange Event + History.Adapter.bind(window,'statechange',function(){ // Note: We are using statechange instead of popstate + var State = History.getState(); // Note: We are using History.getState() instead of event.state + History.log(State.data, State.title, State.url); + }); + + // Change our States + History.pushState({state:1}, "State 1", "?state=1"); // logs {state:1}, "State 1", "?state=1" + History.pushState({state:2}, "State 2", "?state=2"); // logs {state:2}, "State 2", "?state=2" + History.replaceState({state:3}, "State 3", "?state=3"); // logs {state:3}, "State 3", "?state=3" + History.pushState(null, null, "?state=4"); // logs {}, '', "?state=4" + History.back(); // logs {state:3}, "State 3", "?state=3" + History.back(); // logs {state:1}, "State 1", "?state=1" + History.back(); // logs {}, "Home Page", "?" + History.go(2); // logs {state:3}, "State 3", "?state=3" + + })(window); + +To ajaxify your entire website with the HTML5 History API, History.js and jQuery [this snippet of code](https://gist.github.com/854622) is all you need. It's that easy. + +### How would the above operations look in a HTML5 Browser? + +1. www.mysite.com +1. www.mysite.com/?state=1 +1. www.mysite.com/?state=2 +1. www.mysite.com/?state=3 +1. www.mysite.com/?state=4 +1. www.mysite.com/?state=3 +1. www.mysite.com/?state=1 +1. www.mysite.com +1. www.mysite.com/?state=3 + +> Note: These urls also work in HTML4 browsers and Search Engines. So no need for the hashbang (`#!`) fragment-identifier that google ["recommends"](https://github.com/balupton/History.js/wiki/Intelligent-State-Handling). + +### How would they look in a HTML4 Browser? + +1. www.mysite.com +1. www.mysite.com/#?state=1&_suid=1 +1. www.mysite.com/#?state=2&_suid=2 +1. www.mysite.com/#?state=3&_suid=3 +1. www.mysite.com/#?state=4 +1. www.mysite.com/#?state=3&_suid=3 +1. www.mysite.com/#?state=1&_suid=1 +1. www.mysite.com +1. www.mysite.com/#?state=3&_suid=3 + +> Note 1: These urls also work in HTML5 browsers - we use `replaceState` to transform these HTML4 states into their HTML5 equivalents so the user won't even notice :-) +> +> Note 2: These urls will be automatically url-encoded in IE6 to prevent certain browser-specific bugs. +> +> Note 3: Support for HTML4 browsers (this hash fallback) is optional [- why supporting HTML4 browsers could be either good or bad based on my app's use cases](https://github.com/balupton/History.js/wiki/Intelligent-State-Handling) + +### What's the deal with the SUIDs used in the HTML4 States? + +- SUIDs (State Unique Identifiers) are used when we utilise a `title` and/or `data` in our state. Adding a SUID allows us to associate particular states with data and titles while keeping the urls as simple as possible (don't worry it's all tested, working and a lot smarter than I'm making it out to be). +- If you aren't utilising `title` or `data` then we don't even include a SUID (as there is no need for it) - as seen by State 4 above :-) +- We also shrink the urls to make sure that the smallest url will be used. For instance we will adjust `http://www.mysite.com/#http://www.mysite.com/projects/History.js` to become `http://www.mysite.com/#/projects/History.js` automatically. (again tested, working, and smarter). +- It works with domains, subdomains, subdirectories, whatever - doesn't matter where you put it. It's smart. +- Safari 5 will also have a SUID appended to the URL, it is entirely transparent but just a visible side-effect. It is required to fix a bug with Safari 5. + +### Is there a working demo? + +- Sure is, give it a download and navigate to the demo directory in your browser :-) +- If you are after something a bit more adventurous than a end-user demo, open up the tests directory in your browser and editor - it'll rock your world and show all the vast use cases that History.js supports. + + +## Download & Installation + +1. Download History.js and upload it to your webserver. Download links: [tar.gz](https://github.com/balupton/History.js/tarball/master) or [zip](https://github.com/balupton/History.js/zipball/master) + +2. Include [JSON2](http://www.json.org/js.html) for HTML4 Browsers Only *(replace www.yourwebsite.com)* + + + +3. Include [Amplify.js Store](http://amplifyjs.com/) for Data Persistance and Synchronisation Support (optional but recommended) + + + +4. Include the Adapter for your Framework: + + - [jQuery](http://jquery.com/) v1.3+ + + + + - [Mootools](http://mootools.net/) v1.3+ + + + + - [Prototype](http://www.prototypejs.org/) v1.7+ (does not support versions of IE prior to 9 due to a bug in the prototype library) + + + + - [Zepto](http://zeptojs.com/) v0.5+ + + + + - _Would you like to support another framework? No problem! It's very easy to create adapters, and I'll be happy to include them or help out if you [let me know](https://github.com/balupton/history.js/issues) :-)_ + +5. Include History.js + + + + +> Note: If you want to only support HTML5 Browsers and not HTML4 Browsers (so no hash fallback support) then just remove the `history.html4.js` file include in step #5 and the JSON2 (`json2.js`) file include in step #2 [- why supporting HTML4 browsers could be either good or bad based on my app's use cases](https://github.com/balupton/History.js/wiki/Intelligent-State-Handling) + + +## Subscribe to Updates + +- For Email Updates: + - You can subscribe via the subscription form included in the demo page +- For Commit RSS/Atom Updates: + - You can subscribe via the [GitHub Commit Atom Feed](https://github.com/balupton/History.js/commits/master.atom) +- For GitHub News Feed Updates: + - You can click the "watch" button up the top right of History.js's [GitHub Project Page](https://github.com/balupton/History.js) + + +## Getting Support + +History.js is an actively developed, supported and maintained project. You can grab support via its [GitHub Issue Tracker](https://github.com/balupton/History.js/issues). Alternatively you can reach [Benjamin Lupton](http://balupton.com) (the core developer) via [twitter](http://twitter.com/balupton), skype (balupton) or email (contact@balupton.com). + + +## Giving Support + +If you'd love to give some support back and make a difference; here are a few great ways you can give back! + +- Give it your honest rating on its [jQuery Plugin's Page](http://plugins.jquery.com/project/history-js) and its [Ohloh Page](https://www.ohloh.net/p/history-js) +- If you have any feedback or suggestions let me know via its [Issue Tracker](https://github.com/balupton/History.js/issues) - so that I can ensure you get the best experience! +- Spread the word via tweets, blogs, tumblr, whatever - the more people talking about it the better! +- Donate via the donation form at the bottom right of [balupton.com](http://balupton.com) - every cent truly does help! +- Make it easier for me to let you know about future releases and updates by subscribing via the signup form inside the demo page +- Watch it via clicking the "watch" button up the top of its [Project Page](https://github.com/balupton/History.js) + +Thanks! every bit of help really does make a difference. Again thank you. + + +## Browsers: Tested and Working In + +### HTML5 Browsers + +- Chrome 8,9,10 +- Firefox 4 +- Safari 5 +- Safari iOS 4.3 + +### HTML4 Browsers + +- IE 6,7,8,9 +- Firefox 3 +- Opera 10,11 +- Safari 4 +- Safari iOS prior to version 4.3 + + +## Exposed API + +### Functions + +- `History.pushState(data,title,url)`
Pushes a new state to the browser; `data` can be null or an object, `title` can be null or a string, `url` must be a string +- `History.replaceState(data,title,url)`
Replaces the existing state with a new state to the browser; `data` can be null or an object, `title` can be null or a string, `url` must be a string +- `History.getState()`
Gets the current state of the browser, returns an object with `data`, `title` and `url` +- `History.getHash()`
Gets the current hash of the browser +- `History.Adapter.bind(element,event,callback)`
A framework independent event binder, you may either use this or your framework's native event binder. +- `History.Adapter.trigger(element,event)`
A framework independent event trigger, you may either use this or your framework's native event trigger. +- `History.Adapter.onDomLoad(callback)`
A framework independent onDomLoad binder, you may either use this or your framework's native onDomLoad binder. +- `History.back()`
Go back once through the history (same as hitting the browser's back button) +- `History.forward()`
Go forward once through the history (same as hitting the browser's forward button) +- `History.go(X)`
If X is negative go back through history X times, if X is positive go forwards through history X times +- `History.log(...)`
Logs messages to the console, the log element, and fallbacks to alert if neither of those two exist +- `History.debug(...)`
Same as `History.log` but only runs if `History.debug.enable === true` + +### Events + +- `window.onstatechange`
Fired when the state of the page changes (does not include hash changes) +- `window.onanchorchange`
Fired when the anchor of the page changes (does not include state hashes) + + +## Notes on Compatibility + +- History.js **solves** the following browser bugs: + - HTML5 Browsers + - Chrome 8 sometimes does not contain the correct state data when traversing back to the initial state + - Safari 5, Safari iOS 4 and Firefox 3 and 4 do not fire the `onhashchange` event when the page is loaded with a hash + - Safari 5 and Safari iOS 4 do not fire the `onpopstate` event when the hash has changed unlike the other browsers + - Safari 5 and Safari iOS 4 fail to return to the correct state once a hash is replaced by a `replaceState` call / [bug report](https://bugs.webkit.org/show_bug.cgi?id=56249) + - Safari 5 and Safari iOS 4 sometimes fail to apply the state change under busy conditions / [bug report](https://bugs.webkit.org/show_bug.cgi?id=42940) + - Google Chrome 8,9,10 and Firefox 4 prior to the RC will always fire `onpopstate` once the page has loaded / [change recommendation](http://hacks.mozilla.org/2011/03/history-api-changes-in-firefox-4/) + - Safari iOS 4.0, 4.1, 4.2 have a working HTML5 History API - although the actual back buttons of the browsers do not work, therefore we treat them as HTML4 browsers + - None of the HTML5 browsers actually utilise the `title` argument to the `pushState` and `replaceState` calls + - HTML4 Browsers + - Old browsers like MSIE 6,7 and Firefox 2 do not have a `onhashchange` event + - MSIE 6 and 7 sometimes do not apply a hash even it was told to (requiring a second call to the apply function) + - Non-Opera HTML4 browsers sometimes do not apply the hash when the hash is not `urlencoded` + - All Browsers + - State data and titles do not persist once the site is left and then returned (includes page refreshes) + - State titles are never applied to the `document.title` +- ReplaceState functionality is emulated in HTML4 browsers by discarding the replaced state, so when the discarded state is accessed it is skipped using the appropriate `History.back()` / `History.forward()` call +- Data persistance and synchronisation works like so: Every second or so, the SUIDs and URLs of the states will synchronise between the store and the local session. When a new session opens a familiar state (via the SUID or the URL) and it is not found locally then it will attempt to load the last known stored state with that information. +- URLs will be unescaped to the maximum, so for instance the URL `?key=a%20b%252c` will become `?key=a b c`. This is to ensure consistency between browser url encodings. +- Changing the hash of the page causes `onpopstate` to fire (this is expected/standard functionality). To ensure correct compatibility between HTML5 and HTML4 browsers the following events have been created: + - `window.onstatechange`: this is the same as the `onpopstate` event except it does not fire for traditional anchors + - `window.onanchorchange`: this is the same as the `onhashchange` event except it does not fire for states +- Known Issues + - Opera 11 fails to create history entries when under stressful loads (events fire perfectly, just the history events fail) - there is nothing we can do about this + - Mercury iOS fails to apply url changes (hashes and HTML5 History API states) - there is nothing we can do about this + + +## Changelog + +- v1.7.0 - April 01 2011 + - Added `History.enabled` property (refer to usage section). This reflects whether or not History.js is enabled for our particular browser. For instance, if we have not included support for a HTML4 browser and we are accessing through a HTML4 browser then `History.enabled` will be `false`. + - Added (optional but recommended) Data Persistance and Synchronisation Support thanks to [AppendTo's](http://appendto.com/) [Amplify.js](http://amplifyjs.com/) (refer to installation and compatibility sections for details) + - Made HTML5 SUIDs more transparent - [Reported](https://github.com/balupton/History.js/issues#issue/34) by [azago](https://github.com/azago) and [Mark Jaquith](http://markjaquith.com/) + - Fixed Session Storage Issue - Reported by a whole bunch of different people; [one](https://github.com/balupton/History.js/issues#issue/36), [two](https://github.com/balupton/History.js/issues#issue/37), [three](http://getsatisfaction.com/balupton/topics/history_js_1_6_losing_state_after_manual_page_reload) + - Fixed URL Encoding Issue - [Reported](https://github.com/balupton/history.js/issues/#issue/33) by [Rob Madole](http://robmadole.com/) + - Disabled support for IE6,7,8 when using the Prototype Adapter (there is nothing we can do about this, it is due to a bug in the prototype library) - [Reported](https://github.com/balupton/history.js/issues#issue/39) by [Sindre Wimberger](http://sindre.at/) + - URLs in the State Hashes for HTML4 Browsers are now even shorter - [Discussion](https://github.com/balupton/history.js/issues#issue/28) + - Fixed a issue with the MooTools Adapter and JSON with IE7 and IE8 + +- v1.6.0 - March 22 2011 + - Added Zepto adapter thanks to [Matt Garrett](http://twitter.com/#!/matthewgarrett) + - The readme now references the supported versions of the libraries we use + - Updated vendors to the most recent versions. jQuery 1.5.1 and Mootools 1.3.1 + - Reverted versions of Safari iOS prior to version 4.3 to be HTML4 browsers, Safari iOS 4.3 is a HTML5 browser + - Refined code in History.js and its adapters + - Fixed issue with extra state being inserted on Safari 5 requiring an extra click on the back button to go home - [Reported](https://github.com/balupton/history.js/issues#issue/17) by [Rob Madole](http://robmadole.com/) + - Fixed issue with Safari 5 and Safari iOS 4 sometimes failing to apply the state change under busy conditions - Solution conceived with [Matt Garrett](http://twitter.com/matthewgarrett) + - Fixed issue with HTML4 browsers requiring a query-string in the urls of states - [Reported](https://github.com/balupton/history.js/issues#issue/26) by [azago](https://github.com/azago) + - Fixed issue with HTML4 browsers requiring title in the states in order to use state data - [Reported](https://github.com/balupton/history.js/issues#issue/25) by [Jonathan McLaughlin](http://system-werks.com/) + - Fixed issue with HTML4 browsers failing is a state is pushed/replaced twice in a row - [Reported](https://github.com/balupton/history.js/issues#issue/17) by [Joey Baker](http://byjoeybaker.com/) + - **B/C BREAK:** The `statechange` event now only fires if the state has changed; it no longer fires on page initialisation. This is following the [Firefox 4 History API Changes](http://hacks.mozilla.org/2011/03/history-api-changes-in-firefox-4/) which we agree with - this breaks standard, but makes more sense. + +- v1.5.0 - February 12 2011 + - Moved to UglifyJS instead of Google Closure + - Split HTML4 functionality from HTML5 functionality + - Installation details have changed (the filenames are different) + +- v1.4.1 - February 10 2011 + - Added HTML History API Support for Safari 5 and Safari iOS 4.2.1 + - Cleaned code a bit (mostly with unit tests) + +- v1.4.0 - February 10 2011 + - Unit Testing now uses [QUnit](http://docs.jquery.com/Qunit) + - Corrected Safari 5 Support + - Now uses queues instead of timeouts + - This means the API works exactly as expected, no more need to wrap calls in timeouts + - Included a Subscribe Form in the Demo for Version Updates via Email + - Small updates to Documentation + +- v1.3.1 - February 04 2011 + - Improved Documentation + +- v1.3.0 - January 31 2011 + - Support for cleaner HTML4 States + +- v1.2.1 - January 30 2011 + - Fixed History.log always being called - [reported by dlee](https://github.com/balupton/History.js/issues/#issue/2) + - Re-Added `History.go(index)` support + +- v1.2.0 - January 25 2011 + - Support for HTML4 States in HTML5 Browsers (added test) + - Updates of Documentation + +- v1.1.0 - January 24 2011 + - Developed a series of automated test cases + - Fixed issue with traditional anchors + - Fixed issue with differing replaceState functionality in HTML4 Browsers + - Fixed issue with Google Chrome artefacts being carried over to the initial state + - Provided `onstatechange` and `onanchorchange` events + +- v1.0.0 - January 22 2011 + - Supported `History.pushState` and `History.replaceState` degradation + - Supported jQuery, MooTools and Prototype Frameworks + + +## Todo for Upcoming Releases + +- Allow for url to be optional in `pushState` and `replaceState` calls +- Add an Ajax extension to succeed the [jQuery Ajaxy](http://balupton.com/projects/jquery-ajaxy) project +- Add a compilation test to ensure `.debug = false` and no `History.log` or `console.xxx` calls exist. + +It's likely these features and/or others have been included in the latest [dev branch](https://github.com/balupton/History.js/tree/dev). If you are wanting to fork and help out, then be sure to work on the dev branch and not master. diff --git a/admin/thirdparty/history-js/cli b/admin/thirdparty/history-js/cli new file mode 100755 index 000000000..59363c874 --- /dev/null +++ b/admin/thirdparty/history-js/cli @@ -0,0 +1,351 @@ +#!/usr/bin/env ruby + +# == Name +# cli - BalCMS Command Line Interface +# +# == Synopsis +# cli check-env +# cli birth +# cli init-commit +# cli init-new +# cli init-existing +# cli configure +# cli install +# cli permissions +# cli setup +# cli cron +# +# cli add +# cli stable +# cli master +# cli upgrade +# cli update +# cli deploy +# +# cli clean +# cli clean-media +# cli clean-config +# cli clean-styles +# cli clean-scripts +# +# cli [options] +# +# == Examples +# cli check-env +# Checks to see that our environment is properly configured and will support a BalCMS installation. +# +# cli birth +# Executes: init-new, configure, install, init-commit +# +# cli init-commit +# Performs the initial commit (commits new and modified files during the installation to the git repo). +# +# cli init-new +# Initialises the repository as a new installation. Only run this once. +# +# TODO: finish this example section +# +# == Options +# -h, --help Displays help message +# -v, --version Display the version, then exit +# -q, --quiet Output as little as possible, overrides verbose +# -V, --verbose Verbose output +# +# == Author +# Benjamin Arthur Lupton +# +# == Copyright +# Copyright (c) 2008-2011 Benjamin Arthur Lupton +# Licensed under the New BSD License +# http://creativecommons.org/licenses/BSD/ + +require 'optparse' +require 'rdoc/usage' +require 'ostruct' +require 'date' + +class App + SOURCEMAP = './scripts/closure.map' + BUILDDIR = './.build' + UGLIFYURL = 'https://github.com/mishoo/UglifyJS/raw/master/bin/uglifyjs' + UGLIFYDIR = './.build/uglify' + UGLIFYFILE = './.build/uglify/uglify' + CLOSUREURL = 'http://closure-compiler.googlecode.com/files/compiler-latest.zip' + CLOSUREDIR = './.build/closure' + CLOSUREZIP = './.build/closure/compiler.zip' + CLOSUREFILE = './.build/closure/compiler.jar' + YUIURL = 'http://yuilibrary.com/downloads/yuicompressor/yuicompressor-2.4.2.zip' + YUIDIR = './.build/yui' + YUIZIP = './.build/yui/compiler.zip' + YUIFILE = './.build/yui/yuicompressor-2.4.2/build/yuicompressor-2.4.2.jar' + + def initialize + init_env + end + + def init_env + # Check for Requirements + reqs = ['mkdir','curl','tar','git'] + reqs.each do |req| + has_req = `which #{req}`.strip + if has_req.empty? + abort("CLI requires the following binary which is not installed: #{req}") + end + end + + # Check for Closure Compiler + if !File.exists?(CLOSUREFILE) + `mkdir -p #{CLOSUREDIR}` + puts "Downloading the Closure Compiler..." + download(CLOSUREURL, CLOSUREZIP) + extract(CLOSUREDIR, CLOSUREZIP) + `chmod +x #{CLOSUREFILE}` + end + + # Check for Uglify + if !File.exists?(UGLIFYFILE) + `mkdir -p #{UGLIFYDIR}` + puts "Downloading the Uglify Compiler..." + download(UGLIFYURL, UGLIFYFILE) + `chmod +x #{UGLIFYFILE}` + end + + # Check for YUI Compiler + if !File.exists?(YUIFILE) + `mkdir -p #{YUIDIR}` + puts "Downloading the YUI Compiler..." + download(YUIURL, (YUIZIP)) + extract(YUIDIR, YUIZIP) + `chmod +x #{YUIFILE}` + end + end + + def has_changes + result = `git status` + if result.include? 'Changed but not updated' + abort("You have un-committed changes that need to be committed before we can proceed.\n#{result}") + end + end + + # =========================================================================== + # Helpers + + def download ( url, file ) + result = `curl -L #{url} -o #{file}` + end + + def extract ( dir, file ) + file = file.gsub(dir,'.') + result = `cd #{dir} ; tar -xf #{file} ; rm -Rf #{file}` + end + + def compressJavascriptFile ( in_file, out_file ) + # Calculate + in_file_size = File.size(in_file) + + # Handle + if in_file.equal? out_file + out_file = out_file.gsub(/\.js$/, '.min.js') + compressFileUglify(in_file,out_file) + `rm #{in_file}` + `mv #{out_file} #{in_file}` + out_file = in_file + else + compressFileUglify(in_file,out_file) + out_file_size = File.size(out_file) + end + + # Calculate + out_file_size = File.size(out_file) + ratio = Float(out_file_size)/Float(in_file_size) + reduction = ((1-ratio)*100).round + + # Log + puts "Compressed the file [#{in_file}] to [#{out_file}] with a #{reduction}% reduction" + end + + def compressFileUglify ( in_file, out_file ) + result = `#{UGLIFYFILE} -o #{out_file} #{in_file}` + end + + def compressFileClosure ( in_file, out_file ) + result = `java -jar #{CLOSUREFILE} --js_output_file=#{out_file} --js=#{in_file}` + end + + # =========================================================================== + # Installers + + def build + + end + + # =========================================================================== + # Git Helpers + + def add + puts \ + ` git add -u;` + end + + def stable + puts \ + ` git checkout #{BRANCH_STABLE};` + end + + def dev + puts \ + ` git checkout #{BRANCH_DEV};` + end + + def master + puts \ + ` git checkout master;` + end + + def upgrade + puts \ + ` git checkout #{BRANCH_BALCMS}; + git pull balcms #{BRANCH_STABLE}; + git checkout #{BRANCH_DEV}; + git merge #{BRANCH_BALCMS};` + end + + def update + puts \ + ` git pull;` + configure + end + + def deploy + puts \ + ` git checkout #{BRANCH_STABLE}; + git merge #{BRANCH_DEV}; + git checkout #{BRANCH_MASTER}; + git merge #{BRANCH_STABLE}; + git checkout #{BRANCH_DEV}; + git push origin --all;` + end + +end + +# =========================================================================== +# Booter + +class Booter + VERSION = :'0.0.1' + + attr_reader :options + + def initialize(arguments, stdin) + @arguments = arguments + @stdin = stdin + + # Set defaults + @options = OpenStruct.new + @options.verbose = false + @options.quiet = false + # TO DO - add additional defaults + end + + # Parse options, check arguments, then process the command + def run + + if parsed_options? && arguments_valid? + + puts "Start at #{DateTime.now}\n\n" if @options.verbose + + output_options if @options.verbose # [Optional] + + process_arguments + process_command + + puts "\nFinished at #{DateTime.now}" if @options.verbose + + else + output_usage + end + + end + + protected + + def parsed_options? + + # Specify options + opts = OptionParser.new + opts.on('-v', '--version') { output_version ; exit 0 } + opts.on('-h', '--help') { output_help } + opts.on('-V', '--verbose') { @options.verbose = true } + opts.on('-q', '--quiet') { @options.quiet = true } + # TO DO - add additional options + + opts.parse!(@arguments) rescue return false + + process_options + true + end + + # Performs post-parse processing on options + def process_options + @options.verbose = false if @options.quiet + end + + def output_options + puts :"Options:\n" + + @options.marshal_dump.each do |name, val| + puts " #{name} = #{val}" + end + end + + # True if required arguments were provided + def arguments_valid? + # TO DO - implement your real logic here + true if @arguments.length == 1 + end + + # Setup the arguments + def process_arguments + # TO DO - place in local vars, etc + end + + def output_help + output_version + RDoc::usage() #exits app + end + + def output_usage + RDoc::usage(:'usage') # gets usage from comments above + end + + def output_version + puts "#{File.basename(__FILE__)} version #{VERSION}" + end + + def process_command + # Create Application + app = App.new + + # Fetch + Execute + command = @arguments[0].gsub('-','_') + unless app.respond_to?(command) + abort("Unknown command: #{command}") + end + app.send(command) + end + + def process_standard_input + input = @stdin.read + # TO DO - process input + + # [Optional] + #@stdin.each do |line| + # # TO DO - process each line + #end + end +end + + +# Create Booter +booter = Booter.new(ARGV, STDIN) +booter.run diff --git a/admin/thirdparty/history-js/demo/bcherry-orig.html b/admin/thirdparty/history-js/demo/bcherry-orig.html new file mode 100644 index 000000000..43672f499 --- /dev/null +++ b/admin/thirdparty/history-js/demo/bcherry-orig.html @@ -0,0 +1,58 @@ + + + + + + + WebKit is Dropping HTML5 "popstate" Events + + + + + + + + + + + + + +
+

There's a bug in the HTML5 "popstate" event, as implemented in WebKit (Safari and Chrome). View this page in one of those browsers. Your browser has had history entries added from #0 to #19 (you should start at #19). Hitting back/forward will navigate through these. On each URL, the large number above should reflect the hash value. If you hit back/forward quickly, you'll notice that your number gets out of sync with the URL. This is because WebKit is dropping popstate events (they are not firing). It seems to happen when outbound network requests are in progress when the user navigates in their browser happens. In this case, your browser is downloading an image that takes 1s to serve on every popstate, so you'll have to wait 1s between backs/forwards to have the feature work correctly. You could also cause constant network traffic by putting an image download in a setInterval, in which case your popstate events will never fire. This implementation simulates an AJAX application that makes a network request when you navigate between URLs using pushState/popstate. View the source for more info.

+

This was filed as Bug 42940 with WebKit on July 24, 2010. The Firefox 4 beta does not have this bug, which is good news.

+

This is put together by Ben Cherry. Ben is a front-end engineer at Twitter, and you can follow him at @bcherry.

+ + + diff --git a/admin/thirdparty/history-js/demo/bcherry.html b/admin/thirdparty/history-js/demo/bcherry.html new file mode 100644 index 000000000..309f4d442 --- /dev/null +++ b/admin/thirdparty/history-js/demo/bcherry.html @@ -0,0 +1,62 @@ + + + + + + + WebKit is Dropping HTML5 "popstate" Events + + + + + + + + + + + + + +
+

There's a bug in the HTML5 "popstate" event, as implemented in WebKit (Safari and Chrome). View this page in one of those browsers. Your browser has had history entries added from #0 to #19 (you should start at #19). Hitting back/forward will navigate through these. On each URL, the large number above should reflect the hash value. If you hit back/forward quickly, you'll notice that your number gets out of sync with the URL. This is because WebKit is dropping popstate events (they are not firing). It seems to happen when outbound network requests are in progress when the user navigates in their browser happens. In this case, your browser is downloading an image that takes 1s to serve on every popstate, so you'll have to wait 1s between backs/forwards to have the feature work correctly. You could also cause constant network traffic by putting an image download in a setInterval, in which case your popstate events will never fire. This implementation simulates an AJAX application that makes a network request when you navigate between URLs using pushState/popstate. View the source for more info.

+

This was filed as Bug 42940 with WebKit on July 24, 2010. The Firefox 4 beta does not have this bug, which is good news.

+

This is put together by Ben Cherry. Ben is a front-end engineer at Twitter, and you can follow him at @bcherry.

+

This bug was fixed in History.js by Benjamin Lupton. Benjamin is a freelance web 2.0 consultant, and you can follow him at @balupton.

+ + + diff --git a/admin/thirdparty/history-js/demo/chrome.html b/admin/thirdparty/history-js/demo/chrome.html new file mode 100644 index 000000000..a2791a311 --- /dev/null +++ b/admin/thirdparty/history-js/demo/chrome.html @@ -0,0 +1,37 @@ + + + Chrome History API Data Artifact + + +

This demo demonstrates an issue with Google Chrome versions 8-10 (possibly 11) where if you push a state with data, then do history.back to the initial state, the event.state will contain the pushed states data instead of being null.

+

Note: The issue requires a clean history list, as such this should always be opened in a new tab/window where there are no prior history items.

+

Reported by Benjamin Lupton author of History.js

+ + + + + + diff --git a/admin/thirdparty/history-js/demo/index.html b/admin/thirdparty/history-js/demo/index.html new file mode 100644 index 000000000..f3ea291b5 --- /dev/null +++ b/admin/thirdparty/history-js/demo/index.html @@ -0,0 +1,101 @@ + + + + + + + History.js + + + + + + + + + + + + +
+ +

History.js by Benjamin Lupton

+

History.js gracefully supports the HTML5 History/State APIs (pushState, replaceState, onPopState) in all browsers. Including continued support for data, titles, replaceState. Supports jQuery, MooTools and Prototype. For HTML5 browsers this means that you can modify the URL directly, without needing to use hashes anymore. For HTML4 browsers it will revert back to using the old onhashchange functionality.

+ + + + + +

Click through the buttons in order and you'll get the results demonstrated in the README.md file.

+ + +
    +
+ + +

Subscribe to Updates

+

You'll be the first to know when new releases come out. Yes this form actually works, it just isn't styled yet to keep things simple.

+
+
+
+
+
+ +
+
+ + + +
+ + + diff --git a/admin/thirdparty/history-js/demo/native-auto.html b/admin/thirdparty/history-js/demo/native-auto.html new file mode 100644 index 000000000..1ea10ffa3 --- /dev/null +++ b/admin/thirdparty/history-js/demo/native-auto.html @@ -0,0 +1,43 @@ + + + + + + + diff --git a/admin/thirdparty/history-js/demo/native.html b/admin/thirdparty/history-js/demo/native.html new file mode 100644 index 000000000..010f89a0c --- /dev/null +++ b/admin/thirdparty/history-js/demo/native.html @@ -0,0 +1,62 @@ + + + HTML5 History API Demo + + + +
+
+ + + diff --git a/admin/thirdparty/history-js/demo/navigator.html b/admin/thirdparty/history-js/demo/navigator.html new file mode 100644 index 000000000..f9b15844b --- /dev/null +++ b/admin/thirdparty/history-js/demo/navigator.html @@ -0,0 +1,23 @@ + + + + + + Navigator Output + + + + + + + + diff --git a/admin/thirdparty/history-js/demo/safari.html b/admin/thirdparty/history-js/demo/safari.html new file mode 100644 index 000000000..5da177553 --- /dev/null +++ b/admin/thirdparty/history-js/demo/safari.html @@ -0,0 +1,61 @@ + + + Safari Hash ReplaceState History Traversal Bug + + +

This demo demonstrates an issue with Safari 5.0.4 (6533.20.27) handing of hashes and replace state. When a hash is set, and then replaced using replaceState the history list are then broken, when traversing back the hash does not change.

+

Note: The issue requires a clean history list, as such this should always be opened in a new tab/window where there are no prior history items.

+

Reported by Benjamin Lupton author of History.js

+ + + + + + + diff --git a/admin/thirdparty/history-js/license.txt b/admin/thirdparty/history-js/license.txt new file mode 100644 index 000000000..647bfd26d --- /dev/null +++ b/admin/thirdparty/history-js/license.txt @@ -0,0 +1,10 @@ +Copyright (c) 2011, Benjamin Arthur Lupton +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + • Neither the name of Benjamin Arthur Lupton nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/admin/thirdparty/history-js/package.json b/admin/thirdparty/history-js/package.json new file mode 100644 index 000000000..18ba6c559 --- /dev/null +++ b/admin/thirdparty/history-js/package.json @@ -0,0 +1,74 @@ +{ + "name": "history.js", + "version": "1.6.0", + "description": "History.js gracefully supports the HTML5 History/State APIs (pushState, replaceState, onPopState) in all browsers. Including continued support for data, titles, replaceState. Supports jQuery, MooTools and Prototype. For HTML5 browsers this means that you can modify the URL directly, without needing to use hashes anymore. For HTML4 browsers it will revert back to using the old onhashchange functionality.", + "homepage": "https://github.com/balupton/history.js", + "keywords": [ + "javascript", + "html5 history api", + "hashchange", + "popstate", + "pushstate", + "replacestate", + "hashes", + "hashbang" + ], + "author": { + "name": "Benjamin Lupton", + "email": "b@lupton.cc", + "web": "http://balupton.com" + }, + "maintainers": [ + { + "name": "Benjamin Lupton", + "email": "b@lupton.cc", + "web": "http://balupton.com" + } + ], + "contributors": [ + { + "name": "Benjamin Lupton", + "email": "b@lupton.cc", + "web": "http://balupton.com" + } + ], + "bugs": { + "web": "https://github.com/balupton/history.js/issues" + }, + "licenses": [ + { + "type": "New-BSD", + "url": "http://creativecommons.org/licenses/BSD/" + } + ], + "repository" : { + "type" : "git", + "url" : "http://github.com/balupton/history.js.git" + }, + "dependencies": { + }, + "engines" : { + }, + "directories": { + "out": "./scripts/compressed", + "src": "./scripts/uncompressed" + }, + "buildr": { + "compress": { + "js": true, + "css": false, + "img": false, + "html": false + }, + "bundle": false, + "directories": { + "out": "./scripts/compressed", + "src": "./scripts/uncompressed" + }, + "files": { + "js": true, + "css": false, + "img": false + } + } +} diff --git a/admin/thirdparty/history-js/scripts/compressed/amplify.store.js b/admin/thirdparty/history-js/scripts/compressed/amplify.store.js new file mode 100644 index 000000000..4ae9f2b65 --- /dev/null +++ b/admin/thirdparty/history-js/scripts/compressed/amplify.store.js @@ -0,0 +1 @@ +(function(a,b){function d(a,d){var e=d.__amplify__?JSON.parse(d.__amplify__):{};c.addType(a,function(f,g,h){var i=g,j=(new Date).getTime(),k,l;if(!f){i={};for(f in e)k=d[f],l=k?JSON.parse(k):{expires:-1},l.expires&&l.expires<=j?(delete d[f],delete e[f]):i[f.replace(/^__amplify__/,"")]=l.data;d.__amplify__=JSON.stringify(e);return i}f="__amplify__"+f;if(g===b){if(e[f]){k=d[f],l=k?JSON.parse(k):{expires:-1};if(l.expires&&l.expires<=j)delete d[f],delete e[f];else return l.data}}else if(g===null)delete d[f],delete e[f];else{l=JSON.stringify({data:g,expires:h.expires?j+h.expires:null});try{d[f]=l,e[f]=!0}catch(m){c[a]();try{d[f]=l,e[f]=!0}catch(m){throw c.error()}}}d.__amplify__=JSON.stringify(e);return i})}JSON.stringify=JSON.stringify||JSON.encode,JSON.parse=JSON.parse||JSON.decode;var c=a.store=function(a,b,d,e){var e=c.type;d&&d.type&&d.type in c.types&&(e=d.type);return c.types[e](a,b,d||{})};c.types={},c.type=null,c.addType=function(a,b){c.type||(c.type=a),c.types[a]=b,c[a]=function(b,d,e){e=e||{},e.type=a;return c(b,d,e)}},c.error=function(){return"amplify.store quota exceeded"};for(var e in{localStorage:1,sessionStorage:1})try{window[e].getItem&&d(e,window[e])}catch(f){}window.globalStorage&&(d("globalStorage",window.globalStorage[window.location.hostname]),c.type==="sessionStorage"&&(c.type="globalStorage")),function(){var a=document.createElement("div"),d="amplify",e;a.style.display="none",document.getElementsByTagName("head")[0].appendChild(a),a.addBehavior&&(a.addBehavior("#default#userdata"),a.load(d),e=a.getAttribute(d)?JSON.parse(a.getAttribute(d)):{},c.addType("userData",function(f,g,h){var i=g,j=(new Date).getTime(),k,l,m;if(!f){i={};for(f in e)k=a.getAttribute(f),l=k?JSON.parse(k):{expires:-1},l.expires&&l.expires<=j?(a.removeAttribute(f),delete e[f]):i[f]=l.data;a.setAttribute(d,JSON.stringify(e)),a.save(d);return i}f=f.replace(/[^-._0-9A-Za-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u37f-\u1fff\u200c-\u200d\u203f\u2040\u2070-\u218f]/g,"-");if(g===b){if(f in e){k=a.getAttribute(f),l=k?JSON.parse(k):{expires:-1};if(l.expires&&l.expires<=j)a.removeAttribute(f),delete e[f];else return l.data}}else g===null?(a.removeAttribute(f),delete e[f]):(m=a.getAttribute(f),l=JSON.stringify({data:g,expires:h.expires?j+h.expires:null}),a.setAttribute(f,l),e[f]=!0);a.setAttribute(d,JSON.stringify(e));try{a.save(d)}catch(n){m===null?(a.removeAttribute(f),delete e[f]):a.setAttribute(f,m),c.userData();try{a.setAttribute(f,l),e[f]=!0,a.save(d)}catch(n){m===null?(a.removeAttribute(f),delete e[f]):a.setAttribute(f,m);throw c.error()}}return i}))}(),d("memory",{})})(this.amplify=this.amplify||{}) \ No newline at end of file diff --git a/admin/thirdparty/history-js/scripts/compressed/history.adapter.dojo.js b/admin/thirdparty/history-js/scripts/compressed/history.adapter.dojo.js new file mode 100644 index 000000000..e69de29bb diff --git a/admin/thirdparty/history-js/scripts/compressed/history.adapter.jquery.js b/admin/thirdparty/history-js/scripts/compressed/history.adapter.jquery.js new file mode 100644 index 000000000..c72a99f22 --- /dev/null +++ b/admin/thirdparty/history-js/scripts/compressed/history.adapter.jquery.js @@ -0,0 +1 @@ +(function(a,b){var c=a.History=a.History||{},d=a.jQuery;if(typeof c.Adapter!="undefined")throw new Error("History.js Adapter has already been loaded...");c.Adapter={bind:function(a,b,c){d(a).bind(b,c)},trigger:function(a,b){d(a).trigger(b)},onDomLoad:function(a){d(a)}},typeof c.init!="undefined"&&c.init()})(window) \ No newline at end of file diff --git a/admin/thirdparty/history-js/scripts/compressed/history.adapter.mootools.js b/admin/thirdparty/history-js/scripts/compressed/history.adapter.mootools.js new file mode 100644 index 000000000..a31be1c30 --- /dev/null +++ b/admin/thirdparty/history-js/scripts/compressed/history.adapter.mootools.js @@ -0,0 +1 @@ +(function(a,b){var c=a.History=a.History||{},d=a.MooTools;if(typeof c.Adapter!="undefined")throw new Error("History.js Adapter has already been loaded...");Object.append(Element.NativeEvents,{popstate:2,hashchange:2}),c.Adapter={bind:function(a,b,c){var d=typeof a=="string"?document.id(a):a;d.addEvent(b,c)},trigger:function(a,b){var c=typeof a=="string"?document.id(a):a;c.fireEvent(b)},onDomLoad:function(b){a.addEvent("domready",b)}},typeof c.init!="undefined"&&c.init()})(window) \ No newline at end of file diff --git a/admin/thirdparty/history-js/scripts/compressed/history.adapter.prototype.js b/admin/thirdparty/history-js/scripts/compressed/history.adapter.prototype.js new file mode 100644 index 000000000..b6f656d33 --- /dev/null +++ b/admin/thirdparty/history-js/scripts/compressed/history.adapter.prototype.js @@ -0,0 +1 @@ +(function(a,b){var c=a.History=a.History||{},d=a.Prototype,e=a.Element,f=a.Event,g=a.$;if(typeof c.Adapter!="undefined")throw new Error("History.js Adapter has already been loaded...");typeof a.fireEvent=="undefined"&&typeof a.dispatchEvent=="undefined"?c.enable=!1:(function(){var a={HTMLEvents:/^(?:load|unload|abort|error|select|hashchange|popstate|change|submit|reset|focus|blur|resize|scroll)$/,MouseEvents:/^(?:click|mouse(?:down|up|over|move|out))$/},b={pointerX:0,pointerY:0,button:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,bubbles:!0,cancelable:!0};f.hasNativeEvent=function(b,c){var d=null,e;b=g(b);for(var f in a)if(a[f].test(c)){d=f;break}e=d?!0:!1;return e},f.bind=function(a,b,c){a=g(a);return e.hasNativeEvent(a,b)?e.observe(a,b,c):e.observe(a,"custom:"+b,c)},f.trigger=function(c,d){var f=Object.extend(b,arguments[2]||{}),h,i=null;c=g(c);var j;for(j in a)if(a[j].test(d)){i=j;break}if(!i)return e.fire(c,"custom:"+d);document.createEvent?(h=document.createEvent(i),i==="HTMLEvents"?h.initEvent(d,f.bubbles,f.cancelable):i&&h.initMouseEvent(d,f.bubbles,f.cancelable,document.defaultView,f.button,f.pointerX,f.pointerY,f.pointerX,f.pointerY,f.ctrlKey,f.altKey,f.shiftKey,f.metaKey,f.button,c)):document.createEventObject&&(f.clientX=f.pointerX,f.clientY=f.pointerY,h=Object.extend(document.createEventObject(),f));if(c.fireEvent)c.fireEvent("on"+d,h);else if(c.dispatchEvent)c.dispatchEvent(h);else throw new Error("Cannot dispatch the event");return c},e.addMethods({simulate:f.trigger,trigger:f.trigger,bind:f.bind,hasNativeEvent:f.hasNativeEvent})}(),c.Adapter={bind:function(a,b,c){e.bind(a,b,c)},trigger:function(a,b){e.trigger(a,b)},onDomLoad:function(b){f.observe(a.document,"dom:loaded",b)}},typeof c.init!="undefined"&&c.init())})(window) \ No newline at end of file diff --git a/admin/thirdparty/history-js/scripts/compressed/history.adapter.yui.js b/admin/thirdparty/history-js/scripts/compressed/history.adapter.yui.js new file mode 100644 index 000000000..dbd5ccebf --- /dev/null +++ b/admin/thirdparty/history-js/scripts/compressed/history.adapter.yui.js @@ -0,0 +1 @@ +(function(a,b){var c=a.History=a.History||{},d=a.YUI;if(typeof c.Adapter!="undefined")throw new Error("History.js Adapter has already been loaded...");c.Adapter={bind:function(a,b,c){d().use("node-base",function(d){d.one(a).on(b,c)})},trigger:function(a,b){d().use("node-event-simulate",function(c){c.one(a).simulate(b)})},onDomLoad:function(a){d().use("event",function(b){b.on("domready",a)})}},typeof c.init!="undefined"&&c.init()})(window) \ No newline at end of file diff --git a/admin/thirdparty/history-js/scripts/compressed/history.adapter.zepto.js b/admin/thirdparty/history-js/scripts/compressed/history.adapter.zepto.js new file mode 100644 index 000000000..5fd1d3ac6 --- /dev/null +++ b/admin/thirdparty/history-js/scripts/compressed/history.adapter.zepto.js @@ -0,0 +1 @@ +(function(a,b){var c=a.History=a.History||{},d=a.Zepto;if(typeof c.Adapter!="undefined")throw new Error("History.js Adapter has already been loaded...");c.Adapter={bind:function(a,b,c){d(a).bind(b,c)},trigger:function(a,b){d(a).trigger(b)},onDomLoad:function(a){d(a)}},typeof c.init!="undefined"&&c.init()})(window) \ No newline at end of file diff --git a/admin/thirdparty/history-js/scripts/compressed/history.html4.js b/admin/thirdparty/history-js/scripts/compressed/history.html4.js new file mode 100644 index 000000000..cd082cb16 --- /dev/null +++ b/admin/thirdparty/history-js/scripts/compressed/history.html4.js @@ -0,0 +1 @@ +(function(a,b){"use strict";var c=a.document,d=a.setTimeout||d,e=a.clearTimeout||e,f=a.setInterval||f,g=a.History=a.History||{};if(typeof g.initHtml4!="undefined")throw new Error("History.js HTML4 Support has already been loaded...");g.initHtml4=function(){if(typeof g.initHtml4.initialized!="undefined")return!1;g.initHtml4.initialized=!0,g.enabled=!0,g.savedHashes=[],g.isLastHash=function(a){var b=g.getHashByIndex(),c=a===b;return c},g.saveHash=function(a){if(g.isLastHash(a))return!1;g.savedHashes.push(a);return!0},g.getHashByIndex=function(a){var b=null;typeof a=="undefined"?b=g.savedHashes[g.savedHashes.length-1]:a<0?b=g.savedHashes[g.savedHashes.length+a]:b=g.savedHashes[a];return b},g.discardedHashes={},g.discardedStates={},g.discardState=function(a,b,c){var d=g.getHashByState(a),e={discardedState:a,backState:c,forwardState:b};g.discardedStates[d]=e;return!0},g.discardHash=function(a,b,c){var d={discardedHash:a,backState:c,forwardState:b};g.discardedHashes[a]=d;return!0},g.discardedState=function(a){var b=g.getHashByState(a),c=g.discardedStates[b]||!1;return c},g.discardedHash=function(a){var b=g.discardedHashes[a]||!1;return b},g.recycleState=function(a){var b=g.getHashByState(a);g.discardedState(a)&&delete g.discardedStates[b];return!0},g.emulated.hashChange&&(g.hashChangeInit=function(){g.checkerFunction=null;var b="";if(g.isInternetExplorer()){var d="historyjs-iframe",e=c.createElement("iframe");e.setAttribute("id",d),e.style.display="none",c.body.appendChild(e),e.contentWindow.document.open(),e.contentWindow.document.close();var h="",i=!1;g.checkerFunction=function(){if(i)return!1;i=!0;var c=g.getHash()||"",d=g.unescapeHash(e.contentWindow.document.location.hash)||"";c!==b?(b=c,d!==c&&(h=d=c,e.contentWindow.document.open(),e.contentWindow.document.close(),e.contentWindow.document.location.hash=g.escapeHash(c)),g.Adapter.trigger(a,"hashchange")):d!==h&&(h=d,g.setHash(d,!1)),i=!1;return!0}}else g.checkerFunction=function(){var c=g.getHash();c!==b&&(b=c,g.Adapter.trigger(a,"hashchange"));return!0};f(g.checkerFunction,g.options.hashChangeInterval);return!0},g.Adapter.onDomLoad(g.hashChangeInit)),g.emulated.pushState&&(g.onHashChange=function(b){var d=b&&b.newURL||c.location.href,e=g.getHashByUrl(d),f=null,h=null,i=null;if(g.isLastHash(e)){g.busy(!1);return!1}g.doubleCheckComplete(),g.saveHash(e);if(e&&g.isTraditionalAnchor(e)){g.Adapter.trigger(a,"anchorchange"),g.busy(!1);return!1}f=g.extractState(g.getFullUrl(e||c.location.href,!1),!0);if(g.isLastSavedState(f)){g.busy(!1);return!1}h=g.getHashByState(f);var j=g.discardedState(f);if(j){g.getHashByIndex(-2)===g.getHashByState(j.forwardState)?g.back(!1):g.forward(!1);return!1}g.pushState(f.data,f.title,f.url,!1);return!0},g.Adapter.bind(a,"hashchange",g.onHashChange),g.pushState=function(b,d,e,f){if(g.getHashByUrl(e))throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(f!==!1&&g.busy()){g.pushQueue({scope:g,callback:g.pushState,args:arguments,queue:f});return!1}g.busy(!0);var h=g.createStateObject(b,d,e),i=g.getHashByState(h),j=g.getState(!1),k=g.getHashByState(j),l=g.getHash();g.storeState(h),g.expectedStateId=h.id,g.recycleState(h),g.setTitle(h);if(i===k){g.busy(!1);return!1}if(i!==l&&i!==g.getShortUrl(c.location.href)){g.setHash(i,!1);return!1}g.saveState(h),g.Adapter.trigger(a,"statechange"),g.busy(!1);return!0},g.replaceState=function(a,b,c,d){if(g.getHashByUrl(c))throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(d!==!1&&g.busy()){g.pushQueue({scope:g,callback:g.replaceState,args:arguments,queue:d});return!1}g.busy(!0);var e=g.createStateObject(a,b,c),f=g.getState(!1),h=g.getStateByIndex(-2);g.discardState(f,e,h),g.pushState(e.data,e.title,e.url,!1);return!0},g.getHash()&&!g.emulated.hashChange&&g.Adapter.onDomLoad(function(){g.Adapter.trigger(a,"hashchange")}))},g.init()})(window) \ No newline at end of file diff --git a/admin/thirdparty/history-js/scripts/compressed/history.js b/admin/thirdparty/history-js/scripts/compressed/history.js new file mode 100644 index 000000000..2ee495824 --- /dev/null +++ b/admin/thirdparty/history-js/scripts/compressed/history.js @@ -0,0 +1 @@ +(function(a,b){"use strict";var c=a.console||b,d=a.document,e=a.navigator,f=a.amplify||!1,g=a.setTimeout,h=a.clearTimeout,i=a.setInterval,j=a.JSON,k=a.History=a.History||{},l=a.history;j.stringify=j.stringify||j.encode,j.parse=j.parse||j.decode;if(typeof k.init!="undefined")throw new Error("History.js Core has already been loaded...");k.init=function(){if(typeof k.Adapter=="undefined")return!1;typeof k.initCore!="undefined"&&k.initCore(),typeof k.initHtml4!="undefined"&&k.initHtml4();return!0},k.initCore=function(){if(typeof k.initCore.initialized!="undefined")return!1;k.initCore.initialized=!0,k.options=k.options||{},k.options.hashChangeInterval=k.options.hashChangeInterval||100,k.options.safariPollInterval=k.options.safariPollInterval||500,k.options.doubleCheckInterval=k.options.doubleCheckInterval||500,k.options.storeInterval=k.options.storeInterval||1e3,k.options.busyDelay=k.options.busyDelay||250,k.options.debug=k.options.debug||!1,k.options.initialTitle=k.options.initialTitle||d.title,k.debug=function(){(k.options.debug||!1)&&k.log.apply(k,arguments)},k.log=function(){var a=typeof c!="undefined"&&typeof c.log!="undefined"&&typeof c.log.apply!="undefined",b=d.getElementById("log"),e,f,g;if(a){var h=Array.prototype.slice.call(arguments);e=h.shift(),typeof c.debug!="undefined"?c.debug.apply(c,[e,h]):c.log.apply(c,[e,h])}else e="\n"+arguments[0]+"\n";for(f=1,g=arguments.length;f")&&c[0]);return a>4?a:!1}();return a},k.isInternetExplorer=function(){var a=k.isInternetExplorer.cached=typeof k.isInternetExplorer.cached!="undefined"?k.isInternetExplorer.cached:Boolean(k.getInternetExplorerMajorVersion());return a},k.emulated={pushState:!Boolean(a.history&&a.history.pushState&&a.history.replaceState&&!/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i.test(e.userAgent)&&!/AppleWebKit\/5([0-2]|3[0-2])/i.test(e.userAgent)),hashChange:Boolean(!("onhashchange"in a||"onhashchange"in d)||k.isInternetExplorer()&&k.getInternetExplorerMajorVersion()<8)},k.enabled=!k.emulated.pushState,k.bugs={setHash:Boolean(!k.emulated.pushState&&e.vendor==="Apple Computer, Inc."&&/AppleWebKit\/5([0-2]|3[0-3])/.test(e.userAgent)),safariPoll:Boolean(!k.emulated.pushState&&e.vendor==="Apple Computer, Inc."&&/AppleWebKit\/5([0-2]|3[0-3])/.test(e.userAgent)),ieDoubleCheck:Boolean(k.isInternetExplorer()&&k.getInternetExplorerMajorVersion()<8),hashEscape:Boolean(k.isInternetExplorer()&&k.getInternetExplorerMajorVersion()<7)},k.isEmptyObject=function(a){for(var b in a)return!1;return!0},k.cloneObject=function(a){var b,c;a?(b=j.stringify(a),c=j.parse(b)):c={};return c},k.getRootUrl=function(){var a=d.location.protocol+"//"+(d.location.hostname||d.location.host);if(d.location.port||!1)a+=":"+d.location.port;a+="/";return a},k.getBaseHref=function(){var a=d.getElementsByTagName("base"),b=null,c="";a.length===1&&(b=a[0],c=b.href.replace(/[^\/]+$/,"")),c=c.replace(/\/+$/,""),c&&(c+="/");return c},k.getBaseUrl=function(){var a=k.getBaseHref()||k.getBasePageUrl()||k.getRootUrl();return a},k.getPageUrl=function(){var a=k.getState(!1,!1),b=(a||{}).url||d.location.href,c=b.replace(/\/+$/,"").replace(/[^\/]+$/,function(a,b,c){return/\./.test(a)?a:a+"/"});return c},k.getBasePageUrl=function(){var a=d.location.href.replace(/[#\?].*/,"").replace(/[^\/]+$/,function(a,b,c){return/[^\/]$/.test(a)?"":a}).replace(/\/+$/,"")+"/";return a},k.getFullUrl=function(a,b){var c=a,d=a.substring(0,1);b=typeof b=="undefined"?!0:b,/[a-z]+\:\/\//.test(a)||(d==="/"?c=k.getRootUrl()+a.replace(/^\/+/,""):d==="#"?c=k.getPageUrl().replace(/#.*/,"")+a:d==="?"?c=k.getPageUrl().replace(/[\?#].*/,"")+a:b?c=k.getBaseUrl()+a.replace(/^(\.\/)+/,""):c=k.getBasePageUrl()+a.replace(/^(\.\/)+/,""));return c.replace(/\#$/,"")},k.getShortUrl=function(a){var b=a,c=k.getBaseUrl(),d=k.getRootUrl();k.emulated.pushState&&(b=b.replace(c,"")),b=b.replace(d,"/"),k.isTraditionalAnchor(b)&&(b="./"+b),b=b.replace(/^(\.\/)+/g,"./").replace(/\#$/,"");return b},k.store=f?f.store("History.store")||{}:{},k.store.idToState=k.store.idToState||{},k.store.urlToId=k.store.urlToId||{},k.store.stateToId=k.store.stateToId||{},k.idToState=k.idToState||{},k.stateToId=k.stateToId||{},k.urlToId=k.urlToId||{},k.storedStates=k.storedStates||[],k.savedStates=k.savedStates||[],k.getState=function(a,b){typeof a=="undefined"&&(a=!0),typeof b=="undefined"&&(b=!0);var c=k.getLastSavedState();!c&&b&&(c=k.createStateObject()),a&&(c=k.cloneObject(c),c.url=c.cleanUrl||c.url);return c},k.getIdByState=function(a){var b=k.extractId(a.url);if(!b){var c=k.getStateString(a);if(typeof k.stateToId[c]!="undefined")b=k.stateToId[c];else if(typeof k.store.stateToId[c]!="undefined")b=k.store.stateToId[c];else{for(;;){b=String(Math.floor(Math.random()*1e3));if(typeof k.idToState[b]=="undefined"&&typeof k.store.idToState[b]=="undefined")break}k.stateToId[c]=b,k.idToState[b]=a}}return b},k.normalizeState=function(a){if(!a||typeof a!="object")a={};if(typeof a.normalized!="undefined")return a;if(!a.data||typeof a.data!="object")a.data={};var b={};b.normalized=!0,b.title=a.title||"",b.url=k.getFullUrl(k.unescapeString(a.url||d.location.href)),b.hash=k.getShortUrl(b.url),b.data=k.cloneObject(a.data),b.id=k.getIdByState(b),b.cleanUrl=b.url.replace(/\??\&_suid.*/,""),b.url=b.cleanUrl;var c=!k.isEmptyObject(b.data);if(b.title||c)b.hash=k.getShortUrl(b.url).replace(/\??\&_suid.*/,""),/\?/.test(b.hash)||(b.hash+="?"),b.hash+="&_suid="+b.id;b.hashedUrl=k.getFullUrl(b.hash),(k.emulated.pushState||k.bugs.safariPoll)&&k.hasUrlDuplicate(b)&&(b.url=b.hashedUrl);return b},k.createStateObject=function(a,b,c){var d={data:a,title:b,url:c};d=k.normalizeState(d);return d},k.getStateById=function(a){a=String(a);var c=k.idToState[a]||k.store.idToState[a]||b;return c},k.getStateString=function(a){var b=k.normalizeState(a),c={data:b.data,title:a.title,url:a.url},d=j.stringify(c);return d},k.getStateId=function(a){var b=k.normalizeState(a),c=b.id;return c},k.getHashByState=function(a){var b,c=k.normalizeState(a);b=c.hash;return b},k.extractId=function(a){var b,c,d;c=/(.*)\&_suid=([0-9]+)$/.exec(a),d=c?c[1]||a:a,b=c?String(c[2]||""):"";return b||!1},k.isTraditionalAnchor=function(a){var b=!/[\/\?\.]/.test(a);return b},k.extractState=function(a,b){var c=null;b=b||!1;var d=k.extractId(a);d&&(c=k.getStateById(d));if(!c){var e=k.getFullUrl(a);d=k.getIdByUrl(e)||!1,d&&(c=k.getStateById(d)),!c&&b&&!k.isTraditionalAnchor(a)&&(c=k.createStateObject(null,null,e))}return c},k.getIdByUrl=function(a){var c=k.urlToId[a]||k.store.urlToId[a]||b;return c},k.getLastSavedState=function(){return k.savedStates[k.savedStates.length-1]||b},k.getLastStoredState=function(){return k.storedStates[k.storedStates.length-1]||b},k.hasUrlDuplicate=function(a){var b=!1,c=k.extractState(a.url);b=c&&c.id!==a.id;return b},k.storeState=function(a){k.urlToId[a.url]=a.id,k.storedStates.push(k.cloneObject(a));return a},k.isLastSavedState=function(a){var b=!1;if(k.savedStates.length){var c=a.id,d=k.getLastSavedState(),e=d.id;b=c===e}return b},k.saveState=function(a){if(k.isLastSavedState(a))return!1;k.savedStates.push(k.cloneObject(a));return!0},k.getStateByIndex=function(a){var b=null;typeof a=="undefined"?b=k.savedStates[k.savedStates.length-1]:a<0?b=k.savedStates[k.savedStates.length+a]:b=k.savedStates[a];return b},k.getHash=function(){var a=k.unescapeHash(d.location.hash);return a},k.unescapeString=function(b){var c=b,d;for(;;){d=a.unescape(c);if(d===c)break;c=d}return c},k.unescapeHash=function(a){var b=k.normalizeHash(a);b=k.unescapeString(b);return b},k.normalizeHash=function(a){var b=a.replace(/[^#]*#/,"").replace(/#.*/,"");return b},k.setHash=function(a,b){if(b!==!1&&k.busy()){k.pushQueue({scope:k,callback:k.setHash,args:arguments,queue:b});return!1}var c=k.escapeHash(a);k.busy(!0);var e=k.extractState(a,!0);if(e&&!k.emulated.pushState)k.pushState(e.data,e.title,e.url,!1);else if(d.location.hash!==c)if(k.bugs.setHash){var f=k.getPageUrl();k.pushState(null,null,f+"#"+c,!1)}else d.location.hash=c;return k},k.escapeHash=function(b){var c=k.normalizeHash(b);c=a.escape(c),k.bugs.hashEscape||(c=c.replace(/\%21/g,"!").replace(/\%26/g,"&").replace(/\%3D/g,"=").replace(/\%3F/g,"?"));return c},k.getHashByUrl=function(a){var b=String(a).replace(/([^#]*)#?([^#]*)#?(.*)/,"$2");b=k.unescapeHash(b);return b},k.setTitle=function(a){var b=a.title;if(!b){var c=k.getStateByIndex(0);c&&c.url===a.url&&(b=c.title||k.options.initialTitle)}try{d.getElementsByTagName("title")[0].innerHTML=b.replace("<","<").replace(">",">").replace(" & "," & ")}catch(e){}d.title=b;return k},k.queues=[],k.busy=function(a){typeof a!="undefined"?k.busy.flag=a:typeof k.busy.flag=="undefined"&&(k.busy.flag=!1);if(!k.busy.flag){h(k.busy.timeout);var b=function(){if(!k.busy.flag)for(var a=k.queues.length-1;a>=0;--a){var c=k.queues[a];if(c.length===0)continue;var d=c.shift();k.fireQueueItem(d),k.busy.timeout=g(b,k.options.busyDelay)}};k.busy.timeout=g(b,k.options.busyDelay)}return k.busy.flag},k.fireQueueItem=function(a){return a.callback.apply(a.scope||k,a.args||[])},k.pushQueue=function(a){k.queues[a.queue||0]=k.queues[a.queue||0]||[],k.queues[a.queue||0].push(a);return k},k.queue=function(a,b){typeof a=="function"&&(a={callback:a}),typeof b!="undefined"&&(a.queue=b),k.busy()?k.pushQueue(a):k.fireQueueItem(a);return k},k.clearQueue=function(){k.busy.flag=!1,k.queues=[];return k},k.stateChanged=!1,k.doubleChecker=!1,k.doubleCheckComplete=function(){k.stateChanged=!0,k.doubleCheckClear();return k},k.doubleCheckClear=function(){k.doubleChecker&&(h(k.doubleChecker),k.doubleChecker=!1);return k},k.doubleCheck=function(a){k.stateChanged=!1,k.doubleCheckClear(),k.bugs.ieDoubleCheck&&(k.doubleChecker=g(function(){k.doubleCheckClear(),k.stateChanged||a();return!0},k.options.doubleCheckInterval));return k},k.safariStatePoll=function(){var b=k.extractState(d.location.href),c;if(!k.isLastSavedState(b))c=b;else return;c||(c=k.createStateObject()),k.Adapter.trigger(a,"popstate");return k},k.back=function(a){if(a!==!1&&k.busy()){k.pushQueue({scope:k,callback:k.back,args:arguments,queue:a});return!1}k.busy(!0),k.doubleCheck(function(){k.back(!1)}),l.go(-1);return!0},k.forward=function(a){if(a!==!1&&k.busy()){k.pushQueue({scope:k,callback:k.forward,args:arguments,queue:a});return!1}k.busy(!0),k.doubleCheck(function(){k.forward(!1)}),l.go(1);return!0},k.go=function(a,b){var c;if(a>0)for(c=1;c<=a;++c)k.forward(b);else{if(!(a<0))throw new Error("History.go: History.go requires a positive or negative integer passed.");for(c=-1;c>=a;--c)k.back(b)}return k},k.saveState(k.storeState(k.extractState(d.location.href,!0))),f&&(k.onUnload=function(){var a=f.store("History.store")||{},b;a.idToState=a.idToState||{},a.urlToId=a.urlToId||{},a.stateToId=a.stateToId||{};for(b in k.idToState){if(!k.idToState.hasOwnProperty(b))continue;a.idToState[b]=k.idToState[b]}for(b in k.urlToId){if(!k.urlToId.hasOwnProperty(b))continue;a.urlToId[b]=k.urlToId[b]}for(b in k.stateToId){if(!k.stateToId.hasOwnProperty(b))continue;a.stateToId[b]=k.stateToId[b]}k.store=a,f.store("History.store",a)},i(k.onUnload,k.options.storeInterval),k.Adapter.bind(a,"beforeunload",k.onUnload),k.Adapter.bind(a,"unload",k.onUnload));if(k.emulated.pushState){var m=function(){};k.pushState=k.pushState||m,k.replaceState=k.replaceState||m}else{k.onPopState=function(b){k.doubleCheckComplete();var c=k.getHash();if(c){var e=k.extractState(c||d.location.href,!0);e?k.replaceState(e.data,e.title,e.url,!1):(k.Adapter.trigger(a,"anchorchange"),k.busy(!1)),k.expectedStateId=!1;return!1}var f=!1;b=b||{},typeof b.state=="undefined"&&(typeof b.originalEvent!="undefined"&&typeof b.originalEvent.state!="undefined"?b.state=b.originalEvent.state||!1:typeof b.event!="undefined"&&typeof b.event.state!="undefined"&&(b.state=b.event.state||!1)),b.state=b.state||!1,b.state?f=k.getStateById(b.state):k.expectedStateId?f=k.getStateById(k.expectedStateId):f=k.extractState(d.location.href),f||(f=k.createStateObject(null,null,d.location.href)),k.expectedStateId=!1;if(k.isLastSavedState(f)){k.busy(!1);return!1}k.storeState(f),k.saveState(f),k.setTitle(f),k.Adapter.trigger(a,"statechange"),k.busy(!1);return!0},k.Adapter.bind(a,"popstate",k.onPopState),k.pushState=function(b,c,d,e){if(k.getHashByUrl(d)&&k.emulated.pushState)throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(e!==!1&&k.busy()){k.pushQueue({scope:k,callback:k.pushState,args:arguments,queue:e});return!1}k.busy(!0);var f=k.createStateObject(b,c,d);k.isLastSavedState(f)?k.busy(!1):(k.storeState(f),k.expectedStateId=f.id,l.pushState(f.id,f.title,f.url),k.Adapter.trigger(a,"popstate"));return!0},k.replaceState=function(b,c,d,e){if(k.getHashByUrl(d)&&k.emulated.pushState)throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(e!==!1&&k.busy()){k.pushQueue({scope:k,callback:k.replaceState,args:arguments,queue:e});return!1}k.busy(!0);var f=k.createStateObject(b,c,d);k.isLastSavedState(f)?k.busy(!1):(k.storeState(f),k.expectedStateId=f.id,l.replaceState(f.id,f.title,f.url),k.Adapter.trigger(a,"popstate"));return!0},k.bugs.safariPoll&&i(k.safariStatePoll,k.options.safariPollInterval);if(e.vendor==="Apple Computer, Inc."||(e.appCodeName||"")==="Mozilla")k.Adapter.bind(a,"hashchange",function(){k.Adapter.trigger(a,"popstate")}),k.getHash()&&k.Adapter.onDomLoad(function(){k.Adapter.trigger(a,"hashchange")})}},k.init()})(window) \ No newline at end of file diff --git a/admin/thirdparty/history-js/scripts/compressed/json2.js b/admin/thirdparty/history-js/scripts/compressed/json2.js new file mode 100644 index 000000000..704b8812d --- /dev/null +++ b/admin/thirdparty/history-js/scripts/compressed/json2.js @@ -0,0 +1 @@ +var JSON;JSON||(JSON={}),function(){function str(a,b){var c,d,e,f,g=gap,h,i=b[a];i&&typeof i=="object"&&typeof i.toJSON=="function"&&(i=i.toJSON(a)),typeof rep=="function"&&(i=rep.call(b,a,i));switch(typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";gap+=indent,h=[];if(Object.prototype.toString.apply(i)==="[object Array]"){f=i.length;for(c=0;c + * @copyright 2010-2011 Benjamin Arthur Lupton + * @license New BSD License + */ + +// Closure +(function(window,undefined){ + // Localise Globals + var + History = window.History = window.History||{}, + jQuery = window.jQuery; + + // Check Existence + if ( typeof History.Adapter !== 'undefined' ) { + throw new Error('History.js Adapter has already been loaded...'); + } + + // Add the Adapter + History.Adapter = { + /** + * History.Adapter.bind(el,event,callback) + * @param {Element|Selector} el + * @param {String} event - custom and standard events + * @param {Function} callback + * @return + */ + bind: function(el,event,callback){ + jQuery(el).bind(event,callback); + }, + + /** + * History.Adapter.trigger(el,event) + * @param {Element|Selector} el + * @param {String} event - custom and standard events + * @return + */ + trigger: function(el,event){ + jQuery(el).trigger(event); + }, + + /** + * History.Adapter.trigger(el,event,data) + * @param {Function} callback + * @return + */ + onDomLoad: function(callback) { + jQuery(callback); + } + }; + + // Try and Initialise History + if ( typeof History.init !== 'undefined' ) { + History.init(); + } + +})(window); diff --git a/admin/thirdparty/history-js/scripts/uncompressed/history.adapter.mootools.js b/admin/thirdparty/history-js/scripts/uncompressed/history.adapter.mootools.js new file mode 100644 index 000000000..5a07da30e --- /dev/null +++ b/admin/thirdparty/history-js/scripts/uncompressed/history.adapter.mootools.js @@ -0,0 +1,66 @@ +/** + * History.js jQuery Adapter + * @author Benjamin Arthur Lupton + * @copyright 2010-2011 Benjamin Arthur Lupton + * @license New BSD License + */ + +// Closure +(function(window,undefined){ + // Localise Globals + var + History = window.History = window.History||{}, + MooTools = window.MooTools; + + // Check Existence + if ( typeof History.Adapter !== 'undefined' ) { + throw new Error('History.js Adapter has already been loaded...'); + } + + // Make MooTools aware of History.js Events + Object.append(Element.NativeEvents,{ + 'popstate':2, + 'hashchange':2 + }); + + // Add the Adapter + History.Adapter = { + /** + * History.Adapter.bind(el,event,callback) + * @param {Element|Selector} el + * @param {String} event - custom and standard events + * @param {Function} callback + * @return + */ + bind: function(el,event,callback){ + var El = typeof el === 'string' ? document.id(el) : el; + El.addEvent(event,callback); + }, + + /** + * History.Adapter.trigger(el,event) + * @param {Element|Selector} el + * @param {String} event - custom and standard events + * @return + */ + trigger: function(el,event){ + var El = typeof el === 'string' ? document.id(el) : el; + El.fireEvent(event); + }, + + /** + * History.Adapter.trigger(el,event) + * @param {Function} callback + * @return + */ + onDomLoad: function(callback) { + window.addEvent('domready',callback); + } + }; + + // Try and Initialise History + if ( typeof History.init !== 'undefined' ) { + History.init(); + } + +})(window); diff --git a/admin/thirdparty/history-js/scripts/uncompressed/history.adapter.prototype.js b/admin/thirdparty/history-js/scripts/uncompressed/history.adapter.prototype.js new file mode 100644 index 000000000..58d1fc28a --- /dev/null +++ b/admin/thirdparty/history-js/scripts/uncompressed/history.adapter.prototype.js @@ -0,0 +1,197 @@ +/** + * History.js Prototype Adapter + * @author Benjamin Arthur Lupton + * @copyright 2010-2011 Benjamin Arthur Lupton + * @license New BSD License + */ + +// Closure +(function(window,undefined){ + // Localise Globals + var + History = window.History = window.History||{}, + Prototype = window.Prototype, + Element = window.Element, + Event = window.Event, + $ = window.$; + + // Check Existence + if ( typeof History.Adapter !== 'undefined' ) { + throw new Error('History.js Adapter has already been loaded...'); + } + + // Prototype does not support event binding to the window element in IE6-8 + if ( typeof window.fireEvent === 'undefined' && typeof window.dispatchEvent === 'undefined' ) { + History.enable = false; + return; + } + + /** + * Bind and Trigger custom and native events in Prototype + * @author Juriy Zaytsev (kangax) + * @author Benjamin Arthur Lupton + * @copyright MIT license + */ + (function(){ + // Prepare + var + eventMatchers = { + 'HTMLEvents': /^(?:load|unload|abort|error|select|hashchange|popstate|change|submit|reset|focus|blur|resize|scroll)$/, + 'MouseEvents': /^(?:click|mouse(?:down|up|over|move|out))$/ + }, + defaultOptions = { + pointerX: 0, + pointerY: 0, + button: 0, + ctrlKey: false, + altKey: false, + shiftKey: false, + metaKey: false, + bubbles: true, + cancelable: true + }; + + // Check for Native Event + Event.hasNativeEvent = function(element, eventName) { + // Prepare + var eventType = null, result; + element = $(element); + + // Cycle + for (var name in eventMatchers) { + if ( eventMatchers[name].test(eventName) ) { + eventType = name; + break; + } + } + + // Evaluate + result = eventType ? true : false; + + // Return result + return result; + }; + + // Bind a Native or Custom Event + Event.bind = function(element, eventName, eventHandler) { + // Prepare + element = $(element); + + // Native Event? + if ( Element.hasNativeEvent(element,eventName) ) { + return Element.observe(element,eventName,eventHandler); + } + + // Custom Event? + else { + return Element.observe(element,'custom:'+eventName,eventHandler); + } + + // Return element + return element; + }; + + // Trigger + Event.trigger = function(element, eventName) { + // Prepare + var options = Object.extend(defaultOptions, arguments[2] || { }); + var oEvent, eventType = null; + element = $(element); + + // Check for Native Event + var name; for (name in eventMatchers) { + if (eventMatchers[name].test(eventName)) { eventType = name; break; } + } + + // Custom Event? + if ( !eventType ) { + return Element.fire(element,'custom:'+eventName); + } + + // Create Event + if ( document.createEvent ) { + // Firefox + Others + oEvent = document.createEvent(eventType); + + // Normal Event? + if ( eventType === 'HTMLEvents' ) { + oEvent.initEvent(eventName, options.bubbles, options.cancelable); + } + // Mouse Event? + else if ( eventType ) { + oEvent.initMouseEvent(eventName, options.bubbles, options.cancelable, document.defaultView, + options.button, options.pointerX, options.pointerY, options.pointerX, options.pointerY, + options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.button, element); + } + } + else if ( document.createEventObject ) { + // Internet Explorer + options.clientX = options.pointerX; + options.clientY = options.pointerY; + oEvent = Object.extend(document.createEventObject(), options); + } + + // Fire Event + if ( element.fireEvent ) { + element.fireEvent('on'+eventName,oEvent); + } + else if ( element.dispatchEvent ) { + element.dispatchEvent(oEvent); + } + else { + throw new Error('Cannot dispatch the event'); + } + + // Return + return element; + }; + + // Amend Element Prototype + Element.addMethods({ + simulate: Event.trigger, + trigger: Event.trigger, + bind: Event.bind, + hasNativeEvent: Event.hasNativeEvent + }); + })(); + + // Add the Adapter + History.Adapter = { + + /** + * History.Adapter.bind(el,event,callback) + * @param {Element|Selector} el + * @param {String} event - custom and standard events + * @param {Function} callback + * @return + */ + bind: function(el,event,callback){ + Element.bind(el,event,callback); + }, + + /** + * History.Adapter.trigger(el,event) + * @param {Element|Selector} el + * @param {String} event - custom and standard events + * @return + */ + trigger: function(el,event){ + Element.trigger(el,event); + }, + + /** + * History.Adapter.trigger(el,event,data) + * @param {Function} callback + * @return + */ + onDomLoad: function(callback) { + Event.observe(window.document, 'dom:loaded', callback); + } + }; + + // Try and Initialise History + if ( typeof History.init !== 'undefined' ) { + History.init(); + } + +})(window); diff --git a/admin/thirdparty/history-js/scripts/uncompressed/history.adapter.yui.js b/admin/thirdparty/history-js/scripts/uncompressed/history.adapter.yui.js new file mode 100644 index 000000000..a488584e8 --- /dev/null +++ b/admin/thirdparty/history-js/scripts/uncompressed/history.adapter.yui.js @@ -0,0 +1,64 @@ +/** + * History.js YUI Adapter [NOT WORKING] + * @author Benjamin Arthur Lupton + * @copyright 2010-2011 Benjamin Arthur Lupton + * @license New BSD License + */ + +// Closure +(function(window,undefined){ + // Localise Globals + var + History = window.History = window.History||{}, + YUI = window.YUI; + + // Check Existence + if ( typeof History.Adapter !== 'undefined' ) { + throw new Error('History.js Adapter has already been loaded...'); + } + + // Add the Adapter + History.Adapter = { + /** + * History.Adapter.bind(el,event,callback) + * @param {Element|Selector} el + * @param {String} event - custom and standard events + * @param {Function} callback + * @return {element} + */ + bind: function(el,event,callback){ + YUI().use('node-base', function(Y){ + Y.one(el).on(event,callback); + }); + }, + + /** + * History.Adapter.trigger(el,event) + * @param {Element|Selector} el + * @param {String} event - custom and standard events + * @return {element} + */ + trigger: function(el,event){ + YUI().use('node-event-simulate', function(Y){ + Y.one(el).simulate(event); + }); + }, + + /** + * History.Adapter.trigger(el,event,data) + * @param {Function} callback + * @return {true} + */ + onDomLoad: function(callback) { + YUI().use('event', function(Y){ + Y.on('domready', callback); + }); + } + }; + + // Try and Initialise History + if ( typeof History.init !== 'undefined' ) { + History.init(); + } + +})(window); diff --git a/admin/thirdparty/history-js/scripts/uncompressed/history.adapter.zepto.js b/admin/thirdparty/history-js/scripts/uncompressed/history.adapter.zepto.js new file mode 100644 index 000000000..790ea0b48 --- /dev/null +++ b/admin/thirdparty/history-js/scripts/uncompressed/history.adapter.zepto.js @@ -0,0 +1,58 @@ +/** + * History.js Zepto Adapter + * @author Benjamin Arthur Lupton + * @copyright 2010-2011 Benjamin Arthur Lupton + * @license New BSD License + */ + +// Closure +(function(window,undefined){ + // Localise Globals + var + History = window.History = window.History||{}, + Zepto = window.Zepto; + + // Check Existence + if ( typeof History.Adapter !== 'undefined' ) { + throw new Error('History.js Adapter has already been loaded...'); + } + + // Add the Adapter + History.Adapter = { + /** + * History.Adapter.bind(el,event,callback) + * @param {Element|Selector} el + * @param {String} event - custom and standard events + * @param {Function} callback + * @return + */ + bind: function(el,event,callback){ + Zepto(el).bind(event,callback); + }, + + /** + * History.Adapter.trigger(el,event) + * @param {Element|Selector} el + * @param {String} event - custom and standard events + * @return + */ + trigger: function(el,event){ + Zepto(el).trigger(event); + }, + + /** + * History.Adapter.trigger(el,event,data) + * @param {Function} callback + * @return + */ + onDomLoad: function(callback) { + Zepto(callback); + } + }; + + // Try and Initialise History + if ( typeof History.init !== 'undefined' ) { + History.init(); + } + +})(window); diff --git a/admin/thirdparty/history-js/scripts/uncompressed/history.html4.js b/admin/thirdparty/history-js/scripts/uncompressed/history.html4.js new file mode 100644 index 000000000..8f2822a03 --- /dev/null +++ b/admin/thirdparty/history-js/scripts/uncompressed/history.html4.js @@ -0,0 +1,606 @@ +/** + * History.js HTML4 Support + * Depends on the HTML5 Support + * @author Benjamin Arthur Lupton + * @copyright 2010-2011 Benjamin Arthur Lupton + * @license New BSD License + */ + +(function(window,undefined){ + "use strict"; + + // -------------------------------------------------------------------------- + // Initialise + + // Localise Globals + var + document = window.document, // Make sure we are using the correct document + setTimeout = window.setTimeout||setTimeout, + clearTimeout = window.clearTimeout||clearTimeout, + setInterval = window.setInterval||setInterval, + History = window.History = window.History||{}; // Public History Object + + // Check Existence + if ( typeof History.initHtml4 !== 'undefined' ) { + throw new Error('History.js HTML4 Support has already been loaded...'); + } + + // -------------------------------------------------------------------------- + // Initialise HTML4 Support + + // Initialise HTML4 Support + History.initHtml4 = function(){ + // Initialise + if ( typeof History.initHtml4.initialized !== 'undefined' ) { + // Already Loaded + return false; + } + else { + History.initHtml4.initialized = true; + } + + // ---------------------------------------------------------------------- + // Properties + + /** + * History.enabled + * Is History enabled? + */ + History.enabled = true; + + + // ---------------------------------------------------------------------- + // Hash Storage + + /** + * History.savedHashes + * Store the hashes in an array + */ + History.savedHashes = []; + + /** + * History.isLastHash(newHash) + * Checks if the hash is the last hash + * @param {string} newHash + * @return {boolean} true + */ + History.isLastHash = function(newHash){ + // Prepare + var oldHash = History.getHashByIndex(); + + // Check + var isLast = newHash === oldHash; + + // Return isLast + return isLast; + }; + + /** + * History.saveHash(newHash) + * Push a Hash + * @param {string} newHash + * @return {boolean} true + */ + History.saveHash = function(newHash){ + // Check Hash + if ( History.isLastHash(newHash) ) { + return false; + } + + // Push the Hash + History.savedHashes.push(newHash); + + // Return true + return true; + }; + + /** + * History.getHashByIndex() + * Gets a hash by the index + * @param {integer} index + * @return {string} + */ + History.getHashByIndex = function(index){ + // Prepare + var hash = null; + + // Handle + if ( typeof index === 'undefined' ) { + // Get the last inserted + hash = History.savedHashes[History.savedHashes.length-1]; + } + else if ( index < 0 ) { + // Get from the end + hash = History.savedHashes[History.savedHashes.length+index]; + } + else { + // Get from the beginning + hash = History.savedHashes[index]; + } + + // Return hash + return hash; + }; + + // ---------------------------------------------------------------------- + // Discarded States + + /** + * History.discardedHashes + * A hashed array of discarded hashes + */ + History.discardedHashes = {}; + + /** + * History.discardedStates + * A hashed array of discarded states + */ + History.discardedStates = {}; + + /** + * History.discardState(State) + * Discards the state by ignoring it through History + * @param {object} State + * @return {true} + */ + History.discardState = function(discardedState,forwardState,backState){ + //History.debug('History.discardState', arguments); + // Prepare + var discardedStateHash = History.getHashByState(discardedState); + + // Create Discard Object + var discardObject = { + 'discardedState': discardedState, + 'backState': backState, + 'forwardState': forwardState + }; + + // Add to DiscardedStates + History.discardedStates[discardedStateHash] = discardObject; + + // Return true + return true; + }; + + /** + * History.discardHash(hash) + * Discards the hash by ignoring it through History + * @param {string} hash + * @return {true} + */ + History.discardHash = function(discardedHash,forwardState,backState){ + //History.debug('History.discardState', arguments); + // Create Discard Object + var discardObject = { + 'discardedHash': discardedHash, + 'backState': backState, + 'forwardState': forwardState + }; + + // Add to discardedHash + History.discardedHashes[discardedHash] = discardObject; + + // Return true + return true; + }; + + /** + * History.discardState(State) + * Checks to see if the state is discarded + * @param {object} State + * @return {bool} + */ + History.discardedState = function(State){ + // Prepare + var StateHash = History.getHashByState(State); + + // Check + var discarded = History.discardedStates[StateHash]||false; + + // Return true + return discarded; + }; + + /** + * History.discardedHash(hash) + * Checks to see if the state is discarded + * @param {string} State + * @return {bool} + */ + History.discardedHash = function(hash){ + // Check + var discarded = History.discardedHashes[hash]||false; + + // Return true + return discarded; + }; + + /** + * History.recycleState(State) + * Allows a discarded state to be used again + * @param {object} data + * @param {string} title + * @param {string} url + * @return {true} + */ + History.recycleState = function(State){ + //History.debug('History.recycleState', arguments); + // Prepare + var StateHash = History.getHashByState(State); + + // Remove from DiscardedStates + if ( History.discardedState(State) ) { + delete History.discardedStates[StateHash]; + } + + // Return true + return true; + }; + + // ---------------------------------------------------------------------- + // HTML4 HashChange Support + + if ( History.emulated.hashChange ) { + /* + * We must emulate the HTML4 HashChange Support by manually checking for hash changes + */ + + /** + * History.hashChangeInit() + * Init the HashChange Emulation + */ + History.hashChangeInit = function(){ + // Define our Checker Function + History.checkerFunction = null; + + // Define some variables that will help in our checker function + var + lastDocumentHash = ''; + + // Handle depending on the browser + if ( History.isInternetExplorer() ) { + // IE6 and IE7 + // We need to use an iframe to emulate the back and forward buttons + + // Create iFrame + var + iframeId = 'historyjs-iframe', + iframe = document.createElement('iframe'); + + // Adjust iFarme + iframe.setAttribute('id', iframeId); + iframe.style.display = 'none'; + + // Append iFrame + document.body.appendChild(iframe); + + // Create initial history entry + iframe.contentWindow.document.open(); + iframe.contentWindow.document.close(); + + // Define some variables that will help in our checker function + var + lastIframeHash = '', + checkerRunning = false; + + // Define the checker function + History.checkerFunction = function(){ + // Check Running + if ( checkerRunning ) { + return false; + } + + // Update Running + checkerRunning = true; + + // Fetch + var + documentHash = History.getHash()||'', + iframeHash = History.unescapeHash(iframe.contentWindow.document.location.hash)||''; + + // The Document Hash has changed (application caused) + if ( documentHash !== lastDocumentHash ) { + // Equalise + lastDocumentHash = documentHash; + + // Create a history entry in the iframe + if ( iframeHash !== documentHash ) { + //History.debug('hashchange.checker: iframe hash change', 'documentHash (new):', documentHash, 'iframeHash (old):', iframeHash); + + // Equalise + lastIframeHash = iframeHash = documentHash; + + // Create History Entry + iframe.contentWindow.document.open(); + iframe.contentWindow.document.close(); + + // Update the iframe's hash + iframe.contentWindow.document.location.hash = History.escapeHash(documentHash); + } + + // Trigger Hashchange Event + History.Adapter.trigger(window,'hashchange'); + } + + // The iFrame Hash has changed (back button caused) + else if ( iframeHash !== lastIframeHash ) { + //History.debug('hashchange.checker: iframe hash out of sync', 'iframeHash (new):', iframeHash, 'documentHash (old):', documentHash); + + // Equalise + lastIframeHash = iframeHash; + + // Update the Hash + History.setHash(iframeHash,false); + } + + // Reset Running + checkerRunning = false; + + // Return true + return true; + }; + } + else { + // We are not IE + // Firefox 1 or 2, Opera + + // Define the checker function + History.checkerFunction = function(){ + // Prepare + var documentHash = History.getHash(); + + // The Document Hash has changed (application caused) + if ( documentHash !== lastDocumentHash ) { + // Equalise + lastDocumentHash = documentHash; + + // Trigger Hashchange Event + History.Adapter.trigger(window,'hashchange'); + } + + // Return true + return true; + }; + } + + // Apply the checker function + History.intervalList.push(setInterval(History.checkerFunction, History.options.hashChangeInterval)); + + // Done + return true; + }; // History.hashChangeInit + + // Bind hashChangeInit + History.Adapter.onDomLoad(History.hashChangeInit); + + } // History.emulated.hashChange + + + // ---------------------------------------------------------------------- + // HTML5 State Support + + if ( History.emulated.pushState ) { + /* + * We must emulate the HTML5 State Management by using HTML4 HashChange + */ + + /** + * History.onHashChange(event) + * Trigger HTML5's window.onpopstate via HTML4 HashChange Support + */ + History.onHashChange = function(event){ + //History.debug('History.onHashChange', arguments); + + // Prepare + var + currentUrl = ((event && event.newURL) || document.location.href), + currentHash = History.getHashByUrl(currentUrl), + currentState = null, + currentStateHash = null, + currentStateHashExits = null; + + // Check if we are the same state + if ( History.isLastHash(currentHash) ) { + // There has been no change (just the page's hash has finally propagated) + //History.debug('History.onHashChange: no change'); + History.busy(false); + return false; + } + + // Reset the double check + History.doubleCheckComplete(); + + // Store our location for use in detecting back/forward direction + History.saveHash(currentHash); + + // Expand Hash + if ( currentHash && History.isTraditionalAnchor(currentHash) ) { + //History.debug('History.onHashChange: traditional anchor', currentHash); + // Traditional Anchor Hash + History.Adapter.trigger(window,'anchorchange'); + History.busy(false); + return false; + } + + // Create State + currentState = History.extractState(History.getFullUrl(currentHash||document.location.href,false),true); + + // Check if we are the same state + if ( History.isLastSavedState(currentState) ) { + //History.debug('History.onHashChange: no change'); + // There has been no change (just the page's hash has finally propagated) + History.busy(false); + return false; + } + + // Create the state Hash + currentStateHash = History.getHashByState(currentState); + + // Check if we are DiscardedState + var discardObject = History.discardedState(currentState); + if ( discardObject ) { + // Ignore this state as it has been discarded and go back to the state before it + if ( History.getHashByIndex(-2) === History.getHashByState(discardObject.forwardState) ) { + // We are going backwards + //History.debug('History.onHashChange: go backwards'); + History.back(false); + } else { + // We are going forwards + //History.debug('History.onHashChange: go forwards'); + History.forward(false); + } + return false; + } + + // Push the new HTML5 State + //History.debug('History.onHashChange: success hashchange'); + History.pushState(currentState.data,currentState.title,currentState.url,false); + + // End onHashChange closure + return true; + }; + History.Adapter.bind(window,'hashchange',History.onHashChange); + + /** + * History.pushState(data,title,url) + * Add a new State to the history object, become it, and trigger onpopstate + * We have to trigger for HTML4 compatibility + * @param {object} data + * @param {string} title + * @param {string} url + * @return {true} + */ + History.pushState = function(data,title,url,queue){ + //History.debug('History.pushState: called', arguments); + + // Check the State + if ( History.getHashByUrl(url) ) { + throw new Error('History.js does not support states with fragement-identifiers (hashes/anchors).'); + } + + // Handle Queueing + if ( queue !== false && History.busy() ) { + // Wait + Push to Queue + //History.debug('History.pushState: we must wait', arguments); + History.pushQueue({ + scope: History, + callback: History.pushState, + args: arguments, + queue: queue + }); + return false; + } + + // Make Busy + History.busy(true); + + // Fetch the State Object + var + newState = History.createStateObject(data,title,url), + newStateHash = History.getHashByState(newState), + oldState = History.getState(false), + oldStateHash = History.getHashByState(oldState), + html4Hash = History.getHash(); + + // Store the newState + History.storeState(newState); + History.expectedStateId = newState.id; + + // Recycle the State + History.recycleState(newState); + + // Force update of the title + History.setTitle(newState); + + // Check if we are the same State + if ( newStateHash === oldStateHash ) { + //History.debug('History.pushState: no change', newStateHash); + History.busy(false); + return false; + } + + // Update HTML4 Hash + if ( newStateHash !== html4Hash && newStateHash !== History.getShortUrl(document.location.href) ) { + //History.debug('History.pushState: update hash', newStateHash, html4Hash); + History.setHash(newStateHash,false); + return false; + } + + // Update HTML5 State + History.saveState(newState); + + // Fire HTML5 Event + //History.debug('History.pushState: trigger popstate'); + History.Adapter.trigger(window,'statechange'); + History.busy(false); + + // End pushState closure + return true; + }; + + /** + * History.replaceState(data,title,url) + * Replace the State and trigger onpopstate + * We have to trigger for HTML4 compatibility + * @param {object} data + * @param {string} title + * @param {string} url + * @return {true} + */ + History.replaceState = function(data,title,url,queue){ + //History.debug('History.replaceState: called', arguments); + + // Check the State + if ( History.getHashByUrl(url) ) { + throw new Error('History.js does not support states with fragement-identifiers (hashes/anchors).'); + } + + // Handle Queueing + if ( queue !== false && History.busy() ) { + // Wait + Push to Queue + //History.debug('History.replaceState: we must wait', arguments); + History.pushQueue({ + scope: History, + callback: History.replaceState, + args: arguments, + queue: queue + }); + return false; + } + + // Make Busy + History.busy(true); + + // Fetch the State Objects + var + newState = History.createStateObject(data,title,url), + oldState = History.getState(false), + previousState = History.getStateByIndex(-2); + + // Discard Old State + History.discardState(oldState,newState,previousState); + + // Alias to PushState + History.pushState(newState.data,newState.title,newState.url,false); + + // End replaceState closure + return true; + }; + + /** + * Ensure initial state is handled correctly + */ + if ( History.getHash() && !History.emulated.hashChange ) { + History.Adapter.onDomLoad(function(){ + History.Adapter.trigger(window,'hashchange'); + }); + } + + } // History.emulated.pushState + + }; // History.initHtml4 + + // Try and Initialise History + History.init(); + +})(window); diff --git a/admin/thirdparty/history-js/scripts/uncompressed/history.js b/admin/thirdparty/history-js/scripts/uncompressed/history.js new file mode 100644 index 000000000..af06c7e38 --- /dev/null +++ b/admin/thirdparty/history-js/scripts/uncompressed/history.js @@ -0,0 +1,1867 @@ +/** + * History.js Core + * @author Benjamin Arthur Lupton + * @copyright 2010-2011 Benjamin Arthur Lupton + * @license New BSD License + */ + +(function(window,undefined){ + "use strict"; + + // -------------------------------------------------------------------------- + // Initialise + + // Localise Globals + var + console = window.console||undefined, // Prevent a JSLint complain + document = window.document, // Make sure we are using the correct document + navigator = window.navigator, // Make sure we are using the correct navigator + amplify = window.amplify||false, // Amplify.js + setTimeout = window.setTimeout, + clearTimeout = window.clearTimeout, + setInterval = window.setInterval, + clearInterval = window.clearInterval, + JSON = window.JSON, + History = window.History = window.History||{}, // Public History Object + history = window.history; // Old History Object + + // MooTools Compatibility + JSON.stringify = JSON.stringify||JSON.encode; + JSON.parse = JSON.parse||JSON.decode; + + // Check Existence + if ( typeof History.init !== 'undefined' ) { + throw new Error('History.js Core has already been loaded...'); + } + + // Initialise History + History.init = function(){ + // Check Load Status of Adapter + if ( typeof History.Adapter === 'undefined' ) { + return false; + } + + // Check Load Status of Core + if ( typeof History.initCore !== 'undefined' ) { + History.initCore(); + } + + // Check Load Status of HTML4 Support + if ( typeof History.initHtml4 !== 'undefined' ) { + History.initHtml4(); + } + + // Return true + return true; + }; + + // -------------------------------------------------------------------------- + // Initialise Core + + // Initialise Core + History.initCore = function(){ + // Initialise + if ( typeof History.initCore.initialized !== 'undefined' ) { + // Already Loaded + return false; + } + else { + History.initCore.initialized = true; + } + + // ---------------------------------------------------------------------- + // Options + + /** + * History.options + * Configurable options + */ + History.options = History.options||{}; + + /** + * History.options.hashChangeInterval + * How long should the interval be before hashchange checks + */ + History.options.hashChangeInterval = History.options.hashChangeInterval || 100; + + /** + * History.options.safariPollInterval + * How long should the interval be before safari poll checks + */ + History.options.safariPollInterval = History.options.safariPollInterval || 500; + + /** + * History.options.doubleCheckInterval + * How long should the interval be before we perform a double check + */ + History.options.doubleCheckInterval = History.options.doubleCheckInterval || 500; + + /** + * History.options.storeInterval + * How long should we wait between store calls + */ + History.options.storeInterval = History.options.storeInterval || 1000; + + /** + * History.options.busyDelay + * How long should we wait between busy events + */ + History.options.busyDelay = History.options.busyDelay || 250; + + /** + * History.options.debug + * If true will enable debug messages to be logged + */ + History.options.debug = History.options.debug || false; + + /** + * History.options.initialTitle + * What is the title of the initial state + */ + History.options.initialTitle = History.options.initialTitle || document.title; + + + // ---------------------------------------------------------------------- + // Interval record + + /** + * History.intervalList + * List of intervals set, to be cleared when document is unloaded. + */ + History.intervalList = []; + + /** + * History.clearAllIntervals + * Clears all setInterval instances. + */ + History.clearAllIntervals = function(){ + var i, il = History.intervalList; + if (typeof il !== "undefined" && il !== null) { + for (i = 0; i < il.length; i++) { + clearInterval(il[i]); + } + History.intervalList = null; + } + }; + History.Adapter.bind(window,"beforeunload",History.clearAllIntervals); + History.Adapter.bind(window,"unload",History.clearAllIntervals); + + + // ---------------------------------------------------------------------- + // Debug + + /** + * History.debug(message,...) + * Logs the passed arguments if debug enabled + */ + History.debug = function(){ + if ( (History.options.debug||false) ) { + History.log.apply(History,arguments); + } + }; + + /** + * History.log(message,...) + * Logs the passed arguments + */ + History.log = function(){ + // Prepare + var + consoleExists = !(typeof console === 'undefined' || typeof console.log === 'undefined' || typeof console.log.apply === 'undefined'), + textarea = document.getElementById('log'), + message, + i,n + ; + + // Write to Console + if ( consoleExists ) { + var args = Array.prototype.slice.call(arguments); + message = args.shift(); + if ( typeof console.debug !== 'undefined' ) { + console.debug.apply(console,[message,args]); + } + else { + console.log.apply(console,[message,args]); + } + } + else { + message = ("\n"+arguments[0]+"\n"); + } + + // Write to log + for ( i=1,n=arguments.length; i + * @author James Padolsey + */ + History.getInternetExplorerMajorVersion = function(){ + var result = History.getInternetExplorerMajorVersion.cached = + (typeof History.getInternetExplorerMajorVersion.cached !== 'undefined') + ? History.getInternetExplorerMajorVersion.cached + : (function(){ + var v = 3, + div = document.createElement('div'), + all = div.getElementsByTagName('i'); + while ( (div.innerHTML = '') && all[0] ) {} + return (v > 4) ? v : false; + })() + ; + return result; + }; + + /** + * History.isInternetExplorer() + * Are we using Internet Explorer? + * @return {boolean} + * @license Public Domain + * @author Benjamin Arthur Lupton + */ + History.isInternetExplorer = function(){ + var result = + History.isInternetExplorer.cached = + (typeof History.isInternetExplorer.cached !== 'undefined') + ? History.isInternetExplorer.cached + : Boolean(History.getInternetExplorerMajorVersion()) + ; + return result; + }; + + /** + * History.emulated + * Which features require emulating? + */ + History.emulated = { + pushState: !Boolean( + window.history && window.history.pushState && window.history.replaceState + && !( + (/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i).test(navigator.userAgent) /* disable for versions of iOS before version 4.3 (8F190) */ + || (/AppleWebKit\/5([0-2]|3[0-2])/i).test(navigator.userAgent) /* disable for the mercury iOS browser, or at least older versions of the webkit engine */ + ) + ), + hashChange: Boolean( + !(('onhashchange' in window) || ('onhashchange' in document)) + || + (History.isInternetExplorer() && History.getInternetExplorerMajorVersion() < 8) + ) + }; + + /** + * History.enabled + * Is History enabled? + */ + History.enabled = !History.emulated.pushState; + + /** + * History.bugs + * Which bugs are present + */ + History.bugs = { + /** + * Safari 5 and Safari iOS 4 fail to return to the correct state once a hash is replaced by a `replaceState` call + * https://bugs.webkit.org/show_bug.cgi?id=56249 + */ + setHash: Boolean(!History.emulated.pushState && navigator.vendor === 'Apple Computer, Inc.' && /AppleWebKit\/5([0-2]|3[0-3])/.test(navigator.userAgent)), + + /** + * Safari 5 and Safari iOS 4 sometimes fail to apply the state change under busy conditions + * https://bugs.webkit.org/show_bug.cgi?id=42940 + */ + safariPoll: Boolean(!History.emulated.pushState && navigator.vendor === 'Apple Computer, Inc.' && /AppleWebKit\/5([0-2]|3[0-3])/.test(navigator.userAgent)), + + /** + * MSIE 6 and 7 sometimes do not apply a hash even it was told to (requiring a second call to the apply function) + */ + ieDoubleCheck: Boolean(History.isInternetExplorer() && History.getInternetExplorerMajorVersion() < 8), + + /** + * MSIE 6 requires the entire hash to be encoded for the hashes to trigger the onHashChange event + */ + hashEscape: Boolean(History.isInternetExplorer() && History.getInternetExplorerMajorVersion() < 7) + }; + + /** + * History.isEmptyObject(obj) + * Checks to see if the Object is Empty + * @param {Object} obj + * @return {boolean} + */ + History.isEmptyObject = function(obj) { + for ( var name in obj ) { + return false; + } + return true; + }; + + /** + * History.cloneObject(obj) + * Clones a object + * @param {Object} obj + * @return {Object} + */ + History.cloneObject = function(obj) { + var hash,newObj; + if ( obj ) { + hash = JSON.stringify(obj); + newObj = JSON.parse(hash); + } + else { + newObj = {}; + } + return newObj; + }; + + // ---------------------------------------------------------------------- + // URL Helpers + + /** + * History.getRootUrl() + * Turns "http://mysite.com/dir/page.html?asd" into "http://mysite.com" + * @return {String} rootUrl + */ + History.getRootUrl = function(){ + // Create + var rootUrl = document.location.protocol+'//'+(document.location.hostname||document.location.host); + if ( document.location.port||false ) { + rootUrl += ':'+document.location.port; + } + rootUrl += '/'; + + // Return + return rootUrl; + }; + + /** + * History.getBaseHref() + * Fetches the `href` attribute of the `` element if it exists + * @return {String} baseHref + */ + History.getBaseHref = function(){ + // Create + var + baseElements = document.getElementsByTagName('base'), + baseElement = null, + baseHref = ''; + + // Test for Base Element + if ( baseElements.length === 1 ) { + // Prepare for Base Element + baseElement = baseElements[0]; + baseHref = baseElement.href.replace(/[^\/]+$/,''); + } + + // Adjust trailing slash + baseHref = baseHref.replace(/\/+$/,''); + if ( baseHref ) baseHref += '/'; + + // Return + return baseHref; + }; + + /** + * History.getBaseUrl() + * Fetches the baseHref or basePageUrl or rootUrl (whichever one exists first) + * @return {String} baseUrl + */ + History.getBaseUrl = function(){ + // Create + var baseUrl = History.getBaseHref()||History.getBasePageUrl()||History.getRootUrl(); + + // Return + return baseUrl; + }; + + /** + * History.getPageUrl() + * Fetches the URL of the current page + * @return {String} pageUrl + */ + History.getPageUrl = function(){ + // Fetch + var + State = History.getState(false,false), + stateUrl = (State||{}).url||document.location.href; + + // Create + var pageUrl = stateUrl.replace(/\/+$/,'').replace(/[^\/]+$/,function(part,index,string){ + return (/\./).test(part) ? part : part+'/'; + }); + + // Return + return pageUrl; + }; + + /** + * History.getBasePageUrl() + * Fetches the Url of the directory of the current page + * @return {String} basePageUrl + */ + History.getBasePageUrl = function(){ + // Create + var basePageUrl = document.location.href.replace(/[#\?].*/,'').replace(/[^\/]+$/,function(part,index,string){ + return (/[^\/]$/).test(part) ? '' : part; + }).replace(/\/+$/,'')+'/'; + + // Return + return basePageUrl; + }; + + /** + * History.getFullUrl(url) + * Ensures that we have an absolute URL and not a relative URL + * @param {string} url + * @param {Boolean} allowBaseHref + * @return {string} fullUrl + */ + History.getFullUrl = function(url,allowBaseHref){ + // Prepare + var fullUrl = url, firstChar = url.substring(0,1); + allowBaseHref = (typeof allowBaseHref === 'undefined') ? true : allowBaseHref; + + // Check + if ( /[a-z]+\:\/\//.test(url) ) { + // Full URL + } + else if ( firstChar === '/' ) { + // Root URL + fullUrl = History.getRootUrl()+url.replace(/^\/+/,''); + } + else if ( firstChar === '#' ) { + // Anchor URL + fullUrl = History.getPageUrl().replace(/#.*/,'')+url; + } + else if ( firstChar === '?' ) { + // Query URL + fullUrl = History.getPageUrl().replace(/[\?#].*/,'')+url; + } + else { + // Relative URL + if ( allowBaseHref ) { + fullUrl = History.getBaseUrl()+url.replace(/^(\.\/)+/,''); + } else { + fullUrl = History.getBasePageUrl()+url.replace(/^(\.\/)+/,''); + } + // We have an if condition above as we do not want hashes + // which are relative to the baseHref in our URLs + // as if the baseHref changes, then all our bookmarks + // would now point to different locations + // whereas the basePageUrl will always stay the same + } + + // Return + return fullUrl.replace(/\#$/,''); + }; + + /** + * History.getShortUrl(url) + * Ensures that we have a relative URL and not a absolute URL + * @param {string} url + * @return {string} url + */ + History.getShortUrl = function(url){ + // Prepare + var shortUrl = url, baseUrl = History.getBaseUrl(), rootUrl = History.getRootUrl(); + + // Trim baseUrl + if ( History.emulated.pushState ) { + // We are in a if statement as when pushState is not emulated + // The actual url these short urls are relative to can change + // So within the same session, we the url may end up somewhere different + shortUrl = shortUrl.replace(baseUrl,''); + } + + // Trim rootUrl + shortUrl = shortUrl.replace(rootUrl,'/'); + + // Ensure we can still detect it as a state + if ( History.isTraditionalAnchor(shortUrl) ) { + shortUrl = './'+shortUrl; + } + + // Clean It + shortUrl = shortUrl.replace(/^(\.\/)+/g,'./').replace(/\#$/,''); + + // Return + return shortUrl; + }; + + // ---------------------------------------------------------------------- + // State Storage + + /** + * History.store + * The store for all session specific data + */ + History.store = amplify ? (amplify.store('History.store')||{}) : {}; + History.store.idToState = History.store.idToState||{}; + History.store.urlToId = History.store.urlToId||{}; + History.store.stateToId = History.store.stateToId||{}; + + /** + * History.idToState + * 1-1: State ID to State Object + */ + History.idToState = History.idToState||{}; + + /** + * History.stateToId + * 1-1: State String to State ID + */ + History.stateToId = History.stateToId||{}; + + /** + * History.urlToId + * 1-1: State URL to State ID + */ + History.urlToId = History.urlToId||{}; + + /** + * History.storedStates + * Store the states in an array + */ + History.storedStates = History.storedStates||[]; + + /** + * History.savedStates + * Saved the states in an array + */ + History.savedStates = History.savedStates||[]; + + /** + * History.getState() + * Get an object containing the data, title and url of the current state + * @param {Boolean} friendly + * @param {Boolean} create + * @return {Object} State + */ + History.getState = function(friendly,create){ + // Prepare + if ( typeof friendly === 'undefined' ) { friendly = true; } + if ( typeof create === 'undefined' ) { create = true; } + + // Fetch + var State = History.getLastSavedState(); + + // Create + if ( !State && create ) { + State = History.createStateObject(); + } + + // Adjust + if ( friendly ) { + State = History.cloneObject(State); + State.url = State.cleanUrl||State.url; + } + + // Return + return State; + }; + + /** + * History.getIdByState(State) + * Gets a ID for a State + * @param {State} newState + * @return {String} id + */ + History.getIdByState = function(newState){ + + // Fetch ID + var id = History.extractId(newState.url); + if ( !id ) { + // Find ID via State String + var str = History.getStateString(newState); + if ( typeof History.stateToId[str] !== 'undefined' ) { + id = History.stateToId[str]; + } + else if ( typeof History.store.stateToId[str] !== 'undefined' ) { + id = History.store.stateToId[str]; + } + else { + // Generate a new ID + while ( true ) { + id = String(Math.floor(Math.random()*1000)); + if ( typeof History.idToState[id] === 'undefined' && typeof History.store.idToState[id] === 'undefined' ) { + break; + } + } + + // Apply the new State to the ID + History.stateToId[str] = id; + History.idToState[id] = newState; + } + } + + // Return ID + return id; + }; + + /** + * History.normalizeState(State) + * Expands a State Object + * @param {object} State + * @return {object} + */ + History.normalizeState = function(oldState){ + // Prepare + if ( !oldState || (typeof oldState !== 'object') ) { + oldState = {}; + } + + // Check + if ( typeof oldState.normalized !== 'undefined' ) { + return oldState; + } + + // Adjust + if ( !oldState.data || (typeof oldState.data !== 'object') ) { + oldState.data = {}; + } + + // ---------------------------------------------------------------------- + + // Create + var newState = {}; + newState.normalized = true; + newState.title = oldState.title||''; + newState.url = History.getFullUrl(History.unescapeString(oldState.url||document.location.href)); + newState.hash = History.getShortUrl(newState.url); + newState.data = History.cloneObject(oldState.data); + + // Fetch ID + newState.id = History.getIdByState(newState); + + // ---------------------------------------------------------------------- + + // Clean the URL + newState.cleanUrl = newState.url.replace(/\??\&_suid.*/,''); + newState.url = newState.cleanUrl; + + // Check to see if we have more than just a url + var dataNotEmpty = !History.isEmptyObject(newState.data); + + // Apply + if ( newState.title || dataNotEmpty ) { + // Add ID to Hash + newState.hash = History.getShortUrl(newState.url).replace(/\??\&_suid.*/,''); + if ( !/\?/.test(newState.hash) ) { + newState.hash += '?'; + } + newState.hash += '&_suid='+newState.id; + } + + // Create the Hashed URL + newState.hashedUrl = History.getFullUrl(newState.hash); + + // ---------------------------------------------------------------------- + + // Update the URL if we have a duplicate + if ( (History.emulated.pushState || History.bugs.safariPoll) && History.hasUrlDuplicate(newState) ) { + newState.url = newState.hashedUrl; + } + + // ---------------------------------------------------------------------- + + // Return + return newState; + }; + + /** + * History.createStateObject(data,title,url) + * Creates a object based on the data, title and url state params + * @param {object} data + * @param {string} title + * @param {string} url + * @return {object} + */ + History.createStateObject = function(data,title,url){ + // Hashify + var State = { + 'data': data, + 'title': title, + 'url': url + }; + + // Expand the State + State = History.normalizeState(State); + + // Return object + return State; + }; + + /** + * History.getStateById(id) + * Get a state by it's UID + * @param {String} id + */ + History.getStateById = function(id){ + // Prepare + id = String(id); + + // Retrieve + var State = History.idToState[id] || History.store.idToState[id] || undefined; + + // Return State + return State; + }; + + /** + * Get a State's String + * @param {State} passedState + */ + History.getStateString = function(passedState){ + // Prepare + var State = History.normalizeState(passedState); + + // Clean + var cleanedState = { + data: State.data, + title: passedState.title, + url: passedState.url + }; + + // Fetch + var str = JSON.stringify(cleanedState); + + // Return + return str; + }; + + /** + * Get a State's ID + * @param {State} passedState + * @return {String} id + */ + History.getStateId = function(passedState){ + // Prepare + var State = History.normalizeState(passedState); + + // Fetch + var id = State.id; + + // Return + return id; + }; + + /** + * History.getHashByState(State) + * Creates a Hash for the State Object + * @param {State} passedState + * @return {String} hash + */ + History.getHashByState = function(passedState){ + // Prepare + var hash, State = History.normalizeState(passedState); + + // Fetch + hash = State.hash; + + // Return + return hash; + }; + + /** + * History.extractId(url_or_hash) + * Get a State ID by it's URL or Hash + * @param {string} url_or_hash + * @return {string} id + */ + History.extractId = function ( url_or_hash ) { + // Prepare + var id; + + // Extract + var parts,url; + parts = /(.*)\&_suid=([0-9]+)$/.exec(url_or_hash); + url = parts ? (parts[1]||url_or_hash) : url_or_hash; + id = parts ? String(parts[2]||'') : ''; + + // Return + return id||false; + }; + + /** + * History.isTraditionalAnchor + * Checks to see if the url is a traditional anchor or not + * @param {String} url_or_hash + * @return {Boolean} + */ + History.isTraditionalAnchor = function(url_or_hash){ + // Check + var isTraditional = !(/[\/\?\.]/.test(url_or_hash)); + + // Return + return isTraditional; + }; + + /** + * History.extractState + * Get a State by it's URL or Hash + * @param {String} url_or_hash + * @return {State|null} + */ + History.extractState = function(url_or_hash,create){ + // Prepare + var State = null; + create = create||false; + + // Fetch SUID + var id = History.extractId(url_or_hash); + if ( id ) { + State = History.getStateById(id); + } + + // Fetch SUID returned no State + if ( !State ) { + // Fetch URL + var url = History.getFullUrl(url_or_hash); + + // Check URL + id = History.getIdByUrl(url)||false; + if ( id ) { + State = History.getStateById(id); + } + + // Create State + if ( !State && create && !History.isTraditionalAnchor(url_or_hash) ) { + State = History.createStateObject(null,null,url); + } + } + + // Return + return State; + }; + + /** + * History.getIdByUrl() + * Get a State ID by a State URL + */ + History.getIdByUrl = function(url){ + // Fetch + var id = History.urlToId[url] || History.store.urlToId[url] || undefined; + + // Return + return id; + }; + + /** + * History.getLastSavedState() + * Get an object containing the data, title and url of the current state + * @return {Object} State + */ + History.getLastSavedState = function(){ + return History.savedStates[History.savedStates.length-1]||undefined; + }; + + /** + * History.getLastStoredState() + * Get an object containing the data, title and url of the current state + * @return {Object} State + */ + History.getLastStoredState = function(){ + return History.storedStates[History.storedStates.length-1]||undefined; + }; + + /** + * History.hasUrlDuplicate + * Checks if a Url will have a url conflict + * @param {Object} newState + * @return {Boolean} hasDuplicate + */ + History.hasUrlDuplicate = function(newState) { + // Prepare + var hasDuplicate = false; + + // Fetch + var oldState = History.extractState(newState.url); + + // Check + hasDuplicate = oldState && oldState.id !== newState.id; + + // Return + return hasDuplicate; + }; + + /** + * History.storeState + * Store a State + * @param {Object} newState + * @return {Object} newState + */ + History.storeState = function(newState){ + // Store the State + History.urlToId[newState.url] = newState.id; + + // Push the State + History.storedStates.push(History.cloneObject(newState)); + + // Return newState + return newState; + }; + + /** + * History.isLastSavedState(newState) + * Tests to see if the state is the last state + * @param {Object} newState + * @return {boolean} isLast + */ + History.isLastSavedState = function(newState){ + // Prepare + var isLast = false; + + // Check + if ( History.savedStates.length ) { + var + newId = newState.id, + oldState = History.getLastSavedState(), + oldId = oldState.id; + + // Check + isLast = (newId === oldId); + } + + // Return + return isLast; + }; + + /** + * History.saveState + * Push a State + * @param {Object} newState + * @return {boolean} changed + */ + History.saveState = function(newState){ + // Check Hash + if ( History.isLastSavedState(newState) ) { + return false; + } + + // Push the State + History.savedStates.push(History.cloneObject(newState)); + + // Return true + return true; + }; + + /** + * History.getStateByIndex() + * Gets a state by the index + * @param {integer} index + * @return {Object} + */ + History.getStateByIndex = function(index){ + // Prepare + var State = null; + + // Handle + if ( typeof index === 'undefined' ) { + // Get the last inserted + State = History.savedStates[History.savedStates.length-1]; + } + else if ( index < 0 ) { + // Get from the end + State = History.savedStates[History.savedStates.length+index]; + } + else { + // Get from the beginning + State = History.savedStates[index]; + } + + // Return State + return State; + }; + + // ---------------------------------------------------------------------- + // Hash Helpers + + /** + * History.getHash() + * Gets the current document hash + * @return {string} + */ + History.getHash = function(){ + var hash = History.unescapeHash(document.location.hash); + return hash; + }; + + /** + * History.unescapeString() + * Unescape a string + * @param {String} str + * @return {string} + */ + History.unescapeString = function(str){ + // Prepare + var result = str; + + // Unescape hash + var tmp; + while ( true ) { + tmp = window.unescape(result); + if ( tmp === result ) { + break; + } + result = tmp; + } + + // Return result + return result; + }; + + /** + * History.unescapeHash() + * normalize and Unescape a Hash + * @param {String} hash + * @return {string} + */ + History.unescapeHash = function(hash){ + // Prepare + var result = History.normalizeHash(hash); + + // Unescape hash + result = History.unescapeString(result); + + // Return result + return result; + }; + + /** + * History.normalizeHash() + * normalize a hash across browsers + * @return {string} + */ + History.normalizeHash = function(hash){ + var result = hash.replace(/[^#]*#/,'').replace(/#.*/, ''); + + // Return result + return result; + }; + + /** + * History.setHash(hash) + * Sets the document hash + * @param {string} hash + * @return {History} + */ + History.setHash = function(hash,queue){ + // Handle Queueing + if ( queue !== false && History.busy() ) { + // Wait + Push to Queue + //History.debug('History.setHash: we must wait', arguments); + History.pushQueue({ + scope: History, + callback: History.setHash, + args: arguments, + queue: queue + }); + return false; + } + + // Log + //History.debug('History.setHash: called',hash); + + // Prepare + var adjustedHash = History.escapeHash(hash); + + // Make Busy + Continue + History.busy(true); + + // Check if hash is a state + var State = History.extractState(hash,true); + if ( State && !History.emulated.pushState ) { + // Hash is a state so skip the setHash + //History.debug('History.setHash: Hash is a state so skipping the hash set with a direct pushState call',arguments); + + // PushState + History.pushState(State.data,State.title,State.url,false); + } + else if ( document.location.hash !== adjustedHash ) { + // Hash is a proper hash, so apply it + + // Handle browser bugs + if ( History.bugs.setHash ) { + // Fix Safari Bug https://bugs.webkit.org/show_bug.cgi?id=56249 + + // Fetch the base page + var pageUrl = History.getPageUrl(); + + // Safari hash apply + History.pushState(null,null,pageUrl+'#'+adjustedHash,false); + } + else { + // Normal hash apply + document.location.hash = adjustedHash; + } + } + + // Chain + return History; + }; + + /** + * History.escape() + * normalize and Escape a Hash + * @return {string} + */ + History.escapeHash = function(hash){ + var result = History.normalizeHash(hash); + + // Escape hash + result = window.escape(result); + + // IE6 Escape Bug + if ( !History.bugs.hashEscape ) { + // Restore common parts + result = result + .replace(/\%21/g,'!') + .replace(/\%26/g,'&') + .replace(/\%3D/g,'=') + .replace(/\%3F/g,'?'); + } + + // Return result + return result; + }; + + /** + * History.getHashByUrl(url) + * Extracts the Hash from a URL + * @param {string} url + * @return {string} url + */ + History.getHashByUrl = function(url){ + // Extract the hash + var hash = String(url) + .replace(/([^#]*)#?([^#]*)#?(.*)/, '$2') + ; + + // Unescape hash + hash = History.unescapeHash(hash); + + // Return hash + return hash; + }; + + /** + * History.setTitle(title) + * Applies the title to the document + * @param {State} newState + * @return {Boolean} + */ + History.setTitle = function(newState){ + // Prepare + var title = newState.title; + + // Initial + if ( !title ) { + var firstState = History.getStateByIndex(0); + if ( firstState && firstState.url === newState.url ) { + title = firstState.title||History.options.initialTitle; + } + } + + // Apply + try { + document.getElementsByTagName('title')[0].innerHTML = title.replace('<','<').replace('>','>').replace(' & ',' & '); + } + catch ( Exception ) { } + document.title = title; + + // Chain + return History; + }; + + // ---------------------------------------------------------------------- + // Queueing + + /** + * History.queues + * The list of queues to use + * First In, First Out + */ + History.queues = []; + + /** + * History.busy(value) + * @param {boolean} value [optional] + * @return {boolean} busy + */ + History.busy = function(value){ + // Apply + if ( typeof value !== 'undefined' ) { + //History.debug('History.busy: changing ['+(History.busy.flag||false)+'] to ['+(value||false)+']', History.queues.length); + History.busy.flag = value; + } + // Default + else if ( typeof History.busy.flag === 'undefined' ) { + History.busy.flag = false; + } + + // Queue + if ( !History.busy.flag ) { + // Execute the next item in the queue + clearTimeout(History.busy.timeout); + var fireNext = function(){ + if ( History.busy.flag ) return; + for ( var i=History.queues.length-1; i >= 0; --i ) { + var queue = History.queues[i]; + if ( queue.length === 0 ) continue; + var item = queue.shift(); + History.fireQueueItem(item); + History.busy.timeout = setTimeout(fireNext,History.options.busyDelay); + } + }; + History.busy.timeout = setTimeout(fireNext,History.options.busyDelay); + } + + // Return + return History.busy.flag; + }; + + /** + * History.fireQueueItem(item) + * Fire a Queue Item + * @param {Object} item + * @return {Mixed} result + */ + History.fireQueueItem = function(item){ + return item.callback.apply(item.scope||History,item.args||[]); + }; + + /** + * History.pushQueue(callback,args) + * Add an item to the queue + * @param {Object} item [scope,callback,args,queue] + */ + History.pushQueue = function(item){ + // Prepare the queue + History.queues[item.queue||0] = History.queues[item.queue||0]||[]; + + // Add to the queue + History.queues[item.queue||0].push(item); + + // Chain + return History; + }; + + /** + * History.queue (item,queue), (func,queue), (func), (item) + * Either firs the item now if not busy, or adds it to the queue + */ + History.queue = function(item,queue){ + // Prepare + if ( typeof item === 'function' ) { + item = { + callback: item + }; + } + if ( typeof queue !== 'undefined' ) { + item.queue = queue; + } + + // Handle + if ( History.busy() ) { + History.pushQueue(item); + } else { + History.fireQueueItem(item); + } + + // Chain + return History; + }; + + /** + * History.clearQueue() + * Clears the Queue + */ + History.clearQueue = function(){ + History.busy.flag = false; + History.queues = []; + return History; + }; + + + // ---------------------------------------------------------------------- + // IE Bug Fix + + /** + * History.stateChanged + * States whether or not the state has changed since the last double check was initialised + */ + History.stateChanged = false; + + /** + * History.doubleChecker + * Contains the timeout used for the double checks + */ + History.doubleChecker = false; + + /** + * History.doubleCheckComplete() + * Complete a double check + * @return {History} + */ + History.doubleCheckComplete = function(){ + // Update + History.stateChanged = true; + + // Clear + History.doubleCheckClear(); + + // Chain + return History; + }; + + /** + * History.doubleCheckClear() + * Clear a double check + * @return {History} + */ + History.doubleCheckClear = function(){ + // Clear + if ( History.doubleChecker ) { + clearTimeout(History.doubleChecker); + History.doubleChecker = false; + } + + // Chain + return History; + }; + + /** + * History.doubleCheck() + * Create a double check + * @return {History} + */ + History.doubleCheck = function(tryAgain){ + // Reset + History.stateChanged = false; + History.doubleCheckClear(); + + // Fix IE6,IE7 bug where calling history.back or history.forward does not actually change the hash (whereas doing it manually does) + // Fix Safari 5 bug where sometimes the state does not change: https://bugs.webkit.org/show_bug.cgi?id=42940 + if ( History.bugs.ieDoubleCheck ) { + // Apply Check + History.doubleChecker = setTimeout( + function(){ + History.doubleCheckClear(); + if ( !History.stateChanged ) { + //History.debug('History.doubleCheck: State has not yet changed, trying again', arguments); + // Re-Attempt + tryAgain(); + } + return true; + }, + History.options.doubleCheckInterval + ); + } + + // Chain + return History; + }; + + // ---------------------------------------------------------------------- + // Safari Bug Fix + + /** + * History.safariStatePoll() + * Poll the current state + * @return {History} + */ + History.safariStatePoll = function(){ + // Poll the URL + + // Get the Last State which has the new URL + var + urlState = History.extractState(document.location.href), + newState; + + // Check for a difference + if ( !History.isLastSavedState(urlState) ) { + newState = urlState; + } + else { + return; + } + + // Check if we have a state with that url + // If not create it + if ( !newState ) { + //History.debug('History.safariStatePoll: new'); + newState = History.createStateObject(); + } + + // Apply the New State + //History.debug('History.safariStatePoll: trigger'); + History.Adapter.trigger(window,'popstate'); + + // Chain + return History; + }; + + // ---------------------------------------------------------------------- + // State Aliases + + /** + * History.back(queue) + * Send the browser history back one item + * @param {Integer} queue [optional] + */ + History.back = function(queue){ + //History.debug('History.back: called', arguments); + + // Handle Queueing + if ( queue !== false && History.busy() ) { + // Wait + Push to Queue + //History.debug('History.back: we must wait', arguments); + History.pushQueue({ + scope: History, + callback: History.back, + args: arguments, + queue: queue + }); + return false; + } + + // Make Busy + Continue + History.busy(true); + + // Fix certain browser bugs that prevent the state from changing + History.doubleCheck(function(){ + History.back(false); + }); + + // Go back + history.go(-1); + + // End back closure + return true; + }; + + /** + * History.forward(queue) + * Send the browser history forward one item + * @param {Integer} queue [optional] + */ + History.forward = function(queue){ + //History.debug('History.forward: called', arguments); + + // Handle Queueing + if ( queue !== false && History.busy() ) { + // Wait + Push to Queue + //History.debug('History.forward: we must wait', arguments); + History.pushQueue({ + scope: History, + callback: History.forward, + args: arguments, + queue: queue + }); + return false; + } + + // Make Busy + Continue + History.busy(true); + + // Fix certain browser bugs that prevent the state from changing + History.doubleCheck(function(){ + History.forward(false); + }); + + // Go forward + history.go(1); + + // End forward closure + return true; + }; + + /** + * History.go(index,queue) + * Send the browser history back or forward index times + * @param {Integer} queue [optional] + */ + History.go = function(index,queue){ + //History.debug('History.go: called', arguments); + + // Prepare + var i; + + // Handle + if ( index > 0 ) { + // Forward + for ( i=1; i<=index; ++i ) { + History.forward(queue); + } + } + else if ( index < 0 ) { + // Backward + for ( i=-1; i>=index; --i ) { + History.back(queue); + } + } + else { + throw new Error('History.go: History.go requires a positive or negative integer passed.'); + } + + // Chain + return History; + }; + + + // ---------------------------------------------------------------------- + // Initialise + + /** + * Create the initial State + */ + History.saveState(History.storeState(History.extractState(document.location.href,true))); + + /** + * Bind for Saving Store + */ + if ( amplify ) { + History.onUnload = function(){ + // Prepare + var + currentStore = amplify.store('History.store')||{}, + item; + + // Ensure + currentStore.idToState = currentStore.idToState || {}; + currentStore.urlToId = currentStore.urlToId || {}; + currentStore.stateToId = currentStore.stateToId || {}; + + // Sync + for ( item in History.idToState ) { + if ( !History.idToState.hasOwnProperty(item) ) { + continue; + } + currentStore.idToState[item] = History.idToState[item]; + } + for ( item in History.urlToId ) { + if ( !History.urlToId.hasOwnProperty(item) ) { + continue; + } + currentStore.urlToId[item] = History.urlToId[item]; + } + for ( item in History.stateToId ) { + if ( !History.stateToId.hasOwnProperty(item) ) { + continue; + } + currentStore.stateToId[item] = History.stateToId[item]; + } + + // Update + History.store = currentStore; + + // Store + amplify.store('History.store',currentStore); + }; + // For Internet Explorer + History.intervalList.push(setInterval(History.onUnload,History.options.storeInterval)); + // For Other Browsers + History.Adapter.bind(window,'beforeunload',History.onUnload); + History.Adapter.bind(window,'unload',History.onUnload); + // Both are enabled for consistency + } + + + // ---------------------------------------------------------------------- + // HTML5 State Support + + if ( History.emulated.pushState ) { + /* + * Provide Skeleton for HTML4 Browsers + */ + + // Prepare + var emptyFunction = function(){}; + History.pushState = History.pushState||emptyFunction; + History.replaceState = History.replaceState||emptyFunction; + } + else { + /* + * Use native HTML5 History API Implementation + */ + + /** + * History.onPopState(event,extra) + * Refresh the Current State + */ + History.onPopState = function(event){ + // Reset the double check + History.doubleCheckComplete(); + + // Check for a Hash, and handle apporiatly + var currentHash = History.getHash(); + if ( currentHash ) { + // Expand Hash + var currentState = History.extractState(currentHash||document.location.href,true); + if ( currentState ) { + // We were able to parse it, it must be a State! + // Let's forward to replaceState + //History.debug('History.onPopState: state anchor', currentHash, currentState); + History.replaceState(currentState.data, currentState.title, currentState.url, false); + } + else { + // Traditional Anchor + //History.debug('History.onPopState: traditional anchor', currentHash); + History.Adapter.trigger(window,'anchorchange'); + History.busy(false); + } + + // We don't care for hashes + History.expectedStateId = false; + return false; + } + + // Prepare + var newState = false; + + // Prepare + event = event||{}; + if ( typeof event.state === 'undefined' ) { + // jQuery + if ( typeof event.originalEvent !== 'undefined' && typeof event.originalEvent.state !== 'undefined' ) { + event.state = event.originalEvent.state||false; + } + // MooTools + else if ( typeof event.event !== 'undefined' && typeof event.event.state !== 'undefined' ) { + event.state = event.event.state||false; + } + } + + // Ensure + event.state = (event.state||false); + + // Fetch State + if ( event.state ) { + // Vanilla: Back/forward button was used + newState = History.getStateById(event.state); + } + else if ( History.expectedStateId ) { + // Vanilla: A new state was pushed, and popstate was called manually + newState = History.getStateById(History.expectedStateId); + } + else { + // Initial State + newState = History.extractState(document.location.href); + } + + // The State did not exist in our store + if ( !newState ) { + // Regenerate the State + newState = History.createStateObject(null,null,document.location.href); + } + + // Clean + History.expectedStateId = false; + + // Check if we are the same state + if ( History.isLastSavedState(newState) ) { + // There has been no change (just the page's hash has finally propagated) + //History.debug('History.onPopState: no change', newState, History.savedStates); + History.busy(false); + return false; + } + + // Store the State + History.storeState(newState); + History.saveState(newState); + + // Force update of the title + History.setTitle(newState); + + // Fire Our Event + History.Adapter.trigger(window,'statechange'); + History.busy(false); + + // Return true + return true; + }; + History.Adapter.bind(window,'popstate',History.onPopState); + + /** + * History.pushState(data,title,url) + * Add a new State to the history object, become it, and trigger onpopstate + * We have to trigger for HTML4 compatibility + * @param {object} data + * @param {string} title + * @param {string} url + * @return {true} + */ + History.pushState = function(data,title,url,queue){ + //History.debug('History.pushState: called', arguments); + + // Check the State + if ( History.getHashByUrl(url) && History.emulated.pushState ) { + throw new Error('History.js does not support states with fragement-identifiers (hashes/anchors).'); + } + + // Handle Queueing + if ( queue !== false && History.busy() ) { + // Wait + Push to Queue + //History.debug('History.pushState: we must wait', arguments); + History.pushQueue({ + scope: History, + callback: History.pushState, + args: arguments, + queue: queue + }); + return false; + } + + // Make Busy + Continue + History.busy(true); + + // Create the newState + var newState = History.createStateObject(data,title,url); + + // Check it + if ( History.isLastSavedState(newState) ) { + // Won't be a change + History.busy(false); + } + else { + // Store the newState + History.storeState(newState); + History.expectedStateId = newState.id; + + // Push the newState + history.pushState(newState.id,newState.title,newState.url); + + // Fire HTML5 Event + History.Adapter.trigger(window,'popstate'); + } + + // End pushState closure + return true; + }; + + /** + * History.replaceState(data,title,url) + * Replace the State and trigger onpopstate + * We have to trigger for HTML4 compatibility + * @param {object} data + * @param {string} title + * @param {string} url + * @return {true} + */ + History.replaceState = function(data,title,url,queue){ + //History.debug('History.replaceState: called', arguments); + + // Check the State + if ( History.getHashByUrl(url) && History.emulated.pushState ) { + throw new Error('History.js does not support states with fragement-identifiers (hashes/anchors).'); + } + + // Handle Queueing + if ( queue !== false && History.busy() ) { + // Wait + Push to Queue + //History.debug('History.replaceState: we must wait', arguments); + History.pushQueue({ + scope: History, + callback: History.replaceState, + args: arguments, + queue: queue + }); + return false; + } + + // Make Busy + Continue + History.busy(true); + + // Create the newState + var newState = History.createStateObject(data,title,url); + + // Check it + if ( History.isLastSavedState(newState) ) { + // Won't be a change + History.busy(false); + } + else { + // Store the newState + History.storeState(newState); + History.expectedStateId = newState.id; + + // Push the newState + history.replaceState(newState.id,newState.title,newState.url); + + // Fire HTML5 Event + History.Adapter.trigger(window,'popstate'); + } + + // End replaceState closure + return true; + }; + + // Be aware, the following is only for native pushState implementations + // If you are wanting to include something for all browsers + // Then include it above this if block + + /** + * Setup Safari Fix + */ + if ( History.bugs.safariPoll ) { + History.intervalList.push(setInterval(History.safariStatePoll, History.options.safariPollInterval)); + } + + /** + * Ensure Cross Browser Compatibility + */ + if ( navigator.vendor === 'Apple Computer, Inc.' || (navigator.appCodeName||'') === 'Mozilla' ) { + /** + * Fix Safari HashChange Issue + */ + + // Setup Alias + History.Adapter.bind(window,'hashchange',function(){ + History.Adapter.trigger(window,'popstate'); + }); + + // Initialise Alias + if ( History.getHash() ) { + History.Adapter.onDomLoad(function(){ + History.Adapter.trigger(window,'hashchange'); + }); + } + } + + } // !History.emulated.pushState + + }; // History.initCore + + // Try and Initialise History + History.init(); + +})(window); diff --git a/admin/thirdparty/history-js/scripts/uncompressed/json2.js b/admin/thirdparty/history-js/scripts/uncompressed/json2.js new file mode 100644 index 000000000..36d3dc393 --- /dev/null +++ b/admin/thirdparty/history-js/scripts/uncompressed/json2.js @@ -0,0 +1,480 @@ +/* + http://www.JSON.org/json2.js + 2011-01-18 + + Public Domain. + + NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. + + See http://www.JSON.org/js.html + + + This code should be minified before deployment. + See http://javascript.crockford.com/jsmin.html + + USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO + NOT CONTROL. + + + This file creates a global JSON object containing two methods: stringify + and parse. + + JSON.stringify(value, replacer, space) + value any JavaScript value, usually an object or array. + + replacer an optional parameter that determines how object + values are stringified for objects. It can be a + function or an array of strings. + + space an optional parameter that specifies the indentation + of nested structures. If it is omitted, the text will + be packed without extra whitespace. If it is a number, + it will specify the number of spaces to indent at each + level. If it is a string (such as '\t' or ' '), + it contains the characters used to indent at each level. + + This method produces a JSON text from a JavaScript value. + + When an object value is found, if the object contains a toJSON + method, its toJSON method will be called and the result will be + stringified. A toJSON method does not serialize: it returns the + value represented by the name/value pair that should be serialized, + or undefined if nothing should be serialized. The toJSON method + will be passed the key associated with the value, and this will be + bound to the value + + For example, this would serialize Dates as ISO strings. + + Date.prototype.toJSON = function (key) { + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + return this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z'; + }; + + You can provide an optional replacer method. It will be passed the + key and value of each member, with this bound to the containing + object. The value that is returned from your method will be + serialized. If your method returns undefined, then the member will + be excluded from the serialization. + + If the replacer parameter is an array of strings, then it will be + used to select the members to be serialized. It filters the results + such that only members with keys listed in the replacer array are + stringified. + + Values that do not have JSON representations, such as undefined or + functions, will not be serialized. Such values in objects will be + dropped; in arrays they will be replaced with null. You can use + a replacer function to replace those with JSON values. + JSON.stringify(undefined) returns undefined. + + The optional space parameter produces a stringification of the + value that is filled with line breaks and indentation to make it + easier to read. + + If the space parameter is a non-empty string, then that string will + be used for indentation. If the space parameter is a number, then + the indentation will be that many spaces. + + Example: + + text = JSON.stringify(['e', {pluribus: 'unum'}]); + // text is '["e",{"pluribus":"unum"}]' + + + text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); + // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' + + text = JSON.stringify([new Date()], function (key, value) { + return this[key] instanceof Date ? + 'Date(' + this[key] + ')' : value; + }); + // text is '["Date(---current time---)"]' + + + JSON.parse(text, reviver) + This method parses a JSON text to produce an object or array. + It can throw a SyntaxError exception. + + The optional reviver parameter is a function that can filter and + transform the results. It receives each of the keys and values, + and its return value is used instead of the original value. + If it returns what it received, then the structure is not modified. + If it returns undefined then the member is deleted. + + Example: + + // Parse the text. Values that look like ISO date strings will + // be converted to Date objects. + + myData = JSON.parse(text, function (key, value) { + var a; + if (typeof value === 'string') { + a = +/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); + if (a) { + return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], + +a[5], +a[6])); + } + } + return value; + }); + + myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { + var d; + if (typeof value === 'string' && + value.slice(0, 5) === 'Date(' && + value.slice(-1) === ')') { + d = new Date(value.slice(5, -1)); + if (d) { + return d; + } + } + return value; + }); + + + This is a reference implementation. You are free to copy, modify, or + redistribute. +*/ + +/*jslint evil: true, strict: false, regexp: false */ + +/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, + call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, + getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, + lastIndex, length, parse, prototype, push, replace, slice, stringify, + test, toJSON, toString, valueOf +*/ + + +// Create a JSON object only if one does not already exist. We create the +// methods in a closure to avoid creating global variables. + +var JSON; +if (!JSON) { + JSON = {}; +} + +(function () { + "use strict"; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + if (typeof Date.prototype.toJSON !== 'function') { + + Date.prototype.toJSON = function (key) { + + return isFinite(this.valueOf()) ? + this.getUTCFullYear() + '-' + + f(this.getUTCMonth() + 1) + '-' + + f(this.getUTCDate()) + 'T' + + f(this.getUTCHours()) + ':' + + f(this.getUTCMinutes()) + ':' + + f(this.getUTCSeconds()) + 'Z' : null; + }; + + String.prototype.toJSON = + Number.prototype.toJSON = + Boolean.prototype.toJSON = function (key) { + return this.valueOf(); + }; + } + + var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, + gap, + indent, + meta = { // table of character substitutions + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + rep; + + + function quote(string) { + +// If the string contains no control characters, no quote characters, and no +// backslash characters, then we can safely slap some quotes around it. +// Otherwise we must also replace the offending characters with safe escape +// sequences. + + escapable.lastIndex = 0; + return escapable.test(string) ? '"' + string.replace(escapable, function (a) { + var c = meta[a]; + return typeof c === 'string' ? c : + '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }) + '"' : '"' + string + '"'; + } + + + function str(key, holder) { + +// Produce a string from holder[key]. + + var i, // The loop counter. + k, // The member key. + v, // The member value. + length, + mind = gap, + partial, + value = holder[key]; + +// If the value has a toJSON method, call it to obtain a replacement value. + + if (value && typeof value === 'object' && + typeof value.toJSON === 'function') { + value = value.toJSON(key); + } + +// If we were called with a replacer function, then call the replacer to +// obtain a replacement value. + + if (typeof rep === 'function') { + value = rep.call(holder, key, value); + } + +// What happens next depends on the value's type. + + switch (typeof value) { + case 'string': + return quote(value); + + case 'number': + +// JSON numbers must be finite. Encode non-finite numbers as null. + + return isFinite(value) ? String(value) : 'null'; + + case 'boolean': + case 'null': + +// If the value is a boolean or null, convert it to a string. Note: +// typeof null does not produce 'null'. The case is included here in +// the remote chance that this gets fixed someday. + + return String(value); + +// If the type is 'object', we might be dealing with an object or an array or +// null. + + case 'object': + +// Due to a specification blunder in ECMAScript, typeof null is 'object', +// so watch out for that case. + + if (!value) { + return 'null'; + } + +// Make an array to hold the partial results of stringifying this object value. + + gap += indent; + partial = []; + +// Is the value an array? + + if (Object.prototype.toString.apply(value) === '[object Array]') { + +// The value is an array. Stringify every element. Use null as a placeholder +// for non-JSON values. + + length = value.length; + for (i = 0; i < length; i += 1) { + partial[i] = str(i, value) || 'null'; + } + +// Join all of the elements together, separated with commas, and wrap them in +// brackets. + + v = partial.length === 0 ? '[]' : gap ? + '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : + '[' + partial.join(',') + ']'; + gap = mind; + return v; + } + +// If the replacer is an array, use it to select the members to be stringified. + + if (rep && typeof rep === 'object') { + length = rep.length; + for (i = 0; i < length; i += 1) { + k = rep[i]; + if (typeof k === 'string') { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } else { + +// Otherwise, iterate through all of the keys in the object. + + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = str(k, value); + if (v) { + partial.push(quote(k) + (gap ? ': ' : ':') + v); + } + } + } + } + +// Join all of the member texts together, separated with commas, +// and wrap them in braces. + + v = partial.length === 0 ? '{}' : gap ? + '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : + '{' + partial.join(',') + '}'; + gap = mind; + return v; + } + } + +// If the JSON object does not yet have a stringify method, give it one. + + if (typeof JSON.stringify !== 'function') { + JSON.stringify = function (value, replacer, space) { + +// The stringify method takes a value and an optional replacer, and an optional +// space parameter, and returns a JSON text. The replacer can be a function +// that can replace values, or an array of strings that will select the keys. +// A default replacer method can be provided. Use of the space parameter can +// produce text that is more easily readable. + + var i; + gap = ''; + indent = ''; + +// If the space parameter is a number, make an indent string containing that +// many spaces. + + if (typeof space === 'number') { + for (i = 0; i < space; i += 1) { + indent += ' '; + } + +// If the space parameter is a string, it will be used as the indent string. + + } else if (typeof space === 'string') { + indent = space; + } + +// If there is a replacer, it must be a function or an array. +// Otherwise, throw an error. + + rep = replacer; + if (replacer && typeof replacer !== 'function' && + (typeof replacer !== 'object' || + typeof replacer.length !== 'number')) { + throw new Error('JSON.stringify'); + } + +// Make a fake root object containing our value under the key of ''. +// Return the result of stringifying the value. + + return str('', {'': value}); + }; + } + + +// If the JSON object does not yet have a parse method, give it one. + + if (typeof JSON.parse !== 'function') { + JSON.parse = function (text, reviver) { + +// The parse method takes a text and an optional reviver function, and returns +// a JavaScript value if the text is a valid JSON text. + + var j; + + function walk(holder, key) { + +// The walk method is used to recursively walk the resulting structure so +// that modifications can be made. + + var k, v, value = holder[key]; + if (value && typeof value === 'object') { + for (k in value) { + if (Object.hasOwnProperty.call(value, k)) { + v = walk(value, k); + if (v !== undefined) { + value[k] = v; + } else { + delete value[k]; + } + } + } + } + return reviver.call(holder, key, value); + } + + +// Parsing happens in four stages. In the first stage, we replace certain +// Unicode characters with escape sequences. JavaScript handles many characters +// incorrectly, either silently deleting them, or treating them as line endings. + + text = String(text); + cx.lastIndex = 0; + if (cx.test(text)) { + text = text.replace(cx, function (a) { + return '\\u' + + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); + }); + } + +// In the second stage, we run the text against regular expressions that look +// for non-JSON patterns. We are especially concerned with '()' and 'new' +// because they can cause invocation, and '=' because it can cause mutation. +// But just to be safe, we want to reject all unexpected forms. + +// We split the second stage into 4 regexp operations in order to work around +// crippling inefficiencies in IE's and Safari's regexp engines. First we +// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we +// replace all simple value tokens with ']' characters. Third, we delete all +// open brackets that follow a colon or comma or that begin the text. Finally, +// we look to see that the remaining characters are only whitespace or ']' or +// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. + + if (/^[\],:{}\s]*$/ + .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') + .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') + .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { + +// In the third stage we use the eval function to compile the text into a +// JavaScript structure. The '{' operator is subject to a syntactic ambiguity +// in JavaScript: it can begin a block or an object literal. We wrap the text +// in parens to eliminate the ambiguity. + + j = eval('(' + text + ')'); + +// In the optional fourth stage, we recursively walk the new structure, passing +// each name/value pair to a reviver function for possible transformation. + + return typeof reviver === 'function' ? + walk({'': j}, '') : j; + } + +// If the text is not JSON parseable, then a SyntaxError is thrown. + + throw new SyntaxError('JSON.parse'); + }; + } +}()); diff --git a/admin/thirdparty/history-js/tests.src/_header.php b/admin/thirdparty/history-js/tests.src/_header.php new file mode 100644 index 000000000..6196ae6d4 --- /dev/null +++ b/admin/thirdparty/history-js/tests.src/_header.php @@ -0,0 +1,28 @@ + + + + History.js Test Suite + + + +

History.js Test Suite

+

HTML5 Browsers - should pass the HTML4 and HTML5 tests

+

HTML4 Browsers - should pass the HTML4 tests and fail the HTML5 tests

+ '; + foreach ( $supports as $support ) : + echo '
'; + foreach ( $persists as $persist ) : + echo '
'; + foreach ( $adapters as $adapter ) : + echo '
'; + + # Url + $filename = "${compression}-${support}-${persist}-${adapter}.html"; + + # Title + $Support = strtoupper($support); + $Adapter = ucwords($adapter); + $Persist = ucwords($persist); + $Compression = ucwords($compression); + $title = "History.js ${Compression} ${Support} ${Persist} ${Adapter} Test Suite"; + + # Render + ?>'; + endforeach; + echo '
'; + endforeach; + echo '
'; + endforeach; + echo '
'; + endforeach; + ?> + + diff --git a/admin/thirdparty/history-js/tests.src/each.php b/admin/thirdparty/history-js/tests.src/each.php new file mode 100644 index 000000000..7efc47803 --- /dev/null +++ b/admin/thirdparty/history-js/tests.src/each.php @@ -0,0 +1,62 @@ + + + + + + + + <?=$title?> + + + + + + + + + + + + + +

+

+
+

+
    +
    test markup
    + + + + + + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests.src/index.php b/admin/thirdparty/history-js/tests.src/index.php new file mode 100644 index 000000000..744bdf038 --- /dev/null +++ b/admin/thirdparty/history-js/tests.src/index.php @@ -0,0 +1,25 @@ +Tests diff --git a/admin/thirdparty/history-js/tests/.htaccess b/admin/thirdparty/history-js/tests/.htaccess new file mode 100644 index 000000000..2f7dbdde1 --- /dev/null +++ b/admin/thirdparty/history-js/tests/.htaccess @@ -0,0 +1,13 @@ +Options +FollowSymlinks +RewriteEngine On + +# Clean Adapter +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule ([^\.]+)$ $1.html [NC,L,QSA] + +# Can someone smarter than me make it so: +# http://localhost/history.js/tests/uncompressed-html5-persistant-jquery +# Does not redirect to: +# http://localhost/history.js/tests/uncompressed-html5-persistant-jquery.html +# But still accesses that url diff --git a/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-jquery.html b/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-jquery.html new file mode 100644 index 000000000..f6cbef632 --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-jquery.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Compressed HTML4 Nonpersistant Jquery Test Suite + + + + + + + + + + + + + +

    History.js Compressed HTML4 Nonpersistant Jquery Test Suite

    +

    +
    +

    +
      +
      test markup
      + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-mootools.html b/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-mootools.html new file mode 100644 index 000000000..5ddd2b9d5 --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-mootools.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Compressed HTML4 Nonpersistant Mootools Test Suite + + + + + + + + + + + + + +

      History.js Compressed HTML4 Nonpersistant Mootools Test Suite

      +

      +
      +

      +
        +
        test markup
        + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-prototype.html b/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-prototype.html new file mode 100644 index 000000000..1629dac1c --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-prototype.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Compressed HTML4 Nonpersistant Prototype Test Suite + + + + + + + + + + + + + +

        History.js Compressed HTML4 Nonpersistant Prototype Test Suite

        +

        +
        +

        +
          +
          test markup
          + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-zepto.html b/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-zepto.html new file mode 100644 index 000000000..114816eeb --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-zepto.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Compressed HTML4 Nonpersistant Zepto Test Suite + + + + + + + + + + + + + +

          History.js Compressed HTML4 Nonpersistant Zepto Test Suite

          +

          +
          +

          +
            +
            test markup
            + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/compressed-html4-persistant-jquery.html b/admin/thirdparty/history-js/tests/compressed-html4-persistant-jquery.html new file mode 100644 index 000000000..8425e6525 --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html4-persistant-jquery.html @@ -0,0 +1,48 @@ + + + + + + + + History.js Compressed HTML4 Persistant Jquery Test Suite + + + + + + + + + + + + + +

            History.js Compressed HTML4 Persistant Jquery Test Suite

            +

            +
            +

            +
              +
              test markup
              + + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/compressed-html4-persistant-mootools.html b/admin/thirdparty/history-js/tests/compressed-html4-persistant-mootools.html new file mode 100644 index 000000000..19b4899c0 --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html4-persistant-mootools.html @@ -0,0 +1,48 @@ + + + + + + + + History.js Compressed HTML4 Persistant Mootools Test Suite + + + + + + + + + + + + + +

              History.js Compressed HTML4 Persistant Mootools Test Suite

              +

              +
              +

              +
                +
                test markup
                + + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/compressed-html4-persistant-prototype.html b/admin/thirdparty/history-js/tests/compressed-html4-persistant-prototype.html new file mode 100644 index 000000000..f21fa9192 --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html4-persistant-prototype.html @@ -0,0 +1,48 @@ + + + + + + + + History.js Compressed HTML4 Persistant Prototype Test Suite + + + + + + + + + + + + + +

                History.js Compressed HTML4 Persistant Prototype Test Suite

                +

                +
                +

                +
                  +
                  test markup
                  + + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/compressed-html4-persistant-zepto.html b/admin/thirdparty/history-js/tests/compressed-html4-persistant-zepto.html new file mode 100644 index 000000000..07d2c7327 --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html4-persistant-zepto.html @@ -0,0 +1,48 @@ + + + + + + + + History.js Compressed HTML4 Persistant Zepto Test Suite + + + + + + + + + + + + + +

                  History.js Compressed HTML4 Persistant Zepto Test Suite

                  +

                  +
                  +

                  +
                    +
                    test markup
                    + + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-jquery.html b/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-jquery.html new file mode 100644 index 000000000..a32df9220 --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-jquery.html @@ -0,0 +1,46 @@ + + + + + + + + History.js Compressed HTML5 Nonpersistant Jquery Test Suite + + + + + + + + + + + + + +

                    History.js Compressed HTML5 Nonpersistant Jquery Test Suite

                    +

                    +
                    +

                    +
                      +
                      test markup
                      + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-mootools.html b/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-mootools.html new file mode 100644 index 000000000..b1e32a3c2 --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-mootools.html @@ -0,0 +1,46 @@ + + + + + + + + History.js Compressed HTML5 Nonpersistant Mootools Test Suite + + + + + + + + + + + + + +

                      History.js Compressed HTML5 Nonpersistant Mootools Test Suite

                      +

                      +
                      +

                      +
                        +
                        test markup
                        + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-prototype.html b/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-prototype.html new file mode 100644 index 000000000..5e78c3a11 --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-prototype.html @@ -0,0 +1,46 @@ + + + + + + + + History.js Compressed HTML5 Nonpersistant Prototype Test Suite + + + + + + + + + + + + + +

                        History.js Compressed HTML5 Nonpersistant Prototype Test Suite

                        +

                        +
                        +

                        +
                          +
                          test markup
                          + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-zepto.html b/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-zepto.html new file mode 100644 index 000000000..d0c6df4f5 --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-zepto.html @@ -0,0 +1,46 @@ + + + + + + + + History.js Compressed HTML5 Nonpersistant Zepto Test Suite + + + + + + + + + + + + + +

                          History.js Compressed HTML5 Nonpersistant Zepto Test Suite

                          +

                          +
                          +

                          +
                            +
                            test markup
                            + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/compressed-html5-persistant-jquery.html b/admin/thirdparty/history-js/tests/compressed-html5-persistant-jquery.html new file mode 100644 index 000000000..7dde351f8 --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html5-persistant-jquery.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Compressed HTML5 Persistant Jquery Test Suite + + + + + + + + + + + + + +

                            History.js Compressed HTML5 Persistant Jquery Test Suite

                            +

                            +
                            +

                            +
                              +
                              test markup
                              + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/compressed-html5-persistant-mootools.html b/admin/thirdparty/history-js/tests/compressed-html5-persistant-mootools.html new file mode 100644 index 000000000..e1e640e33 --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html5-persistant-mootools.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Compressed HTML5 Persistant Mootools Test Suite + + + + + + + + + + + + + +

                              History.js Compressed HTML5 Persistant Mootools Test Suite

                              +

                              +
                              +

                              +
                                +
                                test markup
                                + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/compressed-html5-persistant-prototype.html b/admin/thirdparty/history-js/tests/compressed-html5-persistant-prototype.html new file mode 100644 index 000000000..f789b8c2f --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html5-persistant-prototype.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Compressed HTML5 Persistant Prototype Test Suite + + + + + + + + + + + + + +

                                History.js Compressed HTML5 Persistant Prototype Test Suite

                                +

                                +
                                +

                                +
                                  +
                                  test markup
                                  + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/compressed-html5-persistant-zepto.html b/admin/thirdparty/history-js/tests/compressed-html5-persistant-zepto.html new file mode 100644 index 000000000..efbdde99f --- /dev/null +++ b/admin/thirdparty/history-js/tests/compressed-html5-persistant-zepto.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Compressed HTML5 Persistant Zepto Test Suite + + + + + + + + + + + + + +

                                  History.js Compressed HTML5 Persistant Zepto Test Suite

                                  +

                                  +
                                  +

                                  +
                                    +
                                    test markup
                                    + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/image.php b/admin/thirdparty/history-js/tests/image.php new file mode 100644 index 000000000..5e7bfc9e9 --- /dev/null +++ b/admin/thirdparty/history-js/tests/image.php @@ -0,0 +1,3 @@ + + + + History.js Test Suite + + + +

                                    History.js Test Suite

                                    +

                                    HTML5 Browsers - should pass the HTML4 and HTML5 tests

                                    +

                                    HTML4 Browsers - should pass the HTML4 tests and fail the HTML5 tests

                                    + + diff --git a/admin/thirdparty/history-js/tests/tests.js b/admin/thirdparty/history-js/tests/tests.js new file mode 100644 index 000000000..47a16eeb1 --- /dev/null +++ b/admin/thirdparty/history-js/tests/tests.js @@ -0,0 +1,254 @@ +(function(){ + +var + History = window.History, + document = window.document, + test = window.test, + same = window.same; + +// Check +if ( !History.enabled ) { + throw new Error('History.js is disabled'); +} + +// Prepare +History.options.debug = false; + +// Variables +var + States = { + // Home + 0: { + 'url': document.location.href.replace(/#.*$/,''), + 'title': '' + }, + // One + 1: { + 'data': { + 'state': 1, + 'rand': Math.random() + }, + 'title': 'State 1', + 'url': '?state=1' + }, + // Two + 2: { + 'data': { + 'state': 2, + 'rand': Math.random() + }, + 'title': 'State 2', + 'url': '?state=2&asd=%20asd%2520asd' + }, + // Three + 3: { + 'url': '?state=3' + }, + // Four + 4: { + 'data': { + 'state': 4, + 'trick': true, + 'rand': Math.random() + }, + 'title': 'State 4', + 'url': '?state=3' + }, + // Log + 5: { + 'url': '?state=1#log' + }, + // Six + 6: { + 'data': { + 'state': 6, + 'rand': Math.random() + }, + 'url': 'six.html' + }, + // Seven + 7: { + 'url': 'seven' + }, + // Eight + 8: { + 'url': '/eight' + } + }, + stateOrder = [0,1,2,3,4,3,1,0,1,3,4,3,1,0,6,7,8,1,8,7,6,0], + currentTest = 0; + +// Original Title +var title = document.title; + +var banner; + +var checkStatus = function(){ + banner = banner || document.getElementById('qunit-banner'); + var status = banner.className !== 'qunit-fail'; + return status; +}; + +// Check State +var checkState = function(){ + if ( !checkStatus() ) { + throw new Error('A test has failed'); + } + + var + stateIndex = stateOrder[currentTest], + expectedState = History.normalizeState(States[stateIndex]), + actualState = History.getState(false); + + ++currentTest; + + document.title = title+': '+actualState.url; + + var + testName = 'Test '+currentTest, + stateName = 'State '+stateIndex; + + test(testName,function(){ + History.log('Completed: '+testName +' / '+ stateName); + same(actualState,expectedState,stateName); + }); + + // Image Load to Stress Test Safari and Opera + (new Image()).src = "image.php"; +}; + +// Check the Initial State +checkState(); + +// State Change +History.Adapter.bind(window,'statechange',checkState); + +// Log +var addLog = function(){ + var args = arguments; + History.queue(function(){ + History.log.apply(History,args); + }); +}; + +// Dom Load +History.Adapter.onDomLoad(function(){ + setTimeout(function(){ + + // ---------------------------------------------------------------------- + // Test State Functionality: Adding + + // Test 2 / State 1 (0 -> 1) + // Tests HTML4 -> HTML5 Graceful Upgrade + addLog('Test 2',History.queues.length,History.busy.flag); + History.setHash(History.getHashByState(States[1])); + + // Test 3 / State 2 (1 -> 2) + addLog('Test 3',History.queues.length,History.busy.flag); + History.pushState(States[2].data, States[2].title, States[2].url); + + // Test 3-2 / State 2 (2 -> 2) / No Change + addLog('Test 3-2',History.queues.length,History.busy.flag); + History.pushState(States[2].data, States[2].title, States[2].url); + + // Test 3-3 / State 2 (2 -> 2) / No Change + addLog('Test 3-3',History.queues.length,History.busy.flag); + History.replaceState(States[2].data, States[2].title, States[2].url); + + // Test 4 / State 3 (2 -> 3) + addLog('Test 4',History.queues.length,History.busy.flag); + History.replaceState(States[3].data, States[3].title, States[3].url); + + // Test 5 / State 4 (3 -> 4) + addLog('Test 5',History.queues.length,History.busy.flag); + History.pushState(States[4].data, States[4].title, States[4].url); + + // ---------------------------------------------------------------------- + // Test State Functionality: Traversing + + // Test 6 / State 3 (4 -> 3) + // Test 7 / State 1 (3 -> 2 -> 1) + addLog('Test 6,7',History.queues.length,History.busy.flag); + History.go(-2); + + // Test 8 / State 0 (1 -> 0) + // Tests Default State + addLog('Test 8',History.queues.length,History.busy.flag); + History.back(); + + // Test 9 / State 1 (0 -> 1) + // Test 10 / State 3 (1 -> 2 -> 3) + addLog('Test 9,10',History.queues.length,History.busy.flag); + History.go(2); + + // Test 11 / State 4 (3 -> 4) + addLog('Test 11',History.queues.length,History.busy.flag); + History.forward(); + + // Test 12 / State 3 (4 -> 3) + addLog('Test 12',History.queues.length,History.busy.flag); + History.back(); + + // Test 13 / State 1 (3 -> 2 -> 1) + addLog('Test 13',History.queues.length,History.busy.flag); + History.back(); + + // ---------------------------------------------------------------------- + // Test State Functionality: Traditional Anchors + + // Test 13-2 / State 1 (1 -> #log) / No Change + addLog('Test 13-2',History.queues.length,History.busy.flag); + History.setHash('log'); + + // Test 13-3 / State 1 (#log -> 1) / No Change + addLog('Test 13-3',History.queues.length,History.busy.flag); + History.back(); + + // Test 14 / State 0 (1 -> 0) + addLog('Test 14',History.queues.length,History.busy.flag); + History.back(); + + // ---------------------------------------------------------------------- + // Test URL Handling: Adding + + // Test 15 / State 6 (1 -> 6) + // Also tests data with no title + addLog('Test 15',History.queues.length,History.busy.flag); + History.pushState(States[6].data, States[6].title, States[6].url); + + // Test 16 / State 7 (6 -> 7) + addLog('Test 16',History.queues.length,History.busy.flag); + History.pushState(States[7].data, States[7].title, States[7].url); + + // Test 17 / State 7 (7 -> 8) + addLog('Test 17',History.queues.length,History.busy.flag); + History.pushState(States[8].data, States[8].title, States[8].url); + + // Test 18 / State 1 (8 -> 1) + // Should be /eight?state=1 + addLog('Test 18',History.queues.length,History.busy.flag); + History.pushState(States[1].data, States[1].title, States[1].url); + + // ---------------------------------------------------------------------- + // Test URL Handling: Traversing + + // Test 19 / State 8 (1 -> 8) + addLog('Test 19',History.queues.length,History.busy.flag); + History.back(); + + // Test 20 / State 7 (8 -> 7) + addLog('Test 20',History.queues.length,History.busy.flag); + History.back(); + + // Test 21 / State 6 (7 -> 6) + addLog('Test 21',History.queues.length,History.busy.flag); + History.back(); + + // Test 22 / State 0 (6 -> 0) + addLog('Test 22',History.queues.length,History.busy.flag); + History.back(); + + },1000); // wait for test one to complete +}); + +})(); diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-jquery.html b/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-jquery.html new file mode 100644 index 000000000..60a049818 --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-jquery.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Uncompressed HTML4 Nonpersistant Jquery Test Suite + + + + + + + + + + + + + +

                                    History.js Uncompressed HTML4 Nonpersistant Jquery Test Suite

                                    +

                                    +
                                    +

                                    +
                                      +
                                      test markup
                                      + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-mootools.html b/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-mootools.html new file mode 100644 index 000000000..17e7b8597 --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-mootools.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Uncompressed HTML4 Nonpersistant Mootools Test Suite + + + + + + + + + + + + + +

                                      History.js Uncompressed HTML4 Nonpersistant Mootools Test Suite

                                      +

                                      +
                                      +

                                      +
                                        +
                                        test markup
                                        + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-prototype.html b/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-prototype.html new file mode 100644 index 000000000..c9f4e44fe --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-prototype.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Uncompressed HTML4 Nonpersistant Prototype Test Suite + + + + + + + + + + + + + +

                                        History.js Uncompressed HTML4 Nonpersistant Prototype Test Suite

                                        +

                                        +
                                        +

                                        +
                                          +
                                          test markup
                                          + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-zepto.html b/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-zepto.html new file mode 100644 index 000000000..0cf315707 --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-zepto.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Uncompressed HTML4 Nonpersistant Zepto Test Suite + + + + + + + + + + + + + +

                                          History.js Uncompressed HTML4 Nonpersistant Zepto Test Suite

                                          +

                                          +
                                          +

                                          +
                                            +
                                            test markup
                                            + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-jquery.html b/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-jquery.html new file mode 100644 index 000000000..5362bf4c0 --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-jquery.html @@ -0,0 +1,48 @@ + + + + + + + + History.js Uncompressed HTML4 Persistant Jquery Test Suite + + + + + + + + + + + + + +

                                            History.js Uncompressed HTML4 Persistant Jquery Test Suite

                                            +

                                            +
                                            +

                                            +
                                              +
                                              test markup
                                              + + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-mootools.html b/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-mootools.html new file mode 100644 index 000000000..a517026ed --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-mootools.html @@ -0,0 +1,48 @@ + + + + + + + + History.js Uncompressed HTML4 Persistant Mootools Test Suite + + + + + + + + + + + + + +

                                              History.js Uncompressed HTML4 Persistant Mootools Test Suite

                                              +

                                              +
                                              +

                                              +
                                                +
                                                test markup
                                                + + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-prototype.html b/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-prototype.html new file mode 100644 index 000000000..43f7261d8 --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-prototype.html @@ -0,0 +1,48 @@ + + + + + + + + History.js Uncompressed HTML4 Persistant Prototype Test Suite + + + + + + + + + + + + + +

                                                History.js Uncompressed HTML4 Persistant Prototype Test Suite

                                                +

                                                +
                                                +

                                                +
                                                  +
                                                  test markup
                                                  + + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-zepto.html b/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-zepto.html new file mode 100644 index 000000000..a52009c55 --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-zepto.html @@ -0,0 +1,48 @@ + + + + + + + + History.js Uncompressed HTML4 Persistant Zepto Test Suite + + + + + + + + + + + + + +

                                                  History.js Uncompressed HTML4 Persistant Zepto Test Suite

                                                  +

                                                  +
                                                  +

                                                  +
                                                    +
                                                    test markup
                                                    + + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-jquery.html b/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-jquery.html new file mode 100644 index 000000000..58314926e --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-jquery.html @@ -0,0 +1,46 @@ + + + + + + + + History.js Uncompressed HTML5 Nonpersistant Jquery Test Suite + + + + + + + + + + + + + +

                                                    History.js Uncompressed HTML5 Nonpersistant Jquery Test Suite

                                                    +

                                                    +
                                                    +

                                                    +
                                                      +
                                                      test markup
                                                      + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-mootools.html b/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-mootools.html new file mode 100644 index 000000000..97166f342 --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-mootools.html @@ -0,0 +1,46 @@ + + + + + + + + History.js Uncompressed HTML5 Nonpersistant Mootools Test Suite + + + + + + + + + + + + + +

                                                      History.js Uncompressed HTML5 Nonpersistant Mootools Test Suite

                                                      +

                                                      +
                                                      +

                                                      +
                                                        +
                                                        test markup
                                                        + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-prototype.html b/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-prototype.html new file mode 100644 index 000000000..da36e23a4 --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-prototype.html @@ -0,0 +1,46 @@ + + + + + + + + History.js Uncompressed HTML5 Nonpersistant Prototype Test Suite + + + + + + + + + + + + + +

                                                        History.js Uncompressed HTML5 Nonpersistant Prototype Test Suite

                                                        +

                                                        +
                                                        +

                                                        +
                                                          +
                                                          test markup
                                                          + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-zepto.html b/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-zepto.html new file mode 100644 index 000000000..4fca56f14 --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-zepto.html @@ -0,0 +1,46 @@ + + + + + + + + History.js Uncompressed HTML5 Nonpersistant Zepto Test Suite + + + + + + + + + + + + + +

                                                          History.js Uncompressed HTML5 Nonpersistant Zepto Test Suite

                                                          +

                                                          +
                                                          +

                                                          +
                                                            +
                                                            test markup
                                                            + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-jquery.html b/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-jquery.html new file mode 100644 index 000000000..d1086b357 --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-jquery.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Uncompressed HTML5 Persistant Jquery Test Suite + + + + + + + + + + + + + +

                                                            History.js Uncompressed HTML5 Persistant Jquery Test Suite

                                                            +

                                                            +
                                                            +

                                                            +
                                                              +
                                                              test markup
                                                              + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-mootools.html b/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-mootools.html new file mode 100644 index 000000000..1f5083724 --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-mootools.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Uncompressed HTML5 Persistant Mootools Test Suite + + + + + + + + + + + + + +

                                                              History.js Uncompressed HTML5 Persistant Mootools Test Suite

                                                              +

                                                              +
                                                              +

                                                              +
                                                                +
                                                                test markup
                                                                + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-prototype.html b/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-prototype.html new file mode 100644 index 000000000..ad5c3634b --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-prototype.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Uncompressed HTML5 Persistant Prototype Test Suite + + + + + + + + + + + + + +

                                                                History.js Uncompressed HTML5 Persistant Prototype Test Suite

                                                                +

                                                                +
                                                                +

                                                                +
                                                                  +
                                                                  test markup
                                                                  + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-zepto.html b/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-zepto.html new file mode 100644 index 000000000..04f272fd1 --- /dev/null +++ b/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-zepto.html @@ -0,0 +1,47 @@ + + + + + + + + History.js Uncompressed HTML5 Persistant Zepto Test Suite + + + + + + + + + + + + + +

                                                                  History.js Uncompressed HTML5 Persistant Zepto Test Suite

                                                                  +

                                                                  +
                                                                  +

                                                                  +
                                                                    +
                                                                    test markup
                                                                    + + + + + + + + + + + + + diff --git a/admin/thirdparty/history-js/vendor/jquery.js b/admin/thirdparty/history-js/vendor/jquery.js new file mode 100644 index 000000000..7932fc701 --- /dev/null +++ b/admin/thirdparty/history-js/vendor/jquery.js @@ -0,0 +1,8316 @@ +/*! + * jQuery JavaScript Library v1.5.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Wed Feb 23 13:55:29 2011 -0500 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // Has the ready events already been bound? + readyBound = false, + + // The deferred used on DOM ready + readyList, + + // Promise methods + promiseMethods = "then done fail isResolved isRejected promise".split( " " ), + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = "body"; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.5.1", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.done( fn ); + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + // A third-party is pushing the ready event forwards + if ( wait === true ) { + jQuery.readyWait--; + } + + // Make sure that the DOM is not already loaded + if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyBound ) { + return; + } + + readyBound = true; + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent("onreadystatechange", DOMContentLoaded); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test(data.replace(rvalidescape, "@") + .replace(rvalidtokens, "]") + .replace(rvalidbraces, "")) ) { + + // Try to use the native JSON parser first + return window.JSON && window.JSON.parse ? + window.JSON.parse( data ) : + (new Function("return " + data))(); + + } else { + jQuery.error( "Invalid JSON: " + data ); + } + }, + + // Cross-browser xml parsing + // (xml & tmp used internally) + parseXML: function( data , xml , tmp ) { + + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + + tmp = xml.documentElement; + + if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { + jQuery.error( "Invalid XML: " + data ); + } + + return xml; + }, + + noop: function() {}, + + // Evalulates a script in a global context + globalEval: function( data ) { + if ( data && rnotwhite.test(data) ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement, + script = document.createElement( "script" ); + + if ( jQuery.support.scriptEval() ) { + script.appendChild( document.createTextNode( data ) ); + } else { + script.text = data; + } + + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709). + head.insertBefore( script, head.firstChild ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction(object); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( var value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type(array); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var ret = [], value; + + // Go through the array, translating each of the items to their + // new value (or values). + for ( var i = 0, length = elems.length; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + proxy: function( fn, proxy, thisObject ) { + if ( arguments.length === 2 ) { + if ( typeof proxy === "string" ) { + thisObject = fn; + fn = thisObject[ proxy ]; + proxy = undefined; + + } else if ( proxy && !jQuery.isFunction( proxy ) ) { + thisObject = proxy; + proxy = undefined; + } + } + + if ( !proxy && fn ) { + proxy = function() { + return fn.apply( thisObject || this, arguments ); + }; + } + + // Set the guid of unique handler to the same of original handler, so it can be removed + if ( fn ) { + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + } + + // So proxy can be declared as an argument + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can be optionally by executed if its a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Create a simple deferred (one callbacks list) + _Deferred: function() { + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + // We have to add a catch block for + // IE prior to 8 or else the finally + // block will never get executed + catch (e) { + throw e; + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }, + + // Full fledged deferred (two callbacks list) + Deferred: function( func ) { + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + var i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; + } + return obj; + } + } ); + // Make sure only one callback list will be used + deferred.done( failDeferred.cancel ).fail( deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }, + + // Deferred helper + when: function( object ) { + var lastIndex = arguments.length, + deferred = lastIndex <= 1 && object && jQuery.isFunction( object.promise ) ? + object : + jQuery.Deferred(), + promise = deferred.promise(); + + if ( lastIndex > 1 ) { + var array = slice.call( arguments, 0 ), + count = lastIndex, + iCallback = function( index ) { + return function( value ) { + array[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value; + if ( !( --count ) ) { + deferred.resolveWith( promise, array ); + } + }; + }; + while( ( lastIndex-- ) ) { + object = array[ lastIndex ]; + if ( object && jQuery.isFunction( object.promise ) ) { + object.promise().then( iCallback(lastIndex), deferred.reject ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( promise, array ); + } + } else if ( deferred !== object ) { + deferred.resolve( object ); + } + return promise; + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySubclass( selector, context ) { + return new jQuerySubclass.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySubclass, this ); + jQuerySubclass.superclass = this; + jQuerySubclass.fn = jQuerySubclass.prototype = this(); + jQuerySubclass.fn.constructor = jQuerySubclass; + jQuerySubclass.subclass = this.subclass; + jQuerySubclass.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySubclass) ) { + context = jQuerySubclass(context); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass ); + }; + jQuerySubclass.fn.init.prototype = jQuerySubclass.fn; + var rootjQuerySubclass = jQuerySubclass(document); + return jQuerySubclass; + }, + + browser: {} +}); + +// Create readyList deferred +readyList = jQuery._Deferred(); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +if ( indexOf ) { + jQuery.inArray = function( elem, array ) { + return indexOf.call( array, elem ); + }; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +// Expose jQuery to the global object +return jQuery; + +})(); + + +(function() { + + jQuery.support = {}; + + var div = document.createElement("div"); + + div.style.display = "none"; + div.innerHTML = "
                                                                    a"; + + var all = div.getElementsByTagName("*"), + a = div.getElementsByTagName("a")[0], + select = document.createElement("select"), + opt = select.appendChild( document.createElement("option") ), + input = div.getElementsByTagName("input")[0]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return; + } + + jQuery.support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: div.firstChild.nodeType === 3, + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText insted) + style: /red/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: a.getAttribute("href") === "/a", + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: input.value === "on", + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Will be defined later + deleteExpando: true, + optDisabled: false, + checkClone: false, + noCloneEvent: true, + noCloneChecked: true, + boxModel: null, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableHiddenOffsets: true + }; + + input.checked = true; + jQuery.support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as diabled) + select.disabled = true; + jQuery.support.optDisabled = !opt.disabled; + + var _scriptEval = null; + jQuery.support.scriptEval = function() { + if ( _scriptEval === null ) { + var root = document.documentElement, + script = document.createElement("script"), + id = "script" + jQuery.now(); + + try { + script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); + } catch(e) {} + + root.insertBefore( script, root.firstChild ); + + // Make sure that the execution of code works by injecting a script + // tag with appendChild/createTextNode + // (IE doesn't support this, fails, and uses .text instead) + if ( window[ id ] ) { + _scriptEval = true; + delete window[ id ]; + } else { + _scriptEval = false; + } + + root.removeChild( script ); + // release memory in IE + root = script = id = null; + } + + return _scriptEval; + }; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + + } catch(e) { + jQuery.support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent("onclick", function click() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + jQuery.support.noCloneEvent = false; + div.detachEvent("onclick", click); + }); + div.cloneNode(true).fireEvent("onclick"); + } + + div = document.createElement("div"); + div.innerHTML = ""; + + var fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; + + // Figure out if the W3C box model works as expected + // document.body must exist before we can do this + jQuery(function() { + var div = document.createElement("div"), + body = document.getElementsByTagName("body")[0]; + + // Frameset documents with no body should not run this code + if ( !body ) { + return; + } + + div.style.width = div.style.paddingLeft = "1px"; + body.appendChild( div ); + jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2; + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
                                                                    "; + jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2; + } + + div.innerHTML = "
                                                                    t
                                                                    "; + var tds = div.getElementsByTagName("td"); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0; + + tds[0].style.display = ""; + tds[1].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0; + div.innerHTML = ""; + + body.removeChild( div ).style.display = "none"; + div = tds = null; + }); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + var eventSupported = function( eventName ) { + var el = document.createElement("div"); + eventName = "on" + eventName; + + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( !el.attachEvent ) { + return true; + } + + var isSupported = (eventName in el); + if ( !isSupported ) { + el.setAttribute(eventName, "return;"); + isSupported = typeof el[eventName] === "function"; + } + el = null; + + return isSupported; + }; + + jQuery.support.submitBubbles = eventSupported("submit"); + jQuery.support.changeBubbles = eventSupported("change"); + + // release memory in IE + div = all = a = null; +})(); + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } else { + id = jQuery.expando; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); + } else { + cache[ id ] = jQuery.extend(cache[ id ], name); + } + } + + thisCache = cache[ id ]; + + // Internal jQuery data is stored in a separate object inside the object's data + // cache in order to avoid key collisions between internal data and user-defined + // data + if ( pvt ) { + if ( !thisCache[ internalKey ] ) { + thisCache[ internalKey ] = {}; + } + + thisCache = thisCache[ internalKey ]; + } + + if ( data !== undefined ) { + thisCache[ name ] = data; + } + + // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should + // not attempt to inspect the internal events object using jQuery.data, as this + // internal data object is undocumented and subject to change. + if ( name === "events" && !thisCache[name] ) { + return thisCache[ internalKey ] && thisCache[ internalKey ].events; + } + + return getByName ? thisCache[ name ] : thisCache; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; + + if ( thisCache ) { + delete thisCache[ name ]; + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !isEmptyDataObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( pvt ) { + delete cache[ id ][ internalKey ]; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + var internalCache = cache[ id ][ internalKey ]; + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + if ( jQuery.support.deleteExpando || cache != window ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the entire user cache at once because it's faster than + // iterating through each key, but we need to continue to persist internal + // data if it existed + if ( internalCache ) { + cache[ id ] = {}; + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + + cache[ id ][ internalKey ] = internalCache; + + // Otherwise, we need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + } else if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } else { + elem[ jQuery.expando ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 ) { + var attr = this[0].attributes, name; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = name.substr( 5 ); + dataAttr( this[0], name, data[ name ] ); + } + } + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), + args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + data = elem.getAttribute( "data-" + key ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON +// property to be considered empty objects; this property always exists in +// order to make sure JSON.stringify does not expose internal metadata +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +jQuery.extend({ + queue: function( elem, type, data ) { + if ( !elem ) { + return; + } + + type = (type || "fx") + "queue"; + var q = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( !data ) { + return q || []; + } + + if ( !q || jQuery.isArray(data) ) { + q = jQuery._data( elem, type, jQuery.makeArray(data) ); + + } else { + q.push( data ); + } + + return q; + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(); + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue", true ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function( i ) { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspaces = /\s+/, + rreturn = /\r/g, + rspecialurl = /^(?:href|src|style)$/, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rradiocheck = /^(?:radio|checkbox)$/i; + +jQuery.props = { + "for": "htmlFor", + "class": "className", + readonly: "readOnly", + maxlength: "maxLength", + cellspacing: "cellSpacing", + rowspan: "rowSpan", + colspan: "colSpan", + tabindex: "tabIndex", + usemap: "useMap", + frameborder: "frameBorder" +}; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name, fn ) { + return this.each(function(){ + jQuery.attr( this, name, "" ); + if ( this.nodeType === 1 ) { + this.removeAttribute( name ); + } + }); + }, + + addClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.addClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( value && typeof value === "string" ) { + var classNames = (value || "").split( rspaces ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className ) { + elem.className = value; + + } else { + var className = " " + elem.className + " ", + setClass = elem.className; + + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { + setClass += " " + classNames[c]; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + self.removeClass( value.call(this, i, self.attr("class")) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + var classNames = (value || "").split( rspaces ); + + for ( var i = 0, l = this.length; i < l; i++ ) { + var elem = this[i]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + var className = (" " + elem.className + " ").replace(rclass, " "); + for ( var c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[c] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this); + self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspaces ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + if ( !arguments.length ) { + var elem = this[0]; + + if ( elem ) { + if ( jQuery.nodeName( elem, "option" ) ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery(option).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + } + + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { + return elem.getAttribute("value") === null ? "on" : elem.value; + } + + // Everything else, we just grab the value + return (elem.value || "").replace(rreturn, ""); + + } + + return undefined; + } + + var isFunction = jQuery.isFunction(value); + + return this.each(function(i) { + var self = jQuery(this), val = value; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call(this, i, self.val()); + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray(val) ) { + val = jQuery.map(val, function (value) { + return value == null ? "" : value + ""; + }); + } + + if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { + this.checked = jQuery.inArray( self.val(), val ) >= 0; + + } else if ( jQuery.nodeName( this, "select" ) ) { + var values = jQuery.makeArray(val); + + jQuery( "option", this ).each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + this.selectedIndex = -1; + } + + } else { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attr: function( elem, name, value, pass ) { + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery(elem)[name](value); + } + + var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), + // Whether we are setting (or getting) + set = value !== undefined; + + // Try to normalize/fix the name + name = notxml && jQuery.props[ name ] || name; + + // Only do all the following if this is a node (faster for style) + if ( elem.nodeType === 1 ) { + // These attributes require special treatment + var special = rspecialurl.test( name ); + + // Safari mis-reports the default selected property of an option + // Accessing the parent's selectedIndex property fixes it + if ( name === "selected" && !jQuery.support.optSelected ) { + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + + // If applicable, access the attribute via the DOM 0 way + // 'in' checks fail in Blackberry 4.7 #6931 + if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) { + if ( set ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } + + if ( value === null ) { + if ( elem.nodeType === 1 ) { + elem.removeAttribute( name ); + } + + } else { + elem[ name ] = value; + } + } + + // browsers index elements by id/name on forms, give priority to attributes. + if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { + return elem.getAttributeNode( name ).nodeValue; + } + + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + if ( name === "tabIndex" ) { + var attributeNode = elem.getAttributeNode( "tabIndex" ); + + return attributeNode && attributeNode.specified ? + attributeNode.value : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + + return elem[ name ]; + } + + if ( !jQuery.support.style && notxml && name === "style" ) { + if ( set ) { + elem.style.cssText = "" + value; + } + + return elem.style.cssText; + } + + if ( set ) { + // convert the value to a string (all browsers do this but IE) see #1070 + elem.setAttribute( name, "" + value ); + } + + // Ensure that missing attributes return undefined + // Blackberry 4.7 returns "" from getAttribute #6938 + if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) { + return undefined; + } + + var attr = !jQuery.support.hrefNormalized && notxml && special ? + // Some attributes require a special call on IE + elem.getAttribute( name, 2 ) : + elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return attr === null ? undefined : attr; + } + // Handle everything which isn't a DOM element node + if ( set ) { + elem[ name ] = value; + } + return elem[ name ]; + } +}); + + + + +var rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspace = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // TODO :: Use a try/catch until it's safe to pull this out (likely 1.6) + // Minor release fix for bug #8018 + try { + // For whatever reason, IE has trouble passing the window object + // around, causing it to be cloned in the process + if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) { + elem = window; + } + } + catch ( e ) {} + + if ( handler === false ) { + handler = returnFalse; + } else if ( !handler ) { + // Fixes bug #7229. Fix recommended by jdalton + return; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery._data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events, + eventHandle = elemData.handle; + + if ( !events ) { + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function() { + // Handle the second event of a trigger and when + // an event is called after a page has unloaded + return typeof jQuery !== "undefined" && !jQuery.event.triggered ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for global triggering + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem, undefined, true ); + } + } + }, + + // bubbling is internal + trigger: function( event, data, elem /*, bubbling */ ) { + // Event object or event type + var type = event.type || event, + bubbling = arguments[3]; + + if ( !bubbling ) { + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + jQuery.extend( jQuery.Event(type), event ) : + // Just the event type (string) + jQuery.Event(type); + + if ( type.indexOf("!") >= 0 ) { + event.type = type = type.slice(0, -1); + event.exclusive = true; + } + + // Handle a global trigger + if ( !elem ) { + // Don't bubble custom events when global (to avoid too much overhead) + event.stopPropagation(); + + // Only trigger if we've ever bound an event for it + if ( jQuery.event.global[ type ] ) { + // XXX This code smells terrible. event.js should not be directly + // inspecting the data cache + jQuery.each( jQuery.cache, function() { + // internalKey variable is just used to make it easier to find + // and potentially change this stuff later; currently it just + // points to jQuery.expando + var internalKey = jQuery.expando, + internalCache = this[ internalKey ]; + if ( internalCache && internalCache.events && internalCache.events[ type ] ) { + jQuery.event.trigger( event, data, internalCache.handle.elem ); + } + }); + } + } + + // Handle triggering a single element + + // don't do events on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { + return undefined; + } + + // Clean up in case it is reused + event.result = undefined; + event.target = elem; + + // Clone the incoming data, if any + data = jQuery.makeArray( data ); + data.unshift( event ); + } + + event.currentTarget = elem; + + // Trigger the event, it is assumed that "handle" is a function + var handle = jQuery._data( elem, "handle" ); + + if ( handle ) { + handle.apply( elem, data ); + } + + var parent = elem.parentNode || elem.ownerDocument; + + // Trigger an inline bound script + try { + if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { + if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { + event.result = false; + event.preventDefault(); + } + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (inlineError) {} + + if ( !event.isPropagationStopped() && parent ) { + jQuery.event.trigger( event, data, parent, true ); + + } else if ( !event.isDefaultPrevented() ) { + var old, + target = event.target, + targetType = type.replace( rnamespaces, "" ), + isClick = jQuery.nodeName( target, "a" ) && targetType === "click", + special = jQuery.event.special[ targetType ] || {}; + + if ( (!special._default || special._default.call( elem, event ) === false) && + !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { + + try { + if ( target[ targetType ] ) { + // Make sure that we don't accidentally re-trigger the onFOO events + old = target[ "on" + targetType ]; + + if ( old ) { + target[ "on" + targetType ] = null; + } + + jQuery.event.triggered = true; + target[ targetType ](); + } + + // prevent IE from throwing an error for some elements with some event types, see #3533 + } catch (triggerError) {} + + if ( old ) { + target[ "on" + targetType ] = old; + } + + jQuery.event.triggered = false; + } + } + }, + + handle: function( event ) { + var all, handlers, namespaces, namespace_re, events, + namespace_sort = [], + args = jQuery.makeArray( arguments ); + + event = args[0] = jQuery.event.fix( event || window.event ); + event.currentTarget = this; + + // Namespaced event handlers + all = event.type.indexOf(".") < 0 && !event.exclusive; + + if ( !all ) { + namespaces = event.type.split("."); + event.type = namespaces.shift(); + namespace_sort = namespaces.slice(0).sort(); + namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.namespace = event.namespace || namespace_sort.join("."); + + events = jQuery._data(this, "events"); + + handlers = (events || {})[ event.type ]; + + if ( events && handlers ) { + // Clone the handlers to prevent manipulation + handlers = handlers.slice(0); + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Filter the functions by class + if ( all || namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + } + + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + // Fixes #1925 where srcElement might not be defined either + event.target = event.srcElement || document; + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var doc = document.documentElement, + body = document.body; + + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + // Check if mouse(over|out) are still within the same parent element + var parent = event.relatedTarget; + + // Firefox sometimes assigns relatedTarget a XUL element + // which we cannot access the parentNode property of + try { + + // Chrome does something similar, the parentNode property + // can be accessed but is null. + if ( parent !== document && !parent.parentNode ) { + return; + } + // Traverse up the tree + while ( parent && parent !== this ) { + parent = parent.parentNode; + } + + if ( parent !== this ) { + // set the correct event type + event.type = event.data; + + // handle event if we actually just moused on to a non sub-element + jQuery.event.handle.apply( this, arguments ); + } + + // assuming we've left the element since we most likely mousedover a xul element + } catch(e) { } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( elem.nodeName.toLowerCase() === "select" ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery._data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery._data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = elem.type; + + if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { + testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = elem.type; + + if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery._data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + // Don't pass args or remember liveFired; they apply to the donor event. + var event = jQuery.extend( {}, args[ 0 ] ); + event.type = type; + event.originalEvent = {}; + event.liveFired = undefined; + jQuery.event.handle.call( elem, event ); + if ( event.isDefaultPrevented() ) { + args[ 0 ].preventDefault(); + } +} + +// Create "bubbling" focus and blur events +if ( document.addEventListener ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + jQuery.event.special[ fix ] = { + setup: function() { + this.addEventListener( orig, handler, true ); + }, + teardown: function() { + this.removeEventListener( orig, handler, true ); + } + }; + + function handler( e ) { + e = jQuery.event.fix( e ); + e.type = fix; + return jQuery.event.handle.call( this, e ); + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( jQuery.isFunction( data ) || data === false ) { + fn = data; + data = undefined; + } + + var handler = name === "one" ? jQuery.proxy( fn, function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }) : fn; + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + var event = jQuery.Event( type ); + event.preventDefault(); + event.stopPropagation(); + jQuery.event.trigger( event, data, this[0] ); + return event.result; + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + i = 1; + + // link all the functions, so any of them can unbind this click handler + while ( i < args.length ) { + jQuery.proxy( fn, args[ i++ ] ); + } + + return this.click( jQuery.proxy( fn, function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + })); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( jQuery.isFunction( data ) ) { + fn = data; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( type === "focus" || type === "blur" ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + elems = [], + selectors = [], + events = jQuery._data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) + if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var match, + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var found, item, + filter = Expr.filter[ type ], + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return "text" === elem.getAttribute( 'type' ); + }, + radio: function( elem ) { + return "radio" === elem.type; + }, + + checkbox: function( elem ) { + return "checkbox" === elem.type; + }, + + file: function( elem ) { + return "file" === elem.type; + }, + password: function( elem ) { + return "password" === elem.type; + }, + + submit: function( elem ) { + return "submit" === elem.type; + }, + + image: function( elem ) { + return "image" === elem.type; + }, + + reset: function( elem ) { + return "reset" === elem.type; + }, + + button: function( elem ) { + return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + var first = match[2], + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // If the nodes are siblings (or identical) we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

                                                                    "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector, + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + if ( matches ) { + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + return matches.call( node, expr ); + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
                                                                    "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var ret = this.pushStack( "", "find", selector ), + length = 0; + + for ( var i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( var n = length; n < ret.length; n++ ) { + for ( var r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && jQuery.filter( selector, this ).length > 0; + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + if ( jQuery.isArray( selectors ) ) { + var match, selector, + matches = {}, + level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[selector] ) { + matches[selector] = jQuery.expr.match.POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[selector]; + + if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + var pos = POS.test( selectors ) ? + jQuery( selectors, context || this.context ) : null; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique(ret) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /", "" ], + legend: [ 1, "
                                                                    ", "
                                                                    " ], + thead: [ 1, "", "
                                                                    " ], + tr: [ 2, "", "
                                                                    " ], + td: [ 3, "", "
                                                                    " ], + col: [ 2, "", "
                                                                    " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and - - - - - -
                                                                    -

                                                                    There's a bug in the HTML5 "popstate" event, as implemented in WebKit (Safari and Chrome). View this page in one of those browsers. Your browser has had history entries added from #0 to #19 (you should start at #19). Hitting back/forward will navigate through these. On each URL, the large number above should reflect the hash value. If you hit back/forward quickly, you'll notice that your number gets out of sync with the URL. This is because WebKit is dropping popstate events (they are not firing). It seems to happen when outbound network requests are in progress when the user navigates in their browser happens. In this case, your browser is downloading an image that takes 1s to serve on every popstate, so you'll have to wait 1s between backs/forwards to have the feature work correctly. You could also cause constant network traffic by putting an image download in a setInterval, in which case your popstate events will never fire. This implementation simulates an AJAX application that makes a network request when you navigate between URLs using pushState/popstate. View the source for more info.

                                                                    -

                                                                    This was filed as Bug 42940 with WebKit on July 24, 2010. The Firefox 4 beta does not have this bug, which is good news.

                                                                    -

                                                                    This is put together by Ben Cherry. Ben is a front-end engineer at Twitter, and you can follow him at @bcherry.

                                                                    - - - diff --git a/admin/thirdparty/history-js/demo/bcherry.html b/admin/thirdparty/history-js/demo/bcherry.html deleted file mode 100644 index 309f4d442..000000000 --- a/admin/thirdparty/history-js/demo/bcherry.html +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - WebKit is Dropping HTML5 "popstate" Events - - - - - - - - - - - - - -
                                                                    -

                                                                    There's a bug in the HTML5 "popstate" event, as implemented in WebKit (Safari and Chrome). View this page in one of those browsers. Your browser has had history entries added from #0 to #19 (you should start at #19). Hitting back/forward will navigate through these. On each URL, the large number above should reflect the hash value. If you hit back/forward quickly, you'll notice that your number gets out of sync with the URL. This is because WebKit is dropping popstate events (they are not firing). It seems to happen when outbound network requests are in progress when the user navigates in their browser happens. In this case, your browser is downloading an image that takes 1s to serve on every popstate, so you'll have to wait 1s between backs/forwards to have the feature work correctly. You could also cause constant network traffic by putting an image download in a setInterval, in which case your popstate events will never fire. This implementation simulates an AJAX application that makes a network request when you navigate between URLs using pushState/popstate. View the source for more info.

                                                                    -

                                                                    This was filed as Bug 42940 with WebKit on July 24, 2010. The Firefox 4 beta does not have this bug, which is good news.

                                                                    -

                                                                    This is put together by Ben Cherry. Ben is a front-end engineer at Twitter, and you can follow him at @bcherry.

                                                                    -

                                                                    This bug was fixed in History.js by Benjamin Lupton. Benjamin is a freelance web 2.0 consultant, and you can follow him at @balupton.

                                                                    - - - diff --git a/admin/thirdparty/history-js/demo/chrome.html b/admin/thirdparty/history-js/demo/chrome.html deleted file mode 100644 index a2791a311..000000000 --- a/admin/thirdparty/history-js/demo/chrome.html +++ /dev/null @@ -1,37 +0,0 @@ - - - Chrome History API Data Artifact - - -

                                                                    This demo demonstrates an issue with Google Chrome versions 8-10 (possibly 11) where if you push a state with data, then do history.back to the initial state, the event.state will contain the pushed states data instead of being null.

                                                                    -

                                                                    Note: The issue requires a clean history list, as such this should always be opened in a new tab/window where there are no prior history items.

                                                                    -

                                                                    Reported by Benjamin Lupton author of History.js

                                                                    - - - - - - diff --git a/admin/thirdparty/history-js/demo/index.html b/admin/thirdparty/history-js/demo/index.html deleted file mode 100644 index f3ea291b5..000000000 --- a/admin/thirdparty/history-js/demo/index.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - History.js - - - - - - - - - - - - -
                                                                    - -

                                                                    History.js by Benjamin Lupton

                                                                    -

                                                                    History.js gracefully supports the HTML5 History/State APIs (pushState, replaceState, onPopState) in all browsers. Including continued support for data, titles, replaceState. Supports jQuery, MooTools and Prototype. For HTML5 browsers this means that you can modify the URL directly, without needing to use hashes anymore. For HTML4 browsers it will revert back to using the old onhashchange functionality.

                                                                    - - - - - -

                                                                    Click through the buttons in order and you'll get the results demonstrated in the README.md file.

                                                                    - - -
                                                                      -
                                                                    - - -

                                                                    Subscribe to Updates

                                                                    -

                                                                    You'll be the first to know when new releases come out. Yes this form actually works, it just isn't styled yet to keep things simple.

                                                                    -
                                                                    -
                                                                    -
                                                                    -
                                                                    -
                                                                    - -
                                                                    -
                                                                    - - - -
                                                                    - - - diff --git a/admin/thirdparty/history-js/demo/native-auto.html b/admin/thirdparty/history-js/demo/native-auto.html deleted file mode 100644 index 1ea10ffa3..000000000 --- a/admin/thirdparty/history-js/demo/native-auto.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - diff --git a/admin/thirdparty/history-js/demo/native.html b/admin/thirdparty/history-js/demo/native.html deleted file mode 100644 index 010f89a0c..000000000 --- a/admin/thirdparty/history-js/demo/native.html +++ /dev/null @@ -1,62 +0,0 @@ - - - HTML5 History API Demo - - - -
                                                                    -
                                                                    - - - diff --git a/admin/thirdparty/history-js/demo/navigator.html b/admin/thirdparty/history-js/demo/navigator.html deleted file mode 100644 index f9b15844b..000000000 --- a/admin/thirdparty/history-js/demo/navigator.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - Navigator Output - - - - - - - - diff --git a/admin/thirdparty/history-js/demo/safari.html b/admin/thirdparty/history-js/demo/safari.html deleted file mode 100644 index 5da177553..000000000 --- a/admin/thirdparty/history-js/demo/safari.html +++ /dev/null @@ -1,61 +0,0 @@ - - - Safari Hash ReplaceState History Traversal Bug - - -

                                                                    This demo demonstrates an issue with Safari 5.0.4 (6533.20.27) handing of hashes and replace state. When a hash is set, and then replaced using replaceState the history list are then broken, when traversing back the hash does not change.

                                                                    -

                                                                    Note: The issue requires a clean history list, as such this should always be opened in a new tab/window where there are no prior history items.

                                                                    -

                                                                    Reported by Benjamin Lupton author of History.js

                                                                    - - - - - - - diff --git a/admin/thirdparty/history-js/tests.src/_header.php b/admin/thirdparty/history-js/tests.src/_header.php deleted file mode 100644 index 6196ae6d4..000000000 --- a/admin/thirdparty/history-js/tests.src/_header.php +++ /dev/null @@ -1,28 +0,0 @@ - - - - History.js Test Suite - - - -

                                                                    History.js Test Suite

                                                                    -

                                                                    HTML5 Browsers - should pass the HTML4 and HTML5 tests

                                                                    -

                                                                    HTML4 Browsers - should pass the HTML4 tests and fail the HTML5 tests

                                                                    - '; - foreach ( $supports as $support ) : - echo '
                                                                    '; - foreach ( $persists as $persist ) : - echo '
                                                                    '; - foreach ( $adapters as $adapter ) : - echo '
                                                                    '; - - # Url - $filename = "${compression}-${support}-${persist}-${adapter}.html"; - - # Title - $Support = strtoupper($support); - $Adapter = ucwords($adapter); - $Persist = ucwords($persist); - $Compression = ucwords($compression); - $title = "History.js ${Compression} ${Support} ${Persist} ${Adapter} Test Suite"; - - # Render - ?>'; - endforeach; - echo '
                                                                    '; - endforeach; - echo '
                                                                    '; - endforeach; - echo '
                                                                    '; - endforeach; - ?> - - diff --git a/admin/thirdparty/history-js/tests.src/each.php b/admin/thirdparty/history-js/tests.src/each.php deleted file mode 100644 index 7efc47803..000000000 --- a/admin/thirdparty/history-js/tests.src/each.php +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - <?=$title?> - - - - - - - - - - - - - -

                                                                    -

                                                                    -
                                                                    -

                                                                    -
                                                                      -
                                                                      test markup
                                                                      - - - - - - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests.src/index.php b/admin/thirdparty/history-js/tests.src/index.php deleted file mode 100644 index 744bdf038..000000000 --- a/admin/thirdparty/history-js/tests.src/index.php +++ /dev/null @@ -1,25 +0,0 @@ -Tests diff --git a/admin/thirdparty/history-js/tests/.htaccess b/admin/thirdparty/history-js/tests/.htaccess deleted file mode 100644 index 2f7dbdde1..000000000 --- a/admin/thirdparty/history-js/tests/.htaccess +++ /dev/null @@ -1,13 +0,0 @@ -Options +FollowSymlinks -RewriteEngine On - -# Clean Adapter -RewriteCond %{REQUEST_FILENAME} !-f -RewriteCond %{REQUEST_FILENAME} !-d -RewriteRule ([^\.]+)$ $1.html [NC,L,QSA] - -# Can someone smarter than me make it so: -# http://localhost/history.js/tests/uncompressed-html5-persistant-jquery -# Does not redirect to: -# http://localhost/history.js/tests/uncompressed-html5-persistant-jquery.html -# But still accesses that url diff --git a/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-jquery.html b/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-jquery.html deleted file mode 100644 index f6cbef632..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-jquery.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Compressed HTML4 Nonpersistant Jquery Test Suite - - - - - - - - - - - - - -

                                                                      History.js Compressed HTML4 Nonpersistant Jquery Test Suite

                                                                      -

                                                                      -
                                                                      -

                                                                      -
                                                                        -
                                                                        test markup
                                                                        - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-mootools.html b/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-mootools.html deleted file mode 100644 index 5ddd2b9d5..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-mootools.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Compressed HTML4 Nonpersistant Mootools Test Suite - - - - - - - - - - - - - -

                                                                        History.js Compressed HTML4 Nonpersistant Mootools Test Suite

                                                                        -

                                                                        -
                                                                        -

                                                                        -
                                                                          -
                                                                          test markup
                                                                          - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-prototype.html b/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-prototype.html deleted file mode 100644 index 1629dac1c..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-prototype.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Compressed HTML4 Nonpersistant Prototype Test Suite - - - - - - - - - - - - - -

                                                                          History.js Compressed HTML4 Nonpersistant Prototype Test Suite

                                                                          -

                                                                          -
                                                                          -

                                                                          -
                                                                            -
                                                                            test markup
                                                                            - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-zepto.html b/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-zepto.html deleted file mode 100644 index 114816eeb..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html4-nonpersistant-zepto.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Compressed HTML4 Nonpersistant Zepto Test Suite - - - - - - - - - - - - - -

                                                                            History.js Compressed HTML4 Nonpersistant Zepto Test Suite

                                                                            -

                                                                            -
                                                                            -

                                                                            -
                                                                              -
                                                                              test markup
                                                                              - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/compressed-html4-persistant-jquery.html b/admin/thirdparty/history-js/tests/compressed-html4-persistant-jquery.html deleted file mode 100644 index 8425e6525..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html4-persistant-jquery.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - History.js Compressed HTML4 Persistant Jquery Test Suite - - - - - - - - - - - - - -

                                                                              History.js Compressed HTML4 Persistant Jquery Test Suite

                                                                              -

                                                                              -
                                                                              -

                                                                              -
                                                                                -
                                                                                test markup
                                                                                - - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/compressed-html4-persistant-mootools.html b/admin/thirdparty/history-js/tests/compressed-html4-persistant-mootools.html deleted file mode 100644 index 19b4899c0..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html4-persistant-mootools.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - History.js Compressed HTML4 Persistant Mootools Test Suite - - - - - - - - - - - - - -

                                                                                History.js Compressed HTML4 Persistant Mootools Test Suite

                                                                                -

                                                                                -
                                                                                -

                                                                                -
                                                                                  -
                                                                                  test markup
                                                                                  - - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/compressed-html4-persistant-prototype.html b/admin/thirdparty/history-js/tests/compressed-html4-persistant-prototype.html deleted file mode 100644 index f21fa9192..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html4-persistant-prototype.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - History.js Compressed HTML4 Persistant Prototype Test Suite - - - - - - - - - - - - - -

                                                                                  History.js Compressed HTML4 Persistant Prototype Test Suite

                                                                                  -

                                                                                  -
                                                                                  -

                                                                                  -
                                                                                    -
                                                                                    test markup
                                                                                    - - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/compressed-html4-persistant-zepto.html b/admin/thirdparty/history-js/tests/compressed-html4-persistant-zepto.html deleted file mode 100644 index 07d2c7327..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html4-persistant-zepto.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - History.js Compressed HTML4 Persistant Zepto Test Suite - - - - - - - - - - - - - -

                                                                                    History.js Compressed HTML4 Persistant Zepto Test Suite

                                                                                    -

                                                                                    -
                                                                                    -

                                                                                    -
                                                                                      -
                                                                                      test markup
                                                                                      - - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-jquery.html b/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-jquery.html deleted file mode 100644 index a32df9220..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-jquery.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - History.js Compressed HTML5 Nonpersistant Jquery Test Suite - - - - - - - - - - - - - -

                                                                                      History.js Compressed HTML5 Nonpersistant Jquery Test Suite

                                                                                      -

                                                                                      -
                                                                                      -

                                                                                      -
                                                                                        -
                                                                                        test markup
                                                                                        - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-mootools.html b/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-mootools.html deleted file mode 100644 index b1e32a3c2..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-mootools.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - History.js Compressed HTML5 Nonpersistant Mootools Test Suite - - - - - - - - - - - - - -

                                                                                        History.js Compressed HTML5 Nonpersistant Mootools Test Suite

                                                                                        -

                                                                                        -
                                                                                        -

                                                                                        -
                                                                                          -
                                                                                          test markup
                                                                                          - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-prototype.html b/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-prototype.html deleted file mode 100644 index 5e78c3a11..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-prototype.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - History.js Compressed HTML5 Nonpersistant Prototype Test Suite - - - - - - - - - - - - - -

                                                                                          History.js Compressed HTML5 Nonpersistant Prototype Test Suite

                                                                                          -

                                                                                          -
                                                                                          -

                                                                                          -
                                                                                            -
                                                                                            test markup
                                                                                            - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-zepto.html b/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-zepto.html deleted file mode 100644 index d0c6df4f5..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html5-nonpersistant-zepto.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - History.js Compressed HTML5 Nonpersistant Zepto Test Suite - - - - - - - - - - - - - -

                                                                                            History.js Compressed HTML5 Nonpersistant Zepto Test Suite

                                                                                            -

                                                                                            -
                                                                                            -

                                                                                            -
                                                                                              -
                                                                                              test markup
                                                                                              - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/compressed-html5-persistant-jquery.html b/admin/thirdparty/history-js/tests/compressed-html5-persistant-jquery.html deleted file mode 100644 index 7dde351f8..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html5-persistant-jquery.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Compressed HTML5 Persistant Jquery Test Suite - - - - - - - - - - - - - -

                                                                                              History.js Compressed HTML5 Persistant Jquery Test Suite

                                                                                              -

                                                                                              -
                                                                                              -

                                                                                              -
                                                                                                -
                                                                                                test markup
                                                                                                - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/compressed-html5-persistant-mootools.html b/admin/thirdparty/history-js/tests/compressed-html5-persistant-mootools.html deleted file mode 100644 index e1e640e33..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html5-persistant-mootools.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Compressed HTML5 Persistant Mootools Test Suite - - - - - - - - - - - - - -

                                                                                                History.js Compressed HTML5 Persistant Mootools Test Suite

                                                                                                -

                                                                                                -
                                                                                                -

                                                                                                -
                                                                                                  -
                                                                                                  test markup
                                                                                                  - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/compressed-html5-persistant-prototype.html b/admin/thirdparty/history-js/tests/compressed-html5-persistant-prototype.html deleted file mode 100644 index f789b8c2f..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html5-persistant-prototype.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Compressed HTML5 Persistant Prototype Test Suite - - - - - - - - - - - - - -

                                                                                                  History.js Compressed HTML5 Persistant Prototype Test Suite

                                                                                                  -

                                                                                                  -
                                                                                                  -

                                                                                                  -
                                                                                                    -
                                                                                                    test markup
                                                                                                    - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/compressed-html5-persistant-zepto.html b/admin/thirdparty/history-js/tests/compressed-html5-persistant-zepto.html deleted file mode 100644 index efbdde99f..000000000 --- a/admin/thirdparty/history-js/tests/compressed-html5-persistant-zepto.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Compressed HTML5 Persistant Zepto Test Suite - - - - - - - - - - - - - -

                                                                                                    History.js Compressed HTML5 Persistant Zepto Test Suite

                                                                                                    -

                                                                                                    -
                                                                                                    -

                                                                                                    -
                                                                                                      -
                                                                                                      test markup
                                                                                                      - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/image.php b/admin/thirdparty/history-js/tests/image.php deleted file mode 100644 index 5e7bfc9e9..000000000 --- a/admin/thirdparty/history-js/tests/image.php +++ /dev/null @@ -1,3 +0,0 @@ - - - - History.js Test Suite - - - -

                                                                                                      History.js Test Suite

                                                                                                      -

                                                                                                      HTML5 Browsers - should pass the HTML4 and HTML5 tests

                                                                                                      -

                                                                                                      HTML4 Browsers - should pass the HTML4 tests and fail the HTML5 tests

                                                                                                      - - diff --git a/admin/thirdparty/history-js/tests/tests.js b/admin/thirdparty/history-js/tests/tests.js deleted file mode 100644 index 47a16eeb1..000000000 --- a/admin/thirdparty/history-js/tests/tests.js +++ /dev/null @@ -1,254 +0,0 @@ -(function(){ - -var - History = window.History, - document = window.document, - test = window.test, - same = window.same; - -// Check -if ( !History.enabled ) { - throw new Error('History.js is disabled'); -} - -// Prepare -History.options.debug = false; - -// Variables -var - States = { - // Home - 0: { - 'url': document.location.href.replace(/#.*$/,''), - 'title': '' - }, - // One - 1: { - 'data': { - 'state': 1, - 'rand': Math.random() - }, - 'title': 'State 1', - 'url': '?state=1' - }, - // Two - 2: { - 'data': { - 'state': 2, - 'rand': Math.random() - }, - 'title': 'State 2', - 'url': '?state=2&asd=%20asd%2520asd' - }, - // Three - 3: { - 'url': '?state=3' - }, - // Four - 4: { - 'data': { - 'state': 4, - 'trick': true, - 'rand': Math.random() - }, - 'title': 'State 4', - 'url': '?state=3' - }, - // Log - 5: { - 'url': '?state=1#log' - }, - // Six - 6: { - 'data': { - 'state': 6, - 'rand': Math.random() - }, - 'url': 'six.html' - }, - // Seven - 7: { - 'url': 'seven' - }, - // Eight - 8: { - 'url': '/eight' - } - }, - stateOrder = [0,1,2,3,4,3,1,0,1,3,4,3,1,0,6,7,8,1,8,7,6,0], - currentTest = 0; - -// Original Title -var title = document.title; - -var banner; - -var checkStatus = function(){ - banner = banner || document.getElementById('qunit-banner'); - var status = banner.className !== 'qunit-fail'; - return status; -}; - -// Check State -var checkState = function(){ - if ( !checkStatus() ) { - throw new Error('A test has failed'); - } - - var - stateIndex = stateOrder[currentTest], - expectedState = History.normalizeState(States[stateIndex]), - actualState = History.getState(false); - - ++currentTest; - - document.title = title+': '+actualState.url; - - var - testName = 'Test '+currentTest, - stateName = 'State '+stateIndex; - - test(testName,function(){ - History.log('Completed: '+testName +' / '+ stateName); - same(actualState,expectedState,stateName); - }); - - // Image Load to Stress Test Safari and Opera - (new Image()).src = "image.php"; -}; - -// Check the Initial State -checkState(); - -// State Change -History.Adapter.bind(window,'statechange',checkState); - -// Log -var addLog = function(){ - var args = arguments; - History.queue(function(){ - History.log.apply(History,args); - }); -}; - -// Dom Load -History.Adapter.onDomLoad(function(){ - setTimeout(function(){ - - // ---------------------------------------------------------------------- - // Test State Functionality: Adding - - // Test 2 / State 1 (0 -> 1) - // Tests HTML4 -> HTML5 Graceful Upgrade - addLog('Test 2',History.queues.length,History.busy.flag); - History.setHash(History.getHashByState(States[1])); - - // Test 3 / State 2 (1 -> 2) - addLog('Test 3',History.queues.length,History.busy.flag); - History.pushState(States[2].data, States[2].title, States[2].url); - - // Test 3-2 / State 2 (2 -> 2) / No Change - addLog('Test 3-2',History.queues.length,History.busy.flag); - History.pushState(States[2].data, States[2].title, States[2].url); - - // Test 3-3 / State 2 (2 -> 2) / No Change - addLog('Test 3-3',History.queues.length,History.busy.flag); - History.replaceState(States[2].data, States[2].title, States[2].url); - - // Test 4 / State 3 (2 -> 3) - addLog('Test 4',History.queues.length,History.busy.flag); - History.replaceState(States[3].data, States[3].title, States[3].url); - - // Test 5 / State 4 (3 -> 4) - addLog('Test 5',History.queues.length,History.busy.flag); - History.pushState(States[4].data, States[4].title, States[4].url); - - // ---------------------------------------------------------------------- - // Test State Functionality: Traversing - - // Test 6 / State 3 (4 -> 3) - // Test 7 / State 1 (3 -> 2 -> 1) - addLog('Test 6,7',History.queues.length,History.busy.flag); - History.go(-2); - - // Test 8 / State 0 (1 -> 0) - // Tests Default State - addLog('Test 8',History.queues.length,History.busy.flag); - History.back(); - - // Test 9 / State 1 (0 -> 1) - // Test 10 / State 3 (1 -> 2 -> 3) - addLog('Test 9,10',History.queues.length,History.busy.flag); - History.go(2); - - // Test 11 / State 4 (3 -> 4) - addLog('Test 11',History.queues.length,History.busy.flag); - History.forward(); - - // Test 12 / State 3 (4 -> 3) - addLog('Test 12',History.queues.length,History.busy.flag); - History.back(); - - // Test 13 / State 1 (3 -> 2 -> 1) - addLog('Test 13',History.queues.length,History.busy.flag); - History.back(); - - // ---------------------------------------------------------------------- - // Test State Functionality: Traditional Anchors - - // Test 13-2 / State 1 (1 -> #log) / No Change - addLog('Test 13-2',History.queues.length,History.busy.flag); - History.setHash('log'); - - // Test 13-3 / State 1 (#log -> 1) / No Change - addLog('Test 13-3',History.queues.length,History.busy.flag); - History.back(); - - // Test 14 / State 0 (1 -> 0) - addLog('Test 14',History.queues.length,History.busy.flag); - History.back(); - - // ---------------------------------------------------------------------- - // Test URL Handling: Adding - - // Test 15 / State 6 (1 -> 6) - // Also tests data with no title - addLog('Test 15',History.queues.length,History.busy.flag); - History.pushState(States[6].data, States[6].title, States[6].url); - - // Test 16 / State 7 (6 -> 7) - addLog('Test 16',History.queues.length,History.busy.flag); - History.pushState(States[7].data, States[7].title, States[7].url); - - // Test 17 / State 7 (7 -> 8) - addLog('Test 17',History.queues.length,History.busy.flag); - History.pushState(States[8].data, States[8].title, States[8].url); - - // Test 18 / State 1 (8 -> 1) - // Should be /eight?state=1 - addLog('Test 18',History.queues.length,History.busy.flag); - History.pushState(States[1].data, States[1].title, States[1].url); - - // ---------------------------------------------------------------------- - // Test URL Handling: Traversing - - // Test 19 / State 8 (1 -> 8) - addLog('Test 19',History.queues.length,History.busy.flag); - History.back(); - - // Test 20 / State 7 (8 -> 7) - addLog('Test 20',History.queues.length,History.busy.flag); - History.back(); - - // Test 21 / State 6 (7 -> 6) - addLog('Test 21',History.queues.length,History.busy.flag); - History.back(); - - // Test 22 / State 0 (6 -> 0) - addLog('Test 22',History.queues.length,History.busy.flag); - History.back(); - - },1000); // wait for test one to complete -}); - -})(); diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-jquery.html b/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-jquery.html deleted file mode 100644 index 60a049818..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-jquery.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Uncompressed HTML4 Nonpersistant Jquery Test Suite - - - - - - - - - - - - - -

                                                                                                      History.js Uncompressed HTML4 Nonpersistant Jquery Test Suite

                                                                                                      -

                                                                                                      -
                                                                                                      -

                                                                                                      -
                                                                                                        -
                                                                                                        test markup
                                                                                                        - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-mootools.html b/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-mootools.html deleted file mode 100644 index 17e7b8597..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-mootools.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Uncompressed HTML4 Nonpersistant Mootools Test Suite - - - - - - - - - - - - - -

                                                                                                        History.js Uncompressed HTML4 Nonpersistant Mootools Test Suite

                                                                                                        -

                                                                                                        -
                                                                                                        -

                                                                                                        -
                                                                                                          -
                                                                                                          test markup
                                                                                                          - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-prototype.html b/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-prototype.html deleted file mode 100644 index c9f4e44fe..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-prototype.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Uncompressed HTML4 Nonpersistant Prototype Test Suite - - - - - - - - - - - - - -

                                                                                                          History.js Uncompressed HTML4 Nonpersistant Prototype Test Suite

                                                                                                          -

                                                                                                          -
                                                                                                          -

                                                                                                          -
                                                                                                            -
                                                                                                            test markup
                                                                                                            - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-zepto.html b/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-zepto.html deleted file mode 100644 index 0cf315707..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html4-nonpersistant-zepto.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Uncompressed HTML4 Nonpersistant Zepto Test Suite - - - - - - - - - - - - - -

                                                                                                            History.js Uncompressed HTML4 Nonpersistant Zepto Test Suite

                                                                                                            -

                                                                                                            -
                                                                                                            -

                                                                                                            -
                                                                                                              -
                                                                                                              test markup
                                                                                                              - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-jquery.html b/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-jquery.html deleted file mode 100644 index 5362bf4c0..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-jquery.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - History.js Uncompressed HTML4 Persistant Jquery Test Suite - - - - - - - - - - - - - -

                                                                                                              History.js Uncompressed HTML4 Persistant Jquery Test Suite

                                                                                                              -

                                                                                                              -
                                                                                                              -

                                                                                                              -
                                                                                                                -
                                                                                                                test markup
                                                                                                                - - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-mootools.html b/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-mootools.html deleted file mode 100644 index a517026ed..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-mootools.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - History.js Uncompressed HTML4 Persistant Mootools Test Suite - - - - - - - - - - - - - -

                                                                                                                History.js Uncompressed HTML4 Persistant Mootools Test Suite

                                                                                                                -

                                                                                                                -
                                                                                                                -

                                                                                                                -
                                                                                                                  -
                                                                                                                  test markup
                                                                                                                  - - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-prototype.html b/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-prototype.html deleted file mode 100644 index 43f7261d8..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-prototype.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - History.js Uncompressed HTML4 Persistant Prototype Test Suite - - - - - - - - - - - - - -

                                                                                                                  History.js Uncompressed HTML4 Persistant Prototype Test Suite

                                                                                                                  -

                                                                                                                  -
                                                                                                                  -

                                                                                                                  -
                                                                                                                    -
                                                                                                                    test markup
                                                                                                                    - - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-zepto.html b/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-zepto.html deleted file mode 100644 index a52009c55..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html4-persistant-zepto.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - History.js Uncompressed HTML4 Persistant Zepto Test Suite - - - - - - - - - - - - - -

                                                                                                                    History.js Uncompressed HTML4 Persistant Zepto Test Suite

                                                                                                                    -

                                                                                                                    -
                                                                                                                    -

                                                                                                                    -
                                                                                                                      -
                                                                                                                      test markup
                                                                                                                      - - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-jquery.html b/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-jquery.html deleted file mode 100644 index 58314926e..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-jquery.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - History.js Uncompressed HTML5 Nonpersistant Jquery Test Suite - - - - - - - - - - - - - -

                                                                                                                      History.js Uncompressed HTML5 Nonpersistant Jquery Test Suite

                                                                                                                      -

                                                                                                                      -
                                                                                                                      -

                                                                                                                      -
                                                                                                                        -
                                                                                                                        test markup
                                                                                                                        - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-mootools.html b/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-mootools.html deleted file mode 100644 index 97166f342..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-mootools.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - History.js Uncompressed HTML5 Nonpersistant Mootools Test Suite - - - - - - - - - - - - - -

                                                                                                                        History.js Uncompressed HTML5 Nonpersistant Mootools Test Suite

                                                                                                                        -

                                                                                                                        -
                                                                                                                        -

                                                                                                                        -
                                                                                                                          -
                                                                                                                          test markup
                                                                                                                          - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-prototype.html b/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-prototype.html deleted file mode 100644 index da36e23a4..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-prototype.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - History.js Uncompressed HTML5 Nonpersistant Prototype Test Suite - - - - - - - - - - - - - -

                                                                                                                          History.js Uncompressed HTML5 Nonpersistant Prototype Test Suite

                                                                                                                          -

                                                                                                                          -
                                                                                                                          -

                                                                                                                          -
                                                                                                                            -
                                                                                                                            test markup
                                                                                                                            - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-zepto.html b/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-zepto.html deleted file mode 100644 index 4fca56f14..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html5-nonpersistant-zepto.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - History.js Uncompressed HTML5 Nonpersistant Zepto Test Suite - - - - - - - - - - - - - -

                                                                                                                            History.js Uncompressed HTML5 Nonpersistant Zepto Test Suite

                                                                                                                            -

                                                                                                                            -
                                                                                                                            -

                                                                                                                            -
                                                                                                                              -
                                                                                                                              test markup
                                                                                                                              - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-jquery.html b/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-jquery.html deleted file mode 100644 index d1086b357..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-jquery.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Uncompressed HTML5 Persistant Jquery Test Suite - - - - - - - - - - - - - -

                                                                                                                              History.js Uncompressed HTML5 Persistant Jquery Test Suite

                                                                                                                              -

                                                                                                                              -
                                                                                                                              -

                                                                                                                              -
                                                                                                                                -
                                                                                                                                test markup
                                                                                                                                - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-mootools.html b/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-mootools.html deleted file mode 100644 index 1f5083724..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-mootools.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Uncompressed HTML5 Persistant Mootools Test Suite - - - - - - - - - - - - - -

                                                                                                                                History.js Uncompressed HTML5 Persistant Mootools Test Suite

                                                                                                                                -

                                                                                                                                -
                                                                                                                                -

                                                                                                                                -
                                                                                                                                  -
                                                                                                                                  test markup
                                                                                                                                  - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-prototype.html b/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-prototype.html deleted file mode 100644 index ad5c3634b..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-prototype.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Uncompressed HTML5 Persistant Prototype Test Suite - - - - - - - - - - - - - -

                                                                                                                                  History.js Uncompressed HTML5 Persistant Prototype Test Suite

                                                                                                                                  -

                                                                                                                                  -
                                                                                                                                  -

                                                                                                                                  -
                                                                                                                                    -
                                                                                                                                    test markup
                                                                                                                                    - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-zepto.html b/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-zepto.html deleted file mode 100644 index 04f272fd1..000000000 --- a/admin/thirdparty/history-js/tests/uncompressed-html5-persistant-zepto.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - History.js Uncompressed HTML5 Persistant Zepto Test Suite - - - - - - - - - - - - - -

                                                                                                                                    History.js Uncompressed HTML5 Persistant Zepto Test Suite

                                                                                                                                    -

                                                                                                                                    -
                                                                                                                                    -

                                                                                                                                    -
                                                                                                                                      -
                                                                                                                                      test markup
                                                                                                                                      - - - - - - - - - - - - - diff --git a/admin/thirdparty/history-js/vendor/jquery.js b/admin/thirdparty/history-js/vendor/jquery.js deleted file mode 100644 index 7932fc701..000000000 --- a/admin/thirdparty/history-js/vendor/jquery.js +++ /dev/null @@ -1,8316 +0,0 @@ -/*! - * jQuery JavaScript Library v1.5.1 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Wed Feb 23 13:55:29 2011 -0500 - */ -(function( window, undefined ) { - -// Use the correct document accordingly with window argument (sandbox) -var document = window.document; -var jQuery = (function() { - -// Define a local copy of jQuery -var jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context, rootjQuery ); - }, - - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - - // Map over the $ in case of overwrite - _$ = window.$, - - // A central reference to the root jQuery(document) - rootjQuery, - - // A simple way to check for HTML strings or ID strings - // (both of which we optimize for) - quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/, - - // Check if a string has a non-whitespace character in it - rnotwhite = /\S/, - - // Used for trimming whitespace - trimLeft = /^\s+/, - trimRight = /\s+$/, - - // Check for digits - rdigit = /\d/, - - // Match a standalone tag - rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, - - // JSON RegExp - rvalidchars = /^[\],:{}\s]*$/, - rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, - rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, - rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, - - // Useragent RegExp - rwebkit = /(webkit)[ \/]([\w.]+)/, - ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, - rmsie = /(msie) ([\w.]+)/, - rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, - - // Keep a UserAgent string for use with jQuery.browser - userAgent = navigator.userAgent, - - // For matching the engine and version of the browser - browserMatch, - - // Has the ready events already been bound? - readyBound = false, - - // The deferred used on DOM ready - readyList, - - // Promise methods - promiseMethods = "then done fail isResolved isRejected promise".split( " " ), - - // The ready event handler - DOMContentLoaded, - - // Save a reference to some core methods - toString = Object.prototype.toString, - hasOwn = Object.prototype.hasOwnProperty, - push = Array.prototype.push, - slice = Array.prototype.slice, - trim = String.prototype.trim, - indexOf = Array.prototype.indexOf, - - // [[Class]] -> type pairs - class2type = {}; - -jQuery.fn = jQuery.prototype = { - constructor: jQuery, - init: function( selector, context, rootjQuery ) { - var match, elem, ret, doc; - - // Handle $(""), $(null), or $(undefined) - if ( !selector ) { - return this; - } - - // Handle $(DOMElement) - if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - } - - // The body element only exists once, optimize finding it - if ( selector === "body" && !context && document.body ) { - this.context = document; - this[0] = document.body; - this.selector = "body"; - this.length = 1; - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - // Are we dealing with HTML string or an ID? - match = quickExpr.exec( selector ); - - // Verify a match, and that no context was specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - doc = (context ? context.ownerDocument || context : document); - - // If a single string is passed in and it's a single tag - // just do a createElement and skip the rest - ret = rsingleTag.exec( selector ); - - if ( ret ) { - if ( jQuery.isPlainObject( context ) ) { - selector = [ document.createElement( ret[1] ) ]; - jQuery.fn.attr.call( selector, context, true ); - - } else { - selector = [ doc.createElement( ret[1] ) ]; - } - - } else { - ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); - selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; - } - - return jQuery.merge( this, selector ); - - // HANDLE: $("#id") - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id !== match[2] ) { - return rootjQuery.find( selector ); - } - - // Otherwise, we inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return (context || rootjQuery).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return rootjQuery.ready( selector ); - } - - if (selector.selector !== undefined) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }, - - // Start with an empty selector - selector: "", - - // The current version of jQuery being used - jquery: "1.5.1", - - // The default length of a jQuery object is 0 - length: 0, - - // The number of elements contained in the matched element set - size: function() { - return this.length; - }, - - toArray: function() { - return slice.call( this, 0 ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num == null ? - - // Return a 'clean' array - this.toArray() : - - // Return just the object - ( num < 0 ? this[ this.length + num ] : this[ num ] ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems, name, selector ) { - // Build a new jQuery matched element set - var ret = this.constructor(); - - if ( jQuery.isArray( elems ) ) { - push.apply( ret, elems ); - - } else { - jQuery.merge( ret, elems ); - } - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - ret.context = this.context; - - if ( name === "find" ) { - ret.selector = this.selector + (this.selector ? " " : "") + selector; - } else if ( name ) { - ret.selector = this.selector + "." + name + "(" + selector + ")"; - } - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - ready: function( fn ) { - // Attach the listeners - jQuery.bindReady(); - - // Add the callback - readyList.done( fn ); - - return this; - }, - - eq: function( i ) { - return i === -1 ? - this.slice( i ) : - this.slice( i, +i + 1 ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ), - "slice", slice.call(arguments).join(",") ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: [].sort, - splice: [].splice -}; - -// Give the init function the jQuery prototype for later instantiation -jQuery.fn.init.prototype = jQuery.fn; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if ( length === i ) { - target = this; - --i; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; - - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend({ - noConflict: function( deep ) { - window.$ = _$; - - if ( deep ) { - window.jQuery = _jQuery; - } - - return jQuery; - }, - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Handle when the DOM is ready - ready: function( wait ) { - // A third-party is pushing the ready event forwards - if ( wait === true ) { - jQuery.readyWait--; - } - - // Make sure that the DOM is not already loaded - if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( !document.body ) { - return setTimeout( jQuery.ready, 1 ); - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.trigger ) { - jQuery( document ).trigger( "ready" ).unbind( "ready" ); - } - } - }, - - bindReady: function() { - if ( readyBound ) { - return; - } - - readyBound = true; - - // Catch cases where $(document).ready() is called after the - // browser event has already occurred. - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - return setTimeout( jQuery.ready, 1 ); - } - - // Mozilla, Opera and webkit nightlies currently support this event - if ( document.addEventListener ) { - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", jQuery.ready, false ); - - // If IE event model is used - } else if ( document.attachEvent ) { - // ensure firing before onload, - // maybe late but safe also for iframes - document.attachEvent("onreadystatechange", DOMContentLoaded); - - // A fallback to window.onload, that will always work - window.attachEvent( "onload", jQuery.ready ); - - // If IE and not a frame - // continually check to see if the document is ready - var toplevel = false; - - try { - toplevel = window.frameElement == null; - } catch(e) {} - - if ( document.documentElement.doScroll && toplevel ) { - doScrollCheck(); - } - } - }, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray || function( obj ) { - return jQuery.type(obj) === "array"; - }, - - // A crude way of determining if an object is a window - isWindow: function( obj ) { - return obj && typeof obj === "object" && "setInterval" in obj; - }, - - isNaN: function( obj ) { - return obj == null || !rdigit.test( obj ) || isNaN( obj ); - }, - - type: function( obj ) { - return obj == null ? - String( obj ) : - class2type[ toString.call(obj) ] || "object"; - }, - - isPlainObject: function( obj ) { - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - // Not own constructor property must be Object - if ( obj.constructor && - !hasOwn.call(obj, "constructor") && - !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { - return false; - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - - var key; - for ( key in obj ) {} - - return key === undefined || hasOwn.call( obj, key ); - }, - - isEmptyObject: function( obj ) { - for ( var name in obj ) { - return false; - } - return true; - }, - - error: function( msg ) { - throw msg; - }, - - parseJSON: function( data ) { - if ( typeof data !== "string" || !data ) { - return null; - } - - // Make sure leading/trailing whitespace is removed (IE can't handle it) - data = jQuery.trim( data ); - - // Make sure the incoming data is actual JSON - // Logic borrowed from http://json.org/json2.js - if ( rvalidchars.test(data.replace(rvalidescape, "@") - .replace(rvalidtokens, "]") - .replace(rvalidbraces, "")) ) { - - // Try to use the native JSON parser first - return window.JSON && window.JSON.parse ? - window.JSON.parse( data ) : - (new Function("return " + data))(); - - } else { - jQuery.error( "Invalid JSON: " + data ); - } - }, - - // Cross-browser xml parsing - // (xml & tmp used internally) - parseXML: function( data , xml , tmp ) { - - if ( window.DOMParser ) { // Standard - tmp = new DOMParser(); - xml = tmp.parseFromString( data , "text/xml" ); - } else { // IE - xml = new ActiveXObject( "Microsoft.XMLDOM" ); - xml.async = "false"; - xml.loadXML( data ); - } - - tmp = xml.documentElement; - - if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { - jQuery.error( "Invalid XML: " + data ); - } - - return xml; - }, - - noop: function() {}, - - // Evalulates a script in a global context - globalEval: function( data ) { - if ( data && rnotwhite.test(data) ) { - // Inspired by code by Andrea Giammarchi - // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html - var head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement, - script = document.createElement( "script" ); - - if ( jQuery.support.scriptEval() ) { - script.appendChild( document.createTextNode( data ) ); - } else { - script.text = data; - } - - // Use insertBefore instead of appendChild to circumvent an IE6 bug. - // This arises when a base node is used (#2709). - head.insertBefore( script, head.firstChild ); - head.removeChild( script ); - } - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); - }, - - // args is for internal usage only - each: function( object, callback, args ) { - var name, i = 0, - length = object.length, - isObj = length === undefined || jQuery.isFunction(object); - - if ( args ) { - if ( isObj ) { - for ( name in object ) { - if ( callback.apply( object[ name ], args ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.apply( object[ i++ ], args ) === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isObj ) { - for ( name in object ) { - if ( callback.call( object[ name ], name, object[ name ] ) === false ) { - break; - } - } - } else { - for ( var value = object[0]; - i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {} - } - } - - return object; - }, - - // Use native String.trim function wherever possible - trim: trim ? - function( text ) { - return text == null ? - "" : - trim.call( text ); - } : - - // Otherwise use our own trimming functionality - function( text ) { - return text == null ? - "" : - text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); - }, - - // results is for internal usage only - makeArray: function( array, results ) { - var ret = results || []; - - if ( array != null ) { - // The window, strings (and functions) also have 'length' - // The extra typeof function check is to prevent crashes - // in Safari 2 (See: #3039) - // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 - var type = jQuery.type(array); - - if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { - push.call( ret, array ); - } else { - jQuery.merge( ret, array ); - } - } - - return ret; - }, - - inArray: function( elem, array ) { - if ( array.indexOf ) { - return array.indexOf( elem ); - } - - for ( var i = 0, length = array.length; i < length; i++ ) { - if ( array[ i ] === elem ) { - return i; - } - } - - return -1; - }, - - merge: function( first, second ) { - var i = first.length, - j = 0; - - if ( typeof second.length === "number" ) { - for ( var l = second.length; j < l; j++ ) { - first[ i++ ] = second[ j ]; - } - - } else { - while ( second[j] !== undefined ) { - first[ i++ ] = second[ j++ ]; - } - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, inv ) { - var ret = [], retVal; - inv = !!inv; - - // Go through the array, only saving the items - // that pass the validator function - for ( var i = 0, length = elems.length; i < length; i++ ) { - retVal = !!callback( elems[ i ], i ); - if ( inv !== retVal ) { - ret.push( elems[ i ] ); - } - } - - return ret; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var ret = [], value; - - // Go through the array, translating each of the items to their - // new value (or values). - for ( var i = 0, length = elems.length; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - - // Flatten any nested arrays - return ret.concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - proxy: function( fn, proxy, thisObject ) { - if ( arguments.length === 2 ) { - if ( typeof proxy === "string" ) { - thisObject = fn; - fn = thisObject[ proxy ]; - proxy = undefined; - - } else if ( proxy && !jQuery.isFunction( proxy ) ) { - thisObject = proxy; - proxy = undefined; - } - } - - if ( !proxy && fn ) { - proxy = function() { - return fn.apply( thisObject || this, arguments ); - }; - } - - // Set the guid of unique handler to the same of original handler, so it can be removed - if ( fn ) { - proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; - } - - // So proxy can be declared as an argument - return proxy; - }, - - // Mutifunctional method to get and set values to a collection - // The value/s can be optionally by executed if its a function - access: function( elems, key, value, exec, fn, pass ) { - var length = elems.length; - - // Setting many attributes - if ( typeof key === "object" ) { - for ( var k in key ) { - jQuery.access( elems, k, key[k], exec, fn, value ); - } - return elems; - } - - // Setting one attribute - if ( value !== undefined ) { - // Optionally, function values get executed if exec is true - exec = !pass && exec && jQuery.isFunction(value); - - for ( var i = 0; i < length; i++ ) { - fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); - } - - return elems; - } - - // Getting an attribute - return length ? fn( elems[0], key ) : undefined; - }, - - now: function() { - return (new Date()).getTime(); - }, - - // Create a simple deferred (one callbacks list) - _Deferred: function() { - var // callbacks list - callbacks = [], - // stored [ context , args ] - fired, - // to avoid firing when already doing so - firing, - // flag to know if the deferred has been cancelled - cancelled, - // the deferred itself - deferred = { - - // done( f1, f2, ...) - done: function() { - if ( !cancelled ) { - var args = arguments, - i, - length, - elem, - type, - _fired; - if ( fired ) { - _fired = fired; - fired = 0; - } - for ( i = 0, length = args.length; i < length; i++ ) { - elem = args[ i ]; - type = jQuery.type( elem ); - if ( type === "array" ) { - deferred.done.apply( deferred, elem ); - } else if ( type === "function" ) { - callbacks.push( elem ); - } - } - if ( _fired ) { - deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); - } - } - return this; - }, - - // resolve with given context and args - resolveWith: function( context, args ) { - if ( !cancelled && !fired && !firing ) { - firing = 1; - try { - while( callbacks[ 0 ] ) { - callbacks.shift().apply( context, args ); - } - } - // We have to add a catch block for - // IE prior to 8 or else the finally - // block will never get executed - catch (e) { - throw e; - } - finally { - fired = [ context, args ]; - firing = 0; - } - } - return this; - }, - - // resolve with this as context and given arguments - resolve: function() { - deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this, arguments ); - return this; - }, - - // Has this deferred been resolved? - isResolved: function() { - return !!( firing || fired ); - }, - - // Cancel - cancel: function() { - cancelled = 1; - callbacks = []; - return this; - } - }; - - return deferred; - }, - - // Full fledged deferred (two callbacks list) - Deferred: function( func ) { - var deferred = jQuery._Deferred(), - failDeferred = jQuery._Deferred(), - promise; - // Add errorDeferred methods, then and promise - jQuery.extend( deferred, { - then: function( doneCallbacks, failCallbacks ) { - deferred.done( doneCallbacks ).fail( failCallbacks ); - return this; - }, - fail: failDeferred.done, - rejectWith: failDeferred.resolveWith, - reject: failDeferred.resolve, - isRejected: failDeferred.isResolved, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - if ( obj == null ) { - if ( promise ) { - return promise; - } - promise = obj = {}; - } - var i = promiseMethods.length; - while( i-- ) { - obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; - } - return obj; - } - } ); - // Make sure only one callback list will be used - deferred.done( failDeferred.cancel ).fail( deferred.cancel ); - // Unexpose cancel - delete deferred.cancel; - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - return deferred; - }, - - // Deferred helper - when: function( object ) { - var lastIndex = arguments.length, - deferred = lastIndex <= 1 && object && jQuery.isFunction( object.promise ) ? - object : - jQuery.Deferred(), - promise = deferred.promise(); - - if ( lastIndex > 1 ) { - var array = slice.call( arguments, 0 ), - count = lastIndex, - iCallback = function( index ) { - return function( value ) { - array[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value; - if ( !( --count ) ) { - deferred.resolveWith( promise, array ); - } - }; - }; - while( ( lastIndex-- ) ) { - object = array[ lastIndex ]; - if ( object && jQuery.isFunction( object.promise ) ) { - object.promise().then( iCallback(lastIndex), deferred.reject ); - } else { - --count; - } - } - if ( !count ) { - deferred.resolveWith( promise, array ); - } - } else if ( deferred !== object ) { - deferred.resolve( object ); - } - return promise; - }, - - // Use of jQuery.browser is frowned upon. - // More details: http://docs.jquery.com/Utilities/jQuery.browser - uaMatch: function( ua ) { - ua = ua.toLowerCase(); - - var match = rwebkit.exec( ua ) || - ropera.exec( ua ) || - rmsie.exec( ua ) || - ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || - []; - - return { browser: match[1] || "", version: match[2] || "0" }; - }, - - sub: function() { - function jQuerySubclass( selector, context ) { - return new jQuerySubclass.fn.init( selector, context ); - } - jQuery.extend( true, jQuerySubclass, this ); - jQuerySubclass.superclass = this; - jQuerySubclass.fn = jQuerySubclass.prototype = this(); - jQuerySubclass.fn.constructor = jQuerySubclass; - jQuerySubclass.subclass = this.subclass; - jQuerySubclass.fn.init = function init( selector, context ) { - if ( context && context instanceof jQuery && !(context instanceof jQuerySubclass) ) { - context = jQuerySubclass(context); - } - - return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass ); - }; - jQuerySubclass.fn.init.prototype = jQuerySubclass.fn; - var rootjQuerySubclass = jQuerySubclass(document); - return jQuerySubclass; - }, - - browser: {} -}); - -// Create readyList deferred -readyList = jQuery._Deferred(); - -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -browserMatch = jQuery.uaMatch( userAgent ); -if ( browserMatch.browser ) { - jQuery.browser[ browserMatch.browser ] = true; - jQuery.browser.version = browserMatch.version; -} - -// Deprecated, use jQuery.browser.webkit instead -if ( jQuery.browser.webkit ) { - jQuery.browser.safari = true; -} - -if ( indexOf ) { - jQuery.inArray = function( elem, array ) { - return indexOf.call( array, elem ); - }; -} - -// IE doesn't match non-breaking spaces with \s -if ( rnotwhite.test( "\xA0" ) ) { - trimLeft = /^[\s\xA0]+/; - trimRight = /[\s\xA0]+$/; -} - -// All jQuery objects should point back to these -rootjQuery = jQuery(document); - -// Cleanup functions for the document ready method -if ( document.addEventListener ) { - DOMContentLoaded = function() { - document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - jQuery.ready(); - }; - -} else if ( document.attachEvent ) { - DOMContentLoaded = function() { - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( document.readyState === "complete" ) { - document.detachEvent( "onreadystatechange", DOMContentLoaded ); - jQuery.ready(); - } - }; -} - -// The DOM ready check for Internet Explorer -function doScrollCheck() { - if ( jQuery.isReady ) { - return; - } - - try { - // If IE is used, use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - document.documentElement.doScroll("left"); - } catch(e) { - setTimeout( doScrollCheck, 1 ); - return; - } - - // and execute any waiting functions - jQuery.ready(); -} - -// Expose jQuery to the global object -return jQuery; - -})(); - - -(function() { - - jQuery.support = {}; - - var div = document.createElement("div"); - - div.style.display = "none"; - div.innerHTML = "
                                                                                                                                      a"; - - var all = div.getElementsByTagName("*"), - a = div.getElementsByTagName("a")[0], - select = document.createElement("select"), - opt = select.appendChild( document.createElement("option") ), - input = div.getElementsByTagName("input")[0]; - - // Can't get basic test support - if ( !all || !all.length || !a ) { - return; - } - - jQuery.support = { - // IE strips leading whitespace when .innerHTML is used - leadingWhitespace: div.firstChild.nodeType === 3, - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - tbody: !div.getElementsByTagName("tbody").length, - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - htmlSerialize: !!div.getElementsByTagName("link").length, - - // Get the style information from getAttribute - // (IE uses .cssText insted) - style: /red/.test( a.getAttribute("style") ), - - // Make sure that URLs aren't manipulated - // (IE normalizes it by default) - hrefNormalized: a.getAttribute("href") === "/a", - - // Make sure that element opacity exists - // (IE uses filter instead) - // Use a regex to work around a WebKit issue. See #5145 - opacity: /^0.55$/.test( a.style.opacity ), - - // Verify style float existence - // (IE uses styleFloat instead of cssFloat) - cssFloat: !!a.style.cssFloat, - - // Make sure that if no value is specified for a checkbox - // that it defaults to "on". - // (WebKit defaults to "" instead) - checkOn: input.value === "on", - - // Make sure that a selected-by-default option has a working selected property. - // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) - optSelected: opt.selected, - - // Will be defined later - deleteExpando: true, - optDisabled: false, - checkClone: false, - noCloneEvent: true, - noCloneChecked: true, - boxModel: null, - inlineBlockNeedsLayout: false, - shrinkWrapBlocks: false, - reliableHiddenOffsets: true - }; - - input.checked = true; - jQuery.support.noCloneChecked = input.cloneNode( true ).checked; - - // Make sure that the options inside disabled selects aren't marked as disabled - // (WebKit marks them as diabled) - select.disabled = true; - jQuery.support.optDisabled = !opt.disabled; - - var _scriptEval = null; - jQuery.support.scriptEval = function() { - if ( _scriptEval === null ) { - var root = document.documentElement, - script = document.createElement("script"), - id = "script" + jQuery.now(); - - try { - script.appendChild( document.createTextNode( "window." + id + "=1;" ) ); - } catch(e) {} - - root.insertBefore( script, root.firstChild ); - - // Make sure that the execution of code works by injecting a script - // tag with appendChild/createTextNode - // (IE doesn't support this, fails, and uses .text instead) - if ( window[ id ] ) { - _scriptEval = true; - delete window[ id ]; - } else { - _scriptEval = false; - } - - root.removeChild( script ); - // release memory in IE - root = script = id = null; - } - - return _scriptEval; - }; - - // Test to see if it's possible to delete an expando from an element - // Fails in Internet Explorer - try { - delete div.test; - - } catch(e) { - jQuery.support.deleteExpando = false; - } - - if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { - div.attachEvent("onclick", function click() { - // Cloning a node shouldn't copy over any - // bound event handlers (IE does this) - jQuery.support.noCloneEvent = false; - div.detachEvent("onclick", click); - }); - div.cloneNode(true).fireEvent("onclick"); - } - - div = document.createElement("div"); - div.innerHTML = ""; - - var fragment = document.createDocumentFragment(); - fragment.appendChild( div.firstChild ); - - // WebKit doesn't clone checked state correctly in fragments - jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked; - - // Figure out if the W3C box model works as expected - // document.body must exist before we can do this - jQuery(function() { - var div = document.createElement("div"), - body = document.getElementsByTagName("body")[0]; - - // Frameset documents with no body should not run this code - if ( !body ) { - return; - } - - div.style.width = div.style.paddingLeft = "1px"; - body.appendChild( div ); - jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2; - - if ( "zoom" in div.style ) { - // Check if natively block-level elements act like inline-block - // elements when setting their display to 'inline' and giving - // them layout - // (IE < 8 does this) - div.style.display = "inline"; - div.style.zoom = 1; - jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2; - - // Check if elements with layout shrink-wrap their children - // (IE 6 does this) - div.style.display = ""; - div.innerHTML = "
                                                                                                                                      "; - jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2; - } - - div.innerHTML = "
                                                                                                                                      t
                                                                                                                                      "; - var tds = div.getElementsByTagName("td"); - - // Check if table cells still have offsetWidth/Height when they are set - // to display:none and there are still other visible table cells in a - // table row; if so, offsetWidth/Height are not reliable for use when - // determining if an element has been hidden directly using - // display:none (it is still safe to use offsets if a parent element is - // hidden; don safety goggles and see bug #4512 for more information). - // (only IE 8 fails this test) - jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0; - - tds[0].style.display = ""; - tds[1].style.display = "none"; - - // Check if empty table cells still have offsetWidth/Height - // (IE < 8 fail this test) - jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0; - div.innerHTML = ""; - - body.removeChild( div ).style.display = "none"; - div = tds = null; - }); - - // Technique from Juriy Zaytsev - // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ - var eventSupported = function( eventName ) { - var el = document.createElement("div"); - eventName = "on" + eventName; - - // We only care about the case where non-standard event systems - // are used, namely in IE. Short-circuiting here helps us to - // avoid an eval call (in setAttribute) which can cause CSP - // to go haywire. See: https://developer.mozilla.org/en/Security/CSP - if ( !el.attachEvent ) { - return true; - } - - var isSupported = (eventName in el); - if ( !isSupported ) { - el.setAttribute(eventName, "return;"); - isSupported = typeof el[eventName] === "function"; - } - el = null; - - return isSupported; - }; - - jQuery.support.submitBubbles = eventSupported("submit"); - jQuery.support.changeBubbles = eventSupported("change"); - - // release memory in IE - div = all = a = null; -})(); - - - -var rbrace = /^(?:\{.*\}|\[.*\])$/; - -jQuery.extend({ - cache: {}, - - // Please use with caution - uuid: 0, - - // Unique for each copy of jQuery on the page - // Non-digits removed to match rinlinejQuery - expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), - - // The following elements throw uncatchable exceptions if you - // attempt to add expando properties to them. - noData: { - "embed": true, - // Ban all objects except for Flash (which handle expandos) - "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", - "applet": true - }, - - hasData: function( elem ) { - elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; - - return !!elem && !isEmptyDataObject( elem ); - }, - - data: function( elem, name, data, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, - - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, - - // Only DOM nodes need the global jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? jQuery.cache : elem, - - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; - - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) { - return; - } - - if ( !id ) { - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if ( isNode ) { - elem[ jQuery.expando ] = id = ++jQuery.uuid; - } else { - id = jQuery.expando; - } - } - - if ( !cache[ id ] ) { - cache[ id ] = {}; - - // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery - // metadata on plain JS objects when the object is serialized using - // JSON.stringify - if ( !isNode ) { - cache[ id ].toJSON = jQuery.noop; - } - } - - // An object can be passed to jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if ( typeof name === "object" || typeof name === "function" ) { - if ( pvt ) { - cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); - } else { - cache[ id ] = jQuery.extend(cache[ id ], name); - } - } - - thisCache = cache[ id ]; - - // Internal jQuery data is stored in a separate object inside the object's data - // cache in order to avoid key collisions between internal data and user-defined - // data - if ( pvt ) { - if ( !thisCache[ internalKey ] ) { - thisCache[ internalKey ] = {}; - } - - thisCache = thisCache[ internalKey ]; - } - - if ( data !== undefined ) { - thisCache[ name ] = data; - } - - // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should - // not attempt to inspect the internal events object using jQuery.data, as this - // internal data object is undocumented and subject to change. - if ( name === "events" && !thisCache[name] ) { - return thisCache[ internalKey ] && thisCache[ internalKey ].events; - } - - return getByName ? thisCache[ name ] : thisCache; - }, - - removeData: function( elem, name, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var internalKey = jQuery.expando, isNode = elem.nodeType, - - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - - // See jQuery.data for more information - id = isNode ? elem[ jQuery.expando ] : jQuery.expando; - - // If there is already no cache entry for this object, there is no - // purpose in continuing - if ( !cache[ id ] ) { - return; - } - - if ( name ) { - var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; - - if ( thisCache ) { - delete thisCache[ name ]; - - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if ( !isEmptyDataObject(thisCache) ) { - return; - } - } - } - - // See jQuery.data for more information - if ( pvt ) { - delete cache[ id ][ internalKey ]; - - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if ( !isEmptyDataObject(cache[ id ]) ) { - return; - } - } - - var internalCache = cache[ id ][ internalKey ]; - - // Browsers that fail expando deletion also refuse to delete expandos on - // the window, but it will allow it on all other JS objects; other browsers - // don't care - if ( jQuery.support.deleteExpando || cache != window ) { - delete cache[ id ]; - } else { - cache[ id ] = null; - } - - // We destroyed the entire user cache at once because it's faster than - // iterating through each key, but we need to continue to persist internal - // data if it existed - if ( internalCache ) { - cache[ id ] = {}; - // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery - // metadata on plain JS objects when the object is serialized using - // JSON.stringify - if ( !isNode ) { - cache[ id ].toJSON = jQuery.noop; - } - - cache[ id ][ internalKey ] = internalCache; - - // Otherwise, we need to eliminate the expando on the node to avoid - // false lookups in the cache for entries that no longer exist - } else if ( isNode ) { - // IE does not allow us to delete expando properties from nodes, - // nor does it have a removeAttribute function on Document nodes; - // we must handle all of these cases - if ( jQuery.support.deleteExpando ) { - delete elem[ jQuery.expando ]; - } else if ( elem.removeAttribute ) { - elem.removeAttribute( jQuery.expando ); - } else { - elem[ jQuery.expando ] = null; - } - } - }, - - // For internal use only. - _data: function( elem, name, data ) { - return jQuery.data( elem, name, data, true ); - }, - - // A method for determining if a DOM node can handle the data expando - acceptData: function( elem ) { - if ( elem.nodeName ) { - var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; - - if ( match ) { - return !(match === true || elem.getAttribute("classid") !== match); - } - } - - return true; - } -}); - -jQuery.fn.extend({ - data: function( key, value ) { - var data = null; - - if ( typeof key === "undefined" ) { - if ( this.length ) { - data = jQuery.data( this[0] ); - - if ( this[0].nodeType === 1 ) { - var attr = this[0].attributes, name; - for ( var i = 0, l = attr.length; i < l; i++ ) { - name = attr[i].name; - - if ( name.indexOf( "data-" ) === 0 ) { - name = name.substr( 5 ); - dataAttr( this[0], name, data[ name ] ); - } - } - } - } - - return data; - - } else if ( typeof key === "object" ) { - return this.each(function() { - jQuery.data( this, key ); - }); - } - - var parts = key.split("."); - parts[1] = parts[1] ? "." + parts[1] : ""; - - if ( value === undefined ) { - data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); - - // Try to fetch any internally stored data first - if ( data === undefined && this.length ) { - data = jQuery.data( this[0], key ); - data = dataAttr( this[0], key, data ); - } - - return data === undefined && parts[1] ? - this.data( parts[0] ) : - data; - - } else { - return this.each(function() { - var $this = jQuery( this ), - args = [ parts[0], value ]; - - $this.triggerHandler( "setData" + parts[1] + "!", args ); - jQuery.data( this, key, value ); - $this.triggerHandler( "changeData" + parts[1] + "!", args ); - }); - } - }, - - removeData: function( key ) { - return this.each(function() { - jQuery.removeData( this, key ); - }); - } -}); - -function dataAttr( elem, key, data ) { - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - data = elem.getAttribute( "data-" + key ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - !jQuery.isNaN( data ) ? parseFloat( data ) : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - jQuery.data( elem, key, data ); - - } else { - data = undefined; - } - } - - return data; -} - -// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON -// property to be considered empty objects; this property always exists in -// order to make sure JSON.stringify does not expose internal metadata -function isEmptyDataObject( obj ) { - for ( var name in obj ) { - if ( name !== "toJSON" ) { - return false; - } - } - - return true; -} - - - - -jQuery.extend({ - queue: function( elem, type, data ) { - if ( !elem ) { - return; - } - - type = (type || "fx") + "queue"; - var q = jQuery._data( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( !data ) { - return q || []; - } - - if ( !q || jQuery.isArray(data) ) { - q = jQuery._data( elem, type, jQuery.makeArray(data) ); - - } else { - q.push( data ); - } - - return q; - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - fn = queue.shift(); - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - } - - if ( fn ) { - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift("inprogress"); - } - - fn.call(elem, function() { - jQuery.dequeue(elem, type); - }); - } - - if ( !queue.length ) { - jQuery.removeData( elem, type + "queue", true ); - } - } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - } - - if ( data === undefined ) { - return jQuery.queue( this[0], type ); - } - return this.each(function( i ) { - var queue = jQuery.queue( this, type, data ); - - if ( type === "fx" && queue[0] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - jQuery.dequeue( this, type ); - }); - }, - - // Based off of the plugin by Clint Helfers, with permission. - // http://blindsignals.com/index.php/2009/07/jquery-delay/ - delay: function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; - type = type || "fx"; - - return this.queue( type, function() { - var elem = this; - setTimeout(function() { - jQuery.dequeue( elem, type ); - }, time ); - }); - }, - - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - } -}); - - - - -var rclass = /[\n\t\r]/g, - rspaces = /\s+/, - rreturn = /\r/g, - rspecialurl = /^(?:href|src|style)$/, - rtype = /^(?:button|input)$/i, - rfocusable = /^(?:button|input|object|select|textarea)$/i, - rclickable = /^a(?:rea)?$/i, - rradiocheck = /^(?:radio|checkbox)$/i; - -jQuery.props = { - "for": "htmlFor", - "class": "className", - readonly: "readOnly", - maxlength: "maxLength", - cellspacing: "cellSpacing", - rowspan: "rowSpan", - colspan: "colSpan", - tabindex: "tabIndex", - usemap: "useMap", - frameborder: "frameBorder" -}; - -jQuery.fn.extend({ - attr: function( name, value ) { - return jQuery.access( this, name, value, true, jQuery.attr ); - }, - - removeAttr: function( name, fn ) { - return this.each(function(){ - jQuery.attr( this, name, "" ); - if ( this.nodeType === 1 ) { - this.removeAttribute( name ); - } - }); - }, - - addClass: function( value ) { - if ( jQuery.isFunction(value) ) { - return this.each(function(i) { - var self = jQuery(this); - self.addClass( value.call(this, i, self.attr("class")) ); - }); - } - - if ( value && typeof value === "string" ) { - var classNames = (value || "").split( rspaces ); - - for ( var i = 0, l = this.length; i < l; i++ ) { - var elem = this[i]; - - if ( elem.nodeType === 1 ) { - if ( !elem.className ) { - elem.className = value; - - } else { - var className = " " + elem.className + " ", - setClass = elem.className; - - for ( var c = 0, cl = classNames.length; c < cl; c++ ) { - if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) { - setClass += " " + classNames[c]; - } - } - elem.className = jQuery.trim( setClass ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - if ( jQuery.isFunction(value) ) { - return this.each(function(i) { - var self = jQuery(this); - self.removeClass( value.call(this, i, self.attr("class")) ); - }); - } - - if ( (value && typeof value === "string") || value === undefined ) { - var classNames = (value || "").split( rspaces ); - - for ( var i = 0, l = this.length; i < l; i++ ) { - var elem = this[i]; - - if ( elem.nodeType === 1 && elem.className ) { - if ( value ) { - var className = (" " + elem.className + " ").replace(rclass, " "); - for ( var c = 0, cl = classNames.length; c < cl; c++ ) { - className = className.replace(" " + classNames[c] + " ", " "); - } - elem.className = jQuery.trim( className ); - - } else { - elem.className = ""; - } - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isBool = typeof stateVal === "boolean"; - - if ( jQuery.isFunction( value ) ) { - return this.each(function(i) { - var self = jQuery(this); - self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal ); - }); - } - - return this.each(function() { - if ( type === "string" ) { - // toggle individual class names - var className, - i = 0, - self = jQuery( this ), - state = stateVal, - classNames = value.split( rspaces ); - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space seperated list - state = isBool ? state : !self.hasClass( className ); - self[ state ? "addClass" : "removeClass" ]( className ); - } - - } else if ( type === "undefined" || type === "boolean" ) { - if ( this.className ) { - // store className if set - jQuery._data( this, "__className__", this.className ); - } - - // toggle whole className - this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; - } - }); - }, - - hasClass: function( selector ) { - var className = " " + selector + " "; - for ( var i = 0, l = this.length; i < l; i++ ) { - if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { - return true; - } - } - - return false; - }, - - val: function( value ) { - if ( !arguments.length ) { - var elem = this[0]; - - if ( elem ) { - if ( jQuery.nodeName( elem, "option" ) ) { - // attributes.value is undefined in Blackberry 4.7 but - // uses .value. See #6932 - var val = elem.attributes.value; - return !val || val.specified ? elem.value : elem.text; - } - - // We need to handle select boxes special - if ( jQuery.nodeName( elem, "select" ) ) { - var index = elem.selectedIndex, - values = [], - options = elem.options, - one = elem.type === "select-one"; - - // Nothing was selected - if ( index < 0 ) { - return null; - } - - // Loop through all the selected options - for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { - var option = options[ i ]; - - // Don't return options that are disabled or in a disabled optgroup - if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && - (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { - - // Get the specific value for the option - value = jQuery(option).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - // Fixes Bug #2551 -- select.val() broken in IE after form.reset() - if ( one && !values.length && options.length ) { - return jQuery( options[ index ] ).val(); - } - - return values; - } - - // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified - if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) { - return elem.getAttribute("value") === null ? "on" : elem.value; - } - - // Everything else, we just grab the value - return (elem.value || "").replace(rreturn, ""); - - } - - return undefined; - } - - var isFunction = jQuery.isFunction(value); - - return this.each(function(i) { - var self = jQuery(this), val = value; - - if ( this.nodeType !== 1 ) { - return; - } - - if ( isFunction ) { - val = value.call(this, i, self.val()); - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - } else if ( typeof val === "number" ) { - val += ""; - } else if ( jQuery.isArray(val) ) { - val = jQuery.map(val, function (value) { - return value == null ? "" : value + ""; - }); - } - - if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) { - this.checked = jQuery.inArray( self.val(), val ) >= 0; - - } else if ( jQuery.nodeName( this, "select" ) ) { - var values = jQuery.makeArray(val); - - jQuery( "option", this ).each(function() { - this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; - }); - - if ( !values.length ) { - this.selectedIndex = -1; - } - - } else { - this.value = val; - } - }); - } -}); - -jQuery.extend({ - attrFn: { - val: true, - css: true, - html: true, - text: true, - data: true, - width: true, - height: true, - offset: true - }, - - attr: function( elem, name, value, pass ) { - // don't get/set attributes on text, comment and attribute nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) { - return undefined; - } - - if ( pass && name in jQuery.attrFn ) { - return jQuery(elem)[name](value); - } - - var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ), - // Whether we are setting (or getting) - set = value !== undefined; - - // Try to normalize/fix the name - name = notxml && jQuery.props[ name ] || name; - - // Only do all the following if this is a node (faster for style) - if ( elem.nodeType === 1 ) { - // These attributes require special treatment - var special = rspecialurl.test( name ); - - // Safari mis-reports the default selected property of an option - // Accessing the parent's selectedIndex property fixes it - if ( name === "selected" && !jQuery.support.optSelected ) { - var parent = elem.parentNode; - if ( parent ) { - parent.selectedIndex; - - // Make sure that it also works with optgroups, see #5701 - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - } - - // If applicable, access the attribute via the DOM 0 way - // 'in' checks fail in Blackberry 4.7 #6931 - if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) { - if ( set ) { - // We can't allow the type property to be changed (since it causes problems in IE) - if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) { - jQuery.error( "type property can't be changed" ); - } - - if ( value === null ) { - if ( elem.nodeType === 1 ) { - elem.removeAttribute( name ); - } - - } else { - elem[ name ] = value; - } - } - - // browsers index elements by id/name on forms, give priority to attributes. - if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) { - return elem.getAttributeNode( name ).nodeValue; - } - - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - if ( name === "tabIndex" ) { - var attributeNode = elem.getAttributeNode( "tabIndex" ); - - return attributeNode && attributeNode.specified ? - attributeNode.value : - rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? - 0 : - undefined; - } - - return elem[ name ]; - } - - if ( !jQuery.support.style && notxml && name === "style" ) { - if ( set ) { - elem.style.cssText = "" + value; - } - - return elem.style.cssText; - } - - if ( set ) { - // convert the value to a string (all browsers do this but IE) see #1070 - elem.setAttribute( name, "" + value ); - } - - // Ensure that missing attributes return undefined - // Blackberry 4.7 returns "" from getAttribute #6938 - if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) { - return undefined; - } - - var attr = !jQuery.support.hrefNormalized && notxml && special ? - // Some attributes require a special call on IE - elem.getAttribute( name, 2 ) : - elem.getAttribute( name ); - - // Non-existent attributes return null, we normalize to undefined - return attr === null ? undefined : attr; - } - // Handle everything which isn't a DOM element node - if ( set ) { - elem[ name ] = value; - } - return elem[ name ]; - } -}); - - - - -var rnamespaces = /\.(.*)$/, - rformElems = /^(?:textarea|input|select)$/i, - rperiod = /\./g, - rspace = / /g, - rescape = /[^\w\s.|`]/g, - fcleanup = function( nm ) { - return nm.replace(rescape, "\\$&"); - }; - -/* - * A number of helper functions used for managing events. - * Many of the ideas behind this code originated from - * Dean Edwards' addEvent library. - */ -jQuery.event = { - - // Bind an event to an element - // Original by Dean Edwards - add: function( elem, types, handler, data ) { - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // TODO :: Use a try/catch until it's safe to pull this out (likely 1.6) - // Minor release fix for bug #8018 - try { - // For whatever reason, IE has trouble passing the window object - // around, causing it to be cloned in the process - if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) { - elem = window; - } - } - catch ( e ) {} - - if ( handler === false ) { - handler = returnFalse; - } else if ( !handler ) { - // Fixes bug #7229. Fix recommended by jdalton - return; - } - - var handleObjIn, handleObj; - - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - } - - // Make sure that the function being executed has a unique ID - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure - var elemData = jQuery._data( elem ); - - // If no elemData is found then we must be trying to bind to one of the - // banned noData elements - if ( !elemData ) { - return; - } - - var events = elemData.events, - eventHandle = elemData.handle; - - if ( !events ) { - elemData.events = events = {}; - } - - if ( !eventHandle ) { - elemData.handle = eventHandle = function() { - // Handle the second event of a trigger and when - // an event is called after a page has unloaded - return typeof jQuery !== "undefined" && !jQuery.event.triggered ? - jQuery.event.handle.apply( eventHandle.elem, arguments ) : - undefined; - }; - } - - // Add elem as a property of the handle function - // This is to prevent a memory leak with non-native events in IE. - eventHandle.elem = elem; - - // Handle multiple events separated by a space - // jQuery(...).bind("mouseover mouseout", fn); - types = types.split(" "); - - var type, i = 0, namespaces; - - while ( (type = types[ i++ ]) ) { - handleObj = handleObjIn ? - jQuery.extend({}, handleObjIn) : - { handler: handler, data: data }; - - // Namespaced event handlers - if ( type.indexOf(".") > -1 ) { - namespaces = type.split("."); - type = namespaces.shift(); - handleObj.namespace = namespaces.slice(0).sort().join("."); - - } else { - namespaces = []; - handleObj.namespace = ""; - } - - handleObj.type = type; - if ( !handleObj.guid ) { - handleObj.guid = handler.guid; - } - - // Get the current list of functions bound to this event - var handlers = events[ type ], - special = jQuery.event.special[ type ] || {}; - - // Init the event handler queue - if ( !handlers ) { - handlers = events[ type ] = []; - - // Check for a special event handler - // Only use addEventListener/attachEvent if the special - // events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - // Bind the global event handler to the element - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add the function to the element's handler list - handlers.push( handleObj ); - - // Keep track of which events have been used, for global triggering - jQuery.event.global[ type ] = true; - } - - // Nullify elem to prevent memory leaks in IE - elem = null; - }, - - global: {}, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, pos ) { - // don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - if ( handler === false ) { - handler = returnFalse; - } - - var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, - elemData = jQuery.hasData( elem ) && jQuery._data( elem ), - events = elemData && elemData.events; - - if ( !elemData || !events ) { - return; - } - - // types is actually an event object here - if ( types && types.type ) { - handler = types.handler; - types = types.type; - } - - // Unbind all events for the element - if ( !types || typeof types === "string" && types.charAt(0) === "." ) { - types = types || ""; - - for ( type in events ) { - jQuery.event.remove( elem, type + types ); - } - - return; - } - - // Handle multiple events separated by a space - // jQuery(...).unbind("mouseover mouseout", fn); - types = types.split(" "); - - while ( (type = types[ i++ ]) ) { - origType = type; - handleObj = null; - all = type.indexOf(".") < 0; - namespaces = []; - - if ( !all ) { - // Namespaced event handlers - namespaces = type.split("."); - type = namespaces.shift(); - - namespace = new RegExp("(^|\\.)" + - jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - eventType = events[ type ]; - - if ( !eventType ) { - continue; - } - - if ( !handler ) { - for ( j = 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( all || namespace.test( handleObj.namespace ) ) { - jQuery.event.remove( elem, origType, handleObj.handler, j ); - eventType.splice( j--, 1 ); - } - } - - continue; - } - - special = jQuery.event.special[ type ] || {}; - - for ( j = pos || 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( handler.guid === handleObj.guid ) { - // remove the given handler for the given type - if ( all || namespace.test( handleObj.namespace ) ) { - if ( pos == null ) { - eventType.splice( j--, 1 ); - } - - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - - if ( pos != null ) { - break; - } - } - } - - // remove generic event handler if no more handlers exist - if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { - if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - - ret = null; - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - var handle = elemData.handle; - if ( handle ) { - handle.elem = null; - } - - delete elemData.events; - delete elemData.handle; - - if ( jQuery.isEmptyObject( elemData ) ) { - jQuery.removeData( elem, undefined, true ); - } - } - }, - - // bubbling is internal - trigger: function( event, data, elem /*, bubbling */ ) { - // Event object or event type - var type = event.type || event, - bubbling = arguments[3]; - - if ( !bubbling ) { - event = typeof event === "object" ? - // jQuery.Event object - event[ jQuery.expando ] ? event : - // Object literal - jQuery.extend( jQuery.Event(type), event ) : - // Just the event type (string) - jQuery.Event(type); - - if ( type.indexOf("!") >= 0 ) { - event.type = type = type.slice(0, -1); - event.exclusive = true; - } - - // Handle a global trigger - if ( !elem ) { - // Don't bubble custom events when global (to avoid too much overhead) - event.stopPropagation(); - - // Only trigger if we've ever bound an event for it - if ( jQuery.event.global[ type ] ) { - // XXX This code smells terrible. event.js should not be directly - // inspecting the data cache - jQuery.each( jQuery.cache, function() { - // internalKey variable is just used to make it easier to find - // and potentially change this stuff later; currently it just - // points to jQuery.expando - var internalKey = jQuery.expando, - internalCache = this[ internalKey ]; - if ( internalCache && internalCache.events && internalCache.events[ type ] ) { - jQuery.event.trigger( event, data, internalCache.handle.elem ); - } - }); - } - } - - // Handle triggering a single element - - // don't do events on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) { - return undefined; - } - - // Clean up in case it is reused - event.result = undefined; - event.target = elem; - - // Clone the incoming data, if any - data = jQuery.makeArray( data ); - data.unshift( event ); - } - - event.currentTarget = elem; - - // Trigger the event, it is assumed that "handle" is a function - var handle = jQuery._data( elem, "handle" ); - - if ( handle ) { - handle.apply( elem, data ); - } - - var parent = elem.parentNode || elem.ownerDocument; - - // Trigger an inline bound script - try { - if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) { - if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) { - event.result = false; - event.preventDefault(); - } - } - - // prevent IE from throwing an error for some elements with some event types, see #3533 - } catch (inlineError) {} - - if ( !event.isPropagationStopped() && parent ) { - jQuery.event.trigger( event, data, parent, true ); - - } else if ( !event.isDefaultPrevented() ) { - var old, - target = event.target, - targetType = type.replace( rnamespaces, "" ), - isClick = jQuery.nodeName( target, "a" ) && targetType === "click", - special = jQuery.event.special[ targetType ] || {}; - - if ( (!special._default || special._default.call( elem, event ) === false) && - !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) { - - try { - if ( target[ targetType ] ) { - // Make sure that we don't accidentally re-trigger the onFOO events - old = target[ "on" + targetType ]; - - if ( old ) { - target[ "on" + targetType ] = null; - } - - jQuery.event.triggered = true; - target[ targetType ](); - } - - // prevent IE from throwing an error for some elements with some event types, see #3533 - } catch (triggerError) {} - - if ( old ) { - target[ "on" + targetType ] = old; - } - - jQuery.event.triggered = false; - } - } - }, - - handle: function( event ) { - var all, handlers, namespaces, namespace_re, events, - namespace_sort = [], - args = jQuery.makeArray( arguments ); - - event = args[0] = jQuery.event.fix( event || window.event ); - event.currentTarget = this; - - // Namespaced event handlers - all = event.type.indexOf(".") < 0 && !event.exclusive; - - if ( !all ) { - namespaces = event.type.split("."); - event.type = namespaces.shift(); - namespace_sort = namespaces.slice(0).sort(); - namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - event.namespace = event.namespace || namespace_sort.join("."); - - events = jQuery._data(this, "events"); - - handlers = (events || {})[ event.type ]; - - if ( events && handlers ) { - // Clone the handlers to prevent manipulation - handlers = handlers.slice(0); - - for ( var j = 0, l = handlers.length; j < l; j++ ) { - var handleObj = handlers[ j ]; - - // Filter the functions by class - if ( all || namespace_re.test( handleObj.namespace ) ) { - // Pass in a reference to the handler function itself - // So that we can later remove it - event.handler = handleObj.handler; - event.data = handleObj.data; - event.handleObj = handleObj; - - var ret = handleObj.handler.apply( this, args ); - - if ( ret !== undefined ) { - event.result = ret; - if ( ret === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - - if ( event.isImmediatePropagationStopped() ) { - break; - } - } - } - } - - return event.result; - }, - - props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // store a copy of the original event object - // and "clone" to set read-only properties - var originalEvent = event; - event = jQuery.Event( originalEvent ); - - for ( var i = this.props.length, prop; i; ) { - prop = this.props[ --i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Fix target property, if necessary - if ( !event.target ) { - // Fixes #1925 where srcElement might not be defined either - event.target = event.srcElement || document; - } - - // check if target is a textnode (safari) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - // Add relatedTarget, if necessary - if ( !event.relatedTarget && event.fromElement ) { - event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; - } - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && event.clientX != null ) { - var doc = document.documentElement, - body = document.body; - - event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); - event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); - } - - // Add which for key events - if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { - event.which = event.charCode != null ? event.charCode : event.keyCode; - } - - // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) - if ( !event.metaKey && event.ctrlKey ) { - event.metaKey = event.ctrlKey; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && event.button !== undefined ) { - event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); - } - - return event; - }, - - // Deprecated, use jQuery.guid instead - guid: 1E8, - - // Deprecated, use jQuery.proxy instead - proxy: jQuery.proxy, - - special: { - ready: { - // Make sure the ready event is setup - setup: jQuery.bindReady, - teardown: jQuery.noop - }, - - live: { - add: function( handleObj ) { - jQuery.event.add( this, - liveConvert( handleObj.origType, handleObj.selector ), - jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); - }, - - remove: function( handleObj ) { - jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); - } - }, - - beforeunload: { - setup: function( data, namespaces, eventHandle ) { - // We only want to do this special case on windows - if ( jQuery.isWindow( this ) ) { - this.onbeforeunload = eventHandle; - } - }, - - teardown: function( namespaces, eventHandle ) { - if ( this.onbeforeunload === eventHandle ) { - this.onbeforeunload = null; - } - } - } - } -}; - -jQuery.removeEvent = document.removeEventListener ? - function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } - } : - function( elem, type, handle ) { - if ( elem.detachEvent ) { - elem.detachEvent( "on" + type, handle ); - } - }; - -jQuery.Event = function( src ) { - // Allow instantiation without the 'new' keyword - if ( !this.preventDefault ) { - return new jQuery.Event( src ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || - src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; - - // Event type - } else { - this.type = src; - } - - // timeStamp is buggy for some events on Firefox(#3843) - // So we won't rely on the native value - this.timeStamp = jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -function returnFalse() { - return false; -} -function returnTrue() { - return true; -} - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - preventDefault: function() { - this.isDefaultPrevented = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - - // if preventDefault exists run it on the original event - if ( e.preventDefault ) { - e.preventDefault(); - - // otherwise set the returnValue property of the original event to false (IE) - } else { - e.returnValue = false; - } - }, - stopPropagation: function() { - this.isPropagationStopped = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - // if stopPropagation exists run it on the original event - if ( e.stopPropagation ) { - e.stopPropagation(); - } - // otherwise set the cancelBubble property of the original event to true (IE) - e.cancelBubble = true; - }, - stopImmediatePropagation: function() { - this.isImmediatePropagationStopped = returnTrue; - this.stopPropagation(); - }, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse -}; - -// Checks if an event happened on an element within another element -// Used in jQuery.event.special.mouseenter and mouseleave handlers -var withinElement = function( event ) { - // Check if mouse(over|out) are still within the same parent element - var parent = event.relatedTarget; - - // Firefox sometimes assigns relatedTarget a XUL element - // which we cannot access the parentNode property of - try { - - // Chrome does something similar, the parentNode property - // can be accessed but is null. - if ( parent !== document && !parent.parentNode ) { - return; - } - // Traverse up the tree - while ( parent && parent !== this ) { - parent = parent.parentNode; - } - - if ( parent !== this ) { - // set the correct event type - event.type = event.data; - - // handle event if we actually just moused on to a non sub-element - jQuery.event.handle.apply( this, arguments ); - } - - // assuming we've left the element since we most likely mousedover a xul element - } catch(e) { } -}, - -// In case of event delegation, we only need to rename the event.type, -// liveHandler will take care of the rest. -delegate = function( event ) { - event.type = event.data; - jQuery.event.handle.apply( this, arguments ); -}; - -// Create mouseenter and mouseleave events -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - setup: function( data ) { - jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); - }, - teardown: function( data ) { - jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); - } - }; -}); - -// submit delegation -if ( !jQuery.support.submitBubbles ) { - - jQuery.event.special.submit = { - setup: function( data, namespaces ) { - if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) { - jQuery.event.add(this, "click.specialSubmit", function( e ) { - var elem = e.target, - type = elem.type; - - if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { - trigger( "submit", this, arguments ); - } - }); - - jQuery.event.add(this, "keypress.specialSubmit", function( e ) { - var elem = e.target, - type = elem.type; - - if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { - trigger( "submit", this, arguments ); - } - }); - - } else { - return false; - } - }, - - teardown: function( namespaces ) { - jQuery.event.remove( this, ".specialSubmit" ); - } - }; - -} - -// change delegation, happens here so we have bind. -if ( !jQuery.support.changeBubbles ) { - - var changeFilters, - - getVal = function( elem ) { - var type = elem.type, val = elem.value; - - if ( type === "radio" || type === "checkbox" ) { - val = elem.checked; - - } else if ( type === "select-multiple" ) { - val = elem.selectedIndex > -1 ? - jQuery.map( elem.options, function( elem ) { - return elem.selected; - }).join("-") : - ""; - - } else if ( elem.nodeName.toLowerCase() === "select" ) { - val = elem.selectedIndex; - } - - return val; - }, - - testChange = function testChange( e ) { - var elem = e.target, data, val; - - if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { - return; - } - - data = jQuery._data( elem, "_change_data" ); - val = getVal(elem); - - // the current data will be also retrieved by beforeactivate - if ( e.type !== "focusout" || elem.type !== "radio" ) { - jQuery._data( elem, "_change_data", val ); - } - - if ( data === undefined || val === data ) { - return; - } - - if ( data != null || val ) { - e.type = "change"; - e.liveFired = undefined; - jQuery.event.trigger( e, arguments[1], elem ); - } - }; - - jQuery.event.special.change = { - filters: { - focusout: testChange, - - beforedeactivate: testChange, - - click: function( e ) { - var elem = e.target, type = elem.type; - - if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) { - testChange.call( this, e ); - } - }, - - // Change has to be called before submit - // Keydown will be called before keypress, which is used in submit-event delegation - keydown: function( e ) { - var elem = e.target, type = elem.type; - - if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") || - (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || - type === "select-multiple" ) { - testChange.call( this, e ); - } - }, - - // Beforeactivate happens also before the previous element is blurred - // with this event you can't trigger a change event, but you can store - // information - beforeactivate: function( e ) { - var elem = e.target; - jQuery._data( elem, "_change_data", getVal(elem) ); - } - }, - - setup: function( data, namespaces ) { - if ( this.type === "file" ) { - return false; - } - - for ( var type in changeFilters ) { - jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); - } - - return rformElems.test( this.nodeName ); - }, - - teardown: function( namespaces ) { - jQuery.event.remove( this, ".specialChange" ); - - return rformElems.test( this.nodeName ); - } - }; - - changeFilters = jQuery.event.special.change.filters; - - // Handle when the input is .focus()'d - changeFilters.focus = changeFilters.beforeactivate; -} - -function trigger( type, elem, args ) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - // Don't pass args or remember liveFired; they apply to the donor event. - var event = jQuery.extend( {}, args[ 0 ] ); - event.type = type; - event.originalEvent = {}; - event.liveFired = undefined; - jQuery.event.handle.call( elem, event ); - if ( event.isDefaultPrevented() ) { - args[ 0 ].preventDefault(); - } -} - -// Create "bubbling" focus and blur events -if ( document.addEventListener ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - jQuery.event.special[ fix ] = { - setup: function() { - this.addEventListener( orig, handler, true ); - }, - teardown: function() { - this.removeEventListener( orig, handler, true ); - } - }; - - function handler( e ) { - e = jQuery.event.fix( e ); - e.type = fix; - return jQuery.event.handle.call( this, e ); - } - }); -} - -jQuery.each(["bind", "one"], function( i, name ) { - jQuery.fn[ name ] = function( type, data, fn ) { - // Handle object literals - if ( typeof type === "object" ) { - for ( var key in type ) { - this[ name ](key, data, type[key], fn); - } - return this; - } - - if ( jQuery.isFunction( data ) || data === false ) { - fn = data; - data = undefined; - } - - var handler = name === "one" ? jQuery.proxy( fn, function( event ) { - jQuery( this ).unbind( event, handler ); - return fn.apply( this, arguments ); - }) : fn; - - if ( type === "unload" && name !== "one" ) { - this.one( type, data, fn ); - - } else { - for ( var i = 0, l = this.length; i < l; i++ ) { - jQuery.event.add( this[i], type, handler, data ); - } - } - - return this; - }; -}); - -jQuery.fn.extend({ - unbind: function( type, fn ) { - // Handle object literals - if ( typeof type === "object" && !type.preventDefault ) { - for ( var key in type ) { - this.unbind(key, type[key]); - } - - } else { - for ( var i = 0, l = this.length; i < l; i++ ) { - jQuery.event.remove( this[i], type, fn ); - } - } - - return this; - }, - - delegate: function( selector, types, data, fn ) { - return this.live( types, data, fn, selector ); - }, - - undelegate: function( selector, types, fn ) { - if ( arguments.length === 0 ) { - return this.unbind( "live" ); - - } else { - return this.die( types, null, fn, selector ); - } - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - - triggerHandler: function( type, data ) { - if ( this[0] ) { - var event = jQuery.Event( type ); - event.preventDefault(); - event.stopPropagation(); - jQuery.event.trigger( event, data, this[0] ); - return event.result; - } - }, - - toggle: function( fn ) { - // Save reference to arguments for access in closure - var args = arguments, - i = 1; - - // link all the functions, so any of them can unbind this click handler - while ( i < args.length ) { - jQuery.proxy( fn, args[ i++ ] ); - } - - return this.click( jQuery.proxy( fn, function( event ) { - // Figure out which function to execute - var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; - jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); - - // Make sure that clicks stop - event.preventDefault(); - - // and execute the function - return args[ lastToggle ].apply( this, arguments ) || false; - })); - }, - - hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); - } -}); - -var liveMap = { - focus: "focusin", - blur: "focusout", - mouseenter: "mouseover", - mouseleave: "mouseout" -}; - -jQuery.each(["live", "die"], function( i, name ) { - jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { - var type, i = 0, match, namespaces, preType, - selector = origSelector || this.selector, - context = origSelector ? this : jQuery( this.context ); - - if ( typeof types === "object" && !types.preventDefault ) { - for ( var key in types ) { - context[ name ]( key, data, types[key], selector ); - } - - return this; - } - - if ( jQuery.isFunction( data ) ) { - fn = data; - data = undefined; - } - - types = (types || "").split(" "); - - while ( (type = types[ i++ ]) != null ) { - match = rnamespaces.exec( type ); - namespaces = ""; - - if ( match ) { - namespaces = match[0]; - type = type.replace( rnamespaces, "" ); - } - - if ( type === "hover" ) { - types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); - continue; - } - - preType = type; - - if ( type === "focus" || type === "blur" ) { - types.push( liveMap[ type ] + namespaces ); - type = type + namespaces; - - } else { - type = (liveMap[ type ] || type) + namespaces; - } - - if ( name === "live" ) { - // bind live handler - for ( var j = 0, l = context.length; j < l; j++ ) { - jQuery.event.add( context[j], "live." + liveConvert( type, selector ), - { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); - } - - } else { - // unbind live handler - context.unbind( "live." + liveConvert( type, selector ), fn ); - } - } - - return this; - }; -}); - -function liveHandler( event ) { - var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, - elems = [], - selectors = [], - events = jQuery._data( this, "events" ); - - // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) - if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { - return; - } - - if ( event.namespace ) { - namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); - } - - event.liveFired = this; - - var live = events.live.slice(0); - - for ( j = 0; j < live.length; j++ ) { - handleObj = live[j]; - - if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { - selectors.push( handleObj.selector ); - - } else { - live.splice( j--, 1 ); - } - } - - match = jQuery( event.target ).closest( selectors, event.currentTarget ); - - for ( i = 0, l = match.length; i < l; i++ ) { - close = match[i]; - - for ( j = 0; j < live.length; j++ ) { - handleObj = live[j]; - - if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { - elem = close.elem; - related = null; - - // Those two events require additional checking - if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { - event.type = handleObj.preType; - related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; - } - - if ( !related || related !== elem ) { - elems.push({ elem: elem, handleObj: handleObj, level: close.level }); - } - } - } - } - - for ( i = 0, l = elems.length; i < l; i++ ) { - match = elems[i]; - - if ( maxLevel && match.level > maxLevel ) { - break; - } - - event.currentTarget = match.elem; - event.data = match.handleObj.data; - event.handleObj = match.handleObj; - - ret = match.handleObj.origHandler.apply( match.elem, arguments ); - - if ( ret === false || event.isPropagationStopped() ) { - maxLevel = match.level; - - if ( ret === false ) { - stop = false; - } - if ( event.isImmediatePropagationStopped() ) { - break; - } - } - } - - return stop; -} - -function liveConvert( type, selector ) { - return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&"); -} - -jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup error").split(" "), function( i, name ) { - - // Handle event binding - jQuery.fn[ name ] = function( data, fn ) { - if ( fn == null ) { - fn = data; - data = null; - } - - return arguments.length > 0 ? - this.bind( name, data, fn ) : - this.trigger( name ); - }; - - if ( jQuery.attrFn ) { - jQuery.attrFn[ name ] = true; - } -}); - - -/*! - * Sizzle CSS Selector Engine - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){ - -var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, - done = 0, - toString = Object.prototype.toString, - hasDuplicate = false, - baseHasDuplicate = true, - rBackslash = /\\/g, - rNonWord = /\W/; - -// Here we check if the JavaScript engine is using some sort of -// optimization where it does not always call our comparision -// function. If that is the case, discard the hasDuplicate value. -// Thus far that includes Google Chrome. -[0, 0].sort(function() { - baseHasDuplicate = false; - return 0; -}); - -var Sizzle = function( selector, context, results, seed ) { - results = results || []; - context = context || document; - - var origContext = context; - - if ( context.nodeType !== 1 && context.nodeType !== 9 ) { - return []; - } - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - var m, set, checkSet, extra, ret, cur, pop, i, - prune = true, - contextXML = Sizzle.isXML( context ), - parts = [], - soFar = selector; - - // Reset the position of the chunker regexp (start from head) - do { - chunker.exec( "" ); - m = chunker.exec( soFar ); - - if ( m ) { - soFar = m[3]; - - parts.push( m[1] ); - - if ( m[2] ) { - extra = m[3]; - break; - } - } - } while ( m ); - - if ( parts.length > 1 && origPOS.exec( selector ) ) { - - if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { - set = posProcess( parts[0] + parts[1], context ); - - } else { - set = Expr.relative[ parts[0] ] ? - [ context ] : - Sizzle( parts.shift(), context ); - - while ( parts.length ) { - selector = parts.shift(); - - if ( Expr.relative[ selector ] ) { - selector += parts.shift(); - } - - set = posProcess( selector, set ); - } - } - - } else { - // Take a shortcut and set the context if the root selector is an ID - // (but not if it'll be faster if the inner selector is an ID) - if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && - Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { - - ret = Sizzle.find( parts.shift(), context, contextXML ); - context = ret.expr ? - Sizzle.filter( ret.expr, ret.set )[0] : - ret.set[0]; - } - - if ( context ) { - ret = seed ? - { expr: parts.pop(), set: makeArray(seed) } : - Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); - - set = ret.expr ? - Sizzle.filter( ret.expr, ret.set ) : - ret.set; - - if ( parts.length > 0 ) { - checkSet = makeArray( set ); - - } else { - prune = false; - } - - while ( parts.length ) { - cur = parts.pop(); - pop = cur; - - if ( !Expr.relative[ cur ] ) { - cur = ""; - } else { - pop = parts.pop(); - } - - if ( pop == null ) { - pop = context; - } - - Expr.relative[ cur ]( checkSet, pop, contextXML ); - } - - } else { - checkSet = parts = []; - } - } - - if ( !checkSet ) { - checkSet = set; - } - - if ( !checkSet ) { - Sizzle.error( cur || selector ); - } - - if ( toString.call(checkSet) === "[object Array]" ) { - if ( !prune ) { - results.push.apply( results, checkSet ); - - } else if ( context && context.nodeType === 1 ) { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { - results.push( set[i] ); - } - } - - } else { - for ( i = 0; checkSet[i] != null; i++ ) { - if ( checkSet[i] && checkSet[i].nodeType === 1 ) { - results.push( set[i] ); - } - } - } - - } else { - makeArray( checkSet, results ); - } - - if ( extra ) { - Sizzle( extra, origContext, results, seed ); - Sizzle.uniqueSort( results ); - } - - return results; -}; - -Sizzle.uniqueSort = function( results ) { - if ( sortOrder ) { - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( var i = 1; i < results.length; i++ ) { - if ( results[i] === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - } - - return results; -}; - -Sizzle.matches = function( expr, set ) { - return Sizzle( expr, null, null, set ); -}; - -Sizzle.matchesSelector = function( node, expr ) { - return Sizzle( expr, null, null, [node] ).length > 0; -}; - -Sizzle.find = function( expr, context, isXML ) { - var set; - - if ( !expr ) { - return []; - } - - for ( var i = 0, l = Expr.order.length; i < l; i++ ) { - var match, - type = Expr.order[i]; - - if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { - var left = match[1]; - match.splice( 1, 1 ); - - if ( left.substr( left.length - 1 ) !== "\\" ) { - match[1] = (match[1] || "").replace( rBackslash, "" ); - set = Expr.find[ type ]( match, context, isXML ); - - if ( set != null ) { - expr = expr.replace( Expr.match[ type ], "" ); - break; - } - } - } - } - - if ( !set ) { - set = typeof context.getElementsByTagName !== "undefined" ? - context.getElementsByTagName( "*" ) : - []; - } - - return { set: set, expr: expr }; -}; - -Sizzle.filter = function( expr, set, inplace, not ) { - var match, anyFound, - old = expr, - result = [], - curLoop = set, - isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); - - while ( expr && set.length ) { - for ( var type in Expr.filter ) { - if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { - var found, item, - filter = Expr.filter[ type ], - left = match[1]; - - anyFound = false; - - match.splice(1,1); - - if ( left.substr( left.length - 1 ) === "\\" ) { - continue; - } - - if ( curLoop === result ) { - result = []; - } - - if ( Expr.preFilter[ type ] ) { - match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); - - if ( !match ) { - anyFound = found = true; - - } else if ( match === true ) { - continue; - } - } - - if ( match ) { - for ( var i = 0; (item = curLoop[i]) != null; i++ ) { - if ( item ) { - found = filter( item, match, i, curLoop ); - var pass = not ^ !!found; - - if ( inplace && found != null ) { - if ( pass ) { - anyFound = true; - - } else { - curLoop[i] = false; - } - - } else if ( pass ) { - result.push( item ); - anyFound = true; - } - } - } - } - - if ( found !== undefined ) { - if ( !inplace ) { - curLoop = result; - } - - expr = expr.replace( Expr.match[ type ], "" ); - - if ( !anyFound ) { - return []; - } - - break; - } - } - } - - // Improper expression - if ( expr === old ) { - if ( anyFound == null ) { - Sizzle.error( expr ); - - } else { - break; - } - } - - old = expr; - } - - return curLoop; -}; - -Sizzle.error = function( msg ) { - throw "Syntax error, unrecognized expression: " + msg; -}; - -var Expr = Sizzle.selectors = { - order: [ "ID", "NAME", "TAG" ], - - match: { - ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, - NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, - ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, - TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, - CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, - POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, - PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ - }, - - leftMatch: {}, - - attrMap: { - "class": "className", - "for": "htmlFor" - }, - - attrHandle: { - href: function( elem ) { - return elem.getAttribute( "href" ); - }, - type: function( elem ) { - return elem.getAttribute( "type" ); - } - }, - - relative: { - "+": function(checkSet, part){ - var isPartStr = typeof part === "string", - isTag = isPartStr && !rNonWord.test( part ), - isPartStrNotTag = isPartStr && !isTag; - - if ( isTag ) { - part = part.toLowerCase(); - } - - for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { - if ( (elem = checkSet[i]) ) { - while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} - - checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? - elem || false : - elem === part; - } - } - - if ( isPartStrNotTag ) { - Sizzle.filter( part, checkSet, true ); - } - }, - - ">": function( checkSet, part ) { - var elem, - isPartStr = typeof part === "string", - i = 0, - l = checkSet.length; - - if ( isPartStr && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - var parent = elem.parentNode; - checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; - } - } - - } else { - for ( ; i < l; i++ ) { - elem = checkSet[i]; - - if ( elem ) { - checkSet[i] = isPartStr ? - elem.parentNode : - elem.parentNode === part; - } - } - - if ( isPartStr ) { - Sizzle.filter( part, checkSet, true ); - } - } - }, - - "": function(checkSet, part, isXML){ - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); - }, - - "~": function( checkSet, part, isXML ) { - var nodeCheck, - doneName = done++, - checkFn = dirCheck; - - if ( typeof part === "string" && !rNonWord.test( part ) ) { - part = part.toLowerCase(); - nodeCheck = part; - checkFn = dirNodeCheck; - } - - checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); - } - }, - - find: { - ID: function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - }, - - NAME: function( match, context ) { - if ( typeof context.getElementsByName !== "undefined" ) { - var ret = [], - results = context.getElementsByName( match[1] ); - - for ( var i = 0, l = results.length; i < l; i++ ) { - if ( results[i].getAttribute("name") === match[1] ) { - ret.push( results[i] ); - } - } - - return ret.length === 0 ? null : ret; - } - }, - - TAG: function( match, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( match[1] ); - } - } - }, - preFilter: { - CLASS: function( match, curLoop, inplace, result, not, isXML ) { - match = " " + match[1].replace( rBackslash, "" ) + " "; - - if ( isXML ) { - return match; - } - - for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { - if ( elem ) { - if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { - if ( !inplace ) { - result.push( elem ); - } - - } else if ( inplace ) { - curLoop[i] = false; - } - } - } - - return false; - }, - - ID: function( match ) { - return match[1].replace( rBackslash, "" ); - }, - - TAG: function( match, curLoop ) { - return match[1].replace( rBackslash, "" ).toLowerCase(); - }, - - CHILD: function( match ) { - if ( match[1] === "nth" ) { - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - match[2] = match[2].replace(/^\+|\s*/g, ''); - - // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' - var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( - match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || - !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); - - // calculate the numbers (first)n+(last) including if they are negative - match[2] = (test[1] + (test[2] || 1)) - 0; - match[3] = test[3] - 0; - } - else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - // TODO: Move to normal caching system - match[0] = done++; - - return match; - }, - - ATTR: function( match, curLoop, inplace, result, not, isXML ) { - var name = match[1] = match[1].replace( rBackslash, "" ); - - if ( !isXML && Expr.attrMap[name] ) { - match[1] = Expr.attrMap[name]; - } - - // Handle if an un-quoted value was used - match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); - - if ( match[2] === "~=" ) { - match[4] = " " + match[4] + " "; - } - - return match; - }, - - PSEUDO: function( match, curLoop, inplace, result, not ) { - if ( match[1] === "not" ) { - // If we're dealing with a complex expression, or a simple one - if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { - match[3] = Sizzle(match[3], null, null, curLoop); - - } else { - var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); - - if ( !inplace ) { - result.push.apply( result, ret ); - } - - return false; - } - - } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { - return true; - } - - return match; - }, - - POS: function( match ) { - match.unshift( true ); - - return match; - } - }, - - filters: { - enabled: function( elem ) { - return elem.disabled === false && elem.type !== "hidden"; - }, - - disabled: function( elem ) { - return elem.disabled === true; - }, - - checked: function( elem ) { - return elem.checked === true; - }, - - selected: function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - parent: function( elem ) { - return !!elem.firstChild; - }, - - empty: function( elem ) { - return !elem.firstChild; - }, - - has: function( elem, i, match ) { - return !!Sizzle( match[3], elem ).length; - }, - - header: function( elem ) { - return (/h\d/i).test( elem.nodeName ); - }, - - text: function( elem ) { - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return "text" === elem.getAttribute( 'type' ); - }, - radio: function( elem ) { - return "radio" === elem.type; - }, - - checkbox: function( elem ) { - return "checkbox" === elem.type; - }, - - file: function( elem ) { - return "file" === elem.type; - }, - password: function( elem ) { - return "password" === elem.type; - }, - - submit: function( elem ) { - return "submit" === elem.type; - }, - - image: function( elem ) { - return "image" === elem.type; - }, - - reset: function( elem ) { - return "reset" === elem.type; - }, - - button: function( elem ) { - return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; - }, - - input: function( elem ) { - return (/input|select|textarea|button/i).test( elem.nodeName ); - } - }, - setFilters: { - first: function( elem, i ) { - return i === 0; - }, - - last: function( elem, i, match, array ) { - return i === array.length - 1; - }, - - even: function( elem, i ) { - return i % 2 === 0; - }, - - odd: function( elem, i ) { - return i % 2 === 1; - }, - - lt: function( elem, i, match ) { - return i < match[3] - 0; - }, - - gt: function( elem, i, match ) { - return i > match[3] - 0; - }, - - nth: function( elem, i, match ) { - return match[3] - 0 === i; - }, - - eq: function( elem, i, match ) { - return match[3] - 0 === i; - } - }, - filter: { - PSEUDO: function( elem, match, i, array ) { - var name = match[1], - filter = Expr.filters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - - } else if ( name === "contains" ) { - return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; - - } else if ( name === "not" ) { - var not = match[3]; - - for ( var j = 0, l = not.length; j < l; j++ ) { - if ( not[j] === elem ) { - return false; - } - } - - return true; - - } else { - Sizzle.error( name ); - } - }, - - CHILD: function( elem, match ) { - var type = match[1], - node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - - case "nth": - var first = match[2], - last = match[3]; - - if ( first === 1 && last === 0 ) { - return true; - } - - var doneName = match[0], - parent = elem.parentNode; - - if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { - var count = 0; - - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - node.nodeIndex = ++count; - } - } - - parent.sizcache = doneName; - } - - var diff = elem.nodeIndex - last; - - if ( first === 0 ) { - return diff === 0; - - } else { - return ( diff % first === 0 && diff / first >= 0 ); - } - } - }, - - ID: function( elem, match ) { - return elem.nodeType === 1 && elem.getAttribute("id") === match; - }, - - TAG: function( elem, match ) { - return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; - }, - - CLASS: function( elem, match ) { - return (" " + (elem.className || elem.getAttribute("class")) + " ") - .indexOf( match ) > -1; - }, - - ATTR: function( elem, match ) { - var name = match[1], - result = Expr.attrHandle[ name ] ? - Expr.attrHandle[ name ]( elem ) : - elem[ name ] != null ? - elem[ name ] : - elem.getAttribute( name ), - value = result + "", - type = match[2], - check = match[4]; - - return result == null ? - type === "!=" : - type === "=" ? - value === check : - type === "*=" ? - value.indexOf(check) >= 0 : - type === "~=" ? - (" " + value + " ").indexOf(check) >= 0 : - !check ? - value && result !== false : - type === "!=" ? - value !== check : - type === "^=" ? - value.indexOf(check) === 0 : - type === "$=" ? - value.substr(value.length - check.length) === check : - type === "|=" ? - value === check || value.substr(0, check.length + 1) === check + "-" : - false; - }, - - POS: function( elem, match, i, array ) { - var name = match[2], - filter = Expr.setFilters[ name ]; - - if ( filter ) { - return filter( elem, i, match, array ); - } - } - } -}; - -var origPOS = Expr.match.POS, - fescape = function(all, num){ - return "\\" + (num - 0 + 1); - }; - -for ( var type in Expr.match ) { - Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); - Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); -} - -var makeArray = function( array, results ) { - array = Array.prototype.slice.call( array, 0 ); - - if ( results ) { - results.push.apply( results, array ); - return results; - } - - return array; -}; - -// Perform a simple check to determine if the browser is capable of -// converting a NodeList to an array using builtin methods. -// Also verifies that the returned array holds DOM nodes -// (which is not the case in the Blackberry browser) -try { - Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; - -// Provide a fallback method if it does not work -} catch( e ) { - makeArray = function( array, results ) { - var i = 0, - ret = results || []; - - if ( toString.call(array) === "[object Array]" ) { - Array.prototype.push.apply( ret, array ); - - } else { - if ( typeof array.length === "number" ) { - for ( var l = array.length; i < l; i++ ) { - ret.push( array[i] ); - } - - } else { - for ( ; array[i]; i++ ) { - ret.push( array[i] ); - } - } - } - - return ret; - }; -} - -var sortOrder, siblingCheck; - -if ( document.documentElement.compareDocumentPosition ) { - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { - return a.compareDocumentPosition ? -1 : 1; - } - - return a.compareDocumentPosition(b) & 4 ? -1 : 1; - }; - -} else { - sortOrder = function( a, b ) { - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // If the nodes are siblings (or identical) we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - - siblingCheck = function( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; - }; -} - -// Utility function for retreiving the text value of an array of DOM nodes -Sizzle.getText = function( elems ) { - var ret = "", elem; - - for ( var i = 0; elems[i]; i++ ) { - elem = elems[i]; - - // Get the text from text nodes and CDATA nodes - if ( elem.nodeType === 3 || elem.nodeType === 4 ) { - ret += elem.nodeValue; - - // Traverse everything else, except comment nodes - } else if ( elem.nodeType !== 8 ) { - ret += Sizzle.getText( elem.childNodes ); - } - } - - return ret; -}; - -// Check to see if the browser returns elements by name when -// querying by getElementById (and provide a workaround) -(function(){ - // We're going to inject a fake input element with a specified name - var form = document.createElement("div"), - id = "script" + (new Date()).getTime(), - root = document.documentElement; - - form.innerHTML = ""; - - // Inject it into the root element, check its status, and remove it quickly - root.insertBefore( form, root.firstChild ); - - // The workaround has to do additional checks after a getElementById - // Which slows things down for other browsers (hence the branching) - if ( document.getElementById( id ) ) { - Expr.find.ID = function( match, context, isXML ) { - if ( typeof context.getElementById !== "undefined" && !isXML ) { - var m = context.getElementById(match[1]); - - return m ? - m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? - [m] : - undefined : - []; - } - }; - - Expr.filter.ID = function( elem, match ) { - var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); - - return elem.nodeType === 1 && node && node.nodeValue === match; - }; - } - - root.removeChild( form ); - - // release memory in IE - root = form = null; -})(); - -(function(){ - // Check to see if the browser returns only elements - // when doing getElementsByTagName("*") - - // Create a fake element - var div = document.createElement("div"); - div.appendChild( document.createComment("") ); - - // Make sure no comments are found - if ( div.getElementsByTagName("*").length > 0 ) { - Expr.find.TAG = function( match, context ) { - var results = context.getElementsByTagName( match[1] ); - - // Filter out possible comments - if ( match[1] === "*" ) { - var tmp = []; - - for ( var i = 0; results[i]; i++ ) { - if ( results[i].nodeType === 1 ) { - tmp.push( results[i] ); - } - } - - results = tmp; - } - - return results; - }; - } - - // Check to see if an attribute returns normalized href attributes - div.innerHTML = ""; - - if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && - div.firstChild.getAttribute("href") !== "#" ) { - - Expr.attrHandle.href = function( elem ) { - return elem.getAttribute( "href", 2 ); - }; - } - - // release memory in IE - div = null; -})(); - -if ( document.querySelectorAll ) { - (function(){ - var oldSizzle = Sizzle, - div = document.createElement("div"), - id = "__sizzle__"; - - div.innerHTML = "

                                                                                                                                      "; - - // Safari can't handle uppercase or unicode characters when - // in quirks mode. - if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { - return; - } - - Sizzle = function( query, context, extra, seed ) { - context = context || document; - - // Only use querySelectorAll on non-XML documents - // (ID selectors don't work in non-HTML documents) - if ( !seed && !Sizzle.isXML(context) ) { - // See if we find a selector to speed up - var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); - - if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { - // Speed-up: Sizzle("TAG") - if ( match[1] ) { - return makeArray( context.getElementsByTagName( query ), extra ); - - // Speed-up: Sizzle(".CLASS") - } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { - return makeArray( context.getElementsByClassName( match[2] ), extra ); - } - } - - if ( context.nodeType === 9 ) { - // Speed-up: Sizzle("body") - // The body element only exists once, optimize finding it - if ( query === "body" && context.body ) { - return makeArray( [ context.body ], extra ); - - // Speed-up: Sizzle("#ID") - } else if ( match && match[3] ) { - var elem = context.getElementById( match[3] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id === match[3] ) { - return makeArray( [ elem ], extra ); - } - - } else { - return makeArray( [], extra ); - } - } - - try { - return makeArray( context.querySelectorAll(query), extra ); - } catch(qsaError) {} - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - var oldContext = context, - old = context.getAttribute( "id" ), - nid = old || id, - hasParent = context.parentNode, - relativeHierarchySelector = /^\s*[+~]/.test( query ); - - if ( !old ) { - context.setAttribute( "id", nid ); - } else { - nid = nid.replace( /'/g, "\\$&" ); - } - if ( relativeHierarchySelector && hasParent ) { - context = context.parentNode; - } - - try { - if ( !relativeHierarchySelector || hasParent ) { - return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); - } - - } catch(pseudoError) { - } finally { - if ( !old ) { - oldContext.removeAttribute( "id" ); - } - } - } - } - - return oldSizzle(query, context, extra, seed); - }; - - for ( var prop in oldSizzle ) { - Sizzle[ prop ] = oldSizzle[ prop ]; - } - - // release memory in IE - div = null; - })(); -} - -(function(){ - var html = document.documentElement, - matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector, - pseudoWorks = false; - - try { - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( document.documentElement, "[test!='']:sizzle" ); - - } catch( pseudoError ) { - pseudoWorks = true; - } - - if ( matches ) { - Sizzle.matchesSelector = function( node, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); - - if ( !Sizzle.isXML( node ) ) { - try { - if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { - return matches.call( node, expr ); - } - } catch(e) {} - } - - return Sizzle(expr, null, null, [node]).length > 0; - }; - } -})(); - -(function(){ - var div = document.createElement("div"); - - div.innerHTML = "
                                                                                                                                      "; - - // Opera can't find a second classname (in 9.6) - // Also, make sure that getElementsByClassName actually exists - if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { - return; - } - - // Safari caches class attributes, doesn't catch changes (in 3.2) - div.lastChild.className = "e"; - - if ( div.getElementsByClassName("e").length === 1 ) { - return; - } - - Expr.order.splice(1, 0, "CLASS"); - Expr.find.CLASS = function( match, context, isXML ) { - if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { - return context.getElementsByClassName(match[1]); - } - }; - - // release memory in IE - div = null; -})(); - -function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 && !isXML ){ - elem.sizcache = doneName; - elem.sizset = i; - } - - if ( elem.nodeName.toLowerCase() === cur ) { - match = elem; - break; - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { - for ( var i = 0, l = checkSet.length; i < l; i++ ) { - var elem = checkSet[i]; - - if ( elem ) { - var match = false; - - elem = elem[dir]; - - while ( elem ) { - if ( elem.sizcache === doneName ) { - match = checkSet[elem.sizset]; - break; - } - - if ( elem.nodeType === 1 ) { - if ( !isXML ) { - elem.sizcache = doneName; - elem.sizset = i; - } - - if ( typeof cur !== "string" ) { - if ( elem === cur ) { - match = true; - break; - } - - } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { - match = elem; - break; - } - } - - elem = elem[dir]; - } - - checkSet[i] = match; - } - } -} - -if ( document.documentElement.contains ) { - Sizzle.contains = function( a, b ) { - return a !== b && (a.contains ? a.contains(b) : true); - }; - -} else if ( document.documentElement.compareDocumentPosition ) { - Sizzle.contains = function( a, b ) { - return !!(a.compareDocumentPosition(b) & 16); - }; - -} else { - Sizzle.contains = function() { - return false; - }; -} - -Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; - - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -var posProcess = function( selector, context ) { - var match, - tmpSet = [], - later = "", - root = context.nodeType ? [context] : context; - - // Position selectors must be done after the filter - // And so must :not(positional) so we move all PSEUDOs to the end - while ( (match = Expr.match.PSEUDO.exec( selector )) ) { - later += match[0]; - selector = selector.replace( Expr.match.PSEUDO, "" ); - } - - selector = Expr.relative[selector] ? selector + "*" : selector; - - for ( var i = 0, l = root.length; i < l; i++ ) { - Sizzle( selector, root[i], tmpSet ); - } - - return Sizzle.filter( later, tmpSet ); -}; - -// EXPOSE -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.filters; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - -})(); - - -var runtil = /Until$/, - rparentsprev = /^(?:parents|prevUntil|prevAll)/, - // Note: This RegExp should be improved, or likely pulled from Sizzle - rmultiselector = /,/, - isSimple = /^.[^:#\[\.,]*$/, - slice = Array.prototype.slice, - POS = jQuery.expr.match.POS, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend({ - find: function( selector ) { - var ret = this.pushStack( "", "find", selector ), - length = 0; - - for ( var i = 0, l = this.length; i < l; i++ ) { - length = ret.length; - jQuery.find( selector, this[i], ret ); - - if ( i > 0 ) { - // Make sure that the results are unique - for ( var n = length; n < ret.length; n++ ) { - for ( var r = 0; r < length; r++ ) { - if ( ret[r] === ret[n] ) { - ret.splice(n--, 1); - break; - } - } - } - } - } - - return ret; - }, - - has: function( target ) { - var targets = jQuery( target ); - return this.filter(function() { - for ( var i = 0, l = targets.length; i < l; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, - - not: function( selector ) { - return this.pushStack( winnow(this, selector, false), "not", selector); - }, - - filter: function( selector ) { - return this.pushStack( winnow(this, selector, true), "filter", selector ); - }, - - is: function( selector ) { - return !!selector && jQuery.filter( selector, this ).length > 0; - }, - - closest: function( selectors, context ) { - var ret = [], i, l, cur = this[0]; - - if ( jQuery.isArray( selectors ) ) { - var match, selector, - matches = {}, - level = 1; - - if ( cur && selectors.length ) { - for ( i = 0, l = selectors.length; i < l; i++ ) { - selector = selectors[i]; - - if ( !matches[selector] ) { - matches[selector] = jQuery.expr.match.POS.test( selector ) ? - jQuery( selector, context || this.context ) : - selector; - } - } - - while ( cur && cur.ownerDocument && cur !== context ) { - for ( selector in matches ) { - match = matches[selector]; - - if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) { - ret.push({ selector: selector, elem: cur, level: level }); - } - } - - cur = cur.parentNode; - level++; - } - } - - return ret; - } - - var pos = POS.test( selectors ) ? - jQuery( selectors, context || this.context ) : null; - - for ( i = 0, l = this.length; i < l; i++ ) { - cur = this[i]; - - while ( cur ) { - if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { - ret.push( cur ); - break; - - } else { - cur = cur.parentNode; - if ( !cur || !cur.ownerDocument || cur === context ) { - break; - } - } - } - } - - ret = ret.length > 1 ? jQuery.unique(ret) : ret; - - return this.pushStack( ret, "closest", selectors ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - if ( !elem || typeof elem === "string" ) { - return jQuery.inArray( this[0], - // If it receives a string, the selector is used - // If it receives nothing, the siblings are used - elem ? jQuery( elem ) : this.parent().children() ); - } - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[0] : elem, this ); - }, - - add: function( selector, context ) { - var set = typeof selector === "string" ? - jQuery( selector, context ) : - jQuery.makeArray( selector ), - all = jQuery.merge( this.get(), set ); - - return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? - all : - jQuery.unique( all ) ); - }, - - andSelf: function() { - return this.add( this.prevObject ); - } -}); - -// A painfully simple check to see if an element is disconnected -// from a document (should be improved, where feasible). -function isDisconnected( node ) { - return !node || !node.parentNode || node.parentNode.nodeType === 11; -} - -jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return jQuery.nth( elem, 2, "nextSibling" ); - }, - prev: function( elem ) { - return jQuery.nth( elem, 2, "previousSibling" ); - }, - nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return jQuery.sibling( elem.parentNode.firstChild, elem ); - }, - children: function( elem ) { - return jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return jQuery.nodeName( elem, "iframe" ) ? - elem.contentDocument || elem.contentWindow.document : - jQuery.makeArray( elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var ret = jQuery.map( this, fn, until ), - // The variable 'args' was introduced in - // https://github.com/jquery/jquery/commit/52a0238 - // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. - // http://code.google.com/p/v8/issues/detail?id=1050 - args = slice.call(arguments); - - if ( !runtil.test( name ) ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - ret = jQuery.filter( selector, ret ); - } - - ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; - - if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { - ret = ret.reverse(); - } - - return this.pushStack( ret, name, args.join(",") ); - }; -}); - -jQuery.extend({ - filter: function( expr, elems, not ) { - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 ? - jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : - jQuery.find.matches(expr, elems); - }, - - dir: function( elem, dir, until ) { - var matched = [], - cur = elem[ dir ]; - - while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { - if ( cur.nodeType === 1 ) { - matched.push( cur ); - } - cur = cur[dir]; - } - return matched; - }, - - nth: function( cur, result, dir, elem ) { - result = result || 1; - var num = 0; - - for ( ; cur; cur = cur[dir] ) { - if ( cur.nodeType === 1 && ++num === result ) { - break; - } - } - - return cur; - }, - - sibling: function( n, elem ) { - var r = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - r.push( n ); - } - } - - return r; - } -}); - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, keep ) { - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep(elements, function( elem, i ) { - var retVal = !!qualifier.call( elem, i, elem ); - return retVal === keep; - }); - - } else if ( qualifier.nodeType ) { - return jQuery.grep(elements, function( elem, i ) { - return (elem === qualifier) === keep; - }); - - } else if ( typeof qualifier === "string" ) { - var filtered = jQuery.grep(elements, function( elem ) { - return elem.nodeType === 1; - }); - - if ( isSimple.test( qualifier ) ) { - return jQuery.filter(qualifier, filtered, !keep); - } else { - qualifier = jQuery.filter( qualifier, filtered ); - } - } - - return jQuery.grep(elements, function( elem, i ) { - return (jQuery.inArray( elem, qualifier ) >= 0) === keep; - }); -} - - - - -var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, - rtagName = /<([\w:]+)/, - rtbody = /", "" ], - legend: [ 1, "
                                                                                                                                      ", "
                                                                                                                                      " ], - thead: [ 1, "", "
                                                                                                                                      " ], - tr: [ 2, "", "
                                                                                                                                      " ], - td: [ 3, "", "
                                                                                                                                      " ], - col: [ 2, "", "
                                                                                                                                      " ], - area: [ 1, "", "" ], - _default: [ 0, "", "" ] - }; - -wrapMap.optgroup = wrapMap.option; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// IE can't serialize and