VE_Ajax - Version 1.0.0.1

Version Notes

Ajax Filter and Cart

Download this release

Release Info

Developer Virtual Employee
Extension VE_Ajax
Version 1.0.0.1
Comparing to
See all releases


Version 1.0.0.1

Files changed (84) hide show
  1. app/code/community/Ve/Ajaxify/Block/Layer/Filter/Attribute.php +118 -0
  2. app/code/community/Ve/Ajaxify/Block/Layer/Filter/Category.php +45 -0
  3. app/code/community/Ve/Ajaxify/Block/Layer/Filter/Categorysearch.php +27 -0
  4. app/code/community/Ve/Ajaxify/Block/Layer/Filter/Price.php +74 -0
  5. app/code/community/Ve/Ajaxify/Block/Layer/View.php +136 -0
  6. app/code/community/Ve/Ajaxify/Block/List.php +103 -0
  7. app/code/community/Ve/Ajaxify/Block/Rewrite/RewriteCatalogCategoryView.php +24 -0
  8. app/code/community/Ve/Ajaxify/Block/Rewrite/RewriteCatalogLayerView.php +16 -0
  9. app/code/community/Ve/Ajaxify/Block/Rewrite/RewriteCatalogsearchResult.php +53 -0
  10. app/code/community/Ve/Ajaxify/Block/Search/Layer.php +43 -0
  11. app/code/community/Ve/Ajaxify/Helper/Data.php +432 -0
  12. app/code/community/Ve/Ajaxify/Model/Layer/Filter/Attribute.php +164 -0
  13. app/code/community/Ve/Ajaxify/Model/Layer/Filter/Category.php +133 -0
  14. app/code/community/Ve/Ajaxify/Model/Layer/Filter/Categorysearch.php +109 -0
  15. app/code/community/Ve/Ajaxify/Model/Layer/Filter/Price.php +606 -0
  16. app/code/community/Ve/Ajaxify/Model/Observer.php +117 -0
  17. app/code/community/Ve/Ajaxify/Model/Response.php +112 -0
  18. app/code/community/Ve/Ajaxify/Model/Select.php +22 -0
  19. app/code/community/Ve/Ajaxify/Model/System/Config/Source/Category.php +30 -0
  20. app/code/community/Ve/Ajaxify/Model/System/Config/Source/Price.php +38 -0
  21. app/code/community/Ve/Ajaxify/Model/System/Config/Source/Swatches.php +34 -0
  22. app/code/community/Ve/Ajaxify/controllers/CategoryController.php +34 -0
  23. app/code/community/Ve/Ajaxify/controllers/Checkout/CartController.php +215 -0
  24. app/code/community/Ve/Ajaxify/controllers/FrontController.php +71 -0
  25. app/code/community/Ve/Ajaxify/etc/adminhtml.xml +22 -0
  26. app/code/community/Ve/Ajaxify/etc/config.xml +171 -0
  27. app/code/community/Ve/Ajaxify/etc/system.xml +106 -0
  28. app/design/frontend/rwd/default/layout/ajaxify.xml +424 -0
  29. app/design/frontend/rwd/default/template/ajaxify/catalog/product/list.phtml +176 -0
  30. app/design/frontend/rwd/default/template/ajaxify/filter_attribute.phtml +11 -0
  31. app/design/frontend/rwd/default/template/ajaxify/filter_category.phtml +18 -0
  32. app/design/frontend/rwd/default/template/ajaxify/filter_category_search.phtml +21 -0
  33. app/design/frontend/rwd/default/template/ajaxify/filter_price_both.phtml +147 -0
  34. app/design/frontend/rwd/default/template/ajaxify/filter_price_default.phtml +7 -0
  35. app/design/frontend/rwd/default/template/ajaxify/filter_price_input.phtml +26 -0
  36. app/design/frontend/rwd/default/template/ajaxify/filter_price_slider.phtml +111 -0
  37. app/design/frontend/rwd/default/template/ajaxify/layer.phtml +54 -0
  38. app/design/frontend/rwd/default/template/ajaxify/layer_pager.phtml +12 -0
  39. app/design/frontend/rwd/default/template/ajaxify/popup.phtml +10 -0
  40. app/design/frontend/rwd/default/template/ajaxify/search.phtml +1 -0
  41. app/etc/modules/Ve_Ajaxify.xml +20 -0
  42. package.xml +18 -0
  43. skin/frontend/rwd/default/css/ve/mullayernav.css +33 -0
  44. skin/frontend/rwd/default/css/ve/ve/jquery-ui.css +1225 -0
  45. skin/frontend/rwd/default/css/ve/ve_layered_nav.css +151 -0
  46. skin/frontend/rwd/default/images/ve/Check-Box.png +0 -0
  47. skin/frontend/rwd/default/images/ve/ajax-loader.gif +0 -0
  48. skin/frontend/rwd/default/images/ve/gray_bar.jpg +0 -0
  49. skin/frontend/rwd/default/images/ve/loader.gif +0 -0
  50. skin/frontend/rwd/default/images/ve/orange_bar.jpg +0 -0
  51. skin/frontend/rwd/default/images/ve/slider_button.png +0 -0
  52. skin/frontend/rwd/default/js/ve/LIVE_chweb_layered_nav.js +242 -0
  53. skin/frontend/rwd/default/js/ve/ajaxwishlist/ajaxwishlist.js +48 -0
  54. skin/frontend/rwd/default/js/ve/fancybox/blank.gif +0 -0
  55. skin/frontend/rwd/default/js/ve/fancybox/fancy_close.png +0 -0
  56. skin/frontend/rwd/default/js/ve/fancybox/fancy_loading.png +0 -0
  57. skin/frontend/rwd/default/js/ve/fancybox/fancy_nav_left.png +0 -0
  58. skin/frontend/rwd/default/js/ve/fancybox/fancy_nav_right.png +0 -0
  59. skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_e.png +0 -0
  60. skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_n.png +0 -0
  61. skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_ne.png +0 -0
  62. skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_nw.png +0 -0
  63. skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_s.png +0 -0
  64. skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_se.png +0 -0
  65. skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_sw.png +0 -0
  66. skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_w.png +0 -0
  67. skin/frontend/rwd/default/js/ve/fancybox/fancy_title_left.png +0 -0
  68. skin/frontend/rwd/default/js/ve/fancybox/fancy_title_main.png +0 -0
  69. skin/frontend/rwd/default/js/ve/fancybox/fancy_title_over.png +0 -0
  70. skin/frontend/rwd/default/js/ve/fancybox/fancy_title_right.png +0 -0
  71. skin/frontend/rwd/default/js/ve/fancybox/fancybox-x.png +0 -0
  72. skin/frontend/rwd/default/js/ve/fancybox/fancybox-y.png +0 -0
  73. skin/frontend/rwd/default/js/ve/fancybox/fancybox.png +0 -0
  74. skin/frontend/rwd/default/js/ve/fancybox/fancybox_loading.gif +0 -0
  75. skin/frontend/rwd/default/js/ve/fancybox/fancybox_loading@2x.gif +0 -0
  76. skin/frontend/rwd/default/js/ve/fancybox/fancybox_overlay.png +0 -0
  77. skin/frontend/rwd/default/js/ve/fancybox/fancybox_sprite.png +0 -0
  78. skin/frontend/rwd/default/js/ve/fancybox/fancybox_sprite@2x.png +0 -0
  79. skin/frontend/rwd/default/js/ve/fancybox/jquery.fancybox.css +274 -0
  80. skin/frontend/rwd/default/js/ve/fancybox/jquery.fancybox.js +2020 -0
  81. skin/frontend/rwd/default/js/ve/fancybox/jquery.mousewheel-3.0.6.pack.js +13 -0
  82. skin/frontend/rwd/default/js/ve/jquery.bpopup.min.js +7 -0
  83. skin/frontend/rwd/default/js/ve/ve/jquery-1.10.2.js +9789 -0
  84. skin/frontend/rwd/default/js/ve/ve/jquery-ui.js +15726 -0
app/code/community/Ve/Ajaxify/Block/Layer/Filter/Attribute.php ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Virtual Employee Ajaxify
5
+ *
6
+ * @category VE
7
+ * @package Ve_Ajaxify
8
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
9
+ * @author VE (Magento Team)
10
+ * @version Release: 1.0.0
11
+ * @Class Ve_Ajaxify_Block_Layer_Filter_Price
12
+ * @Overwrite Mage_Catalog_Block_Layer_Filter_Attribute
13
+ */
14
+ class Ve_Ajaxify_Block_Layer_Filter_Attribute extends Mage_Catalog_Block_Layer_Filter_Attribute {
15
+
16
+ public function __construct() {
17
+ parent::__construct();
18
+ //Load Custom PHTML of attributes
19
+ $this->setTemplate('ajaxify/filter_attribute.phtml');
20
+ //Set Filter Model Name
21
+ $this->_filterModelName = 'ajaxify/layer_filter_attribute';
22
+ }
23
+
24
+ public function getVar() {
25
+ //Get request variable name which is used for apply filter
26
+ return $this->_filter->getRequestVar();
27
+ }
28
+
29
+ public function getClearUrl() {
30
+ //Get URL and rewrite with SEO frieldly URL
31
+ $_seoURL = '';
32
+ //Get request filters with URL
33
+ $query = Mage::helper('ajaxify')->getParams();
34
+ if (!empty($query[$this->getVar()])) {
35
+ $query[$this->getVar()] = null;
36
+ $_seoURL = Mage::getUrl('*/*/*', array(
37
+ '_use_rewrite' => true,
38
+ '_query' => $query,
39
+ ));
40
+ }
41
+
42
+ return $_seoURL;
43
+ }
44
+
45
+ public function getHtmlId($item) {
46
+ //Make HTMLID with requested filter + value of param
47
+ return $this->getVar() . '-' . $item->getValueString();
48
+ }
49
+
50
+ public function Selectedfilter($item) {
51
+ //Set Selected filters
52
+ $ids = (array) $this->_filter->getActiveState();
53
+ return in_array($item->getValueString(), $ids);
54
+ }
55
+
56
+ public function getFiltersArray() {
57
+
58
+ $_filtersArray = array();
59
+ //$hideLinks = Mage::getStoreConfig('ajaxify/ajaxifynavigation/remove_links');
60
+ //Get all filter items ( use getItems method of Mage_Catalog_Model_Layer_Filter_Abstract )
61
+ foreach ($this->getItems() as $_item) {
62
+
63
+
64
+ $showSwatches = Mage::getStoreConfig('ajaxify/ajaxifynavigation/show_swatches');
65
+ $_htmlFilters = 'id="' . $this->getHtmlId($_item) . '" ';
66
+ $var_href = "#";
67
+
68
+ //Create URL
69
+ $var_href = html_entity_decode($currentUrl = Mage::app()->getRequest()->getBaseUrl() . Mage::getSingleton('core/session')->getRequestPath());
70
+ $_htmlFilters .= 'href="' . $var_href . '" ';
71
+
72
+ $_htmlFilters .= 'class="ve_layered_attribute '
73
+ . ($this->Selectedfilter($_item) ? 've_layered_attribute_selected' : '') . '" ';
74
+
75
+ //Check the number of products against filter
76
+ $qty = '';
77
+ if (!$this->getHideQty())
78
+ $qty = ''; //'(' . $_item->getCount() .')';
79
+
80
+
81
+ if ($this->getName() == "Color") {
82
+
83
+ if ($showSwatches == "iconslinks") {
84
+
85
+ $iconCode = Mage::helper('ajaxify')->checkColor($_item->getLabel());
86
+ $_html = "";
87
+ $_html .= '<div class="color">
88
+ <a ' . $_htmlFilters . '><div class="color_box" style="background-color:' . $iconCode . ';"></div>
89
+ ' . $_item->getLabel() . '</a><span>' . $qty . '</span>
90
+ </div>';
91
+ } elseif ($showSwatches == "icons") {
92
+
93
+ $iconCode = Mage::helper('ajaxify')->checkColor($_item->getLabel());
94
+ $_html = "";
95
+ $_html .= '<div class="color">
96
+ <a ' . $_htmlFilters . '><div class="color_box" style="background-color:' . $iconCode . ';"></div>
97
+ </a><span>' . $qty . '</span>
98
+ </div>';
99
+ } else {
100
+
101
+ $_html = "";
102
+ $_html .= '<a ' . $_htmlFilters . '>' . $_item->getLabel() . '</a><span>' . $qty . '</span>';
103
+ }
104
+ }
105
+
106
+
107
+
108
+ if ($this->getName() == "Color") {
109
+ $_filtersArray[] = $_html;
110
+ } else {
111
+ $_filtersArray[] = '<a ' . $_htmlFilters . '>' . $_item->getLabel() . '</a>' . $qty;
112
+ }
113
+ }
114
+
115
+ return $_filtersArray;
116
+ }
117
+
118
+ }
app/code/community/Ve/Ajaxify/Block/Layer/Filter/Category.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Virtual Employee Ajaxify
5
+ *
6
+ * @category VE
7
+ * @package Ve_Ajaxify
8
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
9
+ * @author VE (Magento Team)
10
+ * @version Release: 1.0.0
11
+ * @Class Ve_Ajaxify_Block_Layer_Filter_Price
12
+ * @Overwrite Mage_Catalog_Block_Layer_Filter_Category
13
+ */
14
+ class Ve_Ajaxify_Block_Layer_Filter_Category extends Mage_Catalog_Block_Layer_Filter_Category {
15
+
16
+ public function __construct() {
17
+ parent::__construct();
18
+ //Load Custom PHTML of category
19
+ $this->setTemplate('ajaxify/filter_category.phtml');
20
+ //Set Filter Model Name
21
+ $this->_filterModelName = 'ajaxify/layer_filter_category';
22
+ }
23
+
24
+ public function getVar() {
25
+ //Get request variable name which is used for apply filter
26
+ return $this->_filter->getRequestVar();
27
+ }
28
+
29
+ public function getClearUrl() {
30
+ //Get URL and rewrite with SEO frieldly URL
31
+ $_seoURL = '';
32
+ //Get request filters with URL
33
+ $query = Mage::helper('ajaxify')->getParams();
34
+ if (!empty($query[$this->getVar()])) {
35
+ $query[$this->getVar()] = null;
36
+ $_seoURL = Mage::getUrl('*/*/*', array(
37
+ '_use_rewrite' => true,
38
+ '_query' => $query,
39
+ ));
40
+ }
41
+
42
+ return $_seoURL;
43
+ }
44
+
45
+ }
app/code/community/Ve/Ajaxify/Block/Layer/Filter/Categorysearch.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Block_Layer_Filter_Price
11
+ * @Overwrite Ve_Ajaxify_Block_Layer_Filter_Category
12
+ */
13
+
14
+
15
+ class Ve_Ajaxify_Block_Layer_Filter_Categorysearch extends Ve_Ajaxify_Block_Layer_Filter_Category
16
+ {
17
+ public function __construct()
18
+ {
19
+
20
+ parent::__construct();
21
+ //Load Custom PHTML of category search
22
+ $this->setTemplate('ajaxify/filter_category_search.phtml');
23
+ //Set Filter Model Name
24
+ $this->_filterModelName = 'ajaxify/layer_filter_categorysearch';
25
+ }
26
+
27
+ }
app/code/community/Ve/Ajaxify/Block/Layer/Filter/Price.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Block_Layer_Filter_Price
11
+ */
12
+ class Ve_Ajaxify_Block_Layer_Filter_Price extends Mage_Catalog_Block_Layer_Filter_Price
13
+ {
14
+ private $_filterType;
15
+
16
+ public function __construct()
17
+ {
18
+ parent::__construct();
19
+ $this->_filterType = Mage::getStoreConfig('ajaxify/ajaxifynavigation/price_style');
20
+ //Load Custom PHTML of price
21
+ //echo 'ajaxify/filter_price_' . $this->_filterType . '.phtml';
22
+ $this->setTemplate('ajaxify/filter_price_' . $this->_filterType . '.phtml');
23
+ // $this->setTemplate('ajaxify/filter_price_both.phtml');
24
+
25
+ //Set Filter Model Name
26
+ $this->_filterModelName = 'ajaxify/layer_filter_price';
27
+ }
28
+
29
+ public function getVar(){
30
+ //Get request variable name which is used for apply filter
31
+ return $this->_filter->getRequestVar();
32
+ }
33
+
34
+ public function getClearUrl()
35
+ {
36
+ $_seoURL = '';
37
+ $query = Mage::helper('ajaxify')->getParams();
38
+ if (!empty($query[$this->getVar()])){
39
+ if (!empty($query[$this->getVar()])){
40
+ $query[$this->getVar()] = null;
41
+ $_seoURL = Mage::getUrl('*/*/*', array(
42
+ '_use_rewrite' => true,
43
+ '_query' => $query,
44
+ ));
45
+ }
46
+ }
47
+ return $_seoURL;
48
+ }
49
+
50
+ public function isSelected($item)
51
+ {
52
+ return ($item->getValueString() == $this->_filter->getActiveState());
53
+ }
54
+
55
+ public function getSymbol()
56
+ {
57
+ //To Get the current Currency Symbol
58
+ // Thanks to this blog (http://magento-developer-magento.blogspot.com/2011/11/how-to-get-current-currency-and.html)
59
+ $_symbol = $this->getData('symbol');
60
+ if (!$_symbol){
61
+ $currency_code = Mage::app()->getStore()->getCurrentCurrencyCode();
62
+ $_symbol = trim(Mage::app()->getLocale()->currency(Mage::app()->getStore()->getCurrentCurrencyCode())->getSymbol());
63
+ $this->setData('symbol', $_symbol);
64
+ }
65
+ return $_symbol;
66
+ }
67
+
68
+ public function getOffSet() {
69
+
70
+ $minmaxArray = $this->_filter->getMinMaxPriceInt();
71
+ $fromtoArray = explode(',', $this->_filter->getActiveState());
72
+
73
+ }
74
+ }
app/code/community/Ve/Ajaxify/Block/Layer/View.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Block_Layer_View
11
+ */
12
+ class Ve_Ajaxify_Block_Layer_View extends Mage_Catalog_Block_Layer_View {
13
+
14
+ protected $_filterBlocks = null;
15
+ protected $_helper = null;
16
+
17
+ public function __construct() {
18
+ parent::__construct();
19
+ $this->_helper = Mage::helper('ajaxify');
20
+ }
21
+
22
+ public function getStateInfo() {
23
+ $_hlp = $this->_helper;
24
+ //Check the Layered Nav position (Search or Catalog pages)
25
+ $ajaxUrl = '';
26
+ if ($_hlp->isSearch()) {
27
+ $ajaxUrl = Mage::getUrl('ajaxify/front/search');
28
+ } elseif ($cat = $this->getLayer()->getCurrentCategory()) {
29
+ $ajaxUrl = Mage::getUrl('ajaxify/front/category', array('id' => $cat->getId()));
30
+ }
31
+
32
+
33
+ $ajaxUrl = $_hlp->stripQuery($ajaxUrl);
34
+ $url = $_hlp->getContinueShoppingUrl();
35
+
36
+ //Set the AJAX Pagination
37
+ $pageKey = Mage::getBlockSingleton('page/html_pager')->getPageVarName();
38
+
39
+ //Get parameters of serach
40
+ $queryStr = $_hlp->getParams(true, $pageKey);
41
+ if ($queryStr)
42
+ $queryStr = substr($queryStr, 1);
43
+
44
+ $this->setClearAllUrl($_hlp->getClearAllUrl($url));
45
+
46
+ if (false !== strpos($url, '?')) {
47
+ $url = substr($url, 0, strpos($url, '?'));
48
+ }
49
+ return array($url, $queryStr, $ajaxUrl);
50
+ }
51
+
52
+ public function bNeedClearAll() {
53
+ return $this->_helper->bNeedClearAll();
54
+ }
55
+
56
+ protected function _prepareLayout() {
57
+ $_hlp = $this->_helper;
58
+ // Return an object of current category
59
+ $category = Mage::registry('current_category');
60
+
61
+ if ($category) {
62
+ $currentCategoryID = $category->getId();
63
+ } else {
64
+ $currentCategoryID = null;
65
+ }
66
+
67
+ // Return session object
68
+ $sessionObject = Mage::getSingleton('catalog/session');
69
+ if ($sessionObject AND $lastCategoryID = $sessionObject->getLastCatgeoryID()) {
70
+ if ($currentCategoryID != $lastCategoryID) {
71
+ Mage::register('new_category', true);
72
+ }
73
+ }
74
+ $sessionObject->setLastCatgeoryID($currentCategoryID);
75
+
76
+ //Create Category Blocks
77
+ $this->createCategoriesBlock();
78
+
79
+ //preload setting
80
+ $this->setIsRemoveLinks($_hlp->removeLinks());
81
+
82
+ //Get $this->_getFilterableAttributes() Mage_Catalog_Block_Layer_View
83
+ $filterableAttributes = $this->_getFilterableAttributes();
84
+
85
+
86
+ $blocks = array();
87
+ foreach ($filterableAttributes as $attribute) {
88
+ $blockType = 'ajaxify/layer_filter_attribute';
89
+
90
+ if ($attribute->getFrontendInput() == 'price') {
91
+ $blockType = 'ajaxify/layer_filter_price';
92
+ }
93
+
94
+ $name = $attribute->getAttributeCode() . '_filter';
95
+
96
+ $blocks[$name] = $this->getLayout()->createBlock($blockType)
97
+ ->setLayer($this->getLayer())
98
+ ->setAttributeModel($attribute);
99
+
100
+ $this->setChild($name, $blocks[$name]);
101
+ }
102
+
103
+ foreach ($blocks as $name => $block) {
104
+ $block->init();
105
+ }
106
+ $this->getLayer()->apply();
107
+ return Mage_Core_Block_Template::_prepareLayout();
108
+ }
109
+
110
+ protected function createCategoriesBlock() {
111
+
112
+ $_hlp = $this->_helper;
113
+ if ('none' != $_hlp->catStyle()) {
114
+ $categoryBlock = $this->getLayout()->createBlock('ajaxify/layer_filter_category')
115
+ ->setLayer($this->getLayer())
116
+ ->init();
117
+ $this->setChild('category_filter', $categoryBlock);
118
+ }
119
+ }
120
+
121
+ public function getFilters() {
122
+ if (is_null($this->_filterBlocks)) {
123
+ $this->_filterBlocks = parent::getFilters();
124
+ }
125
+ return $this->_filterBlocks;
126
+ }
127
+
128
+ protected function _toHtml() {
129
+ $html = parent::_toHtml();
130
+ if (!Mage::app()->getRequest()->isXmlHttpRequest()) {
131
+ $html = '<div id="catalog-filters">' . $html . '</div>';
132
+ }
133
+ return $html;
134
+ }
135
+
136
+ }
app/code/community/Ve/Ajaxify/Block/List.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Virtual Employee Ajaxify
5
+ *
6
+ * @category VE
7
+ * @package Ve_Ajaxify
8
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
9
+ * @author VE (Magento Team)
10
+ * @version Release: 1.0.0
11
+ * @Class Ve_Ajaxify_Block_List
12
+ */
13
+ class Ve_Ajaxify_Block_List extends Mage_Core_Block_Template {
14
+
15
+ protected $_productCollection;
16
+ protected $_module = 'catalog';
17
+
18
+ /**
19
+ * @return Mage_Catalog_Block_Product_List
20
+ */
21
+ public function getListBlock() {
22
+
23
+ return $this->getChild('product_list');
24
+ }
25
+
26
+ public function setListOrders() {
27
+ if ('catalogsearch' != $this->_module)
28
+ return $this;
29
+
30
+ $category = Mage::getSingleton('catalog/layer')
31
+ ->getCurrentCategory();
32
+ /* @var $category Mage_Catalog_Model_Category */
33
+ $availableOrders = $category->getAvailableSortByOptions();
34
+ unset($availableOrders['position']);
35
+ $availableOrders = array_merge(array(
36
+ 'relevance' => $this->__('Relevance')
37
+ ), $availableOrders);
38
+
39
+ $this->getListBlock()
40
+ ->setAvailableOrders($availableOrders)
41
+ ->setDefaultDirection('desc')
42
+ ->setSortBy('relevance');
43
+
44
+ return $this;
45
+ }
46
+
47
+ /**
48
+ * Set available view mode
49
+ *
50
+ * @return AdjustWare_Nav_Block_List
51
+
52
+ public function setListModes() {
53
+
54
+ $this->getListBlock()
55
+ ->setModes(array(
56
+ 'grid' => $this->__('Grid'),
57
+ 'list' => $this->__('List'))
58
+ );
59
+ return $this;
60
+ }
61
+ */
62
+ public function setIsSearchMode() {
63
+ $this->_module = 'catalogsearch';
64
+ return $this;
65
+ }
66
+
67
+ /**
68
+ * Set All products collection
69
+ *
70
+ * @return AdjustWare_Nav_Block_List
71
+ */
72
+ public function setListCollection() {
73
+ $this->getListBlock()->setCollection($this->_getProductCollection());
74
+ return $this;
75
+ }
76
+
77
+ protected function _toHtml() {
78
+ $this->setListOrders();
79
+ $this->setListModes();
80
+ $this->setListCollection();
81
+
82
+ $html = $this->getChildHtml('product_list');
83
+ $html = Mage::helper('ajaxify')->wrapProducts($html);
84
+
85
+ return $html;
86
+ }
87
+
88
+ /**
89
+ * Retrieve loaded category collection
90
+ *
91
+ * @return Mage_CatalogSearch_Model_Mysql4_Fulltext_Collection
92
+ */
93
+ protected function _getProductCollection() {
94
+ if (is_null($this->_productCollection)) {
95
+
96
+ $this->_productCollection = Mage::getSingleton($this->_module . '/layer')
97
+ ->getProductCollection();
98
+ }
99
+
100
+ return $this->_productCollection;
101
+ }
102
+
103
+ }
app/code/community/Ve/Ajaxify/Block/Rewrite/RewriteCatalogCategoryView.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Block_Rewrite_RewriteCatalogCategoryView
11
+ */
12
+
13
+
14
+ class Ve_Ajaxify_Block_Rewrite_RewriteCatalogCategoryView extends Mage_Catalog_Block_Category_View
15
+ {
16
+ public function getProductListHtml()
17
+ {
18
+ $html = parent::getProductListHtml();
19
+ if ($this->getCurrentCategory()->getIsAnchor()){
20
+ $html = Mage::helper('ajaxify')->wrapProducts($html);
21
+ }
22
+ return $html;
23
+ }
24
+ }
app/code/community/Ve/Ajaxify/Block/Rewrite/RewriteCatalogLayerView.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Block_Rewrite_RewriteCatalogLayerView
11
+ */
12
+
13
+ class Ve_Ajaxify_Block_Rewrite_RewriteCatalogLayerView extends Mage_Catalog_Block_Layer_View
14
+ {
15
+
16
+ }
app/code/community/Ve/Ajaxify/Block/Rewrite/RewriteCatalogsearchResult.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Block_Rewrite_RewriteCatalogsearchResult
11
+ */
12
+
13
+ class Ve_Ajaxify_Block_Rewrite_RewriteCatalogsearchResult extends Mage_CatalogSearch_Block_Result
14
+ {
15
+ /**
16
+ * Retrieve Search result list HTML output, wrapped with <div>
17
+ * @return string
18
+ */
19
+ public function getProductListHtml()
20
+ {
21
+ $html = parent::getProductListHtml();
22
+ $html = Mage::helper('ajaxify')->wrapProducts($html);
23
+ return $html;
24
+ }
25
+
26
+ /**
27
+ * Set Search Result collection
28
+ *
29
+ * @return Mage_CatalogSearch_Block_Result
30
+ */
31
+ public function setListCollection()
32
+ {
33
+ //benz001 un-comment these two
34
+ $this->getListBlock()
35
+ ->setCollection($this->_getProductCollection());
36
+ return $this;
37
+ }
38
+ /**
39
+ * Retrieve loaded category collection
40
+ *
41
+ * @return Mage_CatalogSearch_Model_Mysql4_Fulltext_Collection
42
+ */
43
+ protected function _getProductCollection()
44
+ {
45
+ if (is_null($this->_productCollection)) {
46
+ //$this->_productCollection = $this->getListBlock()->getLoadedProductCollection();
47
+ $this->_productCollection = Mage::getSingleton('catalogsearch/layer')->getProductCollection();
48
+ }
49
+
50
+ return $this->_productCollection;
51
+ }
52
+
53
+ }
app/code/community/Ve/Ajaxify/Block/Search/Layer.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Block_Search_Layer
11
+ */
12
+ class Ve_Ajaxify_Block_Search_Layer extends Ve_Ajaxify_Block_Layer_View {
13
+
14
+ public function getLayer() {
15
+ return Mage::getSingleton('catalogsearch/layer');
16
+ }
17
+
18
+ /**
19
+ * Check availability display layer block
20
+ *
21
+ * @return bool
22
+ */
23
+ public function canShowBlock() {
24
+
25
+ $availableResCount = (int) Mage::app()->getStore()
26
+ ->getConfig(Mage_CatalogSearch_Model_Layer::XML_PATH_DISPLAY_LAYER_COUNT);
27
+
28
+ if (!$availableResCount || ($availableResCount >= $this->getLayer()->getProductCollection()->getSize())) {
29
+ return parent::canShowBlock();
30
+ }
31
+ return false;
32
+ }
33
+
34
+ protected function createCategoriesBlock() {
35
+
36
+ $categoryBlock = $this->getLayout()
37
+ ->createBlock('ajaxify/layer_filter_categorysearch')
38
+ ->setLayer($this->getLayer())
39
+ ->init();
40
+ $this->setChild('category_filter', $categoryBlock);
41
+ }
42
+
43
+ }
app/code/community/Ve/Ajaxify/Helper/Data.php ADDED
@@ -0,0 +1,432 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Virtual Employee Ajaxify
5
+ *
6
+ * @category VE
7
+ * @package Ve_Ajaxify
8
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
9
+ * @author VE (Magento Team)
10
+ * @version Release: 1.0.0
11
+ * @Class Ve_Ajaxify_Helper_Data
12
+ */
13
+ class Ve_Ajaxify_Helper_Data extends Mage_Core_Helper_Abstract {
14
+
15
+ protected $_params = null;
16
+ protected $_continueShoppingUrl = null;
17
+
18
+ const XML_PATH_CAT_STYLE = 'ajaxify/ajaxifynavigation/cat_style';
19
+ const XML_PATH_REMOVE_LINKS = 'ajaxify/ajaxifynavigation/remove_links';
20
+ const XML_PATH_RESET_FILTERS = 'ajaxify/ajaxifynavigation/reset_filters';
21
+
22
+ public function catStyle($store = null) {
23
+ if ($store == null) {
24
+ $store = Mage::app()->getStore()->getId();
25
+ }
26
+
27
+ return Mage::getStoreConfig(self::XML_PATH_CAT_STYLE, $store);
28
+ }
29
+
30
+ public function removeLinks($store = null) {
31
+
32
+ if ($store == null) {
33
+ $store = Mage::app()->getStore()->getId();
34
+ }
35
+
36
+ return Mage::getStoreConfig(self::XML_PATH_REMOVE_LINKS, $store);
37
+ }
38
+
39
+ public function resetFilters($store = null) {
40
+
41
+ if ($store == null) {
42
+ $store = Mage::app()->getStore()->getId();
43
+ }
44
+
45
+ return Mage::getStoreConfig(self::XML_PATH_RESET_FILTERS, $store);
46
+ }
47
+
48
+ public function isSearch() {
49
+
50
+ $mod = Mage::app()->getRequest()->getModuleName();
51
+ if ('catalogsearch' === $mod) {
52
+ return true;
53
+ }
54
+
55
+ if ('mullayernav' === $mod && 'search' == Mage::app()->getRequest()->getActionName()) {
56
+ return true;
57
+ }
58
+
59
+ return false;
60
+ }
61
+
62
+ public function getContinueShoppingUrl() {
63
+ if (is_null($this->_continueShoppingUrl)) {
64
+ $url = '';
65
+
66
+ $allParams = $this->getParams();
67
+ $keys = $this->getNonFilteringParamKeys();
68
+
69
+ $query = array();
70
+ foreach ($allParams as $k => $v) {
71
+ if (in_array($k, $keys))
72
+ $query[$k] = $v;
73
+ }
74
+
75
+ if ($this->isSearch()) {
76
+
77
+ $url = Mage::getModel('core/url')->getUrl('catalogsearch/result/index', array('_query' => $query));
78
+ } else {
79
+ $category = Mage::registry('current_category');
80
+ $rootId = Mage::app()->getStore()->getRootCategoryId();
81
+ if ($category && $category->getId() != $rootId) {
82
+ $url = $category->getUrl();
83
+ } else {
84
+ $url = Mage::app()->getStore()->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK);
85
+ }
86
+ $url .= $this->toQuery($query);
87
+ }
88
+ $this->_continueShoppingUrl = $url;
89
+ }
90
+
91
+ return $this->_continueShoppingUrl;
92
+ }
93
+
94
+ public function wrapProducts($html) {
95
+ $html = str_replace('onchange="setLocation', 'onchange="catalog_toolbar_make_request', $html);
96
+
97
+ if (Mage::app()->getRequest()->isXmlHttpRequest()) {
98
+ $html = str_replace('?___SID=U&amp;', '?', $html);
99
+ $html = str_replace('?___SID=U', '', $html);
100
+ $html = str_replace('&amp;___SID=U', '', $html);
101
+ $k = Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED;
102
+ $v = Mage::helper('core')->urlEncode($this->getContinueShoppingUrl());
103
+ $html = preg_replace("#$k/[^/]+#", "$k/$v", $html);
104
+ } else {
105
+ $html = '<div id="ve_layered_container">' . $html . '</div>' . '';
106
+ }
107
+
108
+ return $html;
109
+ }
110
+
111
+ public function getParam($k) {
112
+ $p = $this->getParams();
113
+ $v = isset($p[$k]) ? $p[$k] : null;
114
+ return $v;
115
+ }
116
+
117
+ // currently we use $without only if $asString=true
118
+ public function getParams($asString = false, $without = null) {
119
+ if (is_null($this->_params)) {
120
+
121
+ $sessionObject = Mage::getSingleton('catalog/session');
122
+ $bNeedClearAll = false;
123
+
124
+ if ($this->resetFilters() AND Mage::registry('new_category')) {
125
+
126
+ $bNeedClearAll = true;
127
+ }
128
+
129
+ if ($this->isSearch()) {
130
+ $sessionObject = Mage::getSingleton('catalogsearch/session');
131
+ $query = Mage::app()->getRequest()->getQuery();
132
+ if (isset($query['q'])) {
133
+ if ($sessionObject->getData('layquery') && $sessionObject->getData('layquery') != $query['q']) {
134
+ $bNeedClearAll = true;
135
+ }
136
+ $sessionObject->setData('layquery', $query['q']);
137
+ }
138
+ }
139
+
140
+ $nSavedCurrencyRate = $sessionObject->getAdjNavCurrencyRate();
141
+
142
+ $nCurrentCurrencyRate = Mage::app()->getStore()->convertPrice(1000000, false);
143
+ $nCurrentCurrencyRate = $nCurrentCurrencyRate / 1000000;
144
+
145
+ $nSavedPriceStyle = $sessionObject->getAdjNavPriceStyle();
146
+ $nCurrentPriceStyle = Mage::getStoreConfig('ajaxify/ajaxifynavigation/price_style');
147
+
148
+ $bNeedClearPriceFilter = false;
149
+
150
+ if ($nSavedCurrencyRate AND $nSavedCurrencyRate != $nCurrentCurrencyRate) {
151
+ $bNeedClearPriceFilter = true;
152
+ }
153
+
154
+ if ($nSavedPriceStyle != $nCurrentPriceStyle) {
155
+ $bNeedClearPriceFilter = true;
156
+ }
157
+
158
+ if ($bNeedClearPriceFilter) {
159
+ $sess = (array) $sessionObject->getAdjNav();
160
+
161
+ if ($sess) {
162
+ $aNonFilteringParamKeys = $this->getNonFilteringParamKeys();
163
+
164
+ foreach ($sess as $sKey => $sVal) {
165
+ if (!in_array($sKey, $aNonFilteringParamKeys)) {
166
+ $attribute = Mage::getModel('eav/entity_attribute');
167
+
168
+ $attribute->load($sKey, 'attribute_code');
169
+
170
+ if ($attribute->getFrontendInput() == 'price') {
171
+ unset($sess[$sKey]);
172
+ }
173
+ }
174
+ }
175
+
176
+ $sessionObject->setAdjNav($sess);
177
+ }
178
+ }
179
+
180
+ $sessionObject->setAdjNavCurrencyRate($nCurrentCurrencyRate);
181
+ $sessionObject->setAdjNavPriceStyle($nCurrentPriceStyle);
182
+
183
+ $query = Mage::app()->getRequest()->getQuery();
184
+ $sess = (array) $sessionObject->getAdjNav();
185
+ $this->_params = array_merge($sess, $query);
186
+
187
+ if (!empty($query['clearall']) OR $bNeedClearAll) {
188
+ $this->_params = array();
189
+ if ($this->isSearch() && isset($query['q']))
190
+ $this->_params['q'] = $query['q'];
191
+ }
192
+ $sess = array();
193
+ foreach ($this->_params as $k => $v) {
194
+ if ($v && 'clear' != $v)
195
+ $sess[$k] = $v;
196
+ }
197
+
198
+ if (Mage::registry('new_category') AND isset($sess['p'])) {
199
+ unset($sess['p']);
200
+ }
201
+
202
+ $sessionObject->setAdjNav($sess);
203
+ $this->_params = $sess;
204
+
205
+ Mage::register('current_session_params', $sess);
206
+ }
207
+
208
+ if ($asString) {
209
+ return $this->toQuery($this->_params, $without);
210
+ }
211
+
212
+ return $this->_params;
213
+ }
214
+
215
+ public function toQuery($params, $without = null) {
216
+ if (!is_array($without))
217
+ $without = array($without);
218
+
219
+ $queryStr = '?';
220
+ foreach ($params as $k => $v) {
221
+ if (!in_array($k, $without))
222
+ $queryStr .= $k . '=' . urlencode($v) . '&';
223
+ }
224
+ return substr($queryStr, 0, -1);
225
+ }
226
+
227
+ public function stripQuery($url) {
228
+ $pos = strpos($url, '?');
229
+ if (false !== $pos)
230
+ $url = substr($url, 0, $pos);
231
+ return $url;
232
+ }
233
+
234
+ public function getClearAllUrl($baseUrl) {
235
+ $baseUrl .= '?clearall=true';
236
+ if ($this->isSearch()) {
237
+ $baseUrl .= '&q=' . urlencode($this->getParam('q'));
238
+ }
239
+ return $baseUrl;
240
+ }
241
+
242
+ public function bNeedClearAll() {
243
+ if ($aParams = Mage::registry('current_session_params')) {
244
+ $bNeedClearAll = false;
245
+
246
+ $aNonFilteringParamKeys = $this->getNonFilteringParamKeys();
247
+
248
+ foreach ($aParams as $sKey => $sVal) {
249
+ if (!in_array($sKey, $aNonFilteringParamKeys)) {
250
+ $bNeedClearAll = true;
251
+ }
252
+ }
253
+
254
+ return $bNeedClearAll;
255
+ } else {
256
+ return false;
257
+ }
258
+
259
+ return true;
260
+ }
261
+
262
+ public function getCacheKey($attrCode) {
263
+ $keys = $this->getNonFilteringParamKeys();
264
+ $keys[] = $attrCode;
265
+ return md5($this->getParams(true, $keys));
266
+ }
267
+
268
+ protected function getNonFilteringParamKeys() {
269
+ return array('x', 'y', 'mode', 'p', 'order', 'dir', 'limit', 'q', '___store', '___from_store', 'sns');
270
+ }
271
+
272
+ public function checkColor($attrColor) {
273
+
274
+ $colorArray = array('AliceBlue' => '#F0F8FF',
275
+ 'AntiqueWhite' => '#FAEBD7',
276
+ 'Aqua' => '#00FFFF',
277
+ 'Aquamarine' => '#7FFFD4',
278
+ 'Azure' => '#F0FFFF',
279
+ 'Beige' => '#F5F5DC',
280
+ 'Bisque' => '#FFE4C4',
281
+ 'Black' => '#000000',
282
+ 'BlanchedAlmond' => '#FFEBCD',
283
+ 'Blue' => '#0000FF',
284
+ 'BlueViolet' => '#8A2BE2',
285
+ 'Brown' => '#A52A2A',
286
+ 'BurlyWood' => '#DEB887',
287
+ 'CadetBlue' => '#5F9EA0',
288
+ 'Chartreuse' => '#7FFF00',
289
+ 'Chocolate' => '#D2691E',
290
+ 'Coral' => '#FF7F50',
291
+ 'CornflowerBlue' => '#6495ED',
292
+ 'Cornsilk' => '#FFF8DC',
293
+ 'Crimson' => '#DC143C',
294
+ 'Cyan' => '#00FFFF',
295
+ 'DarkBlue' => '#00008B',
296
+ 'DarkCyan' => '#008B8B',
297
+ 'DarkGoldenRod' => '#B8860B',
298
+ 'DarkGray' => '#A9A9A9',
299
+ 'DarkGrey' => '#A9A9A9',
300
+ 'DarkGreen' => '#006400',
301
+ 'DarkKhaki' => '#BDB76B',
302
+ 'DarkMagenta' => '#8B008B',
303
+ 'DarkOliveGreen' => '#556B2F',
304
+ 'Darkorange' => '#FF8C00',
305
+ 'DarkOrchid' => '#9932CC',
306
+ 'DarkRed' => '#8B0000',
307
+ 'DarkSalmon' => '#E9967A',
308
+ 'DarkSeaGreen' => '#8FBC8F',
309
+ 'DarkSlateBlue' => '#483D8B',
310
+ 'DarkSlateGray' => '#2F4F4F',
311
+ 'DarkSlateGrey' => '#2F4F4F',
312
+ 'DarkTurquoise' => '#00CED1',
313
+ 'DarkViolet' => '#9400D3',
314
+ 'DeepPink' => '#FF1493',
315
+ 'DeepSkyBlue' => '#00BFFF',
316
+ 'DimGray' => '#696969',
317
+ 'DimGrey' => '#696969',
318
+ 'DodgerBlue' => '#1E90FF',
319
+ 'FireBrick' => '#B22222',
320
+ 'FloralWhite' => '#FFFAF0',
321
+ 'ForestGreen' => '#228B22',
322
+ 'Fuchsia' => '#FF00FF',
323
+ 'Gainsboro' => '#DCDCDC',
324
+ 'GhostWhite' => '#F8F8FF',
325
+ 'Gold' => '#FFD700',
326
+ 'GoldenRod' => '#DAA520',
327
+ 'Gray' => '#808080',
328
+ 'Grey' => '#808080',
329
+ 'Green' => '#008000',
330
+ 'GreenYellow' => '#ADFF2F',
331
+ 'HoneyDew' => '#F0FFF0',
332
+ 'HotPink' => '#FF69B4',
333
+ 'IndianRed ' => '#CD5C5C',
334
+ 'Indigo ' => '#4B0082',
335
+ 'Ivory' => '#FFFFF0',
336
+ 'Khaki' => '#F0E68C',
337
+ 'Lavender' => '#E6E6FA',
338
+ 'LavenderBlush' => '#FFF0F5',
339
+ 'LawnGreen' => '#7CFC00',
340
+ 'LemonChiffon' => '#FFFACD',
341
+ 'LightBlue' => '#ADD8E6',
342
+ 'LightCoral' => '#F08080',
343
+ 'LightCyan' => '#E0FFFF',
344
+ 'LightGoldenRodYellow' => '#FAFAD2',
345
+ 'LightGray' => '#D3D3D3',
346
+ 'LightGrey' => '#D3D3D3',
347
+ 'LightGreen' => '#90EE90',
348
+ 'LightPink' => '#FFB6C1',
349
+ 'LightSalmon' => '#FFA07A',
350
+ 'LightSeaGreen' => '#20B2AA',
351
+ 'LightSkyBlue' => '#87CEFA',
352
+ 'LightSlateGray' => '#778899',
353
+ 'LightSlateGrey' => '#778899',
354
+ 'LightSteelBlue' => '#B0C4DE',
355
+ 'LightYellow' => '#FFFFE0',
356
+ 'Lime' => '#00FF00',
357
+ 'LimeGreen' => '#32CD32',
358
+ 'Linen' => '#FAF0E6',
359
+ 'Magenta' => '#FF00FF',
360
+ 'Maroon' => '#800000',
361
+ 'MediumAquaMarine' => '#66CDAA',
362
+ 'MediumBlue' => '#0000CD',
363
+ 'MediumOrchid' => '#BA55D3',
364
+ 'MediumPurple' => '#9370D8',
365
+ 'MediumSeaGreen' => '#3CB371',
366
+ 'MediumSlateBlue' => '#7B68EE',
367
+ 'MediumSpringGreen' => '#00FA9A',
368
+ 'MediumTurquoise' => '#48D1CC',
369
+ 'MediumVioletRed' => '#C71585',
370
+ 'MidnightBlue' => '#191970',
371
+ 'MintCream' => '#F5FFFA',
372
+ 'MistyRose' => '#FFE4E1',
373
+ 'Moccasin' => '#FFE4B5',
374
+ 'NavajoWhite' => '#FFDEAD',
375
+ 'Navy' => '#000080',
376
+ 'OldLace' => '#FDF5E6',
377
+ 'Olive' => '#808000',
378
+ 'OliveDrab' => '#6B8E23',
379
+ 'Orange' => '#FFA500',
380
+ 'OrangeRed' => '#FF4500',
381
+ 'Orchid' => '#DA70D6',
382
+ 'PaleGoldenRod' => '#EEE8AA',
383
+ 'PaleGreen' => '#98FB98',
384
+ 'PaleTurquoise' => '#AFEEEE',
385
+ 'PaleVioletRed' => '#D87093',
386
+ 'PapayaWhip' => '#FFEFD5',
387
+ 'PeachPuff' => '#FFDAB9',
388
+ 'Peru' => '#CD853F',
389
+ 'Pink' => '#FFC0CB',
390
+ 'Plum' => '#DDA0DD',
391
+ 'PowderBlue' => '#B0E0E6',
392
+ 'Purple' => '#800080',
393
+ 'Red' => '#FF0000',
394
+ 'RosyBrown' => '#BC8F8F',
395
+ 'RoyalBlue' => '#4169E1',
396
+ 'SaddleBrown' => '#8B4513',
397
+ 'Salmon' => '#FA8072',
398
+ 'SandyBrown' => '#F4A460',
399
+ 'SeaGreen' => '#2E8B57',
400
+ 'SeaShell' => '#FFF5EE',
401
+ 'Sienna' => '#A0522D',
402
+ 'Silver' => '#C0C0C0',
403
+ 'SkyBlue' => '#87CEEB',
404
+ 'SlateBlue' => '#6A5ACD',
405
+ 'SlateGray' => '#708090',
406
+ 'SlateGrey' => '#708090',
407
+ 'Snow' => '#FFFAFA',
408
+ 'SpringGreen' => '#00FF7F',
409
+ 'SteelBlue' => '#4682B4',
410
+ 'Tan' => '#D2B48C',
411
+ 'Teal' => '#008080',
412
+ 'Thistle' => '#D8BFD8',
413
+ 'Tomato' => '#FF6347',
414
+ 'Turquoise' => '#40E0D0',
415
+ 'Violet' => '#EE82EE',
416
+ 'Wheat' => '#F5DEB3',
417
+ 'White' => '#FFFFFF',
418
+ 'WhiteSmoke' => '#F5F5F5',
419
+ 'Yellow' => '#FFFF00',
420
+ 'YellowGreen' => '#9ACD32');
421
+
422
+ $colorArr = unserialize(strtolower(serialize($colorArray)));
423
+
424
+ if (array_key_exists(strtolower($attrColor), $colorArr)) {
425
+ $key = $colorArr[strtolower($attrColor)];
426
+ } else {
427
+ $key = "";
428
+ }
429
+
430
+ return $key;
431
+ }
432
+ }
app/code/community/Ve/Ajaxify/Model/Layer/Filter/Attribute.php ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Model_Layer_Filter_Attribute
11
+ */
12
+ class Ve_Ajaxify_Model_Layer_Filter_Attribute extends Mage_Catalog_Model_Layer_Filter_Attribute
13
+ {
14
+ public function __construct()
15
+ {
16
+ parent::__construct();
17
+ }
18
+
19
+ public function apply(Zend_Controller_Request_Abstract $request, $filterBlock)
20
+ {
21
+
22
+ $filter = Mage::helper('ajaxify')->getParam($this->_requestVar);
23
+ $filter = explode('-', $filter);
24
+
25
+ $ids = array();
26
+ foreach ($filter as $id){
27
+ $id = intVal($id);
28
+ if ($id)
29
+ $ids[] = $id;
30
+ }
31
+ if ($ids){
32
+ $this->applyMultipleValuesFilter($ids);
33
+ }
34
+
35
+ $this->setActiveState($ids);
36
+ return $this;
37
+ }
38
+
39
+ protected function applyMultipleValuesFilter($ids)
40
+ {
41
+ $collection = $this->getLayer()->getProductCollection();
42
+ $attribute = $this->getAttributeModel();
43
+ $table = Mage::getSingleton('core/resource')->getTableName('catalogindex/eav');
44
+
45
+ $alias = 'attr_index_'.$attribute->getId();
46
+ $collection->getSelect()->join(
47
+ array($alias => $table),
48
+ $alias.'.entity_id=e.entity_id',
49
+ array()
50
+ )
51
+ ->where($alias.'.store_id = ?', Mage::app()->getStore()->getId())
52
+ ->where($alias.'.attribute_id = ?', $attribute->getId())
53
+ ->where($alias.'.value IN (?)', $ids);
54
+ if (count($ids)>1){
55
+ $collection->getSelect()->distinct(true);
56
+ }
57
+
58
+ return $this;
59
+ }
60
+
61
+ /**
62
+ * Get data array for building attribute filter items
63
+ *
64
+ * @return array
65
+ */
66
+ protected function _getItemsData()
67
+ {
68
+ $attribute = $this->getAttributeModel();
69
+ $this->_requestVar = $attribute->getAttributeCode();
70
+
71
+ $key = $this->getLayer()->getStateKey();
72
+ $key .= Mage::helper('ajaxify')->getCacheKey($this->_requestVar);
73
+
74
+ $data = $this->getLayer()->getAggregator()->getCacheData($key);
75
+
76
+ if ($data === null) {
77
+ $data = array();
78
+
79
+ $options = $attribute->getFrontend()->getSelectOptions();
80
+
81
+ $optionsCount = Mage::getSingleton('catalogindex/attribute')->getCount(
82
+ $attribute,
83
+ $this->_getBaseCollectionSql()
84
+ );
85
+
86
+ foreach ($options as $option) {
87
+ if (is_array($option['value'])) {
88
+ continue;
89
+ }
90
+ if (Mage::helper('core/string')->strlen($option['value'])) {
91
+ // Check filter type
92
+ if ($attribute->getIsFilterable() == self::OPTIONS_ONLY_WITH_RESULTS) {
93
+ if (!empty($optionsCount[$option['value']])) {
94
+ $data[] = array(
95
+ 'label' => $option['label'],
96
+ 'value' => $option['value'],
97
+ 'count' => $optionsCount[$option['value']],
98
+ );
99
+ }
100
+ }
101
+ else {
102
+ $data[] = array(
103
+ 'label' => $option['label'],
104
+ 'value' => $option['value'],
105
+ 'count' => isset($optionsCount[$option['value']]) ? $optionsCount[$option['value']] : 0,
106
+ );
107
+ }
108
+ }
109
+ }
110
+
111
+ $currentIds = Mage::helper('ajaxify')->getParam($attribute->getAttributeCode());
112
+ $tags = array(
113
+ Mage_Eav_Model_Entity_Attribute::CACHE_TAG . ':' . $currentIds,
114
+ );
115
+
116
+ $tags = $this->getLayer()->getStateTags($tags);
117
+ $this->getLayer()->getAggregator()->saveCacheData($data, $key, $tags);
118
+ }
119
+ return $data;
120
+ }
121
+
122
+ protected function _getBaseCollectionSql()
123
+ {
124
+ $alias = 'attr_index_' . $this->getAttributeModel()->getId();
125
+ // Varien_Db_Select
126
+ $baseSelect = clone parent::_getBaseCollectionSql();
127
+
128
+ // 1) remove from conditions
129
+ $oldWhere = $baseSelect->getPart(Varien_Db_Select::WHERE);
130
+ $newWhere = array();
131
+
132
+ foreach ($oldWhere as $cond){
133
+ if (!strpos($cond, $alias))
134
+ $newWhere[] = $cond;
135
+ }
136
+
137
+ if ($newWhere && substr($newWhere[0], 0, 3) == 'AND')
138
+ $newWhere[0] = substr($newWhere[0],3);
139
+
140
+ $baseSelect->setPart(Varien_Db_Select::WHERE, $newWhere);
141
+
142
+ // 2) remove from joins
143
+ $oldFrom = $baseSelect->getPart(Varien_Db_Select::FROM);
144
+ $newFrom = array();
145
+
146
+ foreach ($oldFrom as $name=>$val){
147
+ if ($name != $alias)
148
+ $newFrom[$name] = $val;
149
+ }
150
+ //it assumes we have at least one table
151
+ $baseSelect->setPart(Varien_Db_Select::FROM, $newFrom);
152
+
153
+ return $baseSelect;
154
+ }
155
+
156
+ protected function _getResource()
157
+ {
158
+ if (is_null($this->_resource)) {
159
+ $this->_resource = Mage::getResourceModel('catalog/layer_filter_attribute');
160
+ }
161
+ return $this->_resource;
162
+ }
163
+
164
+ }
app/code/community/Ve/Ajaxify/Model/Layer/Filter/Category.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Model_Layer_Filter_Category
11
+ */
12
+ class Ve_Ajaxify_Model_Layer_Filter_Category extends Mage_Catalog_Model_Layer_Filter_Category {
13
+
14
+ protected $cat = null;
15
+
16
+ public function apply(Zend_Controller_Request_Abstract $request, $filterBlock) {
17
+ // very small optimization
18
+ $catId = (int) Mage::helper('ajaxify')->getParam($this->getRequestVar());
19
+ if ($catId) {
20
+ $request->setParam($this->getRequestVar(), $catId);
21
+ parent::apply($request, $filterBlock);
22
+ }
23
+ return $this;
24
+ }
25
+
26
+ public function getRootCategory() {
27
+ if (is_null($this->cat)) {
28
+ $this->cat = Mage::getModel('catalog/category')
29
+ ->load($this->getLayer()->getCurrentStore()->getRootCategoryId());
30
+ }
31
+ return $this->cat;
32
+ }
33
+
34
+ protected function _getItemsData() {
35
+ $key = $this->getLayer()->getStateKey() . '_SUBCATEGORIES';
36
+ $key .= Mage::helper('ajaxify')->getCacheKey('cat');
37
+ $pageKey = Mage::getBlockSingleton('page/html_pager')->getPageVarName();
38
+ $queryStr = Mage::helper('ajaxify')->getParams(true, $pageKey);
39
+ $data = $this->getLayer()->getAggregator()->getCacheData($key);
40
+
41
+ if ($data === null) {
42
+ $category = null;
43
+ $showTopCategories = Mage::getStoreConfig('ajaxify/ajaxifynavigation/top_cats');
44
+ if ($showTopCategories)
45
+ $category = $this->getRootCategory();
46
+ else
47
+ $category = $this->getCategory();
48
+ Mage::register('selected_cat_id', $category->getId());
49
+ /** @var $categoty Mage_Catalog_Model_Categeory */
50
+ $categories = $category->getChildrenCategories();
51
+ $data = array();
52
+ $level = 0;
53
+ $parent = null;
54
+ if ($category->getLevel() > 1) { // current category is not root
55
+ $parent = $category->getParentCategory();
56
+
57
+ ++$level;
58
+ if ($parent->getLevel() > 1) {
59
+ $data[] = array(
60
+ 'label' => $parent->getName(),
61
+ 'value' => $parent->getUrl(),
62
+ 'level' => $level,
63
+ 'category_id' => $parent->getId(),
64
+ 'uri' => $queryStr,
65
+ );
66
+ }
67
+ //always include current category
68
+ ++$level;
69
+ $data[] = array(
70
+ 'label' => $category->getName(),
71
+ 'value' => '',
72
+ 'level' => $level,
73
+ 'is_current' => true,
74
+ 'category_id' => $category->getId(),
75
+ 'uri' => $queryStr,
76
+ );
77
+ }
78
+
79
+ if (!$showTopCategories) {
80
+ $this->getLayer()->getProductCollection()
81
+ ->addCountToCategories($categories);
82
+ }
83
+
84
+
85
+ ++$level;
86
+ foreach ($categories as $cat) {
87
+ if ($cat->getIsActive() && ($showTopCategories || $cat->getProductCount())) {
88
+ $data[] = array(
89
+ 'label' => $cat->getName(),
90
+ 'value' => $cat->getId(),
91
+ 'count' => $cat->getProductCount(),
92
+ 'level' => $level,
93
+ 'category_id' => $cat->getId(),
94
+ 'uri' => $cat->getUrl(),
95
+ );
96
+ }
97
+ }
98
+
99
+
100
+
101
+ if (Mage::getStoreConfig('ajaxify/ajaxifynavigation/reset_filters')) {
102
+ $queryStr = '';
103
+ }
104
+
105
+ for ($i = 0, $n = sizeof($data); $i < $n; ++$i) {
106
+ $url = $data[$i]['uri'];
107
+ $pos = strpos($url, '?');
108
+ if ($pos)
109
+ $url = substr($url, 0, $pos);
110
+ $data[$i]['uri'] = $url . $queryStr;
111
+ }
112
+ $tags = $this->getLayer()->getStateTags();
113
+ $this->getLayer()->getAggregator()->saveCacheData($data, $key, $tags);
114
+ }
115
+ // print_r($data);
116
+ return $data;
117
+ }
118
+
119
+ protected function _initItems() {
120
+ $data = $this->_getItemsData();
121
+ $items = array();
122
+ foreach ($data as $itemData) {
123
+ $obj = new Varien_Object();
124
+ $obj->setData($itemData);
125
+ $obj->setUrl($itemData['value']);
126
+
127
+ $items[] = $obj;
128
+ }
129
+ $this->_items = $items;
130
+ return $this;
131
+ }
132
+
133
+ }
app/code/community/Ve/Ajaxify/Model/Layer/Filter/Categorysearch.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Model_Layer_Filter_Categorysearch
11
+ */
12
+
13
+ class Ve_Ajaxify_Model_Layer_Filter_Categorysearch extends Mage_Catalog_Model_Layer_Filter_Category
14
+ {
15
+ protected function _getItemsData()
16
+ {
17
+ $key = $this->getLayer()->getStateKey().'_SEARCH_SUBCATEGORIES';
18
+ $key .= Mage::helper('ajaxify')->getCacheKey('cat');
19
+ $data = $this->getLayer()->getAggregator()->getCacheData($key);
20
+
21
+ if ($data === null) {
22
+ $category = $this->getCategory();
23
+
24
+ /** @var $categoty Mage_Catalog_Model_Categeory */
25
+ $categories = $category->getChildrenCategories();
26
+
27
+ $data = array();
28
+ $level = 0;
29
+ if ($category->getLevel() > 1){ // current category is not root
30
+ $parent = $category->getParentCategory();
31
+
32
+ ++$level;
33
+ if ($parent->getLevel()>1){
34
+ $data[] = array(
35
+ 'label' => $parent->getName(),
36
+ 'value' => $parent->getId(),
37
+ 'count' => 0,
38
+ 'level' => $level,
39
+ 'uri' => $queryStr,
40
+ );
41
+
42
+
43
+ }
44
+ //always include current category
45
+ ++$level;
46
+ $data[] = array(
47
+ 'label' => $category->getName(),
48
+ 'value' => '',
49
+ 'level' => $level,
50
+ 'is_current' => true,
51
+ 'uri' => $queryStr,
52
+ );
53
+ }
54
+
55
+ $this->getLayer()->getProductCollection()
56
+ ->addCountToCategories($categories);
57
+
58
+ if ($parentId){
59
+ $data[0]['count'] = $parent->getProductCount();
60
+ $categories->removeItemByKey($parentId);
61
+ }
62
+
63
+ ++$level;
64
+ foreach ($categories as $cat) {
65
+ if ($cat->getIsActive() && $cat->getProductCount()) {
66
+ $data[] = array(
67
+ 'label' => $cat->getName(),
68
+ 'value' => $cat->getId(),
69
+ 'count' => $cat->getProductCount(),
70
+ 'level' => $level,
71
+ 'category_id' => $cat->getId(),
72
+ 'uri' => $cat->getUrl(),
73
+ );
74
+ }
75
+ }
76
+ $tags = $this->getLayer()->getStateTags();
77
+ $this->getLayer()->getAggregator()->saveCacheData($data, $key, $tags);
78
+ }
79
+ if (Mage::getStoreConfig('ajaxify/ajaxifynavigation/reset_filters'))
80
+ {
81
+ $queryStr = '';
82
+ }
83
+ $pageKey = Mage::getBlockSingleton('page/html_pager')->getPageVarName();
84
+ $queryStr = Mage::helper('ajaxify')->getParams(true, $pageKey);
85
+ for ($i=0, $n=sizeof($data); $i<$n; ++$i) {
86
+ $url = $data[$i]['uri'];
87
+ $pos = strpos($url, '?');
88
+ if ($pos)
89
+ $url = substr($url, 0, $pos);
90
+ $data[$i]['uri'] = $url . $queryStr;
91
+ }
92
+ return $data;
93
+ }
94
+
95
+ protected function _initItems()
96
+ {
97
+ $data = $this->_getItemsData();
98
+ $items = array();
99
+ foreach ($data as $itemData) {
100
+ $obj = Mage::getModel('catalog/layer_filter_item');
101
+ $obj->setData($itemData);
102
+ $obj->setFilter($this);
103
+
104
+ $items[] = $obj;
105
+ }
106
+ $this->_items = $items;
107
+ return $this;
108
+ }
109
+ }
app/code/community/Ve/Ajaxify/Model/Layer/Filter/Price.php ADDED
@@ -0,0 +1,606 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Model_Layer_Filter_Price
11
+ */
12
+
13
+ class Ve_Ajaxify_Model_Layer_Filter_Price extends Mage_Catalog_Model_Layer_Filter_Price
14
+ {
15
+ protected $baseSelect = null;
16
+
17
+ public function __construct()
18
+ {
19
+ parent::__construct();
20
+ }
21
+
22
+ protected function _getItemsData()
23
+ {
24
+ $data = array();
25
+ $style = Mage::getStoreConfig('ajaxify/ajaxifynavigation/price_style');
26
+ if ('default' == $style)
27
+ {
28
+ if ($this->getMaxPriceInt())
29
+ {
30
+ if ($this->getAttributeModel()->getAttributeCode() == 'price')
31
+ {
32
+ try {
33
+ return parent::_getItemsData();
34
+ } catch (Zend_Db_No_Exception $e)
35
+ {
36
+ return array();
37
+ }
38
+ }
39
+ else
40
+ {
41
+ return $this->_getDecimalItemsData();
42
+ }
43
+ }
44
+ else
45
+ {
46
+ return array();
47
+ }
48
+ }
49
+ elseif('input' == $style){
50
+ list($from, $to) = $this->getFilterValueFromRequest();
51
+ $data[] = array(
52
+ 'label' => '',
53
+ 'value' => $from . ',' . $to,
54
+ 'count' => 1,
55
+ );
56
+ }
57
+ elseif('slider' == $style){
58
+ $data[] = array(
59
+ 'label' => '',
60
+ 'value' => 0 . ',' . $this->getMaxPriceInt()+1,
61
+ 'count' => 1,
62
+ );
63
+ }
64
+ elseif('both' == $style){
65
+ list($from, $to) = $this->getFilterValueFromRequest();
66
+ $data[] = array(
67
+ 'label' => '',
68
+ 'value' => $from . ',' . $to,
69
+ 'count' => 1,
70
+ );
71
+ }
72
+
73
+ return $data;
74
+ }
75
+
76
+ protected function _getCacheKey()
77
+ {
78
+ $key = parent::_getCacheKey();
79
+ $key .= Mage::getStoreConfig('ajaxify/ajaxifynavigation/price_style');
80
+ $key .= Mage::helper('ajaxify')->getCacheKey('price');
81
+ return $key;
82
+ }
83
+
84
+ private function getFilterValueFromRequest()
85
+ {
86
+ $filter = Mage::helper('ajaxify')->getParam($this->_requestVar);
87
+
88
+ if (!$filter) {
89
+ return array(0, 0);
90
+ }
91
+
92
+ $filter = explode(',', $filter);
93
+
94
+ if (count($filter) != 2) {
95
+ return array(0, 0);
96
+ }
97
+
98
+ list($from, $to) = $filter;
99
+ $from = sprintf("%.02f", $from);
100
+ $to = sprintf("%.02f", $to);
101
+
102
+ return array($from, $to);
103
+ }
104
+
105
+ /**
106
+ * Apply price range filter to collection
107
+ *
108
+ * @return Mage_Catalog_Model_Layer_Filter_Price
109
+ */
110
+ public function apply(Zend_Controller_Request_Abstract $request, $filterBlock)
111
+ {
112
+ list($from, $to) = $this->getFilterValueFromRequest();
113
+
114
+ if ('default' == Mage::getStoreConfig('ajaxify/ajaxifynavigation/price_style'))
115
+ {
116
+ $attribute = $this->getAttributeModel();
117
+
118
+ $index = $from;
119
+ $rate = $to;
120
+
121
+ $from = ($index-1)*$rate;
122
+ $to = $index*$rate;
123
+
124
+ $this->setActiveState(sprintf('%d,%d', $index, $rate));
125
+ }
126
+ else{
127
+ $this->setActiveState($from . ','. $to);
128
+ }
129
+
130
+ $this->baseSelect = clone $this->getLayer()->getProductCollection()->getSelect();
131
+ if ($from >= 0.01 || $to >= 0.01) {
132
+ $this->applyFromToFilter($from, $to);
133
+
134
+ }
135
+
136
+ return $this;
137
+ }
138
+
139
+ // copied from Mage_CatalogIndex_Model_Mysql4_Price,
140
+ // bacause of AWFULL!!! design: the method accept $range, $index INSTEAD OF $from, $to args
141
+ // hope you, my reader, understand that is it incorrect in terms of tiers (library
142
+ // function shouldn't know about logic of price ranges ...
143
+ protected function applyFromToFilter($from, $to)
144
+ {
145
+ $attribute = $this->getAttributeModel();
146
+
147
+ $tableAlias = $attribute->getAttributeCode() . '_idx';
148
+
149
+ if ($attribute->getAttributeCode() == 'price')
150
+ {
151
+ $bIsBasePrice = true;
152
+ $tableName = Mage::getSingleton('core/resource')->getTableName('catalogindex/price');
153
+ $valueAlias = 'min_price';
154
+ }
155
+ else
156
+ {
157
+ $bIsBasePrice = false;
158
+ $tableName = Mage::getSingleton('core/resource')->getTableName('catalog/product_index_eav_decimal');
159
+ $valueAlias = 'value';
160
+ }
161
+
162
+ $collection = $this->getLayer()->getProductCollection();
163
+ $websiteId = Mage::app()->getStore()->getWebsiteId();
164
+ $custGroupId = Mage::getSingleton('customer/session')->getCustomerGroupId();
165
+
166
+ /**
167
+ * Distinct required for removing duplicates in case when we have grouped products
168
+ * which contain multiple rows for one product id
169
+ */
170
+
171
+ $collection->getSelect()->distinct(true);
172
+
173
+ $sOnStatement = $tableAlias . '.entity_id=e.entity_id';
174
+
175
+ if (!$bIsBasePrice)
176
+ {
177
+ $sOnStatement .= ' AND ' . $tableAlias . '.attribute_id = ' .$attribute->getId() . ' AND ' . $tableAlias . '.store_id = ' . Mage::app()->getStore()->getId();
178
+ }
179
+ try {
180
+ $collection->getSelect()->joinLeft(
181
+ array($tableAlias => $tableName),
182
+ $sOnStatement,
183
+ array()
184
+ );
185
+ } catch (Zend_No_Exception $e) {
186
+ return $this;
187
+ }
188
+
189
+
190
+ $response = new Varien_Object();
191
+ $response->setAdditionalCalculations(array());
192
+
193
+ if ($bIsBasePrice)
194
+ {
195
+ $collection->getSelect()
196
+ ->where($tableAlias . '.website_id = ?', $websiteId) // modified line
197
+ ;
198
+ }
199
+
200
+ if ($attribute->getAttributeCode() == 'price') {
201
+ $collection->getSelect()->where($tableAlias . '.customer_group_id = ?', $custGroupId); // modified line
202
+ $args = array(
203
+ 'select' => $collection->getSelect(),
204
+ 'table' => $tableAlias,
205
+ 'store_id' => Mage::app()->getStore()->getId(), // modified line
206
+ 'response_object'=> $response,
207
+ );
208
+ Mage::dispatchEvent('catalogindex_prepare_price_select', $args);
209
+ }
210
+
211
+ $rate = $this->_getCurrencyRate();
212
+
213
+ // make query a little bit faster
214
+ if ($from > 0.01)
215
+ $collection->getSelect()->where("(({$tableAlias}.{$valueAlias}".implode('', $response->getAdditionalCalculations()).")*$rate) >= ?", $from);
216
+ if ($to > 0.01)
217
+ $collection->getSelect()->where("(({$tableAlias}.{$valueAlias}".implode('', $response->getAdditionalCalculations()).")*$rate) <= ?", $to);
218
+
219
+ $this->_isTableJoined = true;
220
+ return $this;
221
+ }
222
+
223
+ protected $_isTableJoined = null;
224
+
225
+ protected function _getBaseCollectionSql()
226
+ {
227
+ return $this->baseSelect;
228
+ }
229
+
230
+ protected function _getCurrencyRate()
231
+ {
232
+ $rate = Mage::app()->getStore()->convertPrice(1000000, false);
233
+
234
+ $rate = $rate / 1000000;
235
+
236
+ return $rate;
237
+ }
238
+
239
+ public function getMaxPriceInt() /// to do - make like minmax!!
240
+ {
241
+
242
+ list($min,$max) = $this->getMinMaxPriceInt();
243
+
244
+ return $max;
245
+ }
246
+
247
+ protected function getMinMax($filter, $bIsBasePrice)
248
+ {
249
+ $attribute = $this->getAttributeModel();
250
+ $mainCollection = $this->getLayer()->getProductCollection();
251
+ $websiteId = Mage::app()->getStore()->getWebsiteId();
252
+ $custGroupId = Mage::getSingleton('customer/session')->getCustomerGroupId();
253
+
254
+ $select = clone $mainCollection->getSelect();
255
+
256
+ $select->setPart(Varien_Db_Select::COLUMNS, array());
257
+ $select->setPart(Varien_Db_Select::ORDER , array());
258
+
259
+ $select->distinct(false);
260
+
261
+ $tableAlias = $attribute->getAttributeCode() . '_idx';
262
+
263
+ if ($bIsBasePrice)
264
+ {
265
+ $tableName = Mage::getSingleton('core/resource')->getTableName('catalogindex/price');
266
+ $valueAlias = 'min_price';
267
+ }
268
+ else
269
+ {
270
+ $tableName = Mage::getSingleton('core/resource')->getTableName('catalog/product_index_eav_decimal');
271
+ $valueAlias = 'value';
272
+ }
273
+
274
+ $select->columns(array(
275
+ 'min_value' => new Zend_Db_Expr('MIN(' . $tableAlias . '.' . $valueAlias . ')'),
276
+ 'max_value' => new Zend_Db_Expr('MAX(' . $tableAlias . '.' . $valueAlias . ')'),
277
+ ));
278
+
279
+ if ($this->_isTableJoined)
280
+ {
281
+ $oldWhere = $select->getPart(Varien_Db_Select::WHERE);
282
+
283
+ $newWhere = array();
284
+
285
+ $alias = $tableAlias . '.' . $valueAlias;
286
+
287
+ foreach ($oldWhere as $cond){
288
+ if (!strpos($cond, $alias))
289
+ {
290
+ $newWhere[] = $cond;
291
+ }
292
+ }
293
+
294
+ if ($newWhere && substr($newWhere[0], 0, 3) == 'AND')
295
+ $newWhere[0] = substr($newWhere[0],3);
296
+
297
+ $select->setPart(Varien_Db_Select::WHERE, $newWhere);
298
+ }
299
+ else
300
+ {
301
+ $sOnStatement = $tableAlias . '.entity_id=e.entity_id';
302
+
303
+ if (!$bIsBasePrice)
304
+ {
305
+ $sOnStatement .= ' AND ' . $tableAlias . '.attribute_id = ' .$attribute->getId() . ' AND ' . $tableAlias . '.store_id = ' . Mage::app()->getStore()->getId();
306
+ }
307
+ try {
308
+ $select->joinLeft(
309
+ array($tableAlias => $tableName), // modified line
310
+ $sOnStatement,
311
+ array()
312
+ );
313
+ } catch (Zend_Db_No_Exception $e) {
314
+ return $this;
315
+ }
316
+
317
+
318
+ $response = new Varien_Object();
319
+ $response->setAdditionalCalculations(array());
320
+
321
+ if ($bIsBasePrice)
322
+ {
323
+ $select
324
+ ->where($tableAlias . '.website_id = ?', $websiteId) // modified line
325
+ ;
326
+ }
327
+
328
+ if ($bIsBasePrice)
329
+ {
330
+ $select->where($tableAlias . '.customer_group_id = ?', $custGroupId); // modified line
331
+ $args = array(
332
+ 'select' => $select,
333
+ 'table' => $tableAlias,
334
+ 'store_id' => Mage::app()->getStore()->getId(), // modified line
335
+ 'response_object'=> $response,
336
+ );
337
+ Mage::dispatchEvent('catalogindex_prepare_price_select', $args);
338
+ }
339
+ }
340
+
341
+ $adapter = Mage::getSingleton('core/resource')->getConnection('core_read');
342
+ $result = $adapter->fetchRow($select);
343
+ $rate = $this->_getCurrencyRate();
344
+
345
+ return array($result['min_value'] * $rate, ceil($result['max_value'] * $rate));
346
+ }
347
+
348
+
349
+
350
+ public function getMinMaxPriceInt()
351
+ {
352
+ $attribute = $this->getAttributeModel();
353
+
354
+ if ($attribute->getAttributeCode() == 'price')
355
+ {
356
+ list($min, $max) = $this->getMinMax($this, true);
357
+ }
358
+ else
359
+ {
360
+ list($min, $max) = $this->getMinMax($this, false);
361
+ }
362
+
363
+ $max = floor($max);
364
+ $min = floor($min);
365
+
366
+ return array($min, $max);
367
+ }
368
+
369
+ /**
370
+ * Retrieve data for build decimal filter items
371
+ *
372
+ * @return array
373
+ */
374
+ protected function _getDecimalItemsData()
375
+ {
376
+ $key = $this->_getDecimalCacheKey();
377
+
378
+ $data = $this->getLayer()->getAggregator()->getCacheData($key);
379
+
380
+ if ($data === null) {
381
+ $data = array();
382
+ $range = $this->getRange();
383
+ $dbRanges = $this->getDecimalRangeItemCounts($range);
384
+
385
+ foreach ($dbRanges as $index => $count) {
386
+ $data[] = array(
387
+ 'label' => $this->_renderItemLabel($range, $index),
388
+ 'value' => $index . ',' . $range,
389
+ 'count' => $count,
390
+ );
391
+ }
392
+
393
+
394
+ }
395
+ return $data;
396
+ }
397
+
398
+ const MIN_RANGE_POWER = 10;
399
+
400
+ /**
401
+ * Resource instance
402
+ *
403
+ * @var Mage_Catalog_Model_Resource_Eav_Mysql4_Layer_Filter_Decimal
404
+ */
405
+ protected $_resource;
406
+
407
+ protected function _getResource()
408
+ {
409
+ if (is_null($this->_resource)) {
410
+ if ($this->getAttributeModel()->getAttributeCode() == 'price')
411
+ {
412
+ $this->_resource = Mage::getResourceModel('catalog/layer_filter_price');
413
+ }
414
+ else
415
+ {
416
+ $this->_resource = Mage::getResourceModel('catalog/layer_filter_decimal');
417
+ }
418
+ }
419
+ return $this->_resource;
420
+ }
421
+
422
+ /**
423
+ * Apply decimal range filter to product collection
424
+ *
425
+ * @param Zend_Controller_Request_Abstract $request
426
+ * @param Mage_Catalog_Block_Layer_Filter_Decimal $filterBlock
427
+ * @return Mage_Catalog_Model_Layer_Filter_Decimal
428
+ */
429
+
430
+ public function _______apply(Zend_Controller_Request_Abstract $request, $filterBlock)
431
+ {
432
+ parent::apply($request, $filterBlock);
433
+
434
+ /**
435
+ * Filter must be string: $index, $range
436
+ */
437
+ $filter = $request->getParam($this->getRequestVar());
438
+ if (!$filter) {
439
+ return $this;
440
+ }
441
+
442
+ $filter = explode(',', $filter);
443
+ if (count($filter) != 2) {
444
+ return $this;
445
+ }
446
+
447
+ list($index, $range) = $filter;
448
+ if ((int)$index && (int)$range) {
449
+ $this->setRange((int)$range);
450
+
451
+ $this->_getResource()->applyFilterToCollection($this, $range, $index);
452
+ $this->getLayer()->getState()->addFilter(
453
+ $this->_createItem($this->_renderItemLabel($range, $index), $filter)
454
+ );
455
+
456
+ $this->_items = array();
457
+ }
458
+
459
+ return $this;
460
+ }
461
+
462
+ /**
463
+ * Retrieve price aggreagation data cache key
464
+ *
465
+ * @return string
466
+ */
467
+ protected function _getDecimalCacheKey()
468
+ {
469
+ $key = $this->getLayer()->getStateKey()
470
+ . '_ATTR_' . $this->getAttributeModel()->getAttributeCode();
471
+ return $key;
472
+ }
473
+
474
+ /**
475
+ * Prepare text of item label
476
+ *
477
+ * @param int $range
478
+ * @param float $value
479
+ * @return string
480
+ */
481
+ protected function _renderItemLabel($range, $value)
482
+ {
483
+ $from = Mage::app()->getStore()->formatPrice(($value - 1) * $range, false);
484
+ $to = Mage::app()->getStore()->formatPrice($value * $range, false);
485
+ return Mage::helper('catalog')->__('%s - %s', $from, $to);
486
+ }
487
+
488
+ /**
489
+ * Retrieve maximum value from layer products set
490
+ *
491
+ * @return float
492
+ */
493
+ public function getMaxValue()
494
+ {
495
+ $max = $this->getData('max_value');
496
+ if (is_null($max)) {
497
+ // list($min, $max) = $this->_getResource()->getMinMax($this);
498
+ list($min, $max) = $this->getMinMax($this, false);
499
+
500
+ $this->setData('max_value', $max);
501
+ $this->setData('min_value', $min);
502
+ }
503
+ return $max;
504
+ }
505
+
506
+ /**
507
+ * Retrieve minimal value from layer products set
508
+ *
509
+ * @return float
510
+ */
511
+ public function getMinValue()
512
+ {
513
+ $min = $this->getData('min_value');
514
+ if (is_null($min)) {
515
+ list($min, $max) = $this->_getResource()->getMinMax($this);
516
+ $this->setData('max_value', $max);
517
+ $this->setData('min_value', $min);
518
+ }
519
+ return $min;
520
+ }
521
+
522
+ /**
523
+ * Retrieve range for building filter steps
524
+ *
525
+ * @return int
526
+ */
527
+ public function getRange()
528
+ {
529
+ $range = $this->getData('range');
530
+ if (is_null($range)) {
531
+ $max = $this->getMaxValue();
532
+ $index = 1;
533
+ do {
534
+ $range = pow(10, (strlen(floor($max)) - $index));
535
+ $items = $this->getDecimalRangeItemCounts($range);
536
+ $index ++;
537
+ }
538
+ while($range > self::MIN_RANGE_POWER && count($items) < 2);
539
+
540
+ $this->setData('range', $range);
541
+ }
542
+ return $range;
543
+ }
544
+
545
+ /**
546
+ * Retrieve information about products count in range
547
+ *
548
+ * @param int $range
549
+ * @return int
550
+ */
551
+ public function getDecimalRangeItemCounts($range)
552
+ {
553
+ $rangeKey = 'range_item_counts_' . $range;
554
+ $items = $this->getData($rangeKey);
555
+ if (is_null($items)) {
556
+ $items = $this->_getResourceCount($this, $range);
557
+ $this->setData($rangeKey, $items);
558
+ }
559
+ return $items;
560
+ }
561
+
562
+ protected function _getResourceCount($filter, $range)
563
+ {
564
+ $select = $this->_getDecimalSelect($filter);
565
+ $connection = Mage::getSingleton('core/resource')->getConnection('core_read');
566
+
567
+ $table = 'decimal_index';
568
+
569
+ $additional = '';
570
+
571
+ $rate = $filter->getCurrencyRate();
572
+ $countExpr = new Zend_Db_Expr("COUNT(*)");
573
+ $rangeExpr = new Zend_Db_Expr("FLOOR((({$table}.value {$additional}) * {$rate}) / {$range}) + 1");
574
+
575
+ $select->columns(array(
576
+ 'range' => $rangeExpr,
577
+ 'count' => $countExpr
578
+ ));
579
+ $select->where("{$table}.value > 0");
580
+ $select->group('range');
581
+ return $connection->fetchPairs($select);
582
+ }
583
+
584
+ protected function _getDecimalSelect($filter)
585
+ {
586
+ $collection = $filter->getLayer()->getProductCollection();
587
+ $select = clone $collection->getSelect();
588
+ $select->reset(Zend_Db_Select::COLUMNS);
589
+ $select->reset(Zend_Db_Select::ORDER);
590
+ $select->reset(Zend_Db_Select::LIMIT_COUNT);
591
+ $select->reset(Zend_Db_Select::LIMIT_OFFSET);
592
+
593
+ $attributeId = $filter->getAttributeModel()->getId();
594
+ $storeId = $collection->getStoreId();
595
+
596
+ $select->join(
597
+ array('decimal_index' => $this->_getResource()->getMainTable()),
598
+ "e.entity_id=decimal_index.entity_id AND decimal_index.attribute_id={$attributeId}"
599
+ . " AND decimal_index.store_id={$storeId}",
600
+ array()
601
+ );
602
+
603
+ return $select;
604
+ }
605
+
606
+ }
app/code/community/Ve/Ajaxify/Model/Observer.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Model_Observer
11
+ */
12
+ class Ve_Ajaxify_Model_Observer {
13
+
14
+ public function addToCartEvent($observer) {
15
+ if (Mage::getStoreConfig('ajaxify/ajaxifycart/ajaxify_cart') == 0) {
16
+ return $observer;
17
+ }
18
+ $request = Mage::app()->getFrontController()->getRequest();
19
+ if (!$request->getParam('in_cart') && !$request->getParam('is_checkout')) {
20
+
21
+ Mage::getSingleton('checkout/session')->setNoCartRedirect(true);
22
+
23
+ $_response = Mage::getModel('ajaxify/response')
24
+ ->setProductName($observer->getProduct()->getName())
25
+ ->setMessage(Mage::helper('checkout')->__('%s was added into cart.', $observer->getProduct()->getName()));
26
+
27
+ //append updated blocks
28
+ $_response->addUpdatedBlocks($_response);
29
+
30
+ $_response->send();
31
+ }
32
+ if ($request->getParam('is_checkout')) {
33
+
34
+ Mage::getSingleton('checkout/session')->setNoCartRedirect(true);
35
+
36
+ $_response = Mage::getModel('ajaxify/response')
37
+ ->setProductName($observer->getProduct()->getName())
38
+ ->setMessage(Mage::helper('checkout')->__('%s was added into cart.', $observer->getProduct()->getName()));
39
+ $_response->send();
40
+ }
41
+ }
42
+
43
+ public function updateItemEvent($observer) {
44
+ if (Mage::getStoreConfig('ajaxify/ajaxifycart/ajaxify_cart') == 0) {
45
+ return $observer;
46
+ }
47
+
48
+ $request = Mage::app()->getFrontController()->getRequest();
49
+
50
+ if (!$request->getParam('in_cart') && !$request->getParam('is_checkout')) {
51
+
52
+ Mage::getSingleton('checkout/session')->setNoCartRedirect(true);
53
+
54
+ $_response = Mage::getModel('ajaxify/response')
55
+ ->setMessage(Mage::helper('checkout')->__('Item was updated.'));
56
+
57
+ //append updated blocks
58
+ $_response->addUpdatedBlocks($_response);
59
+
60
+ $_response->send();
61
+ }
62
+ if ($request->getParam('is_checkout')) {
63
+
64
+ Mage::getSingleton('checkout/session')->setNoCartRedirect(true);
65
+
66
+ $_response = Mage::getModel('ajaxify/response')
67
+ ->setMessage(Mage::helper('checkout')->__('Item was updated.'));
68
+ $_response->send();
69
+ }
70
+ }
71
+
72
+ public function getConfigurableOptions($observer) {
73
+ if (Mage::getStoreConfig('ajaxify/ajaxifycart/ajaxify_cart') == 0) {
74
+ return $observer;
75
+ }
76
+ $is_ajax = Mage::app()->getFrontController()->getRequest()->getParam('ajax');
77
+
78
+ if ($is_ajax) {
79
+ $_response = Mage::getModel('ajaxify/response');
80
+
81
+ $product = Mage::registry('current_product');
82
+ if (!$product->isConfigurable() && !$product->getTypeId() == 'bundle') {
83
+ return false;
84
+ exit;
85
+ }
86
+
87
+ //append configurable options block
88
+ $_response->addConfigurableOptionsBlock($_response);
89
+ $_response->send();
90
+ }
91
+ return;
92
+ }
93
+
94
+ public function getGroupProductOptions() {
95
+ if (Mage::getStoreConfig('ajaxify/ajaxifycart/ajaxify_cart') == 0) {
96
+ return $observer;
97
+ }
98
+ $id = Mage::app()->getFrontController()->getRequest()->getParam('product');
99
+ $options = Mage::app()->getFrontController()->getRequest()->getParam('super_group');
100
+
101
+ if ($id) {
102
+ $product = Mage::getModel('catalog/product')->load($id);
103
+ if ($product->getData()) {
104
+ if ($product->getTypeId() == 'grouped' && !$options) {
105
+ $_response = Mage::getModel('ajaxify/response');
106
+ Mage::register('product', $product);
107
+ Mage::register('current_product', $product);
108
+
109
+ //add group product's items block
110
+ $_response->addGroupProductItemsBlock($_response);
111
+ $_response->send();
112
+ }
113
+ }
114
+ }
115
+ }
116
+
117
+ }
app/code/community/Ve/Ajaxify/Model/Response.php ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Model_Response
11
+ */
12
+ class Ve_Ajaxify_Model_Response extends Mage_Catalog_Block_Product_Abstract {
13
+
14
+ public function send() {
15
+ Zend_Json::$useBuiltinEncoderDecoder = true;
16
+ if ($this->getError())
17
+ $this->setR('error');
18
+ else
19
+ $this->setR('success');
20
+ Mage::app()->getFrontController()->getResponse()->setHeader('Content-Type', 'text/plain')->setBody(Zend_Json::encode($this->getData()));
21
+ Mage::app()->getFrontController()->getResponse()->sendResponse();
22
+ die;
23
+ }
24
+
25
+ public function addUpdatedBlocks(&$_response) {
26
+ $layout = Mage::getSingleton('core/layout');
27
+ $res = array();
28
+ $value = $layout->getBlock('cart_sidebar');
29
+ if ($value) {
30
+ $res[] = array('key' => '.block.block-cart', 'value' => $value->toHtml());
31
+ }
32
+ $value = $layout->getBlock('top.links');
33
+ if ($value) {
34
+ $res[] = array('key' => '.header .links', 'value' => $value->toHtml());
35
+ }
36
+ $value = $layout->getBlock('checkout.cart');
37
+ if ($value) {
38
+ $res[] = array('key' => '.checkout-cart-index .cart', 'value' => $value->toHtml());
39
+ }
40
+ $value = $layout->getBlock('minicart_head');
41
+ if ($value) {
42
+ $res[] = array('key' => '.header-minicart', 'value' => $value->toHtml());
43
+ }
44
+
45
+ if (!empty($res)) {
46
+ $_response->setUpdateBlocks($res);
47
+ }
48
+ }
49
+
50
+ public function addConfigurableOptionsBlock(&$_response) {
51
+ $layout = Mage::getSingleton('core/layout');
52
+ $res = '';
53
+ $_product = Mage::registry('current_product');
54
+
55
+ $layout->getUpdate()->addHandle('ajaxify_configurable_options');
56
+
57
+ if ($_product->getTypeId() == 'bundle')
58
+ $layout->getUpdate()->addHandle('ajaxify_bundle_options');
59
+
60
+ // set unique cache ID to bypass caching
61
+ $cacheId = 'LAYOUT_' . Mage::app()->getStore()->getId() . md5(join('__', $layout->getUpdate()->getHandles()));
62
+ $layout->getUpdate()->setCacheId($cacheId);
63
+
64
+ $layout->getUpdate()->load();
65
+ $layout->generateXml();
66
+ $layout->generateBlocks();
67
+
68
+ $value = $layout->getBlock('ajaxify.configurable.options');
69
+
70
+ if ($value) {
71
+ $res .= $value->toHtml();
72
+ }
73
+
74
+ if ($_product->getTypeId() == 'bundle') {
75
+ $value = $layout->getBlock('product.info.bundle');
76
+
77
+ if ($value) {
78
+ $res .= $value->toHtml();
79
+ }
80
+ }
81
+
82
+ if (!empty($res)) {
83
+ $_response->setConfigurableOptionsBlock($res);
84
+ }
85
+ }
86
+
87
+ public function addGroupProductItemsBlock(&$_response) {
88
+ $layout = Mage::getSingleton('core/layout');
89
+ $res = '';
90
+
91
+ $layout->getUpdate()->addHandle('ajaxify_grouped_options');
92
+
93
+ // set unique cache ID to bypass caching
94
+ $cacheId = 'LAYOUT_' . Mage::app()->getStore()->getId() . md5(join('__', $layout->getUpdate()->getHandles()));
95
+ $layout->getUpdate()->setCacheId($cacheId);
96
+
97
+ $layout->getUpdate()->load();
98
+ $layout->generateXml();
99
+ $layout->generateBlocks();
100
+
101
+ $value = $layout->getBlock('ajaxify.grouped.options');
102
+
103
+ if ($value) {
104
+ $res .= $value->toHtml();
105
+ }
106
+
107
+ if (!empty($res)) {
108
+ $_response->setConfigurableOptionsBlock($res);
109
+ }
110
+ }
111
+
112
+ }
app/code/community/Ve/Ajaxify/Model/Select.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Model_Select
11
+ */
12
+
13
+ class Ve_Ajaxify_Model_Select extends Zend_Db_Select
14
+ {
15
+ public function __construct()
16
+ {
17
+ }
18
+
19
+ public function setPart($part, $val){
20
+ $this->_parts[$part] = $val;
21
+ }
22
+ }
app/code/community/Ve/Ajaxify/Model/System/Config/Source/Category.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Model_System_Config_Source_Category
11
+ */
12
+
13
+ class Ve_Ajaxify_Model_System_Config_Source_Category extends Varien_Object
14
+ {
15
+ public function toOptionArray()
16
+ {
17
+ $options = array();
18
+
19
+ $options[] = array(
20
+ 'value'=> 'breadcrumbs',
21
+ 'label' => Mage::helper('ajaxify')->__('Breadcrumbs')
22
+ );
23
+ $options[] = array(
24
+ 'value'=> 'none',
25
+ 'label' => Mage::helper('ajaxify')->__('None')
26
+ );
27
+
28
+ return $options;
29
+ }
30
+ }
app/code/community/Ve/Ajaxify/Model/System/Config/Source/Price.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Model_System_Config_Source_Price
11
+ */
12
+
13
+ class Ve_Ajaxify_Model_System_Config_Source_Price extends Varien_Object
14
+ {
15
+ public function toOptionArray()
16
+ {
17
+ $options = array();
18
+
19
+ $options[] = array(
20
+ 'value'=> 'default',
21
+ 'label' => Mage::helper('ajaxify')->__('Default')
22
+ );
23
+ $options[] = array(
24
+ 'value'=> 'slider',
25
+ 'label' => Mage::helper('ajaxify')->__('Slider')
26
+ );
27
+ $options[] = array(
28
+ 'value'=> 'input',
29
+ 'label' => Mage::helper('ajaxify')->__('Input')
30
+ );
31
+ $options[] = array(
32
+ 'value'=> 'both',
33
+ 'label' => Mage::helper('ajaxify')->__('Both Slider with Input')
34
+ );
35
+
36
+ return $options;
37
+ }
38
+ }
app/code/community/Ve/Ajaxify/Model/System/Config/Source/Swatches.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Model_System_Config_Source_Swatches
11
+ */
12
+
13
+ class Ve_Ajaxify_Model_System_Config_Source_Swatches extends Varien_Object
14
+ {
15
+ public function toOptionArray()
16
+ {
17
+ $options = array();
18
+
19
+ $options[] = array(
20
+ 'value'=> 'link',
21
+ 'label' => Mage::helper('ajaxify')->__('Links Only')
22
+ );
23
+ $options[] = array(
24
+ 'value'=> 'icons',
25
+ 'label' => Mage::helper('ajaxify')->__('Icons Only')
26
+ );
27
+ $options[] = array(
28
+ 'value'=> 'iconslinks',
29
+ 'label' => Mage::helper('ajaxify')->__('Icons + Links')
30
+ );
31
+
32
+ return $options;
33
+ }
34
+ }
app/code/community/Ve/Ajaxify/controllers/CategoryController.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_CategoryController
11
+ */
12
+ class Ve_Ajaxify_CategoryController extends Mage_Core_Controller_Front_Action {
13
+
14
+ public function viewAction() {
15
+
16
+ // init category
17
+ $categoryId = (int) $this->getRequest()->getParam('id', false);
18
+ if (!$categoryId) {
19
+ $this->_forward('noRoute');
20
+ return;
21
+ }
22
+
23
+ $category = Mage::getModel('catalog/category')
24
+ ->setStoreId(Mage::app()->getStore()->getId())
25
+ ->load($categoryId);
26
+ Mage::register('current_category', $category);
27
+
28
+
29
+ $this->getLayout()->createBlock('ajaxify/catalog_layer_view');
30
+ $this->loadLayout();
31
+ $this->renderLayout();
32
+ }
33
+
34
+ }
app/code/community/Ve/Ajaxify/controllers/Checkout/CartController.php ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Virtual Employee Ajaxify
4
+ *
5
+ * @category VE
6
+ * @package Ve_Ajaxify
7
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
8
+ * @author VE (Magento Team)
9
+ * @version Release: 1.0.0
10
+ * @Class Ve_Ajaxify_Checkout_CartController
11
+ */
12
+ require_once 'Mage/Checkout/controllers/CartController.php';
13
+
14
+ class Ve_Ajaxify_Checkout_CartController extends Mage_Checkout_CartController {
15
+
16
+ /**
17
+ * Add product to shopping cart action
18
+ */
19
+ public function addAction() {
20
+ if(Mage::getStoreConfig('ajaxify/ajaxifycart/ajaxify_cart') == 0) {
21
+ parent::addAction();
22
+ return;
23
+ }
24
+ $cart = $this->_getCart();
25
+ $params = $this->getRequest()->getParams();
26
+ try {
27
+ if (isset($params['qty'])) {
28
+ $filter = new Zend_Filter_LocalizedToNormalized(
29
+ array('locale' => Mage::app()->getLocale()->getLocaleCode())
30
+ );
31
+ $params['qty'] = $filter->filter($params['qty']);
32
+ }
33
+
34
+ $product = $this->_initProduct();
35
+ $related = $this->getRequest()->getParam('related_product');
36
+
37
+ /**
38
+ * Check product availability
39
+ */
40
+ if (!$product) {
41
+ $this->_goBack();
42
+ return;
43
+ }
44
+
45
+ $cart->addProduct($product, $params);
46
+ if (!empty($related)) {
47
+ $cart->addProductsByIds(explode(',', $related));
48
+ }
49
+
50
+ $cart->save();
51
+
52
+ $this->_getSession()->setCartWasUpdated(true);
53
+
54
+ /**
55
+ * @todo remove wishlist observer processAddToCart
56
+ */
57
+ $this->getLayout()->getUpdate()->addHandle('ajaxify');
58
+ $this->loadLayout();
59
+
60
+ Mage::dispatchEvent('checkout_cart_add_product_complete', array('product' => $product, 'request' => $this->getRequest(), 'response' => $this->getResponse())
61
+ );
62
+
63
+ if (!$this->_getSession()->getNoCartRedirect(true)) {
64
+ if (!$cart->getQuote()->getHasError()) {
65
+ $message = $this->__('%s was added to your shopping cart.', Mage::helper('core')->escapeHtml($product->getName()));
66
+ $this->_getSession()->addSuccess($message);
67
+ }
68
+ $this->_goBack();
69
+ }
70
+ } catch (Mage_Core_Exception $e) {
71
+ $_response = Mage::getModel('ajaxify/response');
72
+ $_response->setError(true);
73
+
74
+ $messages = array_unique(explode("\n", $e->getMessage()));
75
+ $json_messages = array();
76
+ foreach ($messages as $message) {
77
+ $json_messages[] = Mage::helper('core')->escapeHtml($message);
78
+ }
79
+
80
+ $_response->setMessages($json_messages);
81
+
82
+ $url = $this->_getSession()->getRedirectUrl(true);
83
+
84
+ $_response->send();
85
+ } catch (Exception $e) {
86
+ $this->_getSession()->addException($e, $this->__('Cannot add the item to shopping cart.'));
87
+ Mage::logException($e);
88
+
89
+ $_response = Mage::getModel('ajaxify/response');
90
+ $_response->setError(true);
91
+ $_response->setMessage($this->__('Cannot add the item to shopping cart.'));
92
+ $_response->send();
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Update product configuration for a cart item
98
+ */
99
+ public function updateItemOptionsAction() {
100
+ if(Mage::getStoreConfig('ajaxify/ajaxifycart/ajaxify_cart') == 0) {
101
+ parent::updateItemOptionsAction();
102
+ return;
103
+ }
104
+ $cart = $this->_getCart();
105
+ $id = (int) $this->getRequest()->getParam('id');
106
+ $params = $this->getRequest()->getParams();
107
+
108
+ if (!isset($params['options'])) {
109
+ $params['options'] = array();
110
+ }
111
+ try {
112
+ if (isset($params['qty'])) {
113
+ $filter = new Zend_Filter_LocalizedToNormalized(
114
+ array('locale' => Mage::app()->getLocale()->getLocaleCode())
115
+ );
116
+ $params['qty'] = $filter->filter($params['qty']);
117
+ }
118
+
119
+ $quoteItem = $cart->getQuote()->getItemById($id);
120
+ if (!$quoteItem) {
121
+ Mage::throwException($this->__('Quote item is not found.'));
122
+ }
123
+
124
+ $item = $cart->updateItem($id, new Varien_Object($params));
125
+ if (is_string($item)) {
126
+ Mage::throwException($item);
127
+ }
128
+ if ($item->getHasError()) {
129
+ Mage::throwException($item->getMessage());
130
+ }
131
+
132
+ $related = $this->getRequest()->getParam('related_product');
133
+ if (!empty($related)) {
134
+ $cart->addProductsByIds(explode(',', $related));
135
+ }
136
+
137
+ $cart->save();
138
+
139
+ $this->_getSession()->setCartWasUpdated(true);
140
+
141
+ $this->getLayout()->getUpdate()->addHandle('ajaxify');
142
+ $this->loadLayout();
143
+
144
+ Mage::dispatchEvent('checkout_cart_update_item_complete', array('item' => $item, 'request' => $this->getRequest(), 'response' => $this->getResponse())
145
+ );
146
+ if (!$this->_getSession()->getNoCartRedirect(true)) {
147
+ if (!$cart->getQuote()->getHasError()) {
148
+ $message = $this->__('%s was updated in your shopping cart.', Mage::helper('core')->htmlEscape($item->getProduct()->getName()));
149
+ $this->_getSession()->addSuccess($message);
150
+ }
151
+ $this->_goBack();
152
+ }
153
+ } catch (Mage_Core_Exception $e) {
154
+ $_response = Mage::getModel('ajaxify/response');
155
+ $_response->setError(true);
156
+
157
+ $messages = array_unique(explode("\n", $e->getMessage()));
158
+ $json_messages = array();
159
+ foreach ($messages as $message) {
160
+ $json_messages[] = Mage::helper('core')->escapeHtml($message);
161
+ }
162
+
163
+ $_response->setMessages($json_messages);
164
+
165
+ $url = $this->_getSession()->getRedirectUrl(true);
166
+
167
+ $_response->send();
168
+ } catch (Exception $e) {
169
+ $this->_getSession()->addException($e, $this->__('Cannot update the item.'));
170
+ Mage::logException($e);
171
+
172
+ $_response = Mage::getModel('ajaxify/response');
173
+ $_response->setError(true);
174
+ $_response->setMessage($this->__('Cannot update the item.'));
175
+ $_response->send();
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Delete shoping cart item action
181
+ */
182
+ public function deleteAction() {
183
+ if(Mage::getStoreConfig('ajaxify/ajaxifycart/ajaxify_cart') == 0) {
184
+ parent::deleteAction();
185
+ return;
186
+ }
187
+ $id = (int) $this->getRequest()->getParam('id');
188
+ if ($id) {
189
+ try {
190
+ $this->_getCart()->removeItem($id)
191
+ ->save();
192
+ } catch (Exception $e) {
193
+ $_response = Mage::getModel('ajaxify/response');
194
+ $_response->setError(true);
195
+ $_response->setMessage($this->__('Cannot remove the item.'));
196
+ $_response->send();
197
+
198
+ Mage::logException($e);
199
+ }
200
+ }
201
+
202
+ $_response = Mage::getModel('ajaxify/response');
203
+
204
+ $_response->setMessage($this->__('Item was removed.'));
205
+
206
+ //append updated blocks
207
+ $this->getLayout()->getUpdate()->addHandle('ajaxify');
208
+ $this->loadLayout();
209
+
210
+ $_response->addUpdatedBlocks($_response);
211
+
212
+ $_response->send();
213
+ }
214
+
215
+ }
app/code/community/Ve/Ajaxify/controllers/FrontController.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Virtual Employee Ajaxify
5
+ *
6
+ * @category VE
7
+ * @package Ve_Ajaxify
8
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
9
+ * @author VE (Magento Team)
10
+ * @version Release: 1.0.0
11
+ * @Class Ve_Ajaxify_FrontController
12
+ */
13
+ class Ve_Ajaxify_FrontController extends Mage_Core_Controller_Front_Action {
14
+
15
+ public function categoryAction() {
16
+ // init category
17
+ $categoryId = (int) $this->getRequest()->getParam('id', false);
18
+ if (!$categoryId) {
19
+ $this->_forward('noRoute');
20
+ return;
21
+ }
22
+
23
+ $category = Mage::getModel('catalog/category')
24
+ ->setStoreId(Mage::app()->getStore()->getId())
25
+ ->load($categoryId);
26
+ Mage::register('current_category', $category);
27
+
28
+ $this->loadLayout();
29
+
30
+ $response = array();
31
+ $response['layer'] = $this->getLayout()->getBlock('layer')->toHtml();
32
+
33
+ if(Mage::getStoreConfig('ajaxify/ajaxifycart/ajaxify_cart')) {
34
+ $response['products'] = $this->getLayout()->getBlock('root')->toHtml();
35
+ } else {
36
+ $response['products'] = $this->getLayout()->getBlock('defaultroot')->toHtml();
37
+ }
38
+
39
+ $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($response));
40
+ }
41
+
42
+ public function searchAction() {
43
+ $this->loadLayout();
44
+ $response = array();
45
+ $response['layer'] = $this->getLayout()->getBlock('layer')->toHtml();
46
+ if(Mage::getStoreConfig('ajaxify/ajaxifycart/ajaxify_cart')) {
47
+ $response['products'] = $this->getLayout()->getBlock('root')->setIsSearchMode()->toHtml();
48
+ } else {
49
+ $response['products'] = $this->getLayout()->getBlock('defaultroot')->setIsSearchMode()->toHtml();
50
+ }
51
+
52
+
53
+ $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($response));
54
+ }
55
+
56
+ public function productAction() {
57
+ $productid = Mage::app()->getRequest()->getParam('id', false);
58
+ if (!$productid) {
59
+ $this->_forward('noRoute');
60
+ return;
61
+ }
62
+ $_product = Mage::getModel('catalog/product')->load($productid);
63
+ Mage::register('product', $_product);
64
+ Mage::register('current_product', $_product);
65
+
66
+ $this->loadLayout();
67
+ $this->getLayout();
68
+ $this->renderLayout();
69
+ }
70
+
71
+ }
app/code/community/Ve/Ajaxify/etc/adminhtml.xml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <acl>
4
+ <resources>
5
+ <admin>
6
+ <children>
7
+ <system>
8
+ <children>
9
+ <config>
10
+ <children>
11
+ <ajaxify translate="title" module="ajaxify">
12
+ <title>VE Ajaxify </title>
13
+ </ajaxify>
14
+ </children>
15
+ </config>
16
+ </children>
17
+ </system>
18
+ </children>
19
+ </admin>
20
+ </resources>
21
+ </acl>
22
+ </config>
app/code/community/Ve/Ajaxify/etc/config.xml ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Virtual Employee Ajaxify
5
+ *
6
+ * @category VE
7
+ * @package Ve_Ajaxify
8
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
9
+ * @author VE (Magento Team)
10
+ * @version Release: 1.0.0
11
+ */
12
+ -->
13
+ <config>
14
+ <modules>
15
+ <Ve_Ajaxify>
16
+ <version>1.0.0</version>
17
+ </Ve_Ajaxify>
18
+ </modules>
19
+ <frontend>
20
+ <routers>
21
+ <ajaxify>
22
+ <use>standard</use>
23
+ <args>
24
+ <module>Ve_Ajaxify</module>
25
+ <frontName>ajaxify</frontName>
26
+ </args>
27
+ </ajaxify>
28
+ </routers>
29
+ <layout>
30
+ <updates>
31
+ <ajaxify>
32
+ <file>ajaxify.xml</file>
33
+ </ajaxify>
34
+ </updates>
35
+ </layout>
36
+ <translate>
37
+ <modules>
38
+ <Ve_Ajaxify>
39
+ <files>
40
+ <default>Ve_Ajaxify.csv</default>
41
+ </files>
42
+ </Ve_Ajaxify>
43
+ </modules>
44
+ </translate>
45
+ <events>
46
+ <checkout_cart_add_product_complete>
47
+ <observers>
48
+ <ajaxify>
49
+ <type>singleton</type>
50
+ <class>ajaxify/observer</class>
51
+ <method>addToCartEvent</method>
52
+ </ajaxify>
53
+ </observers>
54
+ </checkout_cart_add_product_complete>
55
+ <checkout_cart_update_item_complete>
56
+ <observers>
57
+ <ajaxify>
58
+ <type>singleton</type>
59
+ <class>ajaxify/observer</class>
60
+ <method>updateItemEvent</method>
61
+ </ajaxify>
62
+ </observers>
63
+ </checkout_cart_update_item_complete>
64
+ <!--for configurable products-->
65
+ <controller_action_postdispatch_catalog_product_view>
66
+ <observers>
67
+ <ajaxify>
68
+ <class>ajaxify/observer</class>
69
+ <method>getConfigurableOptions</method>
70
+ </ajaxify>
71
+ </observers>
72
+ </controller_action_postdispatch_catalog_product_view>
73
+ <!--for group products-->
74
+ <controller_action_predispatch_checkout_cart_add>
75
+ <observers>
76
+ <ajaxify>
77
+ <type>singleton</type>
78
+ <class>ajaxify/observer</class>
79
+ <method>getGroupProductOptions</method>
80
+ </ajaxify>
81
+ </observers>
82
+ </controller_action_predispatch_checkout_cart_add>
83
+ </events>
84
+ </frontend>
85
+
86
+ <adminhtml>
87
+ <translate>
88
+ <modules>
89
+ <Ve_Ajaxify>
90
+ <files>
91
+ <default>Ve_Ajaxify.csv</default>
92
+ </files>
93
+ </Ve_Ajaxify>
94
+ </modules>
95
+ </translate>
96
+ </adminhtml>
97
+
98
+
99
+ <global>
100
+ <models>
101
+ <ajaxify>
102
+ <class>Ve_Ajaxify_Model</class>
103
+ </ajaxify>
104
+ </models>
105
+
106
+ <blocks>
107
+ <ajaxify>
108
+ <class>Ve_Ajaxify_Block</class>
109
+ </ajaxify>
110
+
111
+ <catalog>
112
+ <rewrite>
113
+ <category_view>Ve_Ajaxify_Block_Rewrite_RewriteCatalogCategoryView</category_view>
114
+ </rewrite>
115
+ </catalog>
116
+
117
+ <catalog>
118
+ <rewrite>
119
+ <layer_view>Ve_Ajaxify_Block_Rewrite_RewriteCatalogLayerView</layer_view>
120
+ </rewrite>
121
+ </catalog>
122
+ <catalogsearch>
123
+ <rewrite>
124
+ <result>Ve_Ajaxify_Block_Rewrite_RewriteCatalogsearchResult</result>
125
+ </rewrite>
126
+ </catalogsearch>
127
+ </blocks>
128
+ <helpers>
129
+ <ajaxify>
130
+ <class>Ve_Ajaxify_Helper</class>
131
+ </ajaxify>
132
+ </helpers>
133
+ <resources>
134
+ <ajaxify_setup>
135
+ <setup>
136
+ <module>Ve_Ajaxify</module>
137
+ </setup>
138
+ <connection>
139
+ <use>core_setup</use>
140
+ </connection>
141
+ </ajaxify_setup>
142
+ <ajaxify_write>
143
+ <connection>
144
+ <use>core_write</use>
145
+ </connection>
146
+ </ajaxify_write>
147
+ <ajaxify_read>
148
+ <connection>
149
+ <use>core_read</use>
150
+ </connection>
151
+ </ajaxify_read>
152
+ </resources>
153
+ <rewrite>
154
+ <Ve_Ajaxify_checkout_cart>
155
+ <from><![CDATA[#^/checkout/cart/#]]></from>
156
+ <to>/ajaxify/checkout_cart/</to>
157
+ </Ve_Ajaxify_checkout_cart>
158
+ </rewrite>
159
+ </global>
160
+ <default>
161
+ <ajaxify>
162
+ <ajaxify>
163
+ <ajaxify_cart>1</ajaxify_cart>
164
+ <cat_style>breadcrumbs</cat_style>
165
+ <price_style>default</price_style>
166
+ <remove_links>0</remove_links>
167
+ <reset_filters>1</reset_filters>
168
+ </ajaxify>
169
+ </ajaxify>
170
+ </default>
171
+ </config>
app/code/community/Ve/Ajaxify/etc/system.xml ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <tabs>
4
+ <Ve translate="label">
5
+ <label>VE Extensions</label>
6
+ <sort_order>100</sort_order>
7
+ </Ve>
8
+ </tabs>
9
+ <sections>
10
+ <ajaxify translate="label">
11
+ <tab>Ve</tab>
12
+ <label>Ajax Filter and Cart</label>
13
+ <frontend_type>text</frontend_type>
14
+ <sort_order>120</sort_order>
15
+ <show_in_default>1</show_in_default>
16
+ <show_in_website>1</show_in_website>
17
+ <show_in_store>1</show_in_store>
18
+ <groups>
19
+ <ajaxifycart>
20
+ <label>Ajax Cart Settings</label>
21
+ <frontend_type>text</frontend_type>
22
+ <sort_order>100</sort_order>
23
+ <show_in_default>1</show_in_default>
24
+ <show_in_website>1</show_in_website>
25
+ <show_in_store>1</show_in_store>
26
+ <fields>
27
+ <ajaxify_cart translate="label">
28
+ <label>Enable Ajax Cart</label>
29
+ <frontend_type>select</frontend_type>
30
+ <source_model>adminhtml/system_config_source_yesno</source_model>
31
+ <sort_order>0</sort_order>
32
+ <show_in_default>1</show_in_default>
33
+ <show_in_website>1</show_in_website>
34
+ <show_in_store>1</show_in_store>
35
+ </ajaxify_cart>
36
+ </fields>
37
+ </ajaxifycart>
38
+ <ajaxifynavigation>
39
+ <label>Ajax Filter Settings</label>
40
+ <frontend_type>text</frontend_type>
41
+ <sort_order>800</sort_order>
42
+ <show_in_default>1</show_in_default>
43
+ <show_in_website>1</show_in_website>
44
+ <show_in_store>1</show_in_store>
45
+ <fields>
46
+ <cat_style translate="label">
47
+ <label>Categories Filter</label>
48
+ <frontend_type>select</frontend_type>
49
+ <source_model>ajaxify/system_config_source_category</source_model>
50
+ <sort_order>10</sort_order>
51
+ <show_in_default>1</show_in_default>
52
+ <show_in_website>1</show_in_website>
53
+ <show_in_store>1</show_in_store>
54
+ </cat_style>
55
+ <price_style translate="label">
56
+ <label>Price Filter</label>
57
+ <frontend_type>select</frontend_type>
58
+ <source_model>ajaxify/system_config_source_price</source_model>
59
+ <sort_order>30</sort_order>
60
+ <show_in_default>1</show_in_default>
61
+ <show_in_website>1</show_in_website>
62
+ <show_in_store>1</show_in_store>
63
+ </price_style>
64
+ <remove_links translate="label">
65
+ <label>Remove Links from the Navigation</label>
66
+ <frontend_type>select</frontend_type>
67
+ <source_model>adminhtml/system_config_source_yesno</source_model>
68
+ <sort_order>40</sort_order>
69
+ <show_in_default>1</show_in_default>
70
+ <show_in_website>1</show_in_website>
71
+ <show_in_store>1</show_in_store>
72
+ <comment><![CDATA[This prevents `Duplicate content` penalty from search engines, however customers with disabled JavaScript wont be able to use the filters]]></comment>
73
+ </remove_links>
74
+ <reset_filters translate="label">
75
+ <label>Reset Filters while Click on Another Category</label>
76
+ <frontend_type>select</frontend_type>
77
+ <source_model>adminhtml/system_config_source_yesno</source_model>
78
+ <sort_order>50</sort_order>
79
+ <show_in_default>1</show_in_default>
80
+ <show_in_website>1</show_in_website>
81
+ <show_in_store>1</show_in_store>
82
+ </reset_filters>
83
+ <reload_categories translate="label">
84
+ <label>Reload page while Click on Another Category</label>
85
+ <frontend_type>select</frontend_type>
86
+ <source_model>adminhtml/system_config_source_yesno</source_model>
87
+ <sort_order>70</sort_order>
88
+ <show_in_default>1</show_in_default>
89
+ <show_in_website>1</show_in_website>
90
+ <show_in_store>1</show_in_store>
91
+ </reload_categories>
92
+ <show_swatches translate="label">
93
+ <label>Show Icons for Colors ?</label>
94
+ <frontend_type>select</frontend_type>
95
+ <source_model>ajaxify/system_config_source_swatches</source_model>
96
+ <sort_order>80</sort_order>
97
+ <show_in_default>1</show_in_default>
98
+ <show_in_website>1</show_in_website>
99
+ <show_in_store>1</show_in_store>
100
+ </show_swatches>
101
+ </fields>
102
+ </ajaxifynavigation>
103
+ </groups>
104
+ </ajaxify>
105
+ </sections>
106
+ </config>
app/design/frontend/rwd/default/layout/ajaxify.xml ADDED
@@ -0,0 +1,424 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout version="0.1.0">
3
+ <default>
4
+ <reference name="head">
5
+ <action method="addItem">
6
+ <type>skin_js</type>
7
+ <name>js/ve/ve_layered_nav.js</name>
8
+ </action>
9
+ <action method="addItem" ifconfig="ajaxify/ajaxifycart/ajaxify_cart">
10
+ <type>skin_js</type>
11
+ <name>js/ve/ve_ajax_cart.js</name>
12
+ </action>
13
+ <action method="addItem">
14
+ <type>skin_js</type>
15
+ <name>js/ve/jquery.bpopup.min.js</name>
16
+ </action>
17
+ <action method="addItem">
18
+ <type>skin_js</type>
19
+ <name>js/ve/ve/jquery-ui.js</name>
20
+ </action>
21
+ <action method="addCss">
22
+ <stylesheet>css/ve/ve_layered_nav.css</stylesheet>
23
+ </action>
24
+ <action method="addCss">
25
+ <stylesheet>css/ve/ve/jquery-ui.css</stylesheet>
26
+ </action>
27
+ </reference>
28
+ </default>
29
+ <ajaxify>
30
+ <reference name="content">
31
+ <block type="checkout/cart" name="checkout.cart">
32
+ <action method="setCartTemplate">
33
+ <value>checkout/cart.phtml</value>
34
+ </action>
35
+ <action method="setEmptyTemplate">
36
+ <value>checkout/cart/noItems.phtml</value>
37
+ </action>
38
+ <action method="chooseTemplate"/>
39
+ <action method="addItemRender">
40
+ <type>simple</type>
41
+ <block>checkout/cart_item_renderer</block>
42
+ <template>checkout/cart/item/default.phtml</template>
43
+ </action>
44
+ <action method="addItemRender">
45
+ <type>grouped</type>
46
+ <block>checkout/cart_item_renderer_grouped</block>
47
+ <template>checkout/cart/item/default.phtml</template>
48
+ </action>
49
+ <action method="addItemRender">
50
+ <type>configurable</type>
51
+ <block>checkout/cart_item_renderer_configurable</block>
52
+ <template>checkout/cart/item/default.phtml</template>
53
+ </action>
54
+
55
+ <block type="core/text_list" name="checkout.cart.top_methods" as="top_methods" translate="label">
56
+ <label>Payment Methods Before Checkout Button</label>
57
+ <block type="checkout/onepage_link" name="checkout.cart.methods.onepage"
58
+ template="checkout/onepage/link.phtml"/>
59
+ </block>
60
+
61
+ <block type="page/html_wrapper" name="checkout.cart.form.before" as="form_before" translate="label">
62
+ <label>Shopping Cart Form Before</label>
63
+ </block>
64
+
65
+ <block type="core/text_list" name="checkout.cart.methods" as="methods" translate="label">
66
+ <label>Payment Methods After Checkout Button</label>
67
+ <block type="checkout/onepage_link" name="checkout.cart.methods.onepage"
68
+ template="checkout/onepage/link.phtml"/>
69
+ <block type="checkout/multishipping_link" name="checkout.cart.methods.multishipping"
70
+ template="checkout/multishipping/link.phtml"/>
71
+ </block>
72
+
73
+ <block type="checkout/cart_coupon" name="checkout.cart.coupon" as="coupon"
74
+ template="checkout/cart/coupon.phtml"/>
75
+ <block type="checkout/cart_shipping" name="checkout.cart.shipping" as="shipping"
76
+ template="checkout/cart/shipping.phtml"/>
77
+ <block type="checkout/cart_crosssell" name="checkout.cart.crosssell" as="crosssell"
78
+ template="checkout/cart/crosssell.phtml"/>
79
+
80
+ <block type="checkout/cart_totals" name="checkout.cart.totals" as="totals"
81
+ template="checkout/cart/totals.phtml"/>
82
+ </block>
83
+ </reference>
84
+ </ajaxify>
85
+ <ajaxify_front_category>
86
+ <remove name="right"/>
87
+ <remove name="left"/>
88
+ <block type="ajaxify/layer_view" name="layer" template="ajaxify/layer.phtml"/>
89
+ <block type="ajaxify/list" name="root">
90
+ <block type="catalog/product_list" name="product_list" template="ajaxify/catalog/product/list.phtml">
91
+ <block type="catalog/product_list_toolbar" name="product_list_toolbar" template="catalog/product/list/toolbar.phtml">
92
+ <block type="page/html_pager" name="product_list_toolbar_pager"/>
93
+ </block>
94
+ <action method="addColumnCountLayoutDepend">
95
+ <layout>empty</layout>
96
+ <count>6</count>
97
+ </action>
98
+ <action method="addColumnCountLayoutDepend">
99
+ <layout>one_column</layout>
100
+ <count>5</count>
101
+ </action>
102
+ <action method="addColumnCountLayoutDepend">
103
+ <layout>two_columns_left</layout>
104
+ <count>4</count>
105
+ </action>
106
+ <action method="addColumnCountLayoutDepend">
107
+ <layout>two_columns_right</layout>
108
+ <count>4</count>
109
+ </action>
110
+ <action method="addColumnCountLayoutDepend">
111
+ <layout>three_columns</layout>
112
+ <count>3</count>
113
+ </action>
114
+ <action method="setToolbarBlockName">
115
+ <name>product_list_toolbar</name>
116
+ </action>
117
+ </block>
118
+ </block>
119
+ <block type="ajaxify/list" name="defaultroot">
120
+ <block type="catalog/product_list" name="product_list" template="catalog/product/list.phtml">
121
+ <block type="catalog/product_list_toolbar" name="product_list_toolbar" template="catalog/product/list/toolbar.phtml">
122
+ <block type="page/html_pager" name="product_list_toolbar_pager"/>
123
+ </block>
124
+ <action method="addColumnCountLayoutDepend">
125
+ <layout>empty</layout>
126
+ <count>6</count>
127
+ </action>
128
+ <action method="addColumnCountLayoutDepend">
129
+ <layout>one_column</layout>
130
+ <count>5</count>
131
+ </action>
132
+ <action method="addColumnCountLayoutDepend">
133
+ <layout>two_columns_left</layout>
134
+ <count>4</count>
135
+ </action>
136
+ <action method="addColumnCountLayoutDepend">
137
+ <layout>two_columns_right</layout>
138
+ <count>4</count>
139
+ </action>
140
+ <action method="addColumnCountLayoutDepend">
141
+ <layout>three_columns</layout>
142
+ <count>3</count>
143
+ </action>
144
+ <action method="setToolbarBlockName">
145
+ <name>product_list_toolbar</name>
146
+ </action>
147
+ </block>
148
+ </block>
149
+ </ajaxify_front_category>
150
+
151
+ <ajaxify_front_search>
152
+ <remove name="right"/>
153
+ <remove name="left"/>
154
+ <block type="ajaxify/search_layer" name="layer" template="ajaxify/layer.phtml"/>
155
+ <block type="ajaxify/list" name="root">
156
+ <block type="catalog/product_list" name="product_list" template="ajaxify/catalog/product/list.phtml">
157
+ <block type="catalog/product_list_toolbar" name="product_list_toolbar" template="catalog/product/list/toolbar.phtml">
158
+ <block type="page/html_pager" name="product_list_toolbar_pager"/>
159
+ </block>
160
+ <action method="addColumnCountLayoutDepend">
161
+ <layout>empty</layout>
162
+ <count>6</count>
163
+ </action>
164
+ <action method="addColumnCountLayoutDepend">
165
+ <layout>one_column</layout>
166
+ <count>5</count>
167
+ </action>
168
+ <action method="addColumnCountLayoutDepend">
169
+ <layout>two_columns_left</layout>
170
+ <count>4</count>
171
+ </action>
172
+ <action method="addColumnCountLayoutDepend">
173
+ <layout>two_columns_right</layout>
174
+ <count>4</count>
175
+ </action>
176
+ <action method="addColumnCountLayoutDepend">
177
+ <layout>three_columns</layout>
178
+ <count>3</count>
179
+ </action>
180
+ <action method="setToolbarBlockName">
181
+ <name>product_list_toolbar</name>
182
+ </action>
183
+ </block>
184
+ </block>
185
+ <block type="ajaxify/list" name="defaultroot">
186
+ <block type="catalog/product_list" name="product_list" template="catalog/product/list.phtml">
187
+ <block type="catalog/product_list_toolbar" name="product_list_toolbar" template="catalog/product/list/toolbar.phtml">
188
+ <block type="page/html_pager" name="product_list_toolbar_pager"/>
189
+ </block>
190
+ <action method="addColumnCountLayoutDepend">
191
+ <layout>empty</layout>
192
+ <count>6</count>
193
+ </action>
194
+ <action method="addColumnCountLayoutDepend">
195
+ <layout>one_column</layout>
196
+ <count>5</count>
197
+ </action>
198
+ <action method="addColumnCountLayoutDepend">
199
+ <layout>two_columns_left</layout>
200
+ <count>4</count>
201
+ </action>
202
+ <action method="addColumnCountLayoutDepend">
203
+ <layout>two_columns_right</layout>
204
+ <count>4</count>
205
+ </action>
206
+ <action method="addColumnCountLayoutDepend">
207
+ <layout>three_columns</layout>
208
+ <count>3</count>
209
+ </action>
210
+ <action method="setToolbarBlockName">
211
+ <name>product_list_toolbar</name>
212
+ </action>
213
+ </block>
214
+ </block>
215
+ </ajaxify_front_search>
216
+
217
+ <ajaxify_front_product>
218
+ <remove name="header"/>
219
+ <remove name="footer"/>
220
+ <remove name="right"/>
221
+ <remove name="left"/>
222
+ <remove name="breadcrumbs"/>
223
+ <reference name="root">
224
+ <action method="setTemplate">
225
+ <template>page/1column.phtml</template>
226
+ </action>
227
+ </reference>
228
+ <reference name="head">
229
+ <action method="addJs">
230
+ <script>varien/product.js</script>
231
+ </action>
232
+ <action method="addJs">
233
+ <script>varien/configurable.js</script>
234
+ </action>
235
+ <action method="addItem">
236
+ <type>skin_js</type>
237
+ <script>js/lib/elevatezoom/jquery.elevateZoom-3.0.8.min.js</script>
238
+ </action>
239
+ <action method="addItem">
240
+ <type>js_css</type>
241
+ <name>calendar/calendar-win2k-1.css</name>
242
+ <params/><!--<if/><condition>can_load_calendar_js</condition>-->
243
+ </action>
244
+ <action method="addItem">
245
+ <type>js</type>
246
+ <name>calendar/calendar.js</name><!--<params/><if/><condition>can_load_calendar_js</condition>-->
247
+ </action>
248
+ <action method="addItem">
249
+ <type>js</type>
250
+ <name>calendar/calendar-setup.js</name><!--<params/><if/><condition>can_load_calendar_js</condition>-->
251
+ </action>
252
+ </reference>
253
+ <reference name="content">
254
+ <block type="catalog/product_view" name="product.info" template="catalog/product/view.phtml">
255
+ <block type="catalog/product_view_media" name="product.info.media" as="media" template="catalog/product/view/media.phtml">
256
+ <block type="core/text_list" name="product.info.media.after" as="after" />
257
+ </block>
258
+ <block type="core/text_list" name="alert.urls" as="alert_urls" translate="label">
259
+ <label>Alert Urls</label>
260
+ </block>
261
+
262
+ <action method="setTierPriceTemplate">
263
+ <template>catalog/product/view/tierprices.phtml</template>
264
+ </action>
265
+
266
+ <block type="catalog/product_view_additional" name="product.info.additional" as="product_additional_data" />
267
+ <block type="catalog/product_view" name="product.info.addto" as="addto" template="catalog/product/view/addto.phtml"/>
268
+ <block type="catalog/product_view" name="product.info.sharing" as="sharing" template="catalog/product/view/sharing.phtml"/>
269
+ <block type="catalog/product_view" name="product.info.addtocart" as="addtocart" template="catalog/product/view/addtocart.phtml"/>
270
+
271
+ <block type="core/text_list" name="product.info.extrahint" as="extrahint" translate="label">
272
+ <label>Product View Extra Hint</label>
273
+ </block>
274
+
275
+ <block type="catalog/product_view" name="product.info.options.wrapper" as="product_options_wrapper" template="catalog/product/view/options/wrapper.phtml" translate="label">
276
+ <label>Info Column Options Wrapper</label>
277
+ <block type="core/template" name="options_js" template="catalog/product/view/options/js.phtml"/>
278
+ <block type="catalog/product_view_options" name="product.info.options" as="product_options" template="catalog/product/view/options.phtml">
279
+ <action method="addOptionRenderer">
280
+ <type>text</type>
281
+ <block>catalog/product_view_options_type_text</block>
282
+ <template>catalog/product/view/options/type/text.phtml</template>
283
+ </action>
284
+ <action method="addOptionRenderer">
285
+ <type>file</type>
286
+ <block>catalog/product_view_options_type_file</block>
287
+ <template>catalog/product/view/options/type/file.phtml</template>
288
+ </action>
289
+ <action method="addOptionRenderer">
290
+ <type>select</type>
291
+ <block>catalog/product_view_options_type_select</block>
292
+ <template>catalog/product/view/options/type/select.phtml</template>
293
+ </action>
294
+ <action method="addOptionRenderer">
295
+ <type>date</type>
296
+ <block>catalog/product_view_options_type_date</block>
297
+ <template>catalog/product/view/options/type/date.phtml</template>
298
+ </action>
299
+ </block>
300
+ <block type="core/html_calendar" name="html_calendar" as="html_calendar" template="page/js/calendar.phtml"/>
301
+ </block>
302
+ <block type="catalog/product_view" name="product.info.options.wrapper.bottom" as="product_options_wrapper_bottom" template="catalog/product/view/options/wrapper/bottom.phtml" translate="label">
303
+ <label>Bottom Block Options Wrapper</label>
304
+ <action method="insert">
305
+ <block>product.tierprices</block>
306
+ </action>
307
+ <block type="catalog/product_view" name="product.clone_prices" as="prices" template="catalog/product/view/price_clone.phtml"/>
308
+ <action method="append">
309
+ <block>product.info.addtocart</block>
310
+ </action>
311
+ <action method="append">
312
+ <block>product.info.addto</block>
313
+ </action>
314
+ <action method="append">
315
+ <block>product.info.sharing</block>
316
+ </action>
317
+ </block>
318
+
319
+ <block type="core/template_facade" name="product.info.container1" as="container1">
320
+ <action method="setDataByKey">
321
+ <key>alias_in_layout</key>
322
+ <value>container1</value>
323
+ </action>
324
+ <action method="setDataByKeyFromRegistry">
325
+ <key>options_container</key>
326
+ <key_in_registry>product</key_in_registry>
327
+ </action>
328
+ <action method="append">
329
+ <block>product.info.options.wrapper</block>
330
+ </action>
331
+ <action method="append">
332
+ <block>product.info.options.wrapper.bottom</block>
333
+ </action>
334
+ </block>
335
+ <block type="core/template_facade" name="product.info.container2" as="container2">
336
+ <action method="setDataByKey">
337
+ <key>alias_in_layout</key>
338
+ <value>container2</value>
339
+ </action>
340
+ <action method="setDataByKeyFromRegistry">
341
+ <key>options_container</key>
342
+ <key_in_registry>product</key_in_registry>
343
+ </action>
344
+ <action method="append">
345
+ <block>product.info.options.wrapper</block>
346
+ </action>
347
+ <action method="append">
348
+ <block>product.info.options.wrapper.bottom</block>
349
+ </action>
350
+ </block>
351
+ <action method="unsetCallChild">
352
+ <child>container1</child>
353
+ <call>ifEquals</call>
354
+ <if>0</if>
355
+ <key>alias_in_layout</key>
356
+ <key>options_container</key>
357
+ </action>
358
+ <action method="unsetCallChild">
359
+ <child>container2</child>
360
+ <call>ifEquals</call>
361
+ <if>0</if>
362
+ <key>alias_in_layout</key>
363
+ <key>options_container</key>
364
+ </action>
365
+ </block>
366
+ </reference>
367
+ </ajaxify_front_product>
368
+
369
+ <catalogsearch_result_index translate="label">
370
+ <remove name="catalogsearch.leftnav"/>
371
+ <reference name="left">
372
+ <block type="ajaxify/search_layer" name="catalogsearch.ajaxify" after="currency" template="ajaxify/layer.phtml"/>
373
+ </reference>
374
+
375
+ </catalogsearch_result_index>
376
+ <catalog_category_default translate="label">
377
+ <reference name="product_list" ifconfig="ajaxify/ajaxifycart/ajaxify_cart">
378
+ <action method="setTemplate">
379
+ <template>ajaxify/catalog/product/list.phtml</template>
380
+ </action>
381
+ </reference>
382
+ </catalog_category_default>
383
+ <catalog_category_layered translate="label">
384
+ <remove name="catalog.leftnav"/>
385
+ <reference name="left">
386
+ <block type="ajaxify/layer_view" name="filter.catalog" after="currency" template="ajaxify/layer.phtml"/>
387
+ </reference>
388
+ <reference name="head">
389
+ <action method="addJs">
390
+ <script>varien/product.js</script>
391
+ </action>
392
+ <action method="addJs">
393
+ <script>varien/configurable.js</script>
394
+ </action>
395
+ <action method="addItem">
396
+ <type>skin_js</type>
397
+ <script>js/lib/elevatezoom/jquery.elevateZoom-3.0.8.min.js</script>
398
+ </action>
399
+ <action method="addItem">
400
+ <type>js_css</type>
401
+ <name>calendar/calendar-win2k-1.css</name>
402
+ <params/><!--<if/><condition>can_load_calendar_js</condition>-->
403
+ </action>
404
+ <action method="addItem">
405
+ <type>js</type>
406
+ <name>calendar/calendar.js</name><!--<params/><if/><condition>can_load_calendar_js</condition>-->
407
+ </action>
408
+ <action method="addItem">
409
+ <type>js</type>
410
+ <name>calendar/calendar-setup.js</name><!--<params/><if/><condition>can_load_calendar_js</condition>-->
411
+ </action>
412
+ </reference>
413
+ <reference name="product_list">
414
+ <action method="setTemplate" ifconfig="ajaxify/ajaxifycart/ajaxify_cart">
415
+ <template>ajaxify/catalog/product/list.phtml</template>
416
+ </action>
417
+ </reference>
418
+ </catalog_category_layered>
419
+ <catalog_product_view>
420
+ <reference name="product.info.addtocart">
421
+ <block type="core/template" name="setPopupTemplate" template="ajaxify/popup.phtml"/>
422
+ </reference>
423
+ </catalog_product_view>
424
+ </layout>
app/design/frontend/rwd/default/template/ajaxify/catalog/product/list.phtml ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Product list template
4
+ *
5
+ * @see Mage_Catalog_Block_Product_List
6
+ */
7
+ /* @var $this Mage_Catalog_Block_Product_List */
8
+ ?>
9
+ <?php
10
+ $_productCollection = $this->getLoadedProductCollection();
11
+ $_helper = $this->helper('catalog/output');
12
+ ?>
13
+ <?php if (!$_productCollection->count()): ?>
14
+ <p class="note-msg"><?php echo $this->__('There are no products matching the selection.') ?></p>
15
+ <?php else: ?>
16
+ <div class="category-products">
17
+ <?php echo $this->getToolbarHtml() ?>
18
+ <?php // List mode ?>
19
+ <?php if ($this->getMode() != 'grid'): ?>
20
+ <?php $_iterator = 0; ?>
21
+ <ol class="products-list" id="products-list">
22
+ <?php foreach ($_productCollection as $_product): ?>
23
+ <li class="item<?php if (++$_iterator == sizeof($_productCollection)): ?> last<?php endif; ?>">
24
+ <?php // Product Image ?>
25
+ <a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" class="product-image">
26
+ <?php $_imgSize = 300; ?>
27
+ <img id="product-collection-image-<?php echo $_product->getId(); ?>"
28
+ src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->keepFrame(false)->resize($_imgSize); ?>"
29
+ alt="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" />
30
+ </a>
31
+ <?php // Product description ?>
32
+ <div class="product-shop">
33
+ <div class="f-fix">
34
+ <div class="product-primary">
35
+ <?php $_productNameStripped = $this->stripTags($_product->getName(), null, true); ?>
36
+ <h2 class="product-name"><a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $_productNameStripped; ?>"><?php echo $_helper->productAttribute($_product, $_product->getName(), 'name'); ?></a></h2>
37
+ <?php if ($_product->getRatingSummary()): ?>
38
+ <?php echo $this->getReviewsSummaryHtml($_product) ?>
39
+ <?php endif; ?>
40
+ <?php
41
+ // Provides extra blocks on which to hang some features for products in the list
42
+ // Features providing UI elements targeting this block will display directly below the product name
43
+ if ($this->getChild('name.after')) {
44
+ $_nameAfterChildren = $this->getChild('name.after')->getSortedChildren();
45
+ foreach ($_nameAfterChildren as $_nameAfterChildName) {
46
+ $_nameAfterChild = $this->getChild('name.after')->getChild($_nameAfterChildName);
47
+ $_nameAfterChild->setProduct($_product);
48
+ echo $_nameAfterChild->toHtml();
49
+ }
50
+ }
51
+ ?>
52
+ </div>
53
+ <div class="product-secondary">
54
+ <?php echo $this->getPriceHtml($_product, true) ?>
55
+ </div>
56
+ <div class="product-secondary">
57
+ <?php if (!$_product->canConfigure() && $_product->isSaleable() && !$_product->getTypeInstance(true)->hasRequiredOptions($_product)): ?>
58
+ <p class="action">
59
+ <!--<button type="button" title="<?php echo $this->quoteEscape($this->__('Add to Cart')) ?>" class="button btn-cart" onclick="setLocation('<?php echo $this->getAddToCartUrl($_product) ?>')">-->
60
+ <!-- Override add to cart button -->
61
+ <button type="button" title="<?php echo $this->quoteEscape($this->__('Add to Cart')) ?>" class="button btn-cart"
62
+ onclick="popupView('<?php echo $this->getAddToCartUrl($_product); echo "', true"; ?>)">
63
+ <span><span><?php echo $this->__('Add to Cart') ?></span></span>
64
+ </button>
65
+ </p>
66
+ <?php elseif ($_product->getStockItem() && $_product->getStockItem()->getIsInStock()): ?>
67
+ <p class="action"><a title="<?php echo $this->quoteEscape($this->__('View Details')) ?>" class="button" href="<?php echo $_product->getProductUrl() ?>"><?php echo $this->__('View Details') ?></a></p>
68
+ <?php else: ?>
69
+ <p class="action availability out-of-stock"><span><?php echo $this->__('Out of stock') ?></span></p>
70
+ <?php endif; ?>
71
+ <ul class="add-to-links">
72
+ <?php if ($this->helper('wishlist')->isAllow()) : ?>
73
+ <li><a href="<?php echo $this->helper('wishlist')->getAddUrl($_product) ?>" class="link-wishlist"><?php echo $this->__('Add to Wishlist') ?></a></li>
74
+ <?php endif; ?>
75
+ <?php if ($_compareUrl = $this->getAddToCompareUrl($_product)): ?>
76
+ <li><span class="separator">|</span> <a href="<?php echo $_compareUrl ?>" class="link-compare"><?php echo $this->__('Add to Compare') ?></a></li>
77
+ <?php endif; ?>
78
+ </ul>
79
+ </div>
80
+ <div class="desc std">
81
+ <?php echo $_helper->productAttribute($_product, $_product->getShortDescription(), 'short_description') ?>
82
+ <a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $_productNameStripped ?>" class="link-learn"><?php echo $this->__('Learn More') ?></a>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ </li>
87
+ <?php endforeach; ?>
88
+ </ol>
89
+ <script type="text/javascript">decorateList('products-list', 'none-recursive')</script>
90
+
91
+ <?php else: ?>
92
+ <?php // Grid Mode ?>
93
+ <?php $_collectionSize = $_productCollection->count() ?>
94
+ <?php $_columnCount = $this->getColumnCount(); ?>
95
+ <ul class="products-grid products-grid--max-<?php echo $_columnCount; ?>-col">
96
+ <?php
97
+ $i = 0;
98
+ foreach ($_productCollection as $_product):
99
+ ?>
100
+ <?php /* if ($i++%$_columnCount==0): ?>
101
+ <?php endif */ ?>
102
+ <li class="item<?php if (($i - 1) % $_columnCount == 0): ?> first<?php elseif ($i % $_columnCount == 0): ?> last<?php endif; ?>">
103
+ <a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" class="product-image">
104
+ <?php $_imgSize = 210; ?>
105
+ <img id="product-collection-image-<?php echo $_product->getId(); ?>"
106
+ src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize($_imgSize); ?>"
107
+ alt="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" />
108
+ </a>
109
+ <div class="product-info">
110
+ <h2 class="product-name"><a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $this->stripTags($_product->getName(), null, true) ?>"><?php echo $_helper->productAttribute($_product, $_product->getName(), 'name') ?></a></h2>
111
+ <?php
112
+ // Provides extra blocks on which to hang some features for products in the list
113
+ // Features providing UI elements targeting this block will display directly below the product name
114
+ if ($this->getChild('name.after')) {
115
+ $_nameAfterChildren = $this->getChild('name.after')->getSortedChildren();
116
+ foreach ($_nameAfterChildren as $_nameAfterChildName) {
117
+ $_nameAfterChild = $this->getChild('name.after')->getChild($_nameAfterChildName);
118
+ $_nameAfterChild->setProduct($_product);
119
+ echo $_nameAfterChild->toHtml();
120
+ }
121
+ }
122
+ ?>
123
+ <?php echo $this->getPriceHtml($_product, true) ?>
124
+ <?php if ($_product->getRatingSummary()): ?>
125
+ <?php echo $this->getReviewsSummaryHtml($_product, 'short') ?>
126
+ <?php endif; ?>
127
+ <div class="actions">
128
+ <?php if (!$_product->canConfigure() && $_product->isSaleable() && !$_product->getTypeInstance(true)->hasRequiredOptions($_product)): ?>
129
+ <!--<button type="button" title="<?php echo $this->quoteEscape($this->__('Add to Cart')) ?>" class="button btn-cart" onclick="setLocation('<?php echo $this->getAddToCartUrl($_product) ?>')">-->
130
+ <!-- Override add to cart button -->
131
+ <button type="button" title="<?php echo $this->quoteEscape($this->__('Add to Cart')) ?>" class="button btn-cart" onclick="popupView('<?php
132
+ echo $this->getAddToCartUrl($_product);
133
+ echo "', true";
134
+ ?>)">
135
+ <span><span><?php echo $this->__('Add to Cart') ?></span></span>
136
+ </button>
137
+ <?php elseif ($_product->getStockItem() && $_product->getStockItem()->getIsInStock()): ?>
138
+ <a title="<?php echo $this->quoteEscape($this->__('View Details')) ?>" class="button" href="<?php echo $_product->getProductUrl() ?>"><?php echo $this->__('View Details') ?></a>
139
+ <?php else: ?>
140
+ <p class="availability out-of-stock"><span><?php echo $this->__('Out of stock') ?></span></p>
141
+ <?php endif; ?>
142
+ <ul class="add-to-links">
143
+ <?php if ($this->helper('wishlist')->isAllow()) : ?>
144
+ <li><a href="<?php echo $this->helper('wishlist')->getAddUrl($_product) ?>" class="link-wishlist"><?php echo $this->__('Add to Wishlist') ?></a></li>
145
+ <?php endif; ?>
146
+ <?php if ($_compareUrl = $this->getAddToCompareUrl($_product)): ?>
147
+ <li><span class="separator">|</span> <a href="<?php echo $_compareUrl ?>" class="link-compare"><?php echo $this->__('Add to Compare') ?></a></li>
148
+ <?php endif; ?>
149
+ </ul>
150
+ </div>
151
+ </div>
152
+ </li>
153
+ <?php /* if ($i%$_columnCount==0 || $i==$_collectionSize): ?>
154
+ <?php endif */ ?>
155
+ <?php endforeach ?>
156
+ </ul>
157
+ <script type="text/javascript">decorateGeneric($$('ul.products-grid'), ['odd', 'even', 'first', 'last'])</script>
158
+ <?php endif; ?>
159
+ <div class="toolbar-bottom">
160
+ <?php echo $this->getToolbarHtml() ?>
161
+ </div>
162
+ </div>
163
+ <?php endif; ?>
164
+ <?php
165
+ // Provides a block where additional page components may be attached, primarily good for in-page JavaScript
166
+ if ($this->getChild('after')) {
167
+ $_afterChildren = $this->getChild('after')->getSortedChildren();
168
+ foreach ($_afterChildren as $_afterChildName) {
169
+ $_afterChild = $this->getChild('after')->getChild($_afterChildName);
170
+ //set product collection on after blocks
171
+ $_afterChild->setProductCollection($_productCollection);
172
+ echo $_afterChild->toHtml();
173
+ }
174
+ }
175
+ echo $this->getLayout()->createBlock('core/template')->setTemplate('ajaxify/popup.phtml')->toHtml();
176
+ ?>
app/design/frontend/rwd/default/template/ajaxify/filter_attribute.phtml ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $items = $this->getFiltersArray();
3
+ $displayStyle = $this->getColumnsNum();
4
+ ?>
5
+ <ol>
6
+ <?php if ($displayStyle <=1): // one column ?>
7
+ <?php foreach ($items as $_item): ?>
8
+ <li><?php echo $_item?></li>
9
+ <?php endforeach ?>
10
+ <?php endif ?>
11
+ </ol>
app/design/frontend/rwd/default/template/ajaxify/filter_category.phtml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <ol>
2
+ <?php foreach ($this->getItems() as $_item):?>
3
+ <li>
4
+ <?php if ($_item->getIsCurrent()): ?>
5
+ <span class="adj-nav-category-current"><?php echo $_item->getLabel() ?></span>
6
+ <?php else: ?>
7
+ <?php if (Mage::getStoreConfig('ajaxify/ajaxifynavigation/reload_categories')) { ?>
8
+ <a id="cat-<?php echo $_item->getCategoryId()?>" href="<?php echo $this->htmlEscape($_item->getUri()) ?>" class="adj-nav-pad<?php echo $_item->getLevel()?>"><?php echo $_item->getLabel() ?></a>
9
+ <?php } else { ?>
10
+ <a id="cat-<?php echo $_item->getCategoryId()?>" href="<?php echo $this->htmlEscape($_item->getUri()) ?>" class="ve_layered_category adj-nav-pad<?php echo $_item->getLevel()?>"><?php echo $_item->getLabel() ?></a>
11
+ <?php }
12
+ if($_item->getCount()): ?>
13
+ (<?php echo $_item->getCount() ?>)
14
+ <?php endif ?>
15
+ <?php endif ?>
16
+ </li>
17
+ <?php endforeach ?>
18
+ </ol>
app/design/frontend/rwd/default/template/ajaxify/filter_category_search.phtml ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <ol>
2
+ <?php
3
+ foreach ($this->getItems() as $_item):?>
4
+ <li>
5
+ <?php if ($_item->getIsCurrent()): ?>
6
+ <span class="adj-nav-category-current"><?php echo $_item->getLabel() ?></span>
7
+ <?php else: ?>
8
+ <?php
9
+ if (Mage::getStoreConfig('ajaxify/ajaxifynavigation/reload_categories'))
10
+ {
11
+ ?>
12
+ <a id="cat-<?php echo $_item->getValue()?>" href="<?php echo $this->htmlEscape($_item->getUri()) ?>" class="ve_layered_category<?php echo $_item->getLevel()?>"><?php echo $_item->getLabel() ?></a>
13
+ <?php } else { ?>
14
+ <a id="cat-<?php echo $_item->getValue()?>" href="<?php echo $this->htmlEscape($_item->getUri()) ?>" class="ve_layered_category adj-nav-pad<?php echo $_item->getLevel()?>"><?php echo $_item->getLabel() ?></a>
15
+ <?php
16
+ }
17
+ if($_item->getCount()): ?> (<?php echo $_item->getCount() ?>) <?php endif ?>
18
+ <?php endif ?>
19
+ </li>
20
+ <?php endforeach ?>
21
+ </ol>
app/design/frontend/rwd/default/template/ajaxify/filter_price_both.phtml ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //todo: move logic to the block
3
+ list($min,$max) = $this->_filter->getMinMaxPriceInt();
4
+ list($from,$to) = explode(',', $this->_filter->getActiveState());
5
+
6
+ $from = floor(max($from, $min));
7
+
8
+ if ($to) {
9
+ $to = ceil(min($to, $max));
10
+ } else {
11
+ $to = $max;
12
+ }
13
+
14
+ if ($to<1 && $from<1) {
15
+ $to = $max;
16
+ }
17
+
18
+ //Set the slider width
19
+ $width = 170;
20
+
21
+ if ($max) {
22
+ if ($max == $min) {
23
+ $firstOffset = 0;
24
+ $secondOffset = $width;
25
+ } else {
26
+ $firstOffset = ($from-$min)*$width/($max-$min);
27
+ $secondOffset = ($to-$min)*$width/($max-$min);
28
+ }
29
+ } else {
30
+ $firstOffset = 0;
31
+ $secondOffset = 0;
32
+ }
33
+ ?>
34
+
35
+ <!-- jquery slider price range -->
36
+ <ol>
37
+ <li style="padding:10px;">
38
+ <div id="slider-range" style="margin-bottom:10px;"></div>
39
+
40
+ <p style="clear:both; width:100%; margin: 10px 0 10px -10px; display:none;">
41
+ <label for="mullnav_rng" style="float:left; width:37%;padding:4px;">Price range:</label>
42
+ <input type="text" id="mullnav_rng" readonly style="border:0; font-weight:bold; background-color:#ffffff; float:left; width:60%;">
43
+ </p>
44
+ </li>
45
+ </ol>
46
+ <!-- jquery slider price range -->
47
+
48
+ <ol style="display:none !important;">
49
+ <li>
50
+ <?php // echo $to.'!= '.$from; ?>
51
+ <?php if ($to != $from) :?>
52
+ <div id="ve_layered_price_slider<?php echo $this->_filter->getRequestVar()?>" class="price_slider">
53
+ <div class="handle selected" style="left:<?php echo $firstOffset?>px"></div>
54
+ <div class="handle" style="left:<?php echo $secondOffset?>px"></div>
55
+ </div>
56
+ <?php endif;?>
57
+
58
+ <?php if ($to != $from) :?>
59
+ <div class="mullayenav_range">
60
+ <?php echo $this->__('Range:')?>
61
+ <?php echo $this->getSymbol()?><span id="price_range_from<?php echo $this->_filter->getRequestVar()?>"><?php echo $from?></span> - <?php echo $this->getSymbol()?><span id="price_range_to<?php echo $this->_filter->getRequestVar()?>"><?php echo $to?></span>
62
+ <script type="text/javascript">
63
+ var slider = create_price_slider(<?php echo $width.', '.$firstOffset.', '.$secondOffset.', '.$min.', '.$max.',"'.$this->_filter->getRequestVar()?>");
64
+ </script>
65
+ <?php else:?>
66
+ <?php echo $this->__('Value:')?>
67
+ <?php echo $this->getSymbol()?><span id="price_range_from<?php echo $this->_filter->getRequestVar()?>"><?php echo $from?></span>
68
+ <?php endif;?>
69
+ </div>
70
+ </li>
71
+ </ol>
72
+ <ol>
73
+ <?php
74
+
75
+ $from_ve = $from;
76
+ $to_ve = $to;
77
+
78
+ $items = $this->getItems();
79
+ list($from, $to) = explode(',', $items[0]->getValueString());
80
+
81
+ if ($from < 0.01) {
82
+ $from = $this->__('From');
83
+ } else {
84
+ $from = round($from);
85
+ }
86
+
87
+ if ($to < 0.01) {
88
+ $to = $this->__('To');
89
+ } else {
90
+ $to = round($to);
91
+ }
92
+
93
+ ?>
94
+ <li class="mullayenav_range_input">
95
+ <input class="input-text mullayenav_range_from" type="text" maxlength="12" size="4" id="price_range_from---<?php echo $this->_filter->getRequestVar()?>" value="<?php echo $from_ve; ?>"
96
+ onclick="if(this.value==this.name) this.value='';" name="<?php echo $this->__('From')?>" style="background-color:#ffffff !important;"/>
97
+ <span class="mullayenav_range_dash">-</span>
98
+ <input class="input-text mullayenav_range_to" type="text" maxlength="12" size="4" id="price_range_to---<?php echo $this->_filter->getRequestVar()?>" value="<?php echo $to_ve?>"
99
+ onclick="if(this.value==this.name) this.value='';" name="<?php echo $this->__('To')?>" style="background-color:#ffffff !important;"/>
100
+ <button type="button" class="button mullayenav_range_btn" id="price_button_go---<?php echo $this->_filter->getRequestVar()?>"><span><?php echo $this->__('Go')?></span></button>
101
+ </li>
102
+ </ol>
103
+ <input type="hidden" value="<?php echo $this->_filter->getRequestVar()?>" class="price-input">
104
+
105
+
106
+ <?php $currency_code = Mage::app()->getStore()->getCurrentCurrencyCode(); ?>
107
+
108
+
109
+ <script>
110
+ //<![CDATA[
111
+ var $j = jQuery.noConflict();
112
+ //]]>
113
+
114
+ $j(function() {
115
+
116
+ $j( "#slider-range" ).slider({
117
+ range: true,
118
+ min: <?php echo $min; ?>,
119
+ max: <?php echo $max; ?>,
120
+ values: [ <?php echo $from_ve; ?>, <?php echo $to_ve; ?> ],
121
+ slide: function( event, ui ) {
122
+ $j( "#mullnav_rng" ).val( "<?php echo $currency_code; ?>" + ui.values[ 0 ] + " - <?php echo $currency_code; ?>" + ui.values[ 1 ] );
123
+ $j( "#price_range_from---price" ).val( ui.values[ 0 ] );
124
+ $j( "#price_range_to---price" ).val( ui.values[ 1 ] );
125
+
126
+ }
127
+ });
128
+ $j( "#mullnav_rng" ).val( "<?php echo $currency_code; ?>" + $j( "#slider-range" ).slider( "values", 0 ) +
129
+ " - <?php echo $currency_code; ?>" + $j( "#slider-range" ).slider( "values", 1 ) );
130
+ });
131
+
132
+ function mullnav_rng()
133
+ {
134
+ var mullnav_amount = document.getElementById('mullnav_rng').value;
135
+ mullnav_amount = mullnav_amount.replace("<?php echo $currency_code; ?>", "");
136
+ mullnav_amount = mullnav_amount.replace("<?php echo $currency_code; ?>", "");
137
+ mullnav_amount = mullnav_amount.split(" - ");
138
+ mullnav_from_amount = mullnav_amount['0'];
139
+ mullnav_to_amount = mullnav_amount['1'];
140
+ document.getElementById('ve_layered_params').value = "price="+mullnav_from_amount+"%2C"+mullnav_to_amount;
141
+ ve_layered_make_request();
142
+ //alert(mullnav_from_amount);
143
+ //alert(mullnav_to_amount);
144
+ }
145
+
146
+ </script>
147
+
app/design/frontend/rwd/default/template/ajaxify/filter_price_default.phtml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <ol>
2
+ <?php foreach ($this->getItems() as $_item): ?>
3
+ <li>
4
+ <a id="<?php echo $_item->getFilter()->getRequestVar() . '-' . $_item->getValueString()?>" href="<?php echo $this->htmlEscape($_item->getUrl()) ?>" class="ve_layered_price <?php if ($this->isSelected($_item)) echo 'adj-nav-price-selected';?>" ><?php echo $_item->getLabel() ?></a> (<?php echo $_item->getCount() ?>)
5
+ </li>
6
+ <?php endforeach ?>
7
+ </ol>
app/design/frontend/rwd/default/template/ajaxify/filter_price_input.phtml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <ol>
2
+ <?php
3
+ $items = $this->getItems();
4
+ list($from, $to) = explode(',', $items[0]->getValueString());
5
+
6
+ if ($from < 0.01) {
7
+ $from = $this->__('From');
8
+ } else {
9
+ $from = round($from);
10
+ }
11
+
12
+ if ($to < 0.01) {
13
+ $to = $this->__('To');
14
+ } else {
15
+ $to = round($to);
16
+ }
17
+
18
+ ?>
19
+ <li class="mullayenav_range_input">
20
+ <input class="input-text mullayenav_range_from" type="text" maxlength="12" size="4" id="price_range_from---<?php echo $this->_filter->getRequestVar()?>" value="<?php echo $from?>" onclick="if(this.value==this.name) this.value='';" name="<?php echo $this->__('From')?>" style="background-color:#ffffff !important;"/>
21
+ <span class="mullayenav_range_dash">-</span>
22
+ <input class="input-text mullayenav_range_to" type="text" maxlength="12" size="4" id="price_range_to---<?php echo $this->_filter->getRequestVar()?>" value="<?php echo $to?>" onclick="if(this.value==this.name) this.value='';" name="<?php echo $this->__('To')?>" style="background-color:#ffffff !important;"/>
23
+ <button type="button" class="button mullayenav_range_btn" id="price_button_go---<?php echo $this->_filter->getRequestVar()?>"><span><?php echo $this->__('Go')?></span></button>
24
+ </li>
25
+ </ol>
26
+ <input type="hidden" value="<?php echo $this->_filter->getRequestVar()?>" class="price-input">
app/design/frontend/rwd/default/template/ajaxify/filter_price_slider.phtml ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ <?php
3
+ //todo: move logic to the block
4
+ list($min,$max) = $this->_filter->getMinMaxPriceInt();
5
+ list($from,$to) = explode(',', $this->_filter->getActiveState());
6
+
7
+ $from = floor(max($from, $min));
8
+
9
+ if ($to) {
10
+ $to = ceil(min($to, $max));
11
+ } else {
12
+ $to = $max;
13
+ }
14
+
15
+ if ($to<1 && $from<1) {
16
+ $to = $max;
17
+ }
18
+
19
+ $from_ve = $from;
20
+ $to_ve = $to;
21
+
22
+ //Set the slider width
23
+ $width = 170;
24
+
25
+ if ($max) {
26
+ if ($max == $min) {
27
+ $firstOffset = 0;
28
+ $secondOffset = $width;
29
+ } else {
30
+ $firstOffset = ($from-$min)*$width/($max-$min);
31
+ $secondOffset = ($to-$min)*$width/($max-$min);
32
+ }
33
+ } else {
34
+ $firstOffset = 0;
35
+ $secondOffset = 0;
36
+ }
37
+ ?>
38
+ <!-- jquery slider price range -->
39
+ <ol>
40
+ <li style="padding:10px;">
41
+ <div id="slider-range" style=""></div>
42
+
43
+ <p style="clear:both; width:100%; margin: 10px 0 10px -10px;">
44
+ <label for="mullnav_rng" style="float:left; width:37%;padding:4px;">Price range:</label>
45
+ <input type="text" id="mullnav_rng" readonly style="border:0; font-weight:bold; background-color:#ffffff; float:left; width:60%;">
46
+ </p>
47
+ </li>
48
+ </ol>
49
+ <!-- jquery slider price range -->
50
+
51
+ <ol style="display:none !important;">
52
+ <li>
53
+ <?php if ($to != $from) :?>
54
+ <div id="ve_layered_price_slider<?php echo $this->_filter->getRequestVar()?>" class="price_slider">
55
+ <div class="handle selected" style="left:<?php echo $firstOffset?>px"></div>
56
+ <div class="handle" style="left:<?php echo $secondOffset?>px"></div>
57
+ </div>
58
+ <?php endif;?>
59
+
60
+ <?php if ($to != $from) :?>
61
+ <?php echo $this->__('Range:')?>
62
+ <?php echo $this->getSymbol()?><span id="price_range_from<?php echo $this->_filter->getRequestVar()?>"><?php echo $from?></span>-<?php echo $this->getSymbol()?><span id="price_range_to<?php echo $this->_filter->getRequestVar()?>"><?php echo $to?></span>
63
+ <script type="text/javascript">
64
+ var slider = create_price_slider(<?php echo $width.', '.$firstOffset.', '.$secondOffset.', '.$min.', '.$max.',"'.$this->_filter->getRequestVar()?>");
65
+ </script>
66
+ <?php else:?>
67
+ <?php echo $this->__('Value:')?>
68
+ <?php echo $this->getSymbol()?><span id="price_range_from<?php echo $this->_filter->getRequestVar()?>"><?php echo $from?></span>
69
+ <?php endif;?>
70
+ </li>
71
+ </ol>
72
+ <?php $currency_code = Mage::app()->getStore()->getCurrentCurrencyCode(); ?>
73
+
74
+ <script>
75
+ //<![CDATA[
76
+ var $j = jQuery.noConflict();
77
+ //]]>
78
+
79
+ $j(function() {
80
+
81
+ $j( "#slider-range" ).slider({
82
+ range: true,
83
+ min: <?php echo $min; ?>,
84
+ max: <?php echo $max; ?>,
85
+ values: [ <?php echo $from_ve; ?>, <?php echo $to_ve; ?> ],
86
+ slide: function( event, ui ) {
87
+ $j( "#mullnav_rng" ).val( "<?php echo $currency_code; ?>" + ui.values[ 0 ] + " - <?php echo $currency_code; ?>" + ui.values[ 1 ] );
88
+ $j( "#price_range_from---price" ).val( ui.values[ 0 ] );
89
+ $j( "#price_range_to---price" ).val( ui.values[ 1 ] );
90
+
91
+ }
92
+ });
93
+ $j( "#mullnav_rng" ).val( "<?php echo $currency_code; ?>" + $j( "#slider-range" ).slider( "values", 0 ) +
94
+ " - <?php echo $currency_code; ?>" + $j( "#slider-range" ).slider( "values", 1 ) );
95
+ });
96
+
97
+ function mullnav_rng()
98
+ {
99
+ var mullnav_amount = document.getElementById('mullnav_rng').value;
100
+ mullnav_amount = mullnav_amount.replace("<?php echo $currency_code; ?>", "");
101
+ mullnav_amount = mullnav_amount.replace("<?php echo $currency_code; ?>", "");
102
+ mullnav_amount = mullnav_amount.split(" - ");
103
+ mullnav_from_amount = mullnav_amount['0'];
104
+ mullnav_to_amount = mullnav_amount['1'];
105
+ document.getElementById('ve_layered_params').value = "price="+mullnav_from_amount+"%2C"+mullnav_to_amount;
106
+ ve_layered_make_request();
107
+ //alert(mullnav_from_amount);
108
+ //alert(mullnav_to_amount);
109
+ }
110
+
111
+ </script>
app/design/frontend/rwd/default/template/ajaxify/layer.phtml ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if ($this->canShowBlock()): $state = $this->getStateInfo() ?>
2
+ <div class="block block-layered-nav">
3
+ <div class="block-title">
4
+ <strong><span><?php echo $this->__('Shop by') ?></span></strong>
5
+ </div>
6
+ <div class="block-content">
7
+ <?php echo $this->getStateHtml() ?>
8
+ <?php if ($this->canShowOptions()): ?>
9
+ <div class="ve-filter">
10
+ <input type="hidden" id="ve_layered_url" value="<?php echo $this->htmlEscape($state[0]) ?>"/>
11
+ <input type="hidden" id="ve_layered_params" value="<?php echo $this->htmlEscape($state[1]) ?>"/>
12
+ <input type="hidden" id="ve_layered_ajax" value="<?php echo $this->htmlEscape($state[2]) ?>"/>
13
+ <dl id="ve_filters_list">
14
+ <?php if ($state[1] AND $this->bNeedClearAll()): ?>
15
+ <div class="actions ve_layered_clear_all"><a class="ve_layered_clearall" href="<?php echo $this->htmlEscape($this->getClearAllUrl()) ?>"><?php echo $this->__('Clear All') ?></a></div>
16
+ <?php endif ?>
17
+
18
+ <?php $_filters = $this->getFilters() ?>
19
+ <?php foreach ($_filters as $_filter): ?>
20
+ <?php if ($_filter->getItemsCount()): ?>
21
+ <dt class="ve_layered_dt">
22
+ <?php if ($clearUrl = $_filter->getClearUrl()): ?>
23
+ <a id="<?php echo $_filter->getVar() ?>-clear" <?php if (!$this->getIsRemoveLinks()): ?>href="<?php echo $this->htmlEscape($clearUrl) ?>" <?php endif; ?> class="btn-remove ve_layered_clear" title="<?php echo $this->__('Remove This Item') ?>"><?php echo $this->__('Remove This Item') ?></a>
24
+ <?php endif ?>
25
+ <?php echo $this->__($_filter->getName()) ?>
26
+ </dt>
27
+ <dd <?php echo $this->getHeightStyle() ?> id="ve_layered_<?php echo $_filter->getVar() ?>"><?php echo $_filter->getHtml() ?></dd>
28
+ <?php endif; ?>
29
+ <?php endforeach; ?>
30
+ </dl>
31
+ <script type="text/javascript">
32
+ decorateDataList('narrow-by-list');
33
+ ve_layered_init();
34
+ </script>
35
+ </div>
36
+ <?php endif; ?>
37
+ </div>
38
+ <div class="ve_loading_filters" style="display:none"></div>
39
+ </div>
40
+ <?php endif; ?>
41
+ <script type="text/javascript">
42
+ ve_layered_init();
43
+ </script>
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+
app/design/frontend/rwd/default/template/ajaxify/layer_pager.phtml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Adding javascript include
4
+ */
5
+ if ('front' != Mage::app()->getRequest()->getControllerName())
6
+ {
7
+ ?>
8
+ <script>catalog_toolbar_init()</script>
9
+ <?php
10
+
11
+ }
12
+ ?>
app/design/frontend/rwd/default/template/ajaxify/popup.phtml ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <div id="confProductView">
2
+ <span class="button b-close bClose"><span>X</span></span>
3
+ <div class="content">
4
+ <div id="text"></div>
5
+ <div id="nav">
6
+ <button type="button" title="Continue Shopping" class="b-close btn-checkout"><span><span>Continue Shopping</span></span></button>
7
+ <button type="button" title="Proceed to Checkout" class="btn-proceed-checkout btn-checkout" onclick="setLocation('<?php echo Mage::helper('checkout/cart')->getCartUrl(); ?>')"><span><span>Proceed to Checkout</span></span></button>
8
+ </div>
9
+ </div>
10
+ </div>
app/design/frontend/rwd/default/template/ajaxify/search.phtml ADDED
@@ -0,0 +1 @@
 
1
+ <?php echo $this->getProductListHtml() ?>
app/etc/modules/Ve_Ajaxify.xml ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Virtual Employee Ajaxify
5
+ *
6
+ * @category VE
7
+ * @package Ve_Ajaxify
8
+ * @copyright Copyright (c) 2015 VE (http://www.virtualemployee.com/)
9
+ * @author VE (Magento Team)
10
+ * @version Release: 1.0.0
11
+ */
12
+ -->
13
+ <config>
14
+ <modules>
15
+ <Ve_Ajaxify>
16
+ <active>true</active>
17
+ <codePool>community</codePool>
18
+ </Ve_Ajaxify>
19
+ </modules>
20
+ </config>
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>VE_Ajax</name>
4
+ <version>1.0.0.1</version>
5
+ <stability>stable</stability>
6
+ <license>GPL</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Ajax Filter and Cart</summary>
10
+ <description>Ajax Filter and Cart</description>
11
+ <notes>Ajax Filter and Cart</notes>
12
+ <authors><author><name>Virtual Employee</name><user>TeamV</user><email>ve.ppm2@gmail.com</email></author></authors>
13
+ <date>2015-12-29</date>
14
+ <time>13:54:21</time>
15
+ <contents><target name="magecommunity"><dir name="Ve"><dir name="Ajaxify"><dir name="Block"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="6e4f72052b6674c7f0e0305d8aae0bef"/><file name="Category.php" hash="07dd8ef5ae83d9775584e0300cbc8ffa"/><file name="Categorysearch.php" hash="60a8e48f6be8b2857f88cce1f35d2724"/><file name="Price.php" hash="5687ea7a075ebca3ea0b4eb2472f550e"/></dir><file name="View.php" hash="6f52fe25ddd5555760789434f6228d01"/></dir><file name="List.php" hash="4c06b6e17d4553aaadd5cf25621abb78"/><dir name="Rewrite"><file name="RewriteCatalogCategoryView.php" hash="8751a9bf29ba1e6ccb4ce3006c4f75b3"/><file name="RewriteCatalogLayerView.php" hash="ce2d780f73a6fc0e01059da08898a5ee"/><file name="RewriteCatalogsearchResult.php" hash="29ebf30b5fa1b5ce7765176f77cc42c0"/></dir><dir name="Search"><file name="Layer.php" hash="0b6f10bbe15a01ea449b2c96bb522b9c"/></dir></dir><dir name="Helper"><file name="Data.php" hash="3de333ca604f9ce5f4e9ae1cbc00fb80"/></dir><dir name="Model"><dir name="Layer"><dir name="Filter"><file name="Attribute.php" hash="ba7d4e8907cc5cfd7711d28eb37c2f0d"/><file name="Category.php" hash="45442b81ccd17cc234a3e9a63a74a285"/><file name="Categorysearch.php" hash="627de8eb966ede3df57febf5a4f6f6ad"/><file name="Price.php" hash="6a8be219b8d91e7995ddbf5ba705fe3d"/></dir></dir><file name="Observer.php" hash="21bf526bc530cc856d9eaa26a56a1e0e"/><file name="Response.php" hash="f1aacbaa5bafe62a01ef292aeba01642"/><file name="Select.php" hash="8cfbae2aea8c5ff698cc78e59838a1a7"/><dir name="System"><dir name="Config"><dir name="Source"><file name="Category.php" hash="51bdf085df4eb4f9908c6e5ef49b2347"/><file name="Price.php" hash="e36391633784c86364a134dd91f15b02"/><file name="Swatches.php" hash="7459c605d13b4ff0f0aace335a8b5a78"/></dir></dir></dir></dir><dir name="controllers"><file name="CategoryController.php" hash="be194d94d3489159a6034e0f9564a7f3"/><dir name="Checkout"><file name="CartController.php" hash="b14202f70b6365f8036e9f4ddf5b172f"/></dir><file name="FrontController.php" hash="61176a798dc8f2397a1b3a8efffcd060"/></dir><dir name="etc"><file name="adminhtml.xml" hash="a4c0e7c24eee8733189c6aa0f3580aed"/><file name="config.xml" hash="470fa4b26340043cef56cac608630610"/><file name="system.xml" hash="741987f323b212ed3e355cbdcea4d457"/></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="rwd"><dir name="default"><dir name="template"><dir name="ajaxify"><dir name="catalog"><dir name="product"><file name="list.phtml" hash="61234429028ee279b3d47f7276618cdb"/></dir></dir><file name="filter_attribute.phtml" hash="ed5e57a38d9c89b92aa05f3ae475684a"/><file name="filter_category.phtml" hash="b74bbbc701ce3ebbe580bcde8aa8efdd"/><file name="filter_category_search.phtml" hash="e811577cf0abe4ac96f34b2be814eacb"/><file name="filter_price_both.phtml" hash="fcd75184321badc4366f45ff267e6ac7"/><file name="filter_price_default.phtml" hash="c4501043c4c05356e1045276e3d58eaa"/><file name="filter_price_input.phtml" hash="d4c77f152d0fa9d8ea9d84a60d6496ef"/><file name="filter_price_slider.phtml" hash="678fd395f6d4240c68c8927ba451711d"/><file name="layer.phtml" hash="f17959ec528169d80bdc2d814e070c76"/><file name="layer_pager.phtml" hash="ed305aa40e9da6b61e5b10d4e8fdff64"/><file name="popup.phtml" hash="1533a0c656eb3d354ffe68bb23ba82b7"/><file name="search.phtml" hash="8d81223c164cf47e159283d6a7f6d91c"/></dir></dir><dir name="layout"><file name="ajaxify.xml" hash="86b46ccc2a6f690907b0ca339126f138"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Ve_Ajaxify.xml" hash="caa597fe057982d63e314fcafd6dca5a"/></dir></target><target name="mageskin"><dir name="frontend"><dir name="rwd"><dir name="default"><dir name="css"><dir name="ve"><file name="mullayernav.css" hash="445c0015dee3aa9b35a610c60ad58d71"/><dir name="ve"><file name="jquery-ui.css" hash="64dfb75ef30cbf691e7858dc1992b4df"/></dir><file name="ve_layered_nav.css" hash="628c0129d7277d207104a73509979d9c"/></dir></dir><dir name="images"><dir name="ve"><file name="Check-Box.png" hash="6cf2c57774deef6aef41153958a4aeb0"/><file name="ajax-loader.gif" hash="1ae32bc8232ff2527c627e5b38eb319a"/><file name="gray_bar.jpg" hash="8117a86abc6b69b7d96eb24939121a3c"/><file name="loader.gif" hash="f31185b76a60e52d48caacf56063bb74"/><file name="orange_bar.jpg" hash="1b4772295a465846426c8544b399e365"/><file name="slider_button.png" hash="2c9c2460c9c1cefd3e8521744019c7b5"/></dir></dir><dir name="js"><dir name="ve"><file name="LIVE_chweb_layered_nav.js" hash="f4479a02ddc6476849c300a4ee3bbc1a"/><dir name="ajaxwishlist"><file name="ajaxwishlist.js" hash="84efbb4a36a641c2c587a573dd1e4d4f"/></dir><dir name="fancybox"><file name="blank.gif" hash="325472601571f31e1bf00674c368d335"/><file name="fancy_close.png" hash="6e2879a324a76e9972ebc98201aae1d8"/><file name="fancy_loading.png" hash="b1d54c240cf06e7f41e372d56919b738"/><file name="fancy_nav_left.png" hash="3f3e406102152cd8236383568a40ba35"/><file name="fancy_nav_right.png" hash="216e4bde5bddeeaa60dc3d692890a68e"/><file name="fancy_shadow_e.png" hash="fd4f491080d29fade5080877f1ba4c8b"/><file name="fancy_shadow_n.png" hash="18cde16379b2ceadef714d9b346d09ec"/><file name="fancy_shadow_ne.png" hash="63adf788acf193d4e4f3642d7d793125"/><file name="fancy_shadow_nw.png" hash="c820c878aedb7a7f9ebd7135a58e7c65"/><file name="fancy_shadow_s.png" hash="9b9e5c888028aaef40fe5b6a363f1e29"/><file name="fancy_shadow_se.png" hash="a8afd5a008884380ee712d177105268f"/><file name="fancy_shadow_sw.png" hash="f81cc0fee5581d76ad3cebe47e7e791b"/><file name="fancy_shadow_w.png" hash="59b0e63eb059e58d932cfd53da4d87e6"/><file name="fancy_title_left.png" hash="1582ac2d3bef6a6445bf02ceca2741cd"/><file name="fancy_title_main.png" hash="38dad6c1ed4bdc81c0bec721b2deb8c2"/><file name="fancy_title_over.png" hash="b886fd165d4b7ac77d41fb52d87ffc60"/><file name="fancy_title_right.png" hash="6cbe0c935511e7f9a2555ccb6a7324c4"/><file name="fancybox-x.png" hash="168696d8a694214090ef90e029cdf393"/><file name="fancybox-y.png" hash="36a58859beb9a6b19322a37466b9f78e"/><file name="fancybox.png" hash="11e57e492ee0311540967cc7a1e6e3e2"/><file name="fancybox_loading.gif" hash="328cc0f6c78211485058d460e80f4fa8"/><file name="fancybox_loading@2x.gif" hash="f92938639fa894a0e8ded1c3368abe98"/><file name="fancybox_overlay.png" hash="77aeaa52715b898b73c74d68c630330e"/><file name="fancybox_sprite.png" hash="783d4031fe50c3d83c960911e1fbc705"/><file name="fancybox_sprite@2x.png" hash="ed9970ce22242421e66ff150aa97fe5f"/><file name="jquery.fancybox.css" hash="6c55951ce1e3115711f63f99b7501f3a"/><file name="jquery.fancybox.js" hash="921e9cb04ad6e2559869ec845c5be39b"/><file name="jquery.mousewheel-3.0.6.pack.js" hash="fde6509fae2cafdb6d97e4a9a60cce66"/></dir><file name="jquery.bpopup.min.js" hash="204ec5bd1f07bb6eb37b0da75badfc16"/><dir name="ve"><file name="jquery-1.10.2.js" hash="91515770ce8c55de23b306444d8ea998"/><file name="jquery-ui.js" hash="382ba105fe8e819baa49a1df526bddfd"/></dir><file name="ve_ajax_cart.js" hash="b1ba7cbfc470821ea2ee0d0e6dd312ab"/><file name="ve_layered_nav.js" hash="7364f40b8f4e5681698f43bf6e4cc23c"/></dir></dir></dir></dir></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php></required></dependencies>
18
+ </package>
skin/frontend/rwd/default/css/ve/mullayernav.css ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Document : catalogfilters
3
+ Created on : 19.04.2011, 17:19:22
4
+ Author : vinc
5
+ Description:
6
+ Purpose of the stylesheet follows.
7
+ */
8
+
9
+ /*
10
+ TODO customize this sample style
11
+ Syntax recommendation http://www.w3.org/TR/REC-CSS2/
12
+ */
13
+
14
+ .catalogfilter {
15
+ width:100%;
16
+ }
17
+
18
+ .cf-ajax-load{
19
+
20
+ height: 100%;
21
+ left: 0;
22
+ opacity: 0.99;
23
+ position: absolute;
24
+ top: 0;
25
+ width: 100%;
26
+ z-index: 9999;
27
+ }
28
+
29
+ .cf-ajax-load img{
30
+ left: 50%;
31
+ top:50%;
32
+ position: absolute;
33
+ }
skin/frontend/rwd/default/css/ve/ve/jquery-ui.css ADDED
@@ -0,0 +1,1225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! jQuery UI - v1.11.4 - 2015-03-11
2
+ * http://jqueryui.com
3
+ * Includes: core.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, draggable.css, menu.css, progressbar.css, resizable.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css
4
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
5
+ * Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
6
+
7
+ /* Layout helpers
8
+ ----------------------------------*/
9
+ .ui-helper-hidden {
10
+ display: none;
11
+ }
12
+ .ui-helper-hidden-accessible {
13
+ border: 0;
14
+ clip: rect(0 0 0 0);
15
+ height: 1px;
16
+ margin: -1px;
17
+ overflow: hidden;
18
+ padding: 0;
19
+ position: absolute;
20
+ width: 1px;
21
+ }
22
+ .ui-helper-reset {
23
+ margin: 0;
24
+ padding: 0;
25
+ border: 0;
26
+ outline: 0;
27
+ line-height: 1.3;
28
+ text-decoration: none;
29
+ font-size: 100%;
30
+ list-style: none;
31
+ }
32
+ .ui-helper-clearfix:before,
33
+ .ui-helper-clearfix:after {
34
+ content: "";
35
+ display: table;
36
+ border-collapse: collapse;
37
+ }
38
+ .ui-helper-clearfix:after {
39
+ clear: both;
40
+ }
41
+ .ui-helper-clearfix {
42
+ min-height: 0; /* support: IE7 */
43
+ }
44
+ .ui-helper-zfix {
45
+ width: 100%;
46
+ height: 100%;
47
+ top: 0;
48
+ left: 0;
49
+ position: absolute;
50
+ opacity: 0;
51
+ filter:Alpha(Opacity=0); /* support: IE8 */
52
+ }
53
+
54
+ .ui-front {
55
+ z-index: 100;
56
+ }
57
+
58
+
59
+ /* Interaction Cues
60
+ ----------------------------------*/
61
+ .ui-state-disabled {
62
+ cursor: default !important;
63
+ }
64
+
65
+
66
+ /* Icons
67
+ ----------------------------------*/
68
+
69
+ /* states and images */
70
+ .ui-icon {
71
+ display: block;
72
+ text-indent: -99999px;
73
+ overflow: hidden;
74
+ background-repeat: no-repeat;
75
+ }
76
+
77
+
78
+ /* Misc visuals
79
+ ----------------------------------*/
80
+
81
+ /* Overlays */
82
+ .ui-widget-overlay {
83
+ position: fixed;
84
+ top: 0;
85
+ left: 0;
86
+ width: 100%;
87
+ height: 100%;
88
+ }
89
+ .ui-accordion .ui-accordion-header {
90
+ display: block;
91
+ cursor: pointer;
92
+ position: relative;
93
+ margin: 2px 0 0 0;
94
+ padding: .5em .5em .5em .7em;
95
+ min-height: 0; /* support: IE7 */
96
+ font-size: 100%;
97
+ }
98
+ .ui-accordion .ui-accordion-icons {
99
+ padding-left: 2.2em;
100
+ }
101
+ .ui-accordion .ui-accordion-icons .ui-accordion-icons {
102
+ padding-left: 2.2em;
103
+ }
104
+ .ui-accordion .ui-accordion-header .ui-accordion-header-icon {
105
+ position: absolute;
106
+ left: .5em;
107
+ top: 50%;
108
+ margin-top: -8px;
109
+ }
110
+ .ui-accordion .ui-accordion-content {
111
+ padding: 1em 2.2em;
112
+ border-top: 0;
113
+ overflow: auto;
114
+ }
115
+ .ui-autocomplete {
116
+ position: absolute;
117
+ top: 0;
118
+ left: 0;
119
+ cursor: default;
120
+ }
121
+ .ui-button {
122
+ display: inline-block;
123
+ position: relative;
124
+ padding: 0;
125
+ line-height: normal;
126
+ margin-right: .1em;
127
+ cursor: pointer;
128
+ vertical-align: middle;
129
+ text-align: center;
130
+ overflow: visible; /* removes extra width in IE */
131
+ }
132
+ .ui-button,
133
+ .ui-button:link,
134
+ .ui-button:visited,
135
+ .ui-button:hover,
136
+ .ui-button:active {
137
+ text-decoration: none;
138
+ }
139
+ /* to make room for the icon, a width needs to be set here */
140
+ .ui-button-icon-only {
141
+ width: 2.2em;
142
+ }
143
+ /* button elements seem to need a little more width */
144
+ button.ui-button-icon-only {
145
+ width: 2.4em;
146
+ }
147
+ .ui-button-icons-only {
148
+ width: 3.4em;
149
+ }
150
+ button.ui-button-icons-only {
151
+ width: 3.7em;
152
+ }
153
+
154
+ /* button text element */
155
+ .ui-button .ui-button-text {
156
+ display: block;
157
+ line-height: normal;
158
+ }
159
+ .ui-button-text-only .ui-button-text {
160
+ padding: .4em 1em;
161
+ }
162
+ .ui-button-icon-only .ui-button-text,
163
+ .ui-button-icons-only .ui-button-text {
164
+ padding: .4em;
165
+ text-indent: -9999999px;
166
+ }
167
+ .ui-button-text-icon-primary .ui-button-text,
168
+ .ui-button-text-icons .ui-button-text {
169
+ padding: .4em 1em .4em 2.1em;
170
+ }
171
+ .ui-button-text-icon-secondary .ui-button-text,
172
+ .ui-button-text-icons .ui-button-text {
173
+ padding: .4em 2.1em .4em 1em;
174
+ }
175
+ .ui-button-text-icons .ui-button-text {
176
+ padding-left: 2.1em;
177
+ padding-right: 2.1em;
178
+ }
179
+ /* no icon support for input elements, provide padding by default */
180
+ input.ui-button {
181
+ padding: .4em 1em;
182
+ }
183
+
184
+ /* button icon element(s) */
185
+ .ui-button-icon-only .ui-icon,
186
+ .ui-button-text-icon-primary .ui-icon,
187
+ .ui-button-text-icon-secondary .ui-icon,
188
+ .ui-button-text-icons .ui-icon,
189
+ .ui-button-icons-only .ui-icon {
190
+ position: absolute;
191
+ top: 50%;
192
+ margin-top: -8px;
193
+ }
194
+ .ui-button-icon-only .ui-icon {
195
+ left: 50%;
196
+ margin-left: -8px;
197
+ }
198
+ .ui-button-text-icon-primary .ui-button-icon-primary,
199
+ .ui-button-text-icons .ui-button-icon-primary,
200
+ .ui-button-icons-only .ui-button-icon-primary {
201
+ left: .5em;
202
+ }
203
+ .ui-button-text-icon-secondary .ui-button-icon-secondary,
204
+ .ui-button-text-icons .ui-button-icon-secondary,
205
+ .ui-button-icons-only .ui-button-icon-secondary {
206
+ right: .5em;
207
+ }
208
+
209
+ /* button sets */
210
+ .ui-buttonset {
211
+ margin-right: 7px;
212
+ }
213
+ .ui-buttonset .ui-button {
214
+ margin-left: 0;
215
+ margin-right: -.3em;
216
+ }
217
+
218
+ /* workarounds */
219
+ /* reset extra padding in Firefox, see h5bp.com/l */
220
+ input.ui-button::-moz-focus-inner,
221
+ button.ui-button::-moz-focus-inner {
222
+ border: 0;
223
+ padding: 0;
224
+ }
225
+ .ui-datepicker {
226
+ width: 17em;
227
+ padding: .2em .2em 0;
228
+ display: none;
229
+ }
230
+ .ui-datepicker .ui-datepicker-header {
231
+ position: relative;
232
+ padding: .2em 0;
233
+ }
234
+ .ui-datepicker .ui-datepicker-prev,
235
+ .ui-datepicker .ui-datepicker-next {
236
+ position: absolute;
237
+ top: 2px;
238
+ width: 1.8em;
239
+ height: 1.8em;
240
+ }
241
+ .ui-datepicker .ui-datepicker-prev-hover,
242
+ .ui-datepicker .ui-datepicker-next-hover {
243
+ top: 1px;
244
+ }
245
+ .ui-datepicker .ui-datepicker-prev {
246
+ left: 2px;
247
+ }
248
+ .ui-datepicker .ui-datepicker-next {
249
+ right: 2px;
250
+ }
251
+ .ui-datepicker .ui-datepicker-prev-hover {
252
+ left: 1px;
253
+ }
254
+ .ui-datepicker .ui-datepicker-next-hover {
255
+ right: 1px;
256
+ }
257
+ .ui-datepicker .ui-datepicker-prev span,
258
+ .ui-datepicker .ui-datepicker-next span {
259
+ display: block;
260
+ position: absolute;
261
+ left: 50%;
262
+ margin-left: -8px;
263
+ top: 50%;
264
+ margin-top: -8px;
265
+ }
266
+ .ui-datepicker .ui-datepicker-title {
267
+ margin: 0 2.3em;
268
+ line-height: 1.8em;
269
+ text-align: center;
270
+ }
271
+ .ui-datepicker .ui-datepicker-title select {
272
+ font-size: 1em;
273
+ margin: 1px 0;
274
+ }
275
+ .ui-datepicker select.ui-datepicker-month,
276
+ .ui-datepicker select.ui-datepicker-year {
277
+ width: 45%;
278
+ }
279
+ .ui-datepicker table {
280
+ width: 100%;
281
+ font-size: .9em;
282
+ border-collapse: collapse;
283
+ margin: 0 0 .4em;
284
+ }
285
+ .ui-datepicker th {
286
+ padding: .7em .3em;
287
+ text-align: center;
288
+ font-weight: bold;
289
+ border: 0;
290
+ }
291
+ .ui-datepicker td {
292
+ border: 0;
293
+ padding: 1px;
294
+ }
295
+ .ui-datepicker td span,
296
+ .ui-datepicker td a {
297
+ display: block;
298
+ padding: .2em;
299
+ text-align: right;
300
+ text-decoration: none;
301
+ }
302
+ .ui-datepicker .ui-datepicker-buttonpane {
303
+ background-image: none;
304
+ margin: .7em 0 0 0;
305
+ padding: 0 .2em;
306
+ border-left: 0;
307
+ border-right: 0;
308
+ border-bottom: 0;
309
+ }
310
+ .ui-datepicker .ui-datepicker-buttonpane button {
311
+ float: right;
312
+ margin: .5em .2em .4em;
313
+ cursor: pointer;
314
+ padding: .2em .6em .3em .6em;
315
+ width: auto;
316
+ overflow: visible;
317
+ }
318
+ .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
319
+ float: left;
320
+ }
321
+
322
+ /* with multiple calendars */
323
+ .ui-datepicker.ui-datepicker-multi {
324
+ width: auto;
325
+ }
326
+ .ui-datepicker-multi .ui-datepicker-group {
327
+ float: left;
328
+ }
329
+ .ui-datepicker-multi .ui-datepicker-group table {
330
+ width: 95%;
331
+ margin: 0 auto .4em;
332
+ }
333
+ .ui-datepicker-multi-2 .ui-datepicker-group {
334
+ width: 50%;
335
+ }
336
+ .ui-datepicker-multi-3 .ui-datepicker-group {
337
+ width: 33.3%;
338
+ }
339
+ .ui-datepicker-multi-4 .ui-datepicker-group {
340
+ width: 25%;
341
+ }
342
+ .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
343
+ .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
344
+ border-left-width: 0;
345
+ }
346
+ .ui-datepicker-multi .ui-datepicker-buttonpane {
347
+ clear: left;
348
+ }
349
+ .ui-datepicker-row-break {
350
+ clear: both;
351
+ width: 100%;
352
+ font-size: 0;
353
+ }
354
+
355
+ /* RTL support */
356
+ .ui-datepicker-rtl {
357
+ direction: rtl;
358
+ }
359
+ .ui-datepicker-rtl .ui-datepicker-prev {
360
+ right: 2px;
361
+ left: auto;
362
+ }
363
+ .ui-datepicker-rtl .ui-datepicker-next {
364
+ left: 2px;
365
+ right: auto;
366
+ }
367
+ .ui-datepicker-rtl .ui-datepicker-prev:hover {
368
+ right: 1px;
369
+ left: auto;
370
+ }
371
+ .ui-datepicker-rtl .ui-datepicker-next:hover {
372
+ left: 1px;
373
+ right: auto;
374
+ }
375
+ .ui-datepicker-rtl .ui-datepicker-buttonpane {
376
+ clear: right;
377
+ }
378
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button {
379
+ float: left;
380
+ }
381
+ .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
382
+ .ui-datepicker-rtl .ui-datepicker-group {
383
+ float: right;
384
+ }
385
+ .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
386
+ .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
387
+ border-right-width: 0;
388
+ border-left-width: 1px;
389
+ }
390
+ .ui-dialog {
391
+ overflow: hidden;
392
+ position: absolute;
393
+ top: 0;
394
+ left: 0;
395
+ padding: .2em;
396
+ outline: 0;
397
+ }
398
+ .ui-dialog .ui-dialog-titlebar {
399
+ padding: .4em 1em;
400
+ position: relative;
401
+ }
402
+ .ui-dialog .ui-dialog-title {
403
+ float: left;
404
+ margin: .1em 0;
405
+ white-space: nowrap;
406
+ width: 90%;
407
+ overflow: hidden;
408
+ text-overflow: ellipsis;
409
+ }
410
+ .ui-dialog .ui-dialog-titlebar-close {
411
+ position: absolute;
412
+ right: .3em;
413
+ top: 50%;
414
+ width: 20px;
415
+ margin: -10px 0 0 0;
416
+ padding: 1px;
417
+ height: 20px;
418
+ }
419
+ .ui-dialog .ui-dialog-content {
420
+ position: relative;
421
+ border: 0;
422
+ padding: .5em 1em;
423
+ background: none;
424
+ overflow: auto;
425
+ }
426
+ .ui-dialog .ui-dialog-buttonpane {
427
+ text-align: left;
428
+ border-width: 1px 0 0 0;
429
+ background-image: none;
430
+ margin-top: .5em;
431
+ padding: .3em 1em .5em .4em;
432
+ }
433
+ .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
434
+ float: right;
435
+ }
436
+ .ui-dialog .ui-dialog-buttonpane button {
437
+ margin: .5em .4em .5em 0;
438
+ cursor: pointer;
439
+ }
440
+ .ui-dialog .ui-resizable-se {
441
+ width: 12px;
442
+ height: 12px;
443
+ right: -5px;
444
+ bottom: -5px;
445
+ background-position: 16px 16px;
446
+ }
447
+ .ui-draggable .ui-dialog-titlebar {
448
+ cursor: move;
449
+ }
450
+ .ui-draggable-handle {
451
+ -ms-touch-action: none;
452
+ touch-action: none;
453
+ }
454
+ .ui-menu {
455
+ list-style: none;
456
+ padding: 0;
457
+ margin: 0;
458
+ display: block;
459
+ outline: none;
460
+ }
461
+ .ui-menu .ui-menu {
462
+ position: absolute;
463
+ }
464
+ .ui-menu .ui-menu-item {
465
+ position: relative;
466
+ margin: 0;
467
+ padding: 3px 1em 3px .4em;
468
+ cursor: pointer;
469
+ min-height: 0; /* support: IE7 */
470
+ /* support: IE10, see #8844 */
471
+ list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
472
+ }
473
+ .ui-menu .ui-menu-divider {
474
+ margin: 5px 0;
475
+ height: 0;
476
+ font-size: 0;
477
+ line-height: 0;
478
+ border-width: 1px 0 0 0;
479
+ }
480
+ .ui-menu .ui-state-focus,
481
+ .ui-menu .ui-state-active {
482
+ margin: -1px;
483
+ }
484
+
485
+ /* icon support */
486
+ .ui-menu-icons {
487
+ position: relative;
488
+ }
489
+ .ui-menu-icons .ui-menu-item {
490
+ padding-left: 2em;
491
+ }
492
+
493
+ /* left-aligned */
494
+ .ui-menu .ui-icon {
495
+ position: absolute;
496
+ top: 0;
497
+ bottom: 0;
498
+ left: .2em;
499
+ margin: auto 0;
500
+ }
501
+
502
+ /* right-aligned */
503
+ .ui-menu .ui-menu-icon {
504
+ left: auto;
505
+ right: 0;
506
+ }
507
+ .ui-progressbar {
508
+ height: 2em;
509
+ text-align: left;
510
+ overflow: hidden;
511
+ }
512
+ .ui-progressbar .ui-progressbar-value {
513
+ margin: -1px;
514
+ height: 100%;
515
+ }
516
+ .ui-progressbar .ui-progressbar-overlay {
517
+ background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");
518
+ height: 100%;
519
+ filter: alpha(opacity=25); /* support: IE8 */
520
+ opacity: 0.25;
521
+ }
522
+ .ui-progressbar-indeterminate .ui-progressbar-value {
523
+ background-image: none;
524
+ }
525
+ .ui-resizable {
526
+ position: relative;
527
+ }
528
+ .ui-resizable-handle {
529
+ position: absolute;
530
+ font-size: 0.1px;
531
+ display: block;
532
+ -ms-touch-action: none;
533
+ touch-action: none;
534
+ }
535
+ .ui-resizable-disabled .ui-resizable-handle,
536
+ .ui-resizable-autohide .ui-resizable-handle {
537
+ display: none;
538
+ }
539
+ .ui-resizable-n {
540
+ cursor: n-resize;
541
+ height: 7px;
542
+ width: 100%;
543
+ top: -5px;
544
+ left: 0;
545
+ }
546
+ .ui-resizable-s {
547
+ cursor: s-resize;
548
+ height: 7px;
549
+ width: 100%;
550
+ bottom: -5px;
551
+ left: 0;
552
+ }
553
+ .ui-resizable-e {
554
+ cursor: e-resize;
555
+ width: 7px;
556
+ right: -5px;
557
+ top: 0;
558
+ height: 100%;
559
+ }
560
+ .ui-resizable-w {
561
+ cursor: w-resize;
562
+ width: 7px;
563
+ left: -5px;
564
+ top: 0;
565
+ height: 100%;
566
+ }
567
+ .ui-resizable-se {
568
+ cursor: se-resize;
569
+ width: 12px;
570
+ height: 12px;
571
+ right: 1px;
572
+ bottom: 1px;
573
+ }
574
+ .ui-resizable-sw {
575
+ cursor: sw-resize;
576
+ width: 9px;
577
+ height: 9px;
578
+ left: -5px;
579
+ bottom: -5px;
580
+ }
581
+ .ui-resizable-nw {
582
+ cursor: nw-resize;
583
+ width: 9px;
584
+ height: 9px;
585
+ left: -5px;
586
+ top: -5px;
587
+ }
588
+ .ui-resizable-ne {
589
+ cursor: ne-resize;
590
+ width: 9px;
591
+ height: 9px;
592
+ right: -5px;
593
+ top: -5px;
594
+ }
595
+ .ui-selectable {
596
+ -ms-touch-action: none;
597
+ touch-action: none;
598
+ }
599
+ .ui-selectable-helper {
600
+ position: absolute;
601
+ z-index: 100;
602
+ border: 1px dotted black;
603
+ }
604
+ .ui-selectmenu-menu {
605
+ padding: 0;
606
+ margin: 0;
607
+ position: absolute;
608
+ top: 0;
609
+ left: 0;
610
+ display: none;
611
+ }
612
+ .ui-selectmenu-menu .ui-menu {
613
+ overflow: auto;
614
+ /* Support: IE7 */
615
+ overflow-x: hidden;
616
+ padding-bottom: 1px;
617
+ }
618
+ .ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
619
+ font-size: 1em;
620
+ font-weight: bold;
621
+ line-height: 1.5;
622
+ padding: 2px 0.4em;
623
+ margin: 0.5em 0 0 0;
624
+ height: auto;
625
+ border: 0;
626
+ }
627
+ .ui-selectmenu-open {
628
+ display: block;
629
+ }
630
+ .ui-selectmenu-button {
631
+ display: inline-block;
632
+ overflow: hidden;
633
+ position: relative;
634
+ text-decoration: none;
635
+ cursor: pointer;
636
+ }
637
+ .ui-selectmenu-button span.ui-icon {
638
+ right: 0.5em;
639
+ left: auto;
640
+ margin-top: -8px;
641
+ position: absolute;
642
+ top: 50%;
643
+ }
644
+ .ui-selectmenu-button span.ui-selectmenu-text {
645
+ text-align: left;
646
+ padding: 0.4em 2.1em 0.4em 1em;
647
+ display: block;
648
+ line-height: 1.4;
649
+ overflow: hidden;
650
+ text-overflow: ellipsis;
651
+ white-space: nowrap;
652
+ }
653
+ .ui-slider {
654
+ position: relative;
655
+ text-align: left;
656
+ }
657
+ .ui-slider .ui-slider-handle {
658
+ position: absolute;
659
+ z-index: 2;
660
+ width: 1.2em;
661
+ height: 1.2em;
662
+ cursor: default;
663
+ -ms-touch-action: none;
664
+ touch-action: none;
665
+ }
666
+ .ui-slider .ui-slider-range {
667
+ position: absolute;
668
+ z-index: 1;
669
+ font-size: .7em;
670
+ display: block;
671
+ border: 0;
672
+ background-position: 0 0;
673
+ }
674
+
675
+ /* support: IE8 - See #6727 */
676
+ .ui-slider.ui-state-disabled .ui-slider-handle,
677
+ .ui-slider.ui-state-disabled .ui-slider-range {
678
+ filter: inherit;
679
+ }
680
+
681
+ .ui-slider-horizontal {
682
+ height: .8em;
683
+ }
684
+ .ui-slider-horizontal .ui-slider-handle {
685
+ top: -.3em;
686
+ margin-left: -.6em;
687
+ }
688
+ .ui-slider-horizontal .ui-slider-range {
689
+ top: 0;
690
+ height: 100%;
691
+ }
692
+ .ui-slider-horizontal .ui-slider-range-min {
693
+ left: 0;
694
+ }
695
+ .ui-slider-horizontal .ui-slider-range-max {
696
+ right: 0;
697
+ }
698
+
699
+ .ui-slider-vertical {
700
+ width: .8em;
701
+ height: 100px;
702
+ }
703
+ .ui-slider-vertical .ui-slider-handle {
704
+ left: -.3em;
705
+ margin-left: 0;
706
+ margin-bottom: -.6em;
707
+ }
708
+ .ui-slider-vertical .ui-slider-range {
709
+ left: 0;
710
+ width: 100%;
711
+ }
712
+ .ui-slider-vertical .ui-slider-range-min {
713
+ bottom: 0;
714
+ }
715
+ .ui-slider-vertical .ui-slider-range-max {
716
+ top: 0;
717
+ }
718
+ .ui-sortable-handle {
719
+ -ms-touch-action: none;
720
+ touch-action: none;
721
+ }
722
+ .ui-spinner {
723
+ position: relative;
724
+ display: inline-block;
725
+ overflow: hidden;
726
+ padding: 0;
727
+ vertical-align: middle;
728
+ }
729
+ .ui-spinner-input {
730
+ border: none;
731
+ background: none;
732
+ color: inherit;
733
+ padding: 0;
734
+ margin: .2em 0;
735
+ vertical-align: middle;
736
+ margin-left: .4em;
737
+ margin-right: 22px;
738
+ }
739
+ .ui-spinner-button {
740
+ width: 16px;
741
+ height: 50%;
742
+ font-size: .5em;
743
+ padding: 0;
744
+ margin: 0;
745
+ text-align: center;
746
+ position: absolute;
747
+ cursor: default;
748
+ display: block;
749
+ overflow: hidden;
750
+ right: 0;
751
+ }
752
+ /* more specificity required here to override default borders */
753
+ .ui-spinner a.ui-spinner-button {
754
+ border-top: none;
755
+ border-bottom: none;
756
+ border-right: none;
757
+ }
758
+ /* vertically center icon */
759
+ .ui-spinner .ui-icon {
760
+ position: absolute;
761
+ margin-top: -8px;
762
+ top: 50%;
763
+ left: 0;
764
+ }
765
+ .ui-spinner-up {
766
+ top: 0;
767
+ }
768
+ .ui-spinner-down {
769
+ bottom: 0;
770
+ }
771
+
772
+ /* TR overrides */
773
+ .ui-spinner .ui-icon-triangle-1-s {
774
+ /* need to fix icons sprite */
775
+ background-position: -65px -16px;
776
+ }
777
+ .ui-tabs {
778
+ position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
779
+ padding: .2em;
780
+ }
781
+ .ui-tabs .ui-tabs-nav {
782
+ margin: 0;
783
+ padding: .2em .2em 0;
784
+ }
785
+ .ui-tabs .ui-tabs-nav li {
786
+ list-style: none;
787
+ float: left;
788
+ position: relative;
789
+ top: 0;
790
+ margin: 1px .2em 0 0;
791
+ border-bottom-width: 0;
792
+ padding: 0;
793
+ white-space: nowrap;
794
+ }
795
+ .ui-tabs .ui-tabs-nav .ui-tabs-anchor {
796
+ float: left;
797
+ padding: .5em 1em;
798
+ text-decoration: none;
799
+ }
800
+ .ui-tabs .ui-tabs-nav li.ui-tabs-active {
801
+ margin-bottom: -1px;
802
+ padding-bottom: 1px;
803
+ }
804
+ .ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
805
+ .ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
806
+ .ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
807
+ cursor: text;
808
+ }
809
+ .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
810
+ cursor: pointer;
811
+ }
812
+ .ui-tabs .ui-tabs-panel {
813
+ display: block;
814
+ border-width: 0;
815
+ padding: 1em 1.4em;
816
+ background: none;
817
+ }
818
+ .ui-tooltip {
819
+ padding: 8px;
820
+ position: absolute;
821
+ z-index: 9999;
822
+ max-width: 300px;
823
+ -webkit-box-shadow: 0 0 5px #aaa;
824
+ box-shadow: 0 0 5px #aaa;
825
+ }
826
+ body .ui-tooltip {
827
+ border-width: 2px;
828
+ }
829
+
830
+ /* Component containers
831
+ ----------------------------------*/
832
+ .ui-widget {
833
+ font-family: Verdana,Arial,sans-serif;
834
+ font-size: 1.1em;
835
+ }
836
+ .ui-widget .ui-widget {
837
+ font-size: 1em;
838
+ }
839
+ .ui-widget input,
840
+ .ui-widget select,
841
+ .ui-widget textarea,
842
+ .ui-widget button {
843
+ font-family: Verdana,Arial,sans-serif;
844
+ font-size: 1em;
845
+ }
846
+ .ui-widget-content {
847
+ border: 1px solid #aaaaaa;
848
+ background: #ffffff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x;
849
+ color: #222222;
850
+ }
851
+ .ui-widget-content a {
852
+ color: #222222;
853
+ }
854
+ .ui-widget-header {
855
+ border: 1px solid #aaaaaa;
856
+ background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;
857
+ color: #222222;
858
+ font-weight: bold;
859
+ }
860
+ .ui-widget-header a {
861
+ color: #222222;
862
+ }
863
+
864
+ /* Interaction states
865
+ ----------------------------------*/
866
+ .ui-state-default,
867
+ .ui-widget-content .ui-state-default,
868
+ .ui-widget-header .ui-state-default {
869
+ border: 1px solid #d3d3d3;
870
+ background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
871
+ font-weight: normal;
872
+ color: #555555;
873
+ }
874
+ .ui-state-default a,
875
+ .ui-state-default a:link,
876
+ .ui-state-default a:visited {
877
+ color: #555555;
878
+ text-decoration: none;
879
+ }
880
+ .ui-state-hover,
881
+ .ui-widget-content .ui-state-hover,
882
+ .ui-widget-header .ui-state-hover,
883
+ .ui-state-focus,
884
+ .ui-widget-content .ui-state-focus,
885
+ .ui-widget-header .ui-state-focus {
886
+ border: 1px solid #999999;
887
+ background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
888
+ font-weight: normal;
889
+ color: #212121;
890
+ }
891
+ .ui-state-hover a,
892
+ .ui-state-hover a:hover,
893
+ .ui-state-hover a:link,
894
+ .ui-state-hover a:visited,
895
+ .ui-state-focus a,
896
+ .ui-state-focus a:hover,
897
+ .ui-state-focus a:link,
898
+ .ui-state-focus a:visited {
899
+ color: #212121;
900
+ text-decoration: none;
901
+ }
902
+ .ui-state-active,
903
+ .ui-widget-content .ui-state-active,
904
+ .ui-widget-header .ui-state-active {
905
+ border: 1px solid #aaaaaa;
906
+ background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
907
+ font-weight: normal;
908
+ color: #212121;
909
+ }
910
+ .ui-state-active a,
911
+ .ui-state-active a:link,
912
+ .ui-state-active a:visited {
913
+ color: #212121;
914
+ text-decoration: none;
915
+ }
916
+
917
+ /* Interaction Cues
918
+ ----------------------------------*/
919
+ .ui-state-highlight,
920
+ .ui-widget-content .ui-state-highlight,
921
+ .ui-widget-header .ui-state-highlight {
922
+ border: 1px solid #fcefa1;
923
+ background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
924
+ color: #363636;
925
+ }
926
+ .ui-state-highlight a,
927
+ .ui-widget-content .ui-state-highlight a,
928
+ .ui-widget-header .ui-state-highlight a {
929
+ color: #363636;
930
+ }
931
+ .ui-state-error,
932
+ .ui-widget-content .ui-state-error,
933
+ .ui-widget-header .ui-state-error {
934
+ border: 1px solid #cd0a0a;
935
+ background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
936
+ color: #cd0a0a;
937
+ }
938
+ .ui-state-error a,
939
+ .ui-widget-content .ui-state-error a,
940
+ .ui-widget-header .ui-state-error a {
941
+ color: #cd0a0a;
942
+ }
943
+ .ui-state-error-text,
944
+ .ui-widget-content .ui-state-error-text,
945
+ .ui-widget-header .ui-state-error-text {
946
+ color: #cd0a0a;
947
+ }
948
+ .ui-priority-primary,
949
+ .ui-widget-content .ui-priority-primary,
950
+ .ui-widget-header .ui-priority-primary {
951
+ font-weight: bold;
952
+ }
953
+ .ui-priority-secondary,
954
+ .ui-widget-content .ui-priority-secondary,
955
+ .ui-widget-header .ui-priority-secondary {
956
+ opacity: .7;
957
+ filter:Alpha(Opacity=70); /* support: IE8 */
958
+ font-weight: normal;
959
+ }
960
+ .ui-state-disabled,
961
+ .ui-widget-content .ui-state-disabled,
962
+ .ui-widget-header .ui-state-disabled {
963
+ opacity: .35;
964
+ filter:Alpha(Opacity=35); /* support: IE8 */
965
+ background-image: none;
966
+ }
967
+ .ui-state-disabled .ui-icon {
968
+ filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
969
+ }
970
+
971
+ /* Icons
972
+ ----------------------------------*/
973
+
974
+ /* states and images */
975
+ .ui-icon {
976
+ width: 16px;
977
+ height: 16px;
978
+ }
979
+ .ui-icon,
980
+ .ui-widget-content .ui-icon {
981
+ background-image: url("images/ui-icons_222222_256x240.png");
982
+ }
983
+ .ui-widget-header .ui-icon {
984
+ background-image: url("images/ui-icons_222222_256x240.png");
985
+ }
986
+ .ui-state-default .ui-icon {
987
+ background-image: url("images/ui-icons_888888_256x240.png");
988
+ }
989
+ .ui-state-hover .ui-icon,
990
+ .ui-state-focus .ui-icon {
991
+ background-image: url("images/ui-icons_454545_256x240.png");
992
+ }
993
+ .ui-state-active .ui-icon {
994
+ background-image: url("images/ui-icons_454545_256x240.png");
995
+ }
996
+ .ui-state-highlight .ui-icon {
997
+ background-image: url("images/ui-icons_2e83ff_256x240.png");
998
+ }
999
+ .ui-state-error .ui-icon,
1000
+ .ui-state-error-text .ui-icon {
1001
+ background-image: url("images/ui-icons_cd0a0a_256x240.png");
1002
+ }
1003
+
1004
+ /* positioning */
1005
+ .ui-icon-blank { background-position: 16px 16px; }
1006
+ .ui-icon-carat-1-n { background-position: 0 0; }
1007
+ .ui-icon-carat-1-ne { background-position: -16px 0; }
1008
+ .ui-icon-carat-1-e { background-position: -32px 0; }
1009
+ .ui-icon-carat-1-se { background-position: -48px 0; }
1010
+ .ui-icon-carat-1-s { background-position: -64px 0; }
1011
+ .ui-icon-carat-1-sw { background-position: -80px 0; }
1012
+ .ui-icon-carat-1-w { background-position: -96px 0; }
1013
+ .ui-icon-carat-1-nw { background-position: -112px 0; }
1014
+ .ui-icon-carat-2-n-s { background-position: -128px 0; }
1015
+ .ui-icon-carat-2-e-w { background-position: -144px 0; }
1016
+ .ui-icon-triangle-1-n { background-position: 0 -16px; }
1017
+ .ui-icon-triangle-1-ne { background-position: -16px -16px; }
1018
+ .ui-icon-triangle-1-e { background-position: -32px -16px; }
1019
+ .ui-icon-triangle-1-se { background-position: -48px -16px; }
1020
+ .ui-icon-triangle-1-s { background-position: -64px -16px; }
1021
+ .ui-icon-triangle-1-sw { background-position: -80px -16px; }
1022
+ .ui-icon-triangle-1-w { background-position: -96px -16px; }
1023
+ .ui-icon-triangle-1-nw { background-position: -112px -16px; }
1024
+ .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
1025
+ .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
1026
+ .ui-icon-arrow-1-n { background-position: 0 -32px; }
1027
+ .ui-icon-arrow-1-ne { background-position: -16px -32px; }
1028
+ .ui-icon-arrow-1-e { background-position: -32px -32px; }
1029
+ .ui-icon-arrow-1-se { background-position: -48px -32px; }
1030
+ .ui-icon-arrow-1-s { background-position: -64px -32px; }
1031
+ .ui-icon-arrow-1-sw { background-position: -80px -32px; }
1032
+ .ui-icon-arrow-1-w { background-position: -96px -32px; }
1033
+ .ui-icon-arrow-1-nw { background-position: -112px -32px; }
1034
+ .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
1035
+ .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
1036
+ .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
1037
+ .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
1038
+ .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
1039
+ .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
1040
+ .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
1041
+ .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
1042
+ .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
1043
+ .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
1044
+ .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
1045
+ .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
1046
+ .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
1047
+ .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
1048
+ .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
1049
+ .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
1050
+ .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
1051
+ .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
1052
+ .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
1053
+ .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
1054
+ .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
1055
+ .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
1056
+ .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
1057
+ .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
1058
+ .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
1059
+ .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
1060
+ .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
1061
+ .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
1062
+ .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
1063
+ .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
1064
+ .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
1065
+ .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
1066
+ .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
1067
+ .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
1068
+ .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
1069
+ .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
1070
+ .ui-icon-arrow-4 { background-position: 0 -80px; }
1071
+ .ui-icon-arrow-4-diag { background-position: -16px -80px; }
1072
+ .ui-icon-extlink { background-position: -32px -80px; }
1073
+ .ui-icon-newwin { background-position: -48px -80px; }
1074
+ .ui-icon-refresh { background-position: -64px -80px; }
1075
+ .ui-icon-shuffle { background-position: -80px -80px; }
1076
+ .ui-icon-transfer-e-w { background-position: -96px -80px; }
1077
+ .ui-icon-transferthick-e-w { background-position: -112px -80px; }
1078
+ .ui-icon-folder-collapsed { background-position: 0 -96px; }
1079
+ .ui-icon-folder-open { background-position: -16px -96px; }
1080
+ .ui-icon-document { background-position: -32px -96px; }
1081
+ .ui-icon-document-b { background-position: -48px -96px; }
1082
+ .ui-icon-note { background-position: -64px -96px; }
1083
+ .ui-icon-mail-closed { background-position: -80px -96px; }
1084
+ .ui-icon-mail-open { background-position: -96px -96px; }
1085
+ .ui-icon-suitcase { background-position: -112px -96px; }
1086
+ .ui-icon-comment { background-position: -128px -96px; }
1087
+ .ui-icon-person { background-position: -144px -96px; }
1088
+ .ui-icon-print { background-position: -160px -96px; }
1089
+ .ui-icon-trash { background-position: -176px -96px; }
1090
+ .ui-icon-locked { background-position: -192px -96px; }
1091
+ .ui-icon-unlocked { background-position: -208px -96px; }
1092
+ .ui-icon-bookmark { background-position: -224px -96px; }
1093
+ .ui-icon-tag { background-position: -240px -96px; }
1094
+ .ui-icon-home { background-position: 0 -112px; }
1095
+ .ui-icon-flag { background-position: -16px -112px; }
1096
+ .ui-icon-calendar { background-position: -32px -112px; }
1097
+ .ui-icon-cart { background-position: -48px -112px; }
1098
+ .ui-icon-pencil { background-position: -64px -112px; }
1099
+ .ui-icon-clock { background-position: -80px -112px; }
1100
+ .ui-icon-disk { background-position: -96px -112px; }
1101
+ .ui-icon-calculator { background-position: -112px -112px; }
1102
+ .ui-icon-zoomin { background-position: -128px -112px; }
1103
+ .ui-icon-zoomout { background-position: -144px -112px; }
1104
+ .ui-icon-search { background-position: -160px -112px; }
1105
+ .ui-icon-wrench { background-position: -176px -112px; }
1106
+ .ui-icon-gear { background-position: -192px -112px; }
1107
+ .ui-icon-heart { background-position: -208px -112px; }
1108
+ .ui-icon-star { background-position: -224px -112px; }
1109
+ .ui-icon-link { background-position: -240px -112px; }
1110
+ .ui-icon-cancel { background-position: 0 -128px; }
1111
+ .ui-icon-plus { background-position: -16px -128px; }
1112
+ .ui-icon-plusthick { background-position: -32px -128px; }
1113
+ .ui-icon-minus { background-position: -48px -128px; }
1114
+ .ui-icon-minusthick { background-position: -64px -128px; }
1115
+ .ui-icon-close { background-position: -80px -128px; }
1116
+ .ui-icon-closethick { background-position: -96px -128px; }
1117
+ .ui-icon-key { background-position: -112px -128px; }
1118
+ .ui-icon-lightbulb { background-position: -128px -128px; }
1119
+ .ui-icon-scissors { background-position: -144px -128px; }
1120
+ .ui-icon-clipboard { background-position: -160px -128px; }
1121
+ .ui-icon-copy { background-position: -176px -128px; }
1122
+ .ui-icon-contact { background-position: -192px -128px; }
1123
+ .ui-icon-image { background-position: -208px -128px; }
1124
+ .ui-icon-video { background-position: -224px -128px; }
1125
+ .ui-icon-script { background-position: -240px -128px; }
1126
+ .ui-icon-alert { background-position: 0 -144px; }
1127
+ .ui-icon-info { background-position: -16px -144px; }
1128
+ .ui-icon-notice { background-position: -32px -144px; }
1129
+ .ui-icon-help { background-position: -48px -144px; }
1130
+ .ui-icon-check { background-position: -64px -144px; }
1131
+ .ui-icon-bullet { background-position: -80px -144px; }
1132
+ .ui-icon-radio-on { background-position: -96px -144px; }
1133
+ .ui-icon-radio-off { background-position: -112px -144px; }
1134
+ .ui-icon-pin-w { background-position: -128px -144px; }
1135
+ .ui-icon-pin-s { background-position: -144px -144px; }
1136
+ .ui-icon-play { background-position: 0 -160px; }
1137
+ .ui-icon-pause { background-position: -16px -160px; }
1138
+ .ui-icon-seek-next { background-position: -32px -160px; }
1139
+ .ui-icon-seek-prev { background-position: -48px -160px; }
1140
+ .ui-icon-seek-end { background-position: -64px -160px; }
1141
+ .ui-icon-seek-start { background-position: -80px -160px; }
1142
+ /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
1143
+ .ui-icon-seek-first { background-position: -80px -160px; }
1144
+ .ui-icon-stop { background-position: -96px -160px; }
1145
+ .ui-icon-eject { background-position: -112px -160px; }
1146
+ .ui-icon-volume-off { background-position: -128px -160px; }
1147
+ .ui-icon-volume-on { background-position: -144px -160px; }
1148
+ .ui-icon-power { background-position: 0 -176px; }
1149
+ .ui-icon-signal-diag { background-position: -16px -176px; }
1150
+ .ui-icon-signal { background-position: -32px -176px; }
1151
+ .ui-icon-battery-0 { background-position: -48px -176px; }
1152
+ .ui-icon-battery-1 { background-position: -64px -176px; }
1153
+ .ui-icon-battery-2 { background-position: -80px -176px; }
1154
+ .ui-icon-battery-3 { background-position: -96px -176px; }
1155
+ .ui-icon-circle-plus { background-position: 0 -192px; }
1156
+ .ui-icon-circle-minus { background-position: -16px -192px; }
1157
+ .ui-icon-circle-close { background-position: -32px -192px; }
1158
+ .ui-icon-circle-triangle-e { background-position: -48px -192px; }
1159
+ .ui-icon-circle-triangle-s { background-position: -64px -192px; }
1160
+ .ui-icon-circle-triangle-w { background-position: -80px -192px; }
1161
+ .ui-icon-circle-triangle-n { background-position: -96px -192px; }
1162
+ .ui-icon-circle-arrow-e { background-position: -112px -192px; }
1163
+ .ui-icon-circle-arrow-s { background-position: -128px -192px; }
1164
+ .ui-icon-circle-arrow-w { background-position: -144px -192px; }
1165
+ .ui-icon-circle-arrow-n { background-position: -160px -192px; }
1166
+ .ui-icon-circle-zoomin { background-position: -176px -192px; }
1167
+ .ui-icon-circle-zoomout { background-position: -192px -192px; }
1168
+ .ui-icon-circle-check { background-position: -208px -192px; }
1169
+ .ui-icon-circlesmall-plus { background-position: 0 -208px; }
1170
+ .ui-icon-circlesmall-minus { background-position: -16px -208px; }
1171
+ .ui-icon-circlesmall-close { background-position: -32px -208px; }
1172
+ .ui-icon-squaresmall-plus { background-position: -48px -208px; }
1173
+ .ui-icon-squaresmall-minus { background-position: -64px -208px; }
1174
+ .ui-icon-squaresmall-close { background-position: -80px -208px; }
1175
+ .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
1176
+ .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
1177
+ .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
1178
+ .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
1179
+ .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
1180
+ .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
1181
+
1182
+
1183
+ /* Misc visuals
1184
+ ----------------------------------*/
1185
+
1186
+ /* Corner radius */
1187
+ .ui-corner-all,
1188
+ .ui-corner-top,
1189
+ .ui-corner-left,
1190
+ .ui-corner-tl {
1191
+ border-top-left-radius: 4px;
1192
+ }
1193
+ .ui-corner-all,
1194
+ .ui-corner-top,
1195
+ .ui-corner-right,
1196
+ .ui-corner-tr {
1197
+ border-top-right-radius: 4px;
1198
+ }
1199
+ .ui-corner-all,
1200
+ .ui-corner-bottom,
1201
+ .ui-corner-left,
1202
+ .ui-corner-bl {
1203
+ border-bottom-left-radius: 4px;
1204
+ }
1205
+ .ui-corner-all,
1206
+ .ui-corner-bottom,
1207
+ .ui-corner-right,
1208
+ .ui-corner-br {
1209
+ border-bottom-right-radius: 4px;
1210
+ }
1211
+
1212
+ /* Overlays */
1213
+ .ui-widget-overlay {
1214
+ background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
1215
+ opacity: .3;
1216
+ filter: Alpha(Opacity=30); /* support: IE8 */
1217
+ }
1218
+ .ui-widget-shadow {
1219
+ margin: -8px 0 0 -8px;
1220
+ padding: 8px;
1221
+ background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x;
1222
+ opacity: .3;
1223
+ filter: Alpha(Opacity=30); /* support: IE8 */
1224
+ border-radius: 8px;
1225
+ }
skin/frontend/rwd/default/css/ve/ve_layered_nav.css ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ div.ve-filter dd a {padding:0px 5px 0px 0px; display:block; float: left;}
2
+
3
+ /*categories*/
4
+ div.ve-filter span.adj-nav-category-current {font-weight: bold; padding-left: 5px;}
5
+ div.ve-filter a.adj-nav-pad2 {padding-left:5px}
6
+ div.ve-filter a.adj-nav-pad3 {padding-left:10px}
7
+
8
+ /*price ranges*/
9
+ div.ve-filter a.adj-nav-price {}
10
+ div.ve-filter a.adj-nav-price-selected {font-weight: bold}
11
+
12
+ /*attributes*/
13
+ div.ve-filter a.ve_layered_attribute { padding-left:25px; background:transparent url(../../images/ve/Check-Box.png) no-repeat scroll 0px 5px;}
14
+ div.ve-filter a.ve_layered_attribute_selected {padding-left:25px; /*border:dotted;*/ background-position: 0px -16px; font-weight: bold; overflow:hidden;}
15
+ div.ve-filter a.ve_layered_swatches {padding:0px 0px 5px 0px;}
16
+ div.ve-filter a.ve_layered_swatches_selected {opacity:0.5}
17
+
18
+ div.ve-filter a.ve_layered_disabled {color:gray; cursor:wait}
19
+ div.ve-filter input.ve_layered_disabled {background-color:gray; border:1px solid gray; cursor:wait}
20
+
21
+ div.ve-filter a.ve_layered_clear {float: right; cursor:pointer;}
22
+
23
+ div.price_slider { position:relative; z-index:9; height:28px; margin:0 auto 5px auto; background:url(../../images/ve/orange_bar.jpg) no-repeat 50% 50%; cursor:pointer; }
24
+ div.price_slider div.handle { top:3px; width:14px; height:23px; background: transparent url(../../images/ve/slider_button.png) no-repeat; cursor:move; position: absolute; }
25
+
26
+ #adj-nav-container, div.adj-nav {position:relative}
27
+
28
+ .ve_loading_filters{
29
+
30
+ opacity: 0.4;
31
+ filter:progid:DXImageTransform.Microsoft.Alpha(opacity=60);
32
+ background: none repeat scroll 0 0 #fff4e9;
33
+ border: 2px solid #f1af73;
34
+ box-sizing: content-box;
35
+ color: #d85909;
36
+ font-weight: bold;
37
+ left: 50%;
38
+ margin-left: -120px;
39
+ padding: 15px 60px;
40
+ position: fixed;
41
+ text-align: center;
42
+ top: 45%;
43
+ width: 115px;
44
+ height:9%;
45
+ z-index: 20100;
46
+ }
47
+
48
+ .ve_loading_filters img{
49
+ left:48%;
50
+ display:block;
51
+ position:fixed;
52
+ z-index:900;
53
+ }
54
+
55
+ .layered-nav div.ve_layered_clear_all {
56
+ margin:0;
57
+ border:1px solid #b9ccdd;
58
+ border-left:0;
59
+ border-right:0;
60
+ padding:3px 10px;
61
+ color:#1f5070;
62
+ font-weight:bold;
63
+ font-size:1em;
64
+ text-align:center;
65
+ }
66
+
67
+ .ve-filter dt{
68
+ cursor:pointer;
69
+ }
70
+ .ve-filter dt.ve_layered_dt_selected{}
71
+
72
+ div.ve-filter dd li{overflow:hidden;}
73
+
74
+
75
+ .color { width:150px; clear:both; margin:6px 0 6px 0; }
76
+
77
+ .color .color_box { width:17px; height:17px; float:left; display:block; margin-right:4px; }
78
+
79
+ .color a { font-family:Arial; font-size:12px; color:#333; text-decoration:none; }
80
+
81
+ .color a:hover { color:#09F; text-decoration:none; }
82
+
83
+ .color span { font-family:Arial; font-size:11px; color:#999; }
84
+
85
+ .ve_layered_dt{max-width: 260px;}
86
+ #ve_layered_price{max-width:260px !important;}
87
+ .mullayenav_range{width:100%; padding-bottom:10px;}
88
+ .mullayenav_range_from{width:30% !important; float:left;}
89
+ .mullayenav_range_to{width:30% !important; float:left;}
90
+ .mullayenav_range_dash{width:10% !important; float:left;padding: 5px 9px !important;}
91
+ .mullayenav_range_btn{width:20% !important; float:left; margin-left:8px;}
92
+ .mullayenav_range_input{ clear:both;padding-bottom:10px;}
93
+ div.ve-filter a.ve_layered_attribute{padding: 0px 30px;}
94
+
95
+ .button.bClose {
96
+ border-radius: 7px 7px 7px 7px;
97
+ box-shadow: none;
98
+ font: bold 131% sans-serif;
99
+ padding: 0 6px 2px;
100
+ position: absolute;
101
+ right: -7px;
102
+ top: -7px;
103
+ }
104
+ #confProductView, #confProductLoader {
105
+ min-width:300px;
106
+ min-height:200px;
107
+ display:none;
108
+ max-width: 90%!important;
109
+ }
110
+ #confProductView .content {
111
+ background-color: #fff;
112
+ border-radius: 10px 10px 10px 10px;
113
+ box-shadow: 0 0 25px 5px #999;
114
+ }
115
+ #confProductView .content, #confProductLoader .content {
116
+ color: #111;
117
+ padding: 25px;
118
+ width:100%;
119
+ min-height:200px;
120
+ text-align:center;
121
+ }
122
+
123
+ #confProductView .content #text {
124
+ min-height:100px;
125
+ }
126
+ #confProductView .content #nav button{
127
+ background: #3399cc;
128
+ display: inline-block;
129
+ padding: 7px 15px;
130
+ border: 0;
131
+ color: #FFFFFF;
132
+ font-size: 13px;
133
+ font-weight: normal;
134
+ font-family: "Raleway", "Helvetica Neue", Verdana, Arial, sans-serif;
135
+ line-height: 19px;
136
+ text-align: center;
137
+ text-transform: uppercase;
138
+ vertical-align: middle;
139
+ white-space: nowrap;
140
+ }
141
+ #confProductLoader .content #loader{
142
+ background:transparent url(../../images/ve/loader.gif) no-repeat scroll 0px 3px;
143
+ width: 400px;
144
+ height: 300px;
145
+ margin: auto;
146
+ border-radius:20px
147
+ }
148
+
149
+ #confProductView button.btn-checkout {
150
+ margin: 2px 0px;
151
+ }
skin/frontend/rwd/default/images/ve/Check-Box.png ADDED
Binary file
skin/frontend/rwd/default/images/ve/ajax-loader.gif ADDED
Binary file
skin/frontend/rwd/default/images/ve/gray_bar.jpg ADDED
Binary file
skin/frontend/rwd/default/images/ve/loader.gif ADDED
Binary file
skin/frontend/rwd/default/images/ve/orange_bar.jpg ADDED
Binary file
skin/frontend/rwd/default/images/ve/slider_button.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/LIVE_chweb_layered_nav.js ADDED
@@ -0,0 +1,242 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ isIE = /*@cc_on!@*/ false;
2
+ Control.Slider.prototype.setDisabled = function() {
3
+ this.disabled = true;
4
+ if (!isIE) {
5
+ this.track.parentNode.className = this.track.parentNode.className + ' disabled'
6
+ }
7
+ };
8
+
9
+ function ve_layered_hide_products() {
10
+ var items = $('ve_filters_list').select('a', 'input');
11
+ n = items.length;
12
+ for (i = 0; i < n; ++i) {
13
+ items[i].addClassName('ve_layered_disabled')
14
+ }
15
+ if (typeof(ve_slider) != 'undefined') ve_slider.setDisabled();
16
+ var divs = $$('div.ve_loading_filters');
17
+ for (var i = 0; i < divs.length; ++i) divs[i].show()
18
+ }
19
+
20
+ function ve_layered_show_products(transport) {
21
+ var resp = {};
22
+ if (transport && transport.responseText) {
23
+ try {
24
+ resp = eval('(' + transport.responseText + ')')
25
+ } catch (e) {
26
+ resp = {}
27
+ }
28
+ }
29
+ if (resp.products) {
30
+ var el = $('ve_layered_container');
31
+ var ajaxUrl = $('ve_layered_ajax').value;
32
+ el.update(resp.products.gsub(ajaxUrl, $('ve_layered_url').value));
33
+ catalog_toolbar_init();
34
+ $('catalog-filters').update(resp.layer.gsub(ajaxUrl, $('ve_layered_url').value));
35
+ $('ve_layered_ajax').value = ajaxUrl
36
+ }
37
+ var items = $('ve_filters_list').select('a', 'input');
38
+ n = items.length;
39
+ for (i = 0; i < n; ++i) {
40
+ items[i].removeClassName('ve_layered_disabled')
41
+ }
42
+ if (typeof(ve_slider) != 'undefined') ve_slider.setEnabled()
43
+ }
44
+
45
+ function ve_layered_add_params(k, v, isSingleVal) {
46
+ var el = $('ve_layered_params');
47
+ var params = el.value.parseQuery();
48
+ var strVal = params[k];
49
+ if (typeof strVal == 'undefined' || !strVal.length) {
50
+ params[k] = v
51
+ } else if ('clear' == v) {
52
+ params[k] = 'clear'
53
+ } else {
54
+ if (k == 'price') var values = strVal.split(',');
55
+ else var values = strVal.split('-');
56
+ if (-1 == values.indexOf(v)) {
57
+ if (isSingleVal) values = [v];
58
+ else values.push(v)
59
+ } else {
60
+ values = values.without(v)
61
+ }
62
+ params[k] = values.join('-')
63
+ }
64
+ el.value = Object.toQueryString(params).gsub('%2B', '+')
65
+ }
66
+
67
+ function ve_layered_make_request() {
68
+ ve_layered_hide_products();
69
+ var params = $('ve_layered_params').value.parseQuery();
70
+ if (!params['dir']) {
71
+ $('ve_layered_params').value += '&dir=' + 'desc'
72
+ }
73
+ new Ajax.Request($('ve_layered_ajax').value + '?' + $('ve_layered_params').value, {
74
+ method: 'get',
75
+ onSuccess: ve_layered_show_products
76
+ })
77
+ }
78
+
79
+ function ve_layered_update_links(evt, className, isSingleVal) {
80
+ var link = Event.findElement(evt, 'A'),
81
+ sel = className + '-selected';
82
+ if (link.hasClassName(sel)) link.removeClassName(sel);
83
+ else link.addClassName(sel);
84
+ if (isSingleVal) {
85
+ var items = $('ve_filters_list').getElementsByClassName(className);
86
+ var i, n = items.length;
87
+ for (i = 0; i < n; ++i) {
88
+ if (items[i].hasClassName(sel) && items[i].id != link.id) items[i].removeClassName(sel)
89
+ }
90
+ }
91
+ ve_layered_add_params(link.id.split('-')[0], link.id.split('-')[1], isSingleVal);
92
+ ve_layered_make_request();
93
+ Event.stop(evt)
94
+ }
95
+
96
+ function ve_layered_attribute_listener(evt) {
97
+ ve_layered_add_params('p', 'clear', 1);
98
+ ve_layered_update_links(evt, 've_layered_attribute', 0)
99
+ }
100
+
101
+ function ve_layered_price_listener(evt) {
102
+ ve_layered_add_params('p', 'clear', 1);
103
+ ve_layered_update_links(evt, 've_layered_price', 1)
104
+ }
105
+
106
+ function ve_layered_clear_listener(evt) {
107
+ var link = Event.findElement(evt, 'A'),
108
+ varName = link.id.split('-')[0];
109
+ ve_layered_add_params('p', 'clear', 1);
110
+ ve_layered_add_params(varName, 'clear', 1);
111
+ if ('price' == varName) {
112
+ var from = $('adj-nav-price-from'),
113
+ to = $('adj-nav-price-to');
114
+ if (Object.isElement(from)) {
115
+ from.value = from.name;
116
+ to.value = to.name
117
+ }
118
+ }
119
+ ve_layered_make_request();
120
+ Event.stop(evt)
121
+ }
122
+
123
+ function roundPrice(num) {
124
+ num = parseFloat(num);
125
+ if (isNaN(num)) num = 0;
126
+ return Math.round(num)
127
+ }
128
+
129
+ function ve_layered_category_listener(evt) {
130
+ var link = Event.findElement(evt, 'A');
131
+ var catId = link.id.split('-')[1];
132
+ var reg = /cat-/;
133
+ if (reg.test(link.id)) {
134
+ ve_layered_add_params('cat', catId, 1);
135
+ ve_layered_add_params('p', 'clear', 1);
136
+ ve_layered_make_request();
137
+ Event.stop(evt)
138
+ }
139
+ }
140
+
141
+ function catalog_toolbar_listener(evt) {
142
+ catalog_toolbar_make_request(Event.findElement(evt, 'A').href);
143
+ Event.stop(evt)
144
+ }
145
+
146
+ function catalog_toolbar_make_request(href) {
147
+
148
+ var pos = href.indexOf('?');
149
+ if (pos > -1) {
150
+ $('ve_layered_params').value = href.substring(pos + 1, href.length)
151
+ }
152
+ ve_layered_make_request()
153
+ }
154
+
155
+ function catalog_toolbar_init() {
156
+ var items = $('ve_layered_container').select('.pages a', '.view-mode a', '.sort-by a');
157
+ var i, n = items.length;
158
+ for (i = 0; i < n; ++i) {
159
+ Event.observe(items[i], 'click', catalog_toolbar_listener)
160
+ }
161
+ }
162
+
163
+ function ve_layered_dt_listener(evt) {
164
+ var e = Event.findElement(evt, 'DT');
165
+ e.nextSiblings()[0].toggle();
166
+ e.toggleClassName('ve_layered_dt_selected')
167
+ }
168
+
169
+ function ve_layered_clearall_listener(evt) {
170
+ var params = $('ve_layered_params').value.parseQuery();
171
+ $('ve_layered_params').value = 'clearall=true';
172
+ if (params['q']) {
173
+ $('ve_layered_params').value += '&q=' + params['q']
174
+ }
175
+ ve_layered_make_request();
176
+ Event.stop(evt)
177
+ }
178
+
179
+ function price_input_listener(evt) {
180
+ if (evt.type == 'keypress' && 13 != evt.keyCode) return;
181
+ if (evt.type == 'keypress') {
182
+ var inpObj = Event.findElement(evt, 'INPUT')
183
+ } else {
184
+ var inpObj = Event.findElement(evt, 'BUTTON')
185
+ }
186
+ var sKey = inpObj.id.split('---')[1];
187
+ var numFrom = roundPrice($('price_range_from---' + sKey).value),
188
+ numTo = roundPrice($('price_range_to---' + sKey).value);
189
+ if ((numFrom < 0.01 && numTo < 0.01) || numFrom < 0 || numTo < 0) return;
190
+ ve_layered_add_params('p', 'clear', 1);
191
+ ve_layered_add_params(sKey, numFrom + ',' + numTo, true);
192
+ ve_layered_make_request()
193
+ }
194
+
195
+ function ve_layered_init() {
196
+ var items, i, j, n, classes = ['category', 'attribute', 'icon', 'price', 'clear', 'dt', 'clearall'];
197
+ for (j = 0; j < classes.length; ++j) {
198
+ items = $('ve_filters_list').select('.ve_layered_' + classes[j]);
199
+ n = items.length;
200
+ for (i = 0; i < n; ++i) {
201
+ Event.observe(items[i], 'click', eval('ve_layered_' + classes[j] + '_listener'))
202
+ }
203
+ }
204
+ items = $('ve_filters_list').select('.price-input');
205
+ n = items.length;
206
+ var btn = $('price_button_go');
207
+ for (i = 0; i < n; ++i) {
208
+ btn = $('price_button_go---' + items[i].value);
209
+ if (Object.isElement(btn)) {
210
+ Event.observe(btn, 'click', price_input_listener);
211
+ Event.observe($('price_range_from---' + items[i].value), 'keypress', price_input_listener);
212
+ Event.observe($('price_range_to---' + items[i].value), 'keypress', price_input_listener)
213
+ }
214
+ }
215
+ }
216
+
217
+ function create_price_slider(width, from, to, min_price, max_price, sKey) {
218
+
219
+ var price_slider = $('ve_layered_price_slider' + sKey);
220
+ return new Control.Slider(price_slider.select('.handle'), price_slider, {
221
+ range: $R(0, width),
222
+ sliderValue: [from, to],
223
+ restricted: true,
224
+ onChange: function(values) {
225
+ var f = calculateSliderPrice(width, from, to, min_price, max_price, values[0]),
226
+ t = calculateSliderPrice(width, from, to, min_price, max_price, values[1]);
227
+ ve_layered_add_params(sKey, f + ',' + t, true);
228
+ $('price_range_from' + sKey).update(f);
229
+ $('price_range_to' + sKey).update(t);
230
+ ve_layered_make_request()
231
+ },
232
+ onSlide: function(values) {
233
+ $('price_range_from' + sKey).update(calculateSliderPrice(width, from, to, min_price, max_price, values[0]));
234
+ $('price_range_to' + sKey).update(calculateSliderPrice(width, from, to, min_price, max_price, values[1]))
235
+ }
236
+ })
237
+ }
238
+
239
+ function calculateSliderPrice(width, from, to, min_price, max_price, value) {
240
+ var calculated = roundPrice(((max_price - min_price) * value / width) + min_price);
241
+ return calculated
242
+ }
skin/frontend/rwd/default/js/ve/ajaxwishlist/ajaxwishlist.js ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function ajaxCompare(url,id){
2
+ url = url.replace("catalog/product_compare/add","ajax/index/compare");
3
+ url += 'isAjax/1/';
4
+ jQuery('#ajax_loading'+id).show();
5
+ jQuery.ajax( {
6
+ url : url,
7
+ dataType : 'json',
8
+ success : function(data) {
9
+ jQuery('#ajax_loading'+id).hide();
10
+ if(data.status == 'ERROR'){
11
+ alert(data.message);
12
+ }else{
13
+ alert(data.message);
14
+ if(jQuery('.block-compare').length){
15
+ jQuery('.block-compare').replaceWith(data.sidebar);
16
+ }else{
17
+ if(jQuery('.col-right').length){
18
+ jQuery('.col-right').prepend(data.sidebar);
19
+ }
20
+ }
21
+ }
22
+ }
23
+ });
24
+ }
25
+ function ajaxWishlist(url,id){
26
+ url = url.replace("wishlist/index/add","ajax/index/addwish");
27
+ url += 'isAjax/1/';
28
+ jQuery('#ajax_loading'+id).show();
29
+ jQuery.ajax( {
30
+ url : url,
31
+ dataType : 'json',
32
+ success : function(data) {
33
+ jQuery('#ajax_loading'+id).hide();
34
+ if(data.status == 'ERROR'){
35
+ alert(data.message);
36
+ }else{
37
+ alert(data.message);
38
+ if(jQuery('.block-wishlist').length){
39
+ jQuery('.block-wishlist').replaceWith(data.sidebar);
40
+ }else{
41
+ if(jQuery('.col-right').length){
42
+ jQuery('.col-right').prepend(data.sidebar);
43
+ }
44
+ }
45
+ }
46
+ }
47
+ });
48
+ }
skin/frontend/rwd/default/js/ve/fancybox/blank.gif ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_close.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_loading.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_nav_left.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_nav_right.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_e.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_n.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_ne.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_nw.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_s.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_se.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_sw.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_shadow_w.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_title_left.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_title_main.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_title_over.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancy_title_right.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancybox-x.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancybox-y.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancybox.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancybox_loading.gif ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancybox_loading@2x.gif ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancybox_overlay.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancybox_sprite.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/fancybox_sprite@2x.png ADDED
Binary file
skin/frontend/rwd/default/js/ve/fancybox/jquery.fancybox.css ADDED
@@ -0,0 +1,274 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! fancyBox v2.1.5 fancyapps.com | fancyapps.com/fancybox/#license */
2
+ .fancybox-wrap,
3
+ .fancybox-skin,
4
+ .fancybox-outer,
5
+ .fancybox-inner,
6
+ .fancybox-image,
7
+ .fancybox-wrap iframe,
8
+ .fancybox-wrap object,
9
+ .fancybox-nav,
10
+ .fancybox-nav span,
11
+ .fancybox-tmp
12
+ {
13
+ padding: 0;
14
+ margin: 0;
15
+ border: 0;
16
+ outline: none;
17
+ vertical-align: top;
18
+ }
19
+
20
+ .fancybox-wrap {
21
+ position: absolute;
22
+ top: 0;
23
+ left: 0;
24
+ z-index: 8020;
25
+ }
26
+
27
+ .fancybox-skin {
28
+ position: relative;
29
+ background: #f9f9f9;
30
+ color: #444;
31
+ text-shadow: none;
32
+ -webkit-border-radius: 4px;
33
+ -moz-border-radius: 4px;
34
+ border-radius: 4px;
35
+ }
36
+
37
+ .fancybox-opened {
38
+ z-index: 8030;
39
+ }
40
+
41
+ .fancybox-opened .fancybox-skin {
42
+ -webkit-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
43
+ -moz-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
44
+ box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
45
+ }
46
+
47
+ .fancybox-outer, .fancybox-inner {
48
+ position: relative;
49
+ }
50
+
51
+ .fancybox-inner {
52
+ overflow: hidden;
53
+ }
54
+
55
+ .fancybox-type-iframe .fancybox-inner {
56
+ -webkit-overflow-scrolling: touch;
57
+ }
58
+
59
+ .fancybox-error {
60
+ color: #444;
61
+ font: 14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;
62
+ margin: 0;
63
+ padding: 15px;
64
+ white-space: nowrap;
65
+ }
66
+
67
+ .fancybox-image, .fancybox-iframe {
68
+ display: block;
69
+ width: 100%;
70
+ height: 100%;
71
+ }
72
+
73
+ .fancybox-image {
74
+ max-width: 100%;
75
+ max-height: 100%;
76
+ }
77
+
78
+ #fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span {
79
+ background-image: url('fancybox_sprite.png');
80
+ }
81
+
82
+ #fancybox-loading {
83
+ position: fixed;
84
+ top: 50%;
85
+ left: 50%;
86
+ margin-top: -22px;
87
+ margin-left: -22px;
88
+ background-position: 0 -108px;
89
+ opacity: 0.8;
90
+ cursor: pointer;
91
+ z-index: 8060;
92
+ }
93
+
94
+ #fancybox-loading div {
95
+ width: 44px;
96
+ height: 44px;
97
+ background: url('fancybox_loading.gif') center center no-repeat;
98
+ }
99
+
100
+ .fancybox-close {
101
+ position: absolute;
102
+ top: -18px;
103
+ right: -18px;
104
+ width: 36px;
105
+ height: 36px;
106
+ cursor: pointer;
107
+ z-index: 8040;
108
+ }
109
+
110
+ .fancybox-nav {
111
+ position: absolute;
112
+ top: 0;
113
+ width: 40%;
114
+ height: 100%;
115
+ cursor: pointer;
116
+ text-decoration: none;
117
+ background: transparent url('blank.gif'); /* helps IE */
118
+ -webkit-tap-highlight-color: rgba(0,0,0,0);
119
+ z-index: 8040;
120
+ }
121
+
122
+ .fancybox-prev {
123
+ left: 0;
124
+ }
125
+
126
+ .fancybox-next {
127
+ right: 0;
128
+ }
129
+
130
+ .fancybox-nav span {
131
+ position: absolute;
132
+ top: 50%;
133
+ width: 36px;
134
+ height: 34px;
135
+ margin-top: -18px;
136
+ cursor: pointer;
137
+ z-index: 8040;
138
+ visibility: hidden;
139
+ }
140
+
141
+ .fancybox-prev span {
142
+ left: 10px;
143
+ background-position: 0 -36px;
144
+ }
145
+
146
+ .fancybox-next span {
147
+ right: 10px;
148
+ background-position: 0 -72px;
149
+ }
150
+
151
+ .fancybox-nav:hover span {
152
+ visibility: visible;
153
+ }
154
+
155
+ .fancybox-tmp {
156
+ position: absolute;
157
+ top: -99999px;
158
+ left: -99999px;
159
+ visibility: hidden;
160
+ max-width: 99999px;
161
+ max-height: 99999px;
162
+ overflow: visible !important;
163
+ }
164
+
165
+ /* Overlay helper */
166
+
167
+ .fancybox-lock {
168
+ overflow: hidden !important;
169
+ width: auto;
170
+ }
171
+
172
+ .fancybox-lock body {
173
+ overflow: hidden !important;
174
+ }
175
+
176
+ .fancybox-lock-test {
177
+ overflow-y: hidden !important;
178
+ }
179
+
180
+ .fancybox-overlay {
181
+ position: absolute;
182
+ top: 0;
183
+ left: 0;
184
+ overflow: hidden;
185
+ display: none;
186
+ z-index: 8010;
187
+ background: url('fancybox_overlay.png');
188
+ }
189
+
190
+ .fancybox-overlay-fixed {
191
+ position: fixed;
192
+ bottom: 0;
193
+ right: 0;
194
+ }
195
+
196
+ .fancybox-lock .fancybox-overlay {
197
+ overflow: auto;
198
+ overflow-y: scroll;
199
+ }
200
+
201
+ /* Title helper */
202
+
203
+ .fancybox-title {
204
+ visibility: hidden;
205
+ font: normal 13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;
206
+ position: relative;
207
+ text-shadow: none;
208
+ z-index: 8050;
209
+ }
210
+
211
+ .fancybox-opened .fancybox-title {
212
+ visibility: visible;
213
+ }
214
+
215
+ .fancybox-title-float-wrap {
216
+ position: absolute;
217
+ bottom: 0;
218
+ right: 50%;
219
+ margin-bottom: -35px;
220
+ z-index: 8050;
221
+ text-align: center;
222
+ }
223
+
224
+ .fancybox-title-float-wrap .child {
225
+ display: inline-block;
226
+ margin-right: -100%;
227
+ padding: 2px 20px;
228
+ background: transparent; /* Fallback for web browsers that doesn't support RGBa */
229
+ background: rgba(0, 0, 0, 0.8);
230
+ -webkit-border-radius: 15px;
231
+ -moz-border-radius: 15px;
232
+ border-radius: 15px;
233
+ text-shadow: 0 1px 2px #222;
234
+ color: #FFF;
235
+ font-weight: bold;
236
+ line-height: 24px;
237
+ white-space: nowrap;
238
+ }
239
+
240
+ .fancybox-title-outside-wrap {
241
+ position: relative;
242
+ margin-top: 10px;
243
+ color: #fff;
244
+ }
245
+
246
+ .fancybox-title-inside-wrap {
247
+ padding-top: 10px;
248
+ }
249
+
250
+ .fancybox-title-over-wrap {
251
+ position: absolute;
252
+ bottom: 0;
253
+ left: 0;
254
+ color: #fff;
255
+ padding: 10px;
256
+ background: #000;
257
+ background: rgba(0, 0, 0, .8);
258
+ }
259
+
260
+ /*Retina graphics!*/
261
+ @media only screen and (-webkit-min-device-pixel-ratio: 1.5),
262
+ only screen and (min--moz-device-pixel-ratio: 1.5),
263
+ only screen and (min-device-pixel-ratio: 1.5){
264
+
265
+ #fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span {
266
+ background-image: url('fancybox_sprite@2x.png');
267
+ background-size: 44px 152px; /*The size of the normal image, half the size of the hi-res image*/
268
+ }
269
+
270
+ #fancybox-loading div {
271
+ background-image: url('fancybox_loading@2x.gif');
272
+ background-size: 24px 24px; /*The size of the normal image, half the size of the hi-res image*/
273
+ }
274
+ }
skin/frontend/rwd/default/js/ve/fancybox/jquery.fancybox.js ADDED
@@ -0,0 +1,2020 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * fancyBox - jQuery Plugin
3
+ * version: 2.1.5 (Fri, 14 Jun 2013)
4
+ * @requires jQuery v1.6 or later
5
+ *
6
+ * Examples at http://fancyapps.com/fancybox/
7
+ * License: www.fancyapps.com/fancybox/#license
8
+ *
9
+ * Copyright 2012 Janis Skarnelis - janis@fancyapps.com
10
+ *
11
+ */
12
+
13
+ (function (window, document, $, undefined) {
14
+ "use strict";
15
+
16
+ var H = $("html"),
17
+ W = $(window),
18
+ D = $(document),
19
+ F = $.fancybox = function () {
20
+ F.open.apply( this, arguments );
21
+ },
22
+ IE = navigator.userAgent.match(/msie/i),
23
+ didUpdate = null,
24
+ isTouch = document.createTouch !== undefined,
25
+
26
+ isQuery = function(obj) {
27
+ return obj && obj.hasOwnProperty && obj instanceof $;
28
+ },
29
+ isString = function(str) {
30
+ return str && $.type(str) === "string";
31
+ },
32
+ isPercentage = function(str) {
33
+ return isString(str) && str.indexOf('%') > 0;
34
+ },
35
+ isScrollable = function(el) {
36
+ return (el && !(el.style.overflow && el.style.overflow === 'hidden') && ((el.clientWidth && el.scrollWidth > el.clientWidth) || (el.clientHeight && el.scrollHeight > el.clientHeight)));
37
+ },
38
+ getScalar = function(orig, dim) {
39
+ var value = parseInt(orig, 10) || 0;
40
+
41
+ if (dim && isPercentage(orig)) {
42
+ value = F.getViewport()[ dim ] / 100 * value;
43
+ }
44
+
45
+ return Math.ceil(value);
46
+ },
47
+ getValue = function(value, dim) {
48
+ return getScalar(value, dim) + 'px';
49
+ };
50
+
51
+ $.extend(F, {
52
+ // The current version of fancyBox
53
+ version: '2.1.5',
54
+
55
+ defaults: {
56
+ padding : 15,
57
+ margin : 20,
58
+
59
+ width : 800,
60
+ height : 600,
61
+ minWidth : 100,
62
+ minHeight : 100,
63
+ maxWidth : 9999,
64
+ maxHeight : 9999,
65
+ pixelRatio: 1, // Set to 2 for retina display support
66
+
67
+ autoSize : true,
68
+ autoHeight : false,
69
+ autoWidth : false,
70
+
71
+ autoResize : true,
72
+ autoCenter : !isTouch,
73
+ fitToView : true,
74
+ aspectRatio : false,
75
+ topRatio : 0.5,
76
+ leftRatio : 0.5,
77
+
78
+ scrolling : 'auto', // 'auto', 'yes' or 'no'
79
+ wrapCSS : '',
80
+
81
+ arrows : true,
82
+ closeBtn : true,
83
+ closeClick : false,
84
+ nextClick : false,
85
+ mouseWheel : true,
86
+ autoPlay : false,
87
+ playSpeed : 3000,
88
+ preload : 3,
89
+ modal : false,
90
+ loop : true,
91
+
92
+ ajax : {
93
+ dataType : 'html',
94
+ headers : { 'X-fancyBox': true }
95
+ },
96
+ iframe : {
97
+ scrolling : 'auto',
98
+ preload : true
99
+ },
100
+ swf : {
101
+ wmode: 'transparent',
102
+ allowfullscreen : 'true',
103
+ allowscriptaccess : 'always'
104
+ },
105
+
106
+ keys : {
107
+ next : {
108
+ 13 : 'left', // enter
109
+ 34 : 'up', // page down
110
+ 39 : 'left', // right arrow
111
+ 40 : 'up' // down arrow
112
+ },
113
+ prev : {
114
+ 8 : 'right', // backspace
115
+ 33 : 'down', // page up
116
+ 37 : 'right', // left arrow
117
+ 38 : 'down' // up arrow
118
+ },
119
+ close : [27], // escape key
120
+ play : [32], // space - start/stop slideshow
121
+ toggle : [70] // letter "f" - toggle fullscreen
122
+ },
123
+
124
+ direction : {
125
+ next : 'left',
126
+ prev : 'right'
127
+ },
128
+
129
+ scrollOutside : true,
130
+
131
+ // Override some properties
132
+ index : 0,
133
+ type : null,
134
+ href : null,
135
+ content : null,
136
+ title : null,
137
+
138
+ // HTML templates
139
+ tpl: {
140
+ wrap : '<div class="fancybox-wrap" tabIndex="-1"><div class="fancybox-skin"><div class="fancybox-outer"><div class="fancybox-inner"></div></div></div></div>',
141
+ image : '<img class="fancybox-image" src="{href}" alt="" />',
142
+ iframe : '<iframe id="fancybox-frame{rnd}" name="fancybox-frame{rnd}" class="fancybox-iframe" frameborder="0" vspace="0" hspace="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen' + (IE ? ' allowtransparency="true"' : '') + '></iframe>',
143
+ error : '<p class="fancybox-error">The requested content cannot be loaded.<br/>Please try again later.</p>',
144
+ closeBtn : '<a title="Close" class="fancybox-item fancybox-close" href="javascript:;"></a>',
145
+ next : '<a title="Next" class="fancybox-nav fancybox-next" href="javascript:;"><span></span></a>',
146
+ prev : '<a title="Previous" class="fancybox-nav fancybox-prev" href="javascript:;"><span></span></a>'
147
+ },
148
+
149
+ // Properties for each animation type
150
+ // Opening fancyBox
151
+ openEffect : 'fade', // 'elastic', 'fade' or 'none'
152
+ openSpeed : 250,
153
+ openEasing : 'swing',
154
+ openOpacity : true,
155
+ openMethod : 'zoomIn',
156
+
157
+ // Closing fancyBox
158
+ closeEffect : 'fade', // 'elastic', 'fade' or 'none'
159
+ closeSpeed : 250,
160
+ closeEasing : 'swing',
161
+ closeOpacity : true,
162
+ closeMethod : 'zoomOut',
163
+
164
+ // Changing next gallery item
165
+ nextEffect : 'elastic', // 'elastic', 'fade' or 'none'
166
+ nextSpeed : 250,
167
+ nextEasing : 'swing',
168
+ nextMethod : 'changeIn',
169
+
170
+ // Changing previous gallery item
171
+ prevEffect : 'elastic', // 'elastic', 'fade' or 'none'
172
+ prevSpeed : 250,
173
+ prevEasing : 'swing',
174
+ prevMethod : 'changeOut',
175
+
176
+ // Enable default helpers
177
+ helpers : {
178
+ overlay : true,
179
+ title : true
180
+ },
181
+
182
+ // Callbacks
183
+ onCancel : $.noop, // If canceling
184
+ beforeLoad : $.noop, // Before loading
185
+ afterLoad : $.noop, // After loading
186
+ beforeShow : $.noop, // Before changing in current item
187
+ afterShow : $.noop, // After opening
188
+ beforeChange : $.noop, // Before changing gallery item
189
+ beforeClose : $.noop, // Before closing
190
+ afterClose : $.noop // After closing
191
+ },
192
+
193
+ //Current state
194
+ group : {}, // Selected group
195
+ opts : {}, // Group options
196
+ previous : null, // Previous element
197
+ coming : null, // Element being loaded
198
+ current : null, // Currently loaded element
199
+ isActive : false, // Is activated
200
+ isOpen : false, // Is currently open
201
+ isOpened : false, // Have been fully opened at least once
202
+
203
+ wrap : null,
204
+ skin : null,
205
+ outer : null,
206
+ inner : null,
207
+
208
+ player : {
209
+ timer : null,
210
+ isActive : false
211
+ },
212
+
213
+ // Loaders
214
+ ajaxLoad : null,
215
+ imgPreload : null,
216
+
217
+ // Some collections
218
+ transitions : {},
219
+ helpers : {},
220
+
221
+ /*
222
+ * Static methods
223
+ */
224
+
225
+ open: function (group, opts) {
226
+ if (!group) {
227
+ return;
228
+ }
229
+
230
+ if (!$.isPlainObject(opts)) {
231
+ opts = {};
232
+ }
233
+
234
+ // Close if already active
235
+ if (false === F.close(true)) {
236
+ return;
237
+ }
238
+
239
+ // Normalize group
240
+ if (!$.isArray(group)) {
241
+ group = isQuery(group) ? $(group).get() : [group];
242
+ }
243
+
244
+ // Recheck if the type of each element is `object` and set content type (image, ajax, etc)
245
+ $.each(group, function(i, element) {
246
+ var obj = {},
247
+ href,
248
+ title,
249
+ content,
250
+ type,
251
+ rez,
252
+ hrefParts,
253
+ selector;
254
+
255
+ if ($.type(element) === "object") {
256
+ // Check if is DOM element
257
+ if (element.nodeType) {
258
+ element = $(element);
259
+ }
260
+
261
+ if (isQuery(element)) {
262
+ obj = {
263
+ href : element.data('fancybox-href') || element.attr('href'),
264
+ title : element.data('fancybox-title') || element.attr('title'),
265
+ isDom : true,
266
+ element : element
267
+ };
268
+
269
+ if ($.metadata) {
270
+ $.extend(true, obj, element.metadata());
271
+ }
272
+
273
+ } else {
274
+ obj = element;
275
+ }
276
+ }
277
+
278
+ href = opts.href || obj.href || (isString(element) ? element : null);
279
+ title = opts.title !== undefined ? opts.title : obj.title || '';
280
+
281
+ content = opts.content || obj.content;
282
+ type = content ? 'html' : (opts.type || obj.type);
283
+
284
+ if (!type && obj.isDom) {
285
+ type = element.data('fancybox-type');
286
+
287
+ if (!type) {
288
+ rez = element.prop('class').match(/fancybox\.(\w+)/);
289
+ type = rez ? rez[1] : null;
290
+ }
291
+ }
292
+
293
+ if (isString(href)) {
294
+ // Try to guess the content type
295
+ if (!type) {
296
+ if (F.isImage(href)) {
297
+ type = 'image';
298
+
299
+ } else if (F.isSWF(href)) {
300
+ type = 'swf';
301
+
302
+ } else if (href.charAt(0) === '#') {
303
+ type = 'inline';
304
+
305
+ } else if (isString(element)) {
306
+ type = 'html';
307
+ content = element;
308
+ }
309
+ }
310
+
311
+ // Split url into two pieces with source url and content selector, e.g,
312
+ // "/mypage.html #my_id" will load "/mypage.html" and display element having id "my_id"
313
+ if (type === 'ajax') {
314
+ hrefParts = href.split(/\s+/, 2);
315
+ href = hrefParts.shift();
316
+ selector = hrefParts.shift();
317
+ }
318
+ }
319
+
320
+ if (!content) {
321
+ if (type === 'inline') {
322
+ if (href) {
323
+ content = $( isString(href) ? href.replace(/.*(?=#[^\s]+$)/, '') : href ); //strip for ie7
324
+
325
+ } else if (obj.isDom) {
326
+ content = element;
327
+ }
328
+
329
+ } else if (type === 'html') {
330
+ content = href;
331
+
332
+ } else if (!type && !href && obj.isDom) {
333
+ type = 'inline';
334
+ content = element;
335
+ }
336
+ }
337
+
338
+ $.extend(obj, {
339
+ href : href,
340
+ type : type,
341
+ content : content,
342
+ title : title,
343
+ selector : selector
344
+ });
345
+
346
+ group[ i ] = obj;
347
+ });
348
+
349
+ // Extend the defaults
350
+ F.opts = $.extend(true, {}, F.defaults, opts);
351
+
352
+ // All options are merged recursive except keys
353
+ if (opts.keys !== undefined) {
354
+ F.opts.keys = opts.keys ? $.extend({}, F.defaults.keys, opts.keys) : false;
355
+ }
356
+
357
+ F.group = group;
358
+
359
+ return F._start(F.opts.index);
360
+ },
361
+
362
+ // Cancel image loading or abort ajax request
363
+ cancel: function () {
364
+ var coming = F.coming;
365
+
366
+ if (!coming || false === F.trigger('onCancel')) {
367
+ return;
368
+ }
369
+
370
+ F.hideLoading();
371
+
372
+ if (F.ajaxLoad) {
373
+ F.ajaxLoad.abort();
374
+ }
375
+
376
+ F.ajaxLoad = null;
377
+
378
+ if (F.imgPreload) {
379
+ F.imgPreload.onload = F.imgPreload.onerror = null;
380
+ }
381
+
382
+ if (coming.wrap) {
383
+ coming.wrap.stop(true, true).trigger('onReset').remove();
384
+ }
385
+
386
+ F.coming = null;
387
+
388
+ // If the first item has been canceled, then clear everything
389
+ if (!F.current) {
390
+ F._afterZoomOut( coming );
391
+ }
392
+ },
393
+
394
+ // Start closing animation if is open; remove immediately if opening/closing
395
+ close: function (event) {
396
+ F.cancel();
397
+
398
+ if (false === F.trigger('beforeClose')) {
399
+ return;
400
+ }
401
+
402
+ F.unbindEvents();
403
+
404
+ if (!F.isActive) {
405
+ return;
406
+ }
407
+
408
+ if (!F.isOpen || event === true) {
409
+ $('.fancybox-wrap').stop(true).trigger('onReset').remove();
410
+
411
+ F._afterZoomOut();
412
+
413
+ } else {
414
+ F.isOpen = F.isOpened = false;
415
+ F.isClosing = true;
416
+
417
+ $('.fancybox-item, .fancybox-nav').remove();
418
+
419
+ F.wrap.stop(true, true).removeClass('fancybox-opened');
420
+
421
+ F.transitions[ F.current.closeMethod ]();
422
+ }
423
+ },
424
+
425
+ // Manage slideshow:
426
+ // $.fancybox.play(); - toggle slideshow
427
+ // $.fancybox.play( true ); - start
428
+ // $.fancybox.play( false ); - stop
429
+ play: function ( action ) {
430
+ var clear = function () {
431
+ clearTimeout(F.player.timer);
432
+ },
433
+ set = function () {
434
+ clear();
435
+
436
+ if (F.current && F.player.isActive) {
437
+ F.player.timer = setTimeout(F.next, F.current.playSpeed);
438
+ }
439
+ },
440
+ stop = function () {
441
+ clear();
442
+
443
+ D.unbind('.player');
444
+
445
+ F.player.isActive = false;
446
+
447
+ F.trigger('onPlayEnd');
448
+ },
449
+ start = function () {
450
+ if (F.current && (F.current.loop || F.current.index < F.group.length - 1)) {
451
+ F.player.isActive = true;
452
+
453
+ D.bind({
454
+ 'onCancel.player beforeClose.player' : stop,
455
+ 'onUpdate.player' : set,
456
+ 'beforeLoad.player' : clear
457
+ });
458
+
459
+ set();
460
+
461
+ F.trigger('onPlayStart');
462
+ }
463
+ };
464
+
465
+ if (action === true || (!F.player.isActive && action !== false)) {
466
+ start();
467
+ } else {
468
+ stop();
469
+ }
470
+ },
471
+
472
+ // Navigate to next gallery item
473
+ next: function ( direction ) {
474
+ var current = F.current;
475
+
476
+ if (current) {
477
+ if (!isString(direction)) {
478
+ direction = current.direction.next;
479
+ }
480
+
481
+ F.jumpto(current.index + 1, direction, 'next');
482
+ }
483
+ },
484
+
485
+ // Navigate to previous gallery item
486
+ prev: function ( direction ) {
487
+ var current = F.current;
488
+
489
+ if (current) {
490
+ if (!isString(direction)) {
491
+ direction = current.direction.prev;
492
+ }
493
+
494
+ F.jumpto(current.index - 1, direction, 'prev');
495
+ }
496
+ },
497
+
498
+ // Navigate to gallery item by index
499
+ jumpto: function ( index, direction, router ) {
500
+ var current = F.current;
501
+
502
+ if (!current) {
503
+ return;
504
+ }
505
+
506
+ index = getScalar(index);
507
+
508
+ F.direction = direction || current.direction[ (index >= current.index ? 'next' : 'prev') ];
509
+ F.router = router || 'jumpto';
510
+
511
+ if (current.loop) {
512
+ if (index < 0) {
513
+ index = current.group.length + (index % current.group.length);
514
+ }
515
+
516
+ index = index % current.group.length;
517
+ }
518
+
519
+ if (current.group[ index ] !== undefined) {
520
+ F.cancel();
521
+
522
+ F._start(index);
523
+ }
524
+ },
525
+
526
+ // Center inside viewport and toggle position type to fixed or absolute if needed
527
+ reposition: function (e, onlyAbsolute) {
528
+ var current = F.current,
529
+ wrap = current ? current.wrap : null,
530
+ pos;
531
+
532
+ if (wrap) {
533
+ pos = F._getPosition(onlyAbsolute);
534
+
535
+ if (e && e.type === 'scroll') {
536
+ delete pos.position;
537
+
538
+ wrap.stop(true, true).animate(pos, 200);
539
+
540
+ } else {
541
+ wrap.css(pos);
542
+
543
+ current.pos = $.extend({}, current.dim, pos);
544
+ }
545
+ }
546
+ },
547
+
548
+ update: function (e) {
549
+ var type = (e && e.type),
550
+ anyway = !type || type === 'orientationchange';
551
+
552
+ if (anyway) {
553
+ clearTimeout(didUpdate);
554
+
555
+ didUpdate = null;
556
+ }
557
+
558
+ if (!F.isOpen || didUpdate) {
559
+ return;
560
+ }
561
+
562
+ didUpdate = setTimeout(function() {
563
+ var current = F.current;
564
+
565
+ if (!current || F.isClosing) {
566
+ return;
567
+ }
568
+
569
+ F.wrap.removeClass('fancybox-tmp');
570
+
571
+ if (anyway || type === 'load' || (type === 'resize' && current.autoResize)) {
572
+ F._setDimension();
573
+ }
574
+
575
+ if (!(type === 'scroll' && current.canShrink)) {
576
+ F.reposition(e);
577
+ }
578
+
579
+ F.trigger('onUpdate');
580
+
581
+ didUpdate = null;
582
+
583
+ }, (anyway && !isTouch ? 0 : 300));
584
+ },
585
+
586
+ // Shrink content to fit inside viewport or restore if resized
587
+ toggle: function ( action ) {
588
+ if (F.isOpen) {
589
+ F.current.fitToView = $.type(action) === "boolean" ? action : !F.current.fitToView;
590
+
591
+ // Help browser to restore document dimensions
592
+ if (isTouch) {
593
+ F.wrap.removeAttr('style').addClass('fancybox-tmp');
594
+
595
+ F.trigger('onUpdate');
596
+ }
597
+
598
+ F.update();
599
+ }
600
+ },
601
+
602
+ hideLoading: function () {
603
+ D.unbind('.loading');
604
+
605
+ $('#fancybox-loading').remove();
606
+ },
607
+
608
+ showLoading: function () {
609
+ var el, viewport;
610
+
611
+ F.hideLoading();
612
+
613
+ el = $('<div id="fancybox-loading"><div></div></div>').click(F.cancel).appendTo('body');
614
+
615
+ // If user will press the escape-button, the request will be canceled
616
+ D.bind('keydown.loading', function(e) {
617
+ if ((e.which || e.keyCode) === 27) {
618
+ e.preventDefault();
619
+
620
+ F.cancel();
621
+ }
622
+ });
623
+
624
+ if (!F.defaults.fixed) {
625
+ viewport = F.getViewport();
626
+
627
+ el.css({
628
+ position : 'absolute',
629
+ top : (viewport.h * 0.5) + viewport.y,
630
+ left : (viewport.w * 0.5) + viewport.x
631
+ });
632
+ }
633
+ },
634
+
635
+ getViewport: function () {
636
+ var locked = (F.current && F.current.locked) || false,
637
+ rez = {
638
+ x: W.scrollLeft(),
639
+ y: W.scrollTop()
640
+ };
641
+
642
+ if (locked) {
643
+ rez.w = locked[0].clientWidth;
644
+ rez.h = locked[0].clientHeight;
645
+
646
+ } else {
647
+ // See http://bugs.jquery.com/ticket/6724
648
+ rez.w = isTouch && window.innerWidth ? window.innerWidth : W.width();
649
+ rez.h = isTouch && window.innerHeight ? window.innerHeight : W.height();
650
+ }
651
+
652
+ return rez;
653
+ },
654
+
655
+ // Unbind the keyboard / clicking actions
656
+ unbindEvents: function () {
657
+ if (F.wrap && isQuery(F.wrap)) {
658
+ F.wrap.unbind('.fb');
659
+ }
660
+
661
+ D.unbind('.fb');
662
+ W.unbind('.fb');
663
+ },
664
+
665
+ bindEvents: function () {
666
+ var current = F.current,
667
+ keys;
668
+
669
+ if (!current) {
670
+ return;
671
+ }
672
+
673
+ // Changing document height on iOS devices triggers a 'resize' event,
674
+ // that can change document height... repeating infinitely
675
+ W.bind('orientationchange.fb' + (isTouch ? '' : ' resize.fb') + (current.autoCenter && !current.locked ? ' scroll.fb' : ''), F.update);
676
+
677
+ keys = current.keys;
678
+
679
+ if (keys) {
680
+ D.bind('keydown.fb', function (e) {
681
+ var code = e.which || e.keyCode,
682
+ target = e.target || e.srcElement;
683
+
684
+ // Skip esc key if loading, because showLoading will cancel preloading
685
+ if (code === 27 && F.coming) {
686
+ return false;
687
+ }
688
+
689
+ // Ignore key combinations and key events within form elements
690
+ if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey && !(target && (target.type || $(target).is('[contenteditable]')))) {
691
+ $.each(keys, function(i, val) {
692
+ if (current.group.length > 1 && val[ code ] !== undefined) {
693
+ F[ i ]( val[ code ] );
694
+
695
+ e.preventDefault();
696
+ return false;
697
+ }
698
+
699
+ if ($.inArray(code, val) > -1) {
700
+ F[ i ] ();
701
+
702
+ e.preventDefault();
703
+ return false;
704
+ }
705
+ });
706
+ }
707
+ });
708
+ }
709
+
710
+ if ($.fn.mousewheel && current.mouseWheel) {
711
+ F.wrap.bind('mousewheel.fb', function (e, delta, deltaX, deltaY) {
712
+ var target = e.target || null,
713
+ parent = $(target),
714
+ canScroll = false;
715
+
716
+ while (parent.length) {
717
+ if (canScroll || parent.is('.fancybox-skin') || parent.is('.fancybox-wrap')) {
718
+ break;
719
+ }
720
+
721
+ canScroll = isScrollable( parent[0] );
722
+ parent = $(parent).parent();
723
+ }
724
+
725
+ if (delta !== 0 && !canScroll) {
726
+ if (F.group.length > 1 && !current.canShrink) {
727
+ if (deltaY > 0 || deltaX > 0) {
728
+ F.prev( deltaY > 0 ? 'down' : 'left' );
729
+
730
+ } else if (deltaY < 0 || deltaX < 0) {
731
+ F.next( deltaY < 0 ? 'up' : 'right' );
732
+ }
733
+
734
+ e.preventDefault();
735
+ }
736
+ }
737
+ });
738
+ }
739
+ },
740
+
741
+ trigger: function (event, o) {
742
+ var ret, obj = o || F.coming || F.current;
743
+
744
+ if (!obj) {
745
+ return;
746
+ }
747
+
748
+ if ($.isFunction( obj[event] )) {
749
+ ret = obj[event].apply(obj, Array.prototype.slice.call(arguments, 1));
750
+ }
751
+
752
+ if (ret === false) {
753
+ return false;
754
+ }
755
+
756
+ if (obj.helpers) {
757
+ $.each(obj.helpers, function (helper, opts) {
758
+ if (opts && F.helpers[helper] && $.isFunction(F.helpers[helper][event])) {
759
+ F.helpers[helper][event]($.extend(true, {}, F.helpers[helper].defaults, opts), obj);
760
+ }
761
+ });
762
+ }
763
+
764
+ D.trigger(event);
765
+ },
766
+
767
+ isImage: function (str) {
768
+ return isString(str) && str.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp|svg)((\?|#).*)?$)/i);
769
+ },
770
+
771
+ isSWF: function (str) {
772
+ return isString(str) && str.match(/\.(swf)((\?|#).*)?$/i);
773
+ },
774
+
775
+ _start: function (index) {
776
+ var coming = {},
777
+ obj,
778
+ href,
779
+ type,
780
+ margin,
781
+ padding;
782
+
783
+ index = getScalar( index );
784
+ obj = F.group[ index ] || null;
785
+
786
+ if (!obj) {
787
+ return false;
788
+ }
789
+
790
+ coming = $.extend(true, {}, F.opts, obj);
791
+
792
+ // Convert margin and padding properties to array - top, right, bottom, left
793
+ margin = coming.margin;
794
+ padding = coming.padding;
795
+
796
+ if ($.type(margin) === 'number') {
797
+ coming.margin = [margin, margin, margin, margin];
798
+ }
799
+
800
+ if ($.type(padding) === 'number') {
801
+ coming.padding = [padding, padding, padding, padding];
802
+ }
803
+
804
+ // 'modal' propery is just a shortcut
805
+ if (coming.modal) {
806
+ $.extend(true, coming, {
807
+ closeBtn : false,
808
+ closeClick : false,
809
+ nextClick : false,
810
+ arrows : false,
811
+ mouseWheel : false,
812
+ keys : null,
813
+ helpers: {
814
+ overlay : {
815
+ closeClick : false
816
+ }
817
+ }
818
+ });
819
+ }
820
+
821
+ // 'autoSize' property is a shortcut, too
822
+ if (coming.autoSize) {
823
+ coming.autoWidth = coming.autoHeight = true;
824
+ }
825
+
826
+ if (coming.width === 'auto') {
827
+ coming.autoWidth = true;
828
+ }
829
+
830
+ if (coming.height === 'auto') {
831
+ coming.autoHeight = true;
832
+ }
833
+
834
+ /*
835
+ * Add reference to the group, so it`s possible to access from callbacks, example:
836
+ * afterLoad : function() {
837
+ * this.title = 'Image ' + (this.index + 1) + ' of ' + this.group.length + (this.title ? ' - ' + this.title : '');
838
+ * }
839
+ */
840
+
841
+ coming.group = F.group;
842
+ coming.index = index;
843
+
844
+ // Give a chance for callback or helpers to update coming item (type, title, etc)
845
+ F.coming = coming;
846
+
847
+ if (false === F.trigger('beforeLoad')) {
848
+ F.coming = null;
849
+
850
+ return;
851
+ }
852
+
853
+ type = coming.type;
854
+ href = coming.href;
855
+
856
+ if (!type) {
857
+ F.coming = null;
858
+
859
+ //If we can not determine content type then drop silently or display next/prev item if looping through gallery
860
+ if (F.current && F.router && F.router !== 'jumpto') {
861
+ F.current.index = index;
862
+
863
+ return F[ F.router ]( F.direction );
864
+ }
865
+
866
+ return false;
867
+ }
868
+
869
+ F.isActive = true;
870
+
871
+ if (type === 'image' || type === 'swf') {
872
+ coming.autoHeight = coming.autoWidth = false;
873
+ coming.scrolling = 'visible';
874
+ }
875
+
876
+ if (type === 'image') {
877
+ coming.aspectRatio = true;
878
+ }
879
+
880
+ if (type === 'iframe' && isTouch) {
881
+ coming.scrolling = 'scroll';
882
+ }
883
+
884
+ // Build the neccessary markup
885
+ coming.wrap = $(coming.tpl.wrap).addClass('fancybox-' + (isTouch ? 'mobile' : 'desktop') + ' fancybox-type-' + type + ' fancybox-tmp ' + coming.wrapCSS).appendTo( coming.parent || 'body' );
886
+
887
+ $.extend(coming, {
888
+ skin : $('.fancybox-skin', coming.wrap),
889
+ outer : $('.fancybox-outer', coming.wrap),
890
+ inner : $('.fancybox-inner', coming.wrap)
891
+ });
892
+
893
+ $.each(["Top", "Right", "Bottom", "Left"], function(i, v) {
894
+ coming.skin.css('padding' + v, getValue(coming.padding[ i ]));
895
+ });
896
+
897
+ F.trigger('onReady');
898
+
899
+ // Check before try to load; 'inline' and 'html' types need content, others - href
900
+ if (type === 'inline' || type === 'html') {
901
+ if (!coming.content || !coming.content.length) {
902
+ return F._error( 'content' );
903
+ }
904
+
905
+ } else if (!href) {
906
+ return F._error( 'href' );
907
+ }
908
+
909
+ if (type === 'image') {
910
+ F._loadImage();
911
+
912
+ } else if (type === 'ajax') {
913
+ F._loadAjax();
914
+
915
+ } else if (type === 'iframe') {
916
+ F._loadIframe();
917
+
918
+ } else {
919
+ F._afterLoad();
920
+ }
921
+ },
922
+
923
+ _error: function ( type ) {
924
+ $.extend(F.coming, {
925
+ type : 'html',
926
+ autoWidth : true,
927
+ autoHeight : true,
928
+ minWidth : 0,
929
+ minHeight : 0,
930
+ scrolling : 'no',
931
+ hasError : type,
932
+ content : F.coming.tpl.error
933
+ });
934
+
935
+ F._afterLoad();
936
+ },
937
+
938
+ _loadImage: function () {
939
+ // Reset preload image so it is later possible to check "complete" property
940
+ var img = F.imgPreload = new Image();
941
+
942
+ img.onload = function () {
943
+ this.onload = this.onerror = null;
944
+
945
+ F.coming.width = this.width / F.opts.pixelRatio;
946
+ F.coming.height = this.height / F.opts.pixelRatio;
947
+
948
+ F._afterLoad();
949
+ };
950
+
951
+ img.onerror = function () {
952
+ this.onload = this.onerror = null;
953
+
954
+ F._error( 'image' );
955
+ };
956
+
957
+ img.src = F.coming.href;
958
+
959
+ if (img.complete !== true) {
960
+ F.showLoading();
961
+ }
962
+ },
963
+
964
+ _loadAjax: function () {
965
+ var coming = F.coming;
966
+
967
+ F.showLoading();
968
+
969
+ F.ajaxLoad = $.ajax($.extend({}, coming.ajax, {
970
+ url: coming.href,
971
+ error: function (jqXHR, textStatus) {
972
+ if (F.coming && textStatus !== 'abort') {
973
+ F._error( 'ajax', jqXHR );
974
+
975
+ } else {
976
+ F.hideLoading();
977
+ }
978
+ },
979
+ success: function (data, textStatus) {
980
+ if (textStatus === 'success') {
981
+ coming.content = data;
982
+
983
+ F._afterLoad();
984
+ }
985
+ }
986
+ }));
987
+ },
988
+
989
+ _loadIframe: function() {
990
+ var coming = F.coming,
991
+ iframe = $(coming.tpl.iframe.replace(/\{rnd\}/g, new Date().getTime()))
992
+ .attr('scrolling', isTouch ? 'auto' : coming.iframe.scrolling)
993
+ .attr('src', coming.href);
994
+
995
+ // This helps IE
996
+ $(coming.wrap).bind('onReset', function () {
997
+ try {
998
+ $(this).find('iframe').hide().attr('src', '//about:blank').end().empty();
999
+ } catch (e) {}
1000
+ });
1001
+
1002
+ if (coming.iframe.preload) {
1003
+ F.showLoading();
1004
+
1005
+ iframe.one('load', function() {
1006
+ $(this).data('ready', 1);
1007
+
1008
+ // iOS will lose scrolling if we resize
1009
+ if (!isTouch) {
1010
+ $(this).bind('load.fb', F.update);
1011
+ }
1012
+
1013
+ // Without this trick:
1014
+ // - iframe won't scroll on iOS devices
1015
+ // - IE7 sometimes displays empty iframe
1016
+ $(this).parents('.fancybox-wrap').width('100%').removeClass('fancybox-tmp').show();
1017
+
1018
+ F._afterLoad();
1019
+ });
1020
+ }
1021
+
1022
+ coming.content = iframe.appendTo( coming.inner );
1023
+
1024
+ if (!coming.iframe.preload) {
1025
+ F._afterLoad();
1026
+ }
1027
+ },
1028
+
1029
+ _preloadImages: function() {
1030
+ var group = F.group,
1031
+ current = F.current,
1032
+ len = group.length,
1033
+ cnt = current.preload ? Math.min(current.preload, len - 1) : 0,
1034
+ item,
1035
+ i;
1036
+
1037
+ for (i = 1; i <= cnt; i += 1) {
1038
+ item = group[ (current.index + i ) % len ];
1039
+
1040
+ if (item.type === 'image' && item.href) {
1041
+ new Image().src = item.href;
1042
+ }
1043
+ }
1044
+ },
1045
+
1046
+ _afterLoad: function () {
1047
+ var coming = F.coming,
1048
+ previous = F.current,
1049
+ placeholder = 'fancybox-placeholder',
1050
+ current,
1051
+ content,
1052
+ type,
1053
+ scrolling,
1054
+ href,
1055
+ embed;
1056
+
1057
+ F.hideLoading();
1058
+
1059
+ if (!coming || F.isActive === false) {
1060
+ return;
1061
+ }
1062
+
1063
+ if (false === F.trigger('afterLoad', coming, previous)) {
1064
+ coming.wrap.stop(true).trigger('onReset').remove();
1065
+
1066
+ F.coming = null;
1067
+
1068
+ return;
1069
+ }
1070
+
1071
+ if (previous) {
1072
+ F.trigger('beforeChange', previous);
1073
+
1074
+ previous.wrap.stop(true).removeClass('fancybox-opened')
1075
+ .find('.fancybox-item, .fancybox-nav')
1076
+ .remove();
1077
+ }
1078
+
1079
+ F.unbindEvents();
1080
+
1081
+ current = coming;
1082
+ content = coming.content;
1083
+ type = coming.type;
1084
+ scrolling = coming.scrolling;
1085
+
1086
+ $.extend(F, {
1087
+ wrap : current.wrap,
1088
+ skin : current.skin,
1089
+ outer : current.outer,
1090
+ inner : current.inner,
1091
+ current : current,
1092
+ previous : previous
1093
+ });
1094
+
1095
+ href = current.href;
1096
+
1097
+ switch (type) {
1098
+ case 'inline':
1099
+ case 'ajax':
1100
+ case 'html':
1101
+ if (current.selector) {
1102
+ content = $('<div>').html(content).find(current.selector);
1103
+
1104
+ } else if (isQuery(content)) {
1105
+ if (!content.data(placeholder)) {
1106
+ content.data(placeholder, $('<div class="' + placeholder + '"></div>').insertAfter( content ).hide() );
1107
+ }
1108
+
1109
+ content = content.show().detach();
1110
+
1111
+ current.wrap.bind('onReset', function () {
1112
+ if ($(this).find(content).length) {
1113
+ content.hide().replaceAll( content.data(placeholder) ).data(placeholder, false);
1114
+ }
1115
+ });
1116
+ }
1117
+ break;
1118
+
1119
+ case 'image':
1120
+ content = current.tpl.image.replace('{href}', href);
1121
+ break;
1122
+
1123
+ case 'swf':
1124
+ content = '<object id="fancybox-swf" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%"><param name="movie" value="' + href + '"></param>';
1125
+ embed = '';
1126
+
1127
+ $.each(current.swf, function(name, val) {
1128
+ content += '<param name="' + name + '" value="' + val + '"></param>';
1129
+ embed += ' ' + name + '="' + val + '"';
1130
+ });
1131
+
1132
+ content += '<embed src="' + href + '" type="application/x-shockwave-flash" width="100%" height="100%"' + embed + '></embed></object>';
1133
+ break;
1134
+ }
1135
+
1136
+ if (!(isQuery(content) && content.parent().is(current.inner))) {
1137
+ current.inner.append( content );
1138
+ }
1139
+
1140
+ // Give a chance for helpers or callbacks to update elements
1141
+ F.trigger('beforeShow');
1142
+
1143
+ // Set scrolling before calculating dimensions
1144
+ current.inner.css('overflow', scrolling === 'yes' ? 'scroll' : (scrolling === 'no' ? 'hidden' : scrolling));
1145
+
1146
+ // Set initial dimensions and start position
1147
+ F._setDimension();
1148
+
1149
+ F.reposition();
1150
+
1151
+ F.isOpen = false;
1152
+ F.coming = null;
1153
+
1154
+ F.bindEvents();
1155
+
1156
+ if (!F.isOpened) {
1157
+ $('.fancybox-wrap').not( current.wrap ).stop(true).trigger('onReset').remove();
1158
+
1159
+ } else if (previous.prevMethod) {
1160
+ F.transitions[ previous.prevMethod ]();
1161
+ }
1162
+
1163
+ F.transitions[ F.isOpened ? current.nextMethod : current.openMethod ]();
1164
+
1165
+ F._preloadImages();
1166
+ },
1167
+
1168
+ _setDimension: function () {
1169
+ var viewport = F.getViewport(),
1170
+ steps = 0,
1171
+ canShrink = false,
1172
+ canExpand = false,
1173
+ wrap = F.wrap,
1174
+ skin = F.skin,
1175
+ inner = F.inner,
1176
+ current = F.current,
1177
+ width = current.width,
1178
+ height = current.height,
1179
+ minWidth = current.minWidth,
1180
+ minHeight = current.minHeight,
1181
+ maxWidth = current.maxWidth,
1182
+ maxHeight = current.maxHeight,
1183
+ scrolling = current.scrolling,
1184
+ scrollOut = current.scrollOutside ? current.scrollbarWidth : 0,
1185
+ margin = current.margin,
1186
+ wMargin = getScalar(margin[1] + margin[3]),
1187
+ hMargin = getScalar(margin[0] + margin[2]),
1188
+ wPadding,
1189
+ hPadding,
1190
+ wSpace,
1191
+ hSpace,
1192
+ origWidth,
1193
+ origHeight,
1194
+ origMaxWidth,
1195
+ origMaxHeight,
1196
+ ratio,
1197
+ width_,
1198
+ height_,
1199
+ maxWidth_,
1200
+ maxHeight_,
1201
+ iframe,
1202
+ body;
1203
+
1204
+ // Reset dimensions so we could re-check actual size
1205
+ wrap.add(skin).add(inner).width('auto').height('auto').removeClass('fancybox-tmp');
1206
+
1207
+ wPadding = getScalar(skin.outerWidth(true) - skin.width());
1208
+ hPadding = getScalar(skin.outerHeight(true) - skin.height());
1209
+
1210
+ // Any space between content and viewport (margin, padding, border, title)
1211
+ wSpace = wMargin + wPadding;
1212
+ hSpace = hMargin + hPadding;
1213
+
1214
+ origWidth = isPercentage(width) ? (viewport.w - wSpace) * getScalar(width) / 100 : width;
1215
+ origHeight = isPercentage(height) ? (viewport.h - hSpace) * getScalar(height) / 100 : height;
1216
+
1217
+ if (current.type === 'iframe') {
1218
+ iframe = current.content;
1219
+
1220
+ if (current.autoHeight && iframe.data('ready') === 1) {
1221
+ try {
1222
+ if (iframe[0].contentWindow.document.location) {
1223
+ inner.width( origWidth ).height(9999);
1224
+
1225
+ body = iframe.contents().find('body');
1226
+
1227
+ if (scrollOut) {
1228
+ body.css('overflow-x', 'hidden');
1229
+ }
1230
+
1231
+ origHeight = body.outerHeight(true);
1232
+ }
1233
+
1234
+ } catch (e) {}
1235
+ }
1236
+
1237
+ } else if (current.autoWidth || current.autoHeight) {
1238
+ inner.addClass( 'fancybox-tmp' );
1239
+
1240
+ // Set width or height in case we need to calculate only one dimension
1241
+ if (!current.autoWidth) {
1242
+ inner.width( origWidth );
1243
+ }
1244
+
1245
+ if (!current.autoHeight) {
1246
+ inner.height( origHeight );
1247
+ }
1248
+
1249
+ if (current.autoWidth) {
1250
+ origWidth = inner.width();
1251
+ }
1252
+
1253
+ if (current.autoHeight) {
1254
+ origHeight = inner.height();
1255
+ }
1256
+
1257
+ inner.removeClass( 'fancybox-tmp' );
1258
+ }
1259
+
1260
+ width = getScalar( origWidth );
1261
+ height = getScalar( origHeight );
1262
+
1263
+ ratio = origWidth / origHeight;
1264
+
1265
+ // Calculations for the content
1266
+ minWidth = getScalar(isPercentage(minWidth) ? getScalar(minWidth, 'w') - wSpace : minWidth);
1267
+ maxWidth = getScalar(isPercentage(maxWidth) ? getScalar(maxWidth, 'w') - wSpace : maxWidth);
1268
+
1269
+ minHeight = getScalar(isPercentage(minHeight) ? getScalar(minHeight, 'h') - hSpace : minHeight);
1270
+ maxHeight = getScalar(isPercentage(maxHeight) ? getScalar(maxHeight, 'h') - hSpace : maxHeight);
1271
+
1272
+ // These will be used to determine if wrap can fit in the viewport
1273
+ origMaxWidth = maxWidth;
1274
+ origMaxHeight = maxHeight;
1275
+
1276
+ if (current.fitToView) {
1277
+ maxWidth = Math.min(viewport.w - wSpace, maxWidth);
1278
+ maxHeight = Math.min(viewport.h - hSpace, maxHeight);
1279
+ }
1280
+
1281
+ maxWidth_ = viewport.w - wMargin;
1282
+ maxHeight_ = viewport.h - hMargin;
1283
+
1284
+ if (current.aspectRatio) {
1285
+ if (width > maxWidth) {
1286
+ width = maxWidth;
1287
+ height = getScalar(width / ratio);
1288
+ }
1289
+
1290
+ if (height > maxHeight) {
1291
+ height = maxHeight;
1292
+ width = getScalar(height * ratio);
1293
+ }
1294
+
1295
+ if (width < minWidth) {
1296
+ width = minWidth;
1297
+ height = getScalar(width / ratio);
1298
+ }
1299
+
1300
+ if (height < minHeight) {
1301
+ height = minHeight;
1302
+ width = getScalar(height * ratio);
1303
+ }
1304
+
1305
+ } else {
1306
+ width = Math.max(minWidth, Math.min(width, maxWidth));
1307
+
1308
+ if (current.autoHeight && current.type !== 'iframe') {
1309
+ inner.width( width );
1310
+
1311
+ height = inner.height();
1312
+ }
1313
+
1314
+ height = Math.max(minHeight, Math.min(height, maxHeight));
1315
+ }
1316
+
1317
+ // Try to fit inside viewport (including the title)
1318
+ if (current.fitToView) {
1319
+ inner.width( width ).height( height );
1320
+
1321
+ wrap.width( width + wPadding );
1322
+
1323
+ // Real wrap dimensions
1324
+ width_ = wrap.width();
1325
+ height_ = wrap.height();
1326
+
1327
+ if (current.aspectRatio) {
1328
+ while ((width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight) {
1329
+ if (steps++ > 19) {
1330
+ break;
1331
+ }
1332
+
1333
+ height = Math.max(minHeight, Math.min(maxHeight, height - 10));
1334
+ width = getScalar(height * ratio);
1335
+
1336
+ if (width < minWidth) {
1337
+ width = minWidth;
1338
+ height = getScalar(width / ratio);
1339
+ }
1340
+
1341
+ if (width > maxWidth) {
1342
+ width = maxWidth;
1343
+ height = getScalar(width / ratio);
1344
+ }
1345
+
1346
+ inner.width( width ).height( height );
1347
+
1348
+ wrap.width( width + wPadding );
1349
+
1350
+ width_ = wrap.width();
1351
+ height_ = wrap.height();
1352
+ }
1353
+
1354
+ } else {
1355
+ width = Math.max(minWidth, Math.min(width, width - (width_ - maxWidth_)));
1356
+ height = Math.max(minHeight, Math.min(height, height - (height_ - maxHeight_)));
1357
+ }
1358
+ }
1359
+
1360
+ if (scrollOut && scrolling === 'auto' && height < origHeight && (width + wPadding + scrollOut) < maxWidth_) {
1361
+ width += scrollOut;
1362
+ }
1363
+
1364
+ inner.width( width ).height( height );
1365
+
1366
+ wrap.width( width + wPadding );
1367
+
1368
+ width_ = wrap.width();
1369
+ height_ = wrap.height();
1370
+
1371
+ canShrink = (width_ > maxWidth_ || height_ > maxHeight_) && width > minWidth && height > minHeight;
1372
+ canExpand = current.aspectRatio ? (width < origMaxWidth && height < origMaxHeight && width < origWidth && height < origHeight) : ((width < origMaxWidth || height < origMaxHeight) && (width < origWidth || height < origHeight));
1373
+
1374
+ $.extend(current, {
1375
+ dim : {
1376
+ width : getValue( width_ ),
1377
+ height : getValue( height_ )
1378
+ },
1379
+ origWidth : origWidth,
1380
+ origHeight : origHeight,
1381
+ canShrink : canShrink,
1382
+ canExpand : canExpand,
1383
+ wPadding : wPadding,
1384
+ hPadding : hPadding,
1385
+ wrapSpace : height_ - skin.outerHeight(true),
1386
+ skinSpace : skin.height() - height
1387
+ });
1388
+
1389
+ if (!iframe && current.autoHeight && height > minHeight && height < maxHeight && !canExpand) {
1390
+ inner.height('auto');
1391
+ }
1392
+ },
1393
+
1394
+ _getPosition: function (onlyAbsolute) {
1395
+ var current = F.current,
1396
+ viewport = F.getViewport(),
1397
+ margin = current.margin,
1398
+ width = F.wrap.width() + margin[1] + margin[3],
1399
+ height = F.wrap.height() + margin[0] + margin[2],
1400
+ rez = {
1401
+ position: 'absolute',
1402
+ top : margin[0],
1403
+ left : margin[3]
1404
+ };
1405
+
1406
+ if (current.autoCenter && current.fixed && !onlyAbsolute && height <= viewport.h && width <= viewport.w) {
1407
+ rez.position = 'fixed';
1408
+
1409
+ } else if (!current.locked) {
1410
+ rez.top += viewport.y;
1411
+ rez.left += viewport.x;
1412
+ }
1413
+
1414
+ rez.top = getValue(Math.max(rez.top, rez.top + ((viewport.h - height) * current.topRatio)));
1415
+ rez.left = getValue(Math.max(rez.left, rez.left + ((viewport.w - width) * current.leftRatio)));
1416
+
1417
+ return rez;
1418
+ },
1419
+
1420
+ _afterZoomIn: function () {
1421
+ var current = F.current;
1422
+
1423
+ if (!current) {
1424
+ return;
1425
+ }
1426
+
1427
+ F.isOpen = F.isOpened = true;
1428
+
1429
+ F.wrap.css('overflow', 'visible').addClass('fancybox-opened');
1430
+
1431
+ F.update();
1432
+
1433
+ // Assign a click event
1434
+ if ( current.closeClick || (current.nextClick && F.group.length > 1) ) {
1435
+ F.inner.css('cursor', 'pointer').bind('click.fb', function(e) {
1436
+ if (!$(e.target).is('a') && !$(e.target).parent().is('a')) {
1437
+ e.preventDefault();
1438
+
1439
+ F[ current.closeClick ? 'close' : 'next' ]();
1440
+ }
1441
+ });
1442
+ }
1443
+
1444
+ // Create a close button
1445
+ if (current.closeBtn) {
1446
+ $(current.tpl.closeBtn).appendTo(F.skin).bind('click.fb', function(e) {
1447
+ e.preventDefault();
1448
+
1449
+ F.close();
1450
+ });
1451
+ }
1452
+
1453
+ // Create navigation arrows
1454
+ if (current.arrows && F.group.length > 1) {
1455
+ if (current.loop || current.index > 0) {
1456
+ $(current.tpl.prev).appendTo(F.outer).bind('click.fb', F.prev);
1457
+ }
1458
+
1459
+ if (current.loop || current.index < F.group.length - 1) {
1460
+ $(current.tpl.next).appendTo(F.outer).bind('click.fb', F.next);
1461
+ }
1462
+ }
1463
+
1464
+ F.trigger('afterShow');
1465
+
1466
+ // Stop the slideshow if this is the last item
1467
+ if (!current.loop && current.index === current.group.length - 1) {
1468
+ F.play( false );
1469
+
1470
+ } else if (F.opts.autoPlay && !F.player.isActive) {
1471
+ F.opts.autoPlay = false;
1472
+
1473
+ F.play();
1474
+ }
1475
+ },
1476
+
1477
+ _afterZoomOut: function ( obj ) {
1478
+ obj = obj || F.current;
1479
+
1480
+ $('.fancybox-wrap').trigger('onReset').remove();
1481
+
1482
+ $.extend(F, {
1483
+ group : {},
1484
+ opts : {},
1485
+ router : false,
1486
+ current : null,
1487
+ isActive : false,
1488
+ isOpened : false,
1489
+ isOpen : false,
1490
+ isClosing : false,
1491
+ wrap : null,
1492
+ skin : null,
1493
+ outer : null,
1494
+ inner : null
1495
+ });
1496
+
1497
+ F.trigger('afterClose', obj);
1498
+ }
1499
+ });
1500
+
1501
+ /*
1502
+ * Default transitions
1503
+ */
1504
+
1505
+ F.transitions = {
1506
+ getOrigPosition: function () {
1507
+ var current = F.current,
1508
+ element = current.element,
1509
+ orig = current.orig,
1510
+ pos = {},
1511
+ width = 50,
1512
+ height = 50,
1513
+ hPadding = current.hPadding,
1514
+ wPadding = current.wPadding,
1515
+ viewport = F.getViewport();
1516
+
1517
+ if (!orig && current.isDom && element.is(':visible')) {
1518
+ orig = element.find('img:first');
1519
+
1520
+ if (!orig.length) {
1521
+ orig = element;
1522
+ }
1523
+ }
1524
+
1525
+ if (isQuery(orig)) {
1526
+ pos = orig.offset();
1527
+
1528
+ if (orig.is('img')) {
1529
+ width = orig.outerWidth();
1530
+ height = orig.outerHeight();
1531
+ }
1532
+
1533
+ } else {
1534
+ pos.top = viewport.y + (viewport.h - height) * current.topRatio;
1535
+ pos.left = viewport.x + (viewport.w - width) * current.leftRatio;
1536
+ }
1537
+
1538
+ if (F.wrap.css('position') === 'fixed' || current.locked) {
1539
+ pos.top -= viewport.y;
1540
+ pos.left -= viewport.x;
1541
+ }
1542
+
1543
+ pos = {
1544
+ top : getValue(pos.top - hPadding * current.topRatio),
1545
+ left : getValue(pos.left - wPadding * current.leftRatio),
1546
+ width : getValue(width + wPadding),
1547
+ height : getValue(height + hPadding)
1548
+ };
1549
+
1550
+ return pos;
1551
+ },
1552
+
1553
+ step: function (now, fx) {
1554
+ var ratio,
1555
+ padding,
1556
+ value,
1557
+ prop = fx.prop,
1558
+ current = F.current,
1559
+ wrapSpace = current.wrapSpace,
1560
+ skinSpace = current.skinSpace;
1561
+
1562
+ if (prop === 'width' || prop === 'height') {
1563
+ ratio = fx.end === fx.start ? 1 : (now - fx.start) / (fx.end - fx.start);
1564
+
1565
+ if (F.isClosing) {
1566
+ ratio = 1 - ratio;
1567
+ }
1568
+
1569
+ padding = prop === 'width' ? current.wPadding : current.hPadding;
1570
+ value = now - padding;
1571
+
1572
+ F.skin[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) ) );
1573
+ F.inner[ prop ]( getScalar( prop === 'width' ? value : value - (wrapSpace * ratio) - (skinSpace * ratio) ) );
1574
+ }
1575
+ },
1576
+
1577
+ zoomIn: function () {
1578
+ var current = F.current,
1579
+ startPos = current.pos,
1580
+ effect = current.openEffect,
1581
+ elastic = effect === 'elastic',
1582
+ endPos = $.extend({opacity : 1}, startPos);
1583
+
1584
+ // Remove "position" property that breaks older IE
1585
+ delete endPos.position;
1586
+
1587
+ if (elastic) {
1588
+ startPos = this.getOrigPosition();
1589
+
1590
+ if (current.openOpacity) {
1591
+ startPos.opacity = 0.1;
1592
+ }
1593
+
1594
+ } else if (effect === 'fade') {
1595
+ startPos.opacity = 0.1;
1596
+ }
1597
+
1598
+ F.wrap.css(startPos).animate(endPos, {
1599
+ duration : effect === 'none' ? 0 : current.openSpeed,
1600
+ easing : current.openEasing,
1601
+ step : elastic ? this.step : null,
1602
+ complete : F._afterZoomIn
1603
+ });
1604
+ },
1605
+
1606
+ zoomOut: function () {
1607
+ var current = F.current,
1608
+ effect = current.closeEffect,
1609
+ elastic = effect === 'elastic',
1610
+ endPos = {opacity : 0.1};
1611
+
1612
+ if (elastic) {
1613
+ endPos = this.getOrigPosition();
1614
+
1615
+ if (current.closeOpacity) {
1616
+ endPos.opacity = 0.1;
1617
+ }
1618
+ }
1619
+
1620
+ F.wrap.animate(endPos, {
1621
+ duration : effect === 'none' ? 0 : current.closeSpeed,
1622
+ easing : current.closeEasing,
1623
+ step : elastic ? this.step : null,
1624
+ complete : F._afterZoomOut
1625
+ });
1626
+ },
1627
+
1628
+ changeIn: function () {
1629
+ var current = F.current,
1630
+ effect = current.nextEffect,
1631
+ startPos = current.pos,
1632
+ endPos = { opacity : 1 },
1633
+ direction = F.direction,
1634
+ distance = 200,
1635
+ field;
1636
+
1637
+ startPos.opacity = 0.1;
1638
+
1639
+ if (effect === 'elastic') {
1640
+ field = direction === 'down' || direction === 'up' ? 'top' : 'left';
1641
+
1642
+ if (direction === 'down' || direction === 'right') {
1643
+ startPos[ field ] = getValue(getScalar(startPos[ field ]) - distance);
1644
+ endPos[ field ] = '+=' + distance + 'px';
1645
+
1646
+ } else {
1647
+ startPos[ field ] = getValue(getScalar(startPos[ field ]) + distance);
1648
+ endPos[ field ] = '-=' + distance + 'px';
1649
+ }
1650
+ }
1651
+
1652
+ // Workaround for http://bugs.jquery.com/ticket/12273
1653
+ if (effect === 'none') {
1654
+ F._afterZoomIn();
1655
+
1656
+ } else {
1657
+ F.wrap.css(startPos).animate(endPos, {
1658
+ duration : current.nextSpeed,
1659
+ easing : current.nextEasing,
1660
+ complete : F._afterZoomIn
1661
+ });
1662
+ }
1663
+ },
1664
+
1665
+ changeOut: function () {
1666
+ var previous = F.previous,
1667
+ effect = previous.prevEffect,
1668
+ endPos = { opacity : 0.1 },
1669
+ direction = F.direction,
1670
+ distance = 200;
1671
+
1672
+ if (effect === 'elastic') {
1673
+ endPos[ direction === 'down' || direction === 'up' ? 'top' : 'left' ] = ( direction === 'up' || direction === 'left' ? '-' : '+' ) + '=' + distance + 'px';
1674
+ }
1675
+
1676
+ previous.wrap.animate(endPos, {
1677
+ duration : effect === 'none' ? 0 : previous.prevSpeed,
1678
+ easing : previous.prevEasing,
1679
+ complete : function () {
1680
+ $(this).trigger('onReset').remove();
1681
+ }
1682
+ });
1683
+ }
1684
+ };
1685
+
1686
+ /*
1687
+ * Overlay helper
1688
+ */
1689
+
1690
+ F.helpers.overlay = {
1691
+ defaults : {
1692
+ closeClick : true, // if true, fancyBox will be closed when user clicks on the overlay
1693
+ speedOut : 200, // duration of fadeOut animation
1694
+ showEarly : true, // indicates if should be opened immediately or wait until the content is ready
1695
+ css : {}, // custom CSS properties
1696
+ locked : !isTouch, // if true, the content will be locked into overlay
1697
+ fixed : true // if false, the overlay CSS position property will not be set to "fixed"
1698
+ },
1699
+
1700
+ overlay : null, // current handle
1701
+ fixed : false, // indicates if the overlay has position "fixed"
1702
+ el : $('html'), // element that contains "the lock"
1703
+
1704
+ // Public methods
1705
+ create : function(opts) {
1706
+ opts = $.extend({}, this.defaults, opts);
1707
+
1708
+ if (this.overlay) {
1709
+ this.close();
1710
+ }
1711
+
1712
+ this.overlay = $('<div class="fancybox-overlay"></div>').appendTo( F.coming ? F.coming.parent : opts.parent );
1713
+ this.fixed = false;
1714
+
1715
+ if (opts.fixed && F.defaults.fixed) {
1716
+ this.overlay.addClass('fancybox-overlay-fixed');
1717
+
1718
+ this.fixed = true;
1719
+ }
1720
+ },
1721
+
1722
+ open : function(opts) {
1723
+ var that = this;
1724
+
1725
+ opts = $.extend({}, this.defaults, opts);
1726
+
1727
+ if (this.overlay) {
1728
+ this.overlay.unbind('.overlay').width('auto').height('auto');
1729
+
1730
+ } else {
1731
+ this.create(opts);
1732
+ }
1733
+
1734
+ if (!this.fixed) {
1735
+ W.bind('resize.overlay', $.proxy( this.update, this) );
1736
+
1737
+ this.update();
1738
+ }
1739
+
1740
+ if (opts.closeClick) {
1741
+ this.overlay.bind('click.overlay', function(e) {
1742
+ if ($(e.target).hasClass('fancybox-overlay')) {
1743
+ if (F.isActive) {
1744
+ F.close();
1745
+ } else {
1746
+ that.close();
1747
+ }
1748
+
1749
+ return false;
1750
+ }
1751
+ });
1752
+ }
1753
+
1754
+ this.overlay.css( opts.css ).show();
1755
+ },
1756
+
1757
+ close : function() {
1758
+ var scrollV, scrollH;
1759
+
1760
+ W.unbind('resize.overlay');
1761
+
1762
+ if (this.el.hasClass('fancybox-lock')) {
1763
+ $('.fancybox-margin').removeClass('fancybox-margin');
1764
+
1765
+ scrollV = W.scrollTop();
1766
+ scrollH = W.scrollLeft();
1767
+
1768
+ this.el.removeClass('fancybox-lock');
1769
+
1770
+ W.scrollTop( scrollV ).scrollLeft( scrollH );
1771
+ }
1772
+
1773
+ $('.fancybox-overlay').remove().hide();
1774
+
1775
+ $.extend(this, {
1776
+ overlay : null,
1777
+ fixed : false
1778
+ });
1779
+ },
1780
+
1781
+ // Private, callbacks
1782
+
1783
+ update : function () {
1784
+ var width = '100%', offsetWidth;
1785
+
1786
+ // Reset width/height so it will not mess
1787
+ this.overlay.width(width).height('100%');
1788
+
1789
+ // jQuery does not return reliable result for IE
1790
+ if (IE) {
1791
+ offsetWidth = Math.max(document.documentElement.offsetWidth, document.body.offsetWidth);
1792
+
1793
+ if (D.width() > offsetWidth) {
1794
+ width = D.width();
1795
+ }
1796
+
1797
+ } else if (D.width() > W.width()) {
1798
+ width = D.width();
1799
+ }
1800
+
1801
+ this.overlay.width(width).height(D.height());
1802
+ },
1803
+
1804
+ // This is where we can manipulate DOM, because later it would cause iframes to reload
1805
+ onReady : function (opts, obj) {
1806
+ var overlay = this.overlay;
1807
+
1808
+ $('.fancybox-overlay').stop(true, true);
1809
+
1810
+ if (!overlay) {
1811
+ this.create(opts);
1812
+ }
1813
+
1814
+ if (opts.locked && this.fixed && obj.fixed) {
1815
+ if (!overlay) {
1816
+ this.margin = D.height() > W.height() ? $('html').css('margin-right').replace("px", "") : false;
1817
+ }
1818
+
1819
+ obj.locked = this.overlay.append( obj.wrap );
1820
+ obj.fixed = false;
1821
+ }
1822
+
1823
+ if (opts.showEarly === true) {
1824
+ this.beforeShow.apply(this, arguments);
1825
+ }
1826
+ },
1827
+
1828
+ beforeShow : function(opts, obj) {
1829
+ var scrollV, scrollH;
1830
+
1831
+ if (obj.locked) {
1832
+ if (this.margin !== false) {
1833
+ $('*').filter(function(){
1834
+ return ($(this).css('position') === 'fixed' && !$(this).hasClass("fancybox-overlay") && !$(this).hasClass("fancybox-wrap") );
1835
+ }).addClass('fancybox-margin');
1836
+
1837
+ this.el.addClass('fancybox-margin');
1838
+ }
1839
+
1840
+ scrollV = W.scrollTop();
1841
+ scrollH = W.scrollLeft();
1842
+
1843
+ this.el.addClass('fancybox-lock');
1844
+
1845
+ W.scrollTop( scrollV ).scrollLeft( scrollH );
1846
+ }
1847
+
1848
+ this.open(opts);
1849
+ },
1850
+
1851
+ onUpdate : function() {
1852
+ if (!this.fixed) {
1853
+ this.update();
1854
+ }
1855
+ },
1856
+
1857
+ afterClose: function (opts) {
1858
+ // Remove overlay if exists and fancyBox is not opening
1859
+ // (e.g., it is not being open using afterClose callback)
1860
+ //if (this.overlay && !F.isActive) {
1861
+ if (this.overlay && !F.coming) {
1862
+ this.overlay.fadeOut(opts.speedOut, $.proxy( this.close, this ));
1863
+ }
1864
+ }
1865
+ };
1866
+
1867
+ /*
1868
+ * Title helper
1869
+ */
1870
+
1871
+ F.helpers.title = {
1872
+ defaults : {
1873
+ type : 'float', // 'float', 'inside', 'outside' or 'over',
1874
+ position : 'bottom' // 'top' or 'bottom'
1875
+ },
1876
+
1877
+ beforeShow: function (opts) {
1878
+ var current = F.current,
1879
+ text = current.title,
1880
+ type = opts.type,
1881
+ title,
1882
+ target;
1883
+
1884
+ if ($.isFunction(text)) {
1885
+ text = text.call(current.element, current);
1886
+ }
1887
+
1888
+ if (!isString(text) || $.trim(text) === '') {
1889
+ return;
1890
+ }
1891
+
1892
+ title = $('<div class="fancybox-title fancybox-title-' + type + '-wrap">' + text + '</div>');
1893
+
1894
+ switch (type) {
1895
+ case 'inside':
1896
+ target = F.skin;
1897
+ break;
1898
+
1899
+ case 'outside':
1900
+ target = F.wrap;
1901
+ break;
1902
+
1903
+ case 'over':
1904
+ target = F.inner;
1905
+ break;
1906
+
1907
+ default: // 'float'
1908
+ target = F.skin;
1909
+
1910
+ title.appendTo('body');
1911
+
1912
+ if (IE) {
1913
+ title.width( title.width() );
1914
+ }
1915
+
1916
+ title.wrapInner('<span class="child"></span>');
1917
+
1918
+ //Increase bottom margin so this title will also fit into viewport
1919
+ F.current.margin[2] += Math.abs( getScalar(title.css('margin-bottom')) );
1920
+ break;
1921
+ }
1922
+
1923
+ title[ (opts.position === 'top' ? 'prependTo' : 'appendTo') ](target);
1924
+ }
1925
+ };
1926
+
1927
+ // jQuery plugin initialization
1928
+ $.fn.fancybox = function (options) {
1929
+ var index,
1930
+ that = $(this),
1931
+ selector = this.selector || '',
1932
+ run = function(e) {
1933
+ var what = $(this).blur(), idx = index, relType, relVal;
1934
+
1935
+ if (!(e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) && !what.is('.fancybox-wrap')) {
1936
+ relType = options.groupAttr || 'data-fancybox-group';
1937
+ relVal = what.attr(relType);
1938
+
1939
+ if (!relVal) {
1940
+ relType = 'rel';
1941
+ relVal = what.get(0)[ relType ];
1942
+ }
1943
+
1944
+ if (relVal && relVal !== '' && relVal !== 'nofollow') {
1945
+ what = selector.length ? $(selector) : that;
1946
+ what = what.filter('[' + relType + '="' + relVal + '"]');
1947
+ idx = what.index(this);
1948
+ }
1949
+
1950
+ options.index = idx;
1951
+
1952
+ // Stop an event from bubbling if everything is fine
1953
+ if (F.open(what, options) !== false) {
1954
+ e.preventDefault();
1955
+ }
1956
+ }
1957
+ };
1958
+
1959
+ options = options || {};
1960
+ index = options.index || 0;
1961
+
1962
+ if (!selector || options.live === false) {
1963
+ that.unbind('click.fb-start').bind('click.fb-start', run);
1964
+
1965
+ } else {
1966
+ D.undelegate(selector, 'click.fb-start').delegate(selector + ":not('.fancybox-item, .fancybox-nav')", 'click.fb-start', run);
1967
+ }
1968
+
1969
+ this.filter('[data-fancybox-start=1]').trigger('click');
1970
+
1971
+ return this;
1972
+ };
1973
+
1974
+ // Tests that need a body at doc ready
1975
+ D.ready(function() {
1976
+ var w1, w2;
1977
+
1978
+ if ( $.scrollbarWidth === undefined ) {
1979
+ // http://benalman.com/projects/jquery-misc-plugins/#scrollbarwidth
1980
+ $.scrollbarWidth = function() {
1981
+ var parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body'),
1982
+ child = parent.children(),
1983
+ width = child.innerWidth() - child.height( 99 ).innerWidth();
1984
+
1985
+ parent.remove();
1986
+
1987
+ return width;
1988
+ };
1989
+ }
1990
+
1991
+ if ( $.support.fixedPosition === undefined ) {
1992
+ $.support.fixedPosition = (function() {
1993
+ var elem = $('<div style="position:fixed;top:20px;"></div>').appendTo('body'),
1994
+ fixed = ( elem[0].offsetTop === 20 || elem[0].offsetTop === 15 );
1995
+
1996
+ elem.remove();
1997
+
1998
+ return fixed;
1999
+ }());
2000
+ }
2001
+
2002
+ $.extend(F.defaults, {
2003
+ scrollbarWidth : $.scrollbarWidth(),
2004
+ fixed : $.support.fixedPosition,
2005
+ parent : $('body')
2006
+ });
2007
+
2008
+ //Get real width of page scroll-bar
2009
+ w1 = $(window).width();
2010
+
2011
+ H.addClass('fancybox-lock-test');
2012
+
2013
+ w2 = $(window).width();
2014
+
2015
+ H.removeClass('fancybox-lock-test');
2016
+
2017
+ $("<style type='text/css'>.fancybox-margin{margin-right:" + (w2 - w1) + "px;}</style>").appendTo("head");
2018
+ });
2019
+
2020
+ }(window, document, jQuery));
skin/frontend/rwd/default/js/ve/fancybox/jquery.mousewheel-3.0.6.pack.js ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
2
+ * Licensed under the MIT License (LICENSE.txt).
3
+ *
4
+ * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
5
+ * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
6
+ * Thanks to: Seamus Leahy for adding deltaX and deltaY
7
+ *
8
+ * Version: 3.0.6
9
+ *
10
+ * Requires: 1.2.2+
11
+ */
12
+ (function(d){function e(a){var b=a||window.event,c=[].slice.call(arguments,1),f=0,e=0,g=0,a=d.event.fix(b);a.type="mousewheel";b.wheelDelta&&(f=b.wheelDelta/120);b.detail&&(f=-b.detail/3);g=f;b.axis!==void 0&&b.axis===b.HORIZONTAL_AXIS&&(g=0,e=-1*f);b.wheelDeltaY!==void 0&&(g=b.wheelDeltaY/120);b.wheelDeltaX!==void 0&&(e=-1*b.wheelDeltaX/120);c.unshift(a,f,e,g);return(d.event.dispatch||d.event.handle).apply(this,c)}var c=["DOMMouseScroll","mousewheel"];if(d.event.fixHooks)for(var h=c.length;h;)d.event.fixHooks[c[--h]]=
13
+ d.event.mouseHooks;d.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=c.length;a;)this.addEventListener(c[--a],e,false);else this.onmousewheel=e},teardown:function(){if(this.removeEventListener)for(var a=c.length;a;)this.removeEventListener(c[--a],e,false);else this.onmousewheel=null}};d.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);
skin/frontend/rwd/default/js/ve/jquery.bpopup.min.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ /*================================================================================
2
+ * @name: bPopup - if you can't get it up, use bPopup
3
+ * @author: (c)Bjoern Klinggaard (twitter@bklinggaard)
4
+ * @demo: http://dinbror.dk/bpopup
5
+ * @version: 0.11.0.min
6
+ ================================================================================*/
7
+ (function(c){c.fn.bPopup=function(A,E){function L(){a.contentContainer=c(a.contentContainer||b);switch(a.content){case "iframe":var d=c('<iframe class="b-iframe" '+a.iframeAttr+"></iframe>");d.appendTo(a.contentContainer);t=b.outerHeight(!0);u=b.outerWidth(!0);B();d.attr("src",a.loadUrl);l(a.loadCallback);break;case "image":B();c("<img />").load(function(){l(a.loadCallback);F(c(this))}).attr("src",a.loadUrl).hide().appendTo(a.contentContainer);break;default:B(),c('<div class="b-ajax-wrapper"></div>').load(a.loadUrl,a.loadData,function(d,b,e){l(a.loadCallback,b);F(c(this))}).hide().appendTo(a.contentContainer)}}function B(){a.modal&&c('<div class="b-modal '+e+'"></div>').css({backgroundColor:a.modalColor,position:"fixed",top:0,right:0,bottom:0,left:0,opacity:0,zIndex:a.zIndex+v}).appendTo(a.appendTo).fadeTo(a.speed,a.opacity);C();b.data("bPopup",a).data("id",e).css({left:"slideIn"==a.transition||"slideBack"==a.transition?"slideBack"==a.transition?f.scrollLeft()+w:-1*(x+u):m(!(!a.follow[0]&&n||g)),position:a.positionStyle||"absolute",top:"slideDown"==a.transition||"slideUp"==a.transition?"slideUp"==a.transition?f.scrollTop()+y:z+-1*t:p(!(!a.follow[1]&&q||g)),"z-index":a.zIndex+v+1}).each(function(){a.appending&&c(this).appendTo(a.appendTo)});G(!0)}function r(){a.modal&&c(".b-modal."+b.data("id")).fadeTo(a.speed,0,function(){c(this).remove()});a.scrollBar||c("html").css("overflow","auto");c(".b-modal."+e).unbind("click");f.unbind("keydown."+e);k.unbind("."+e).data("bPopup",0<k.data("bPopup")-1?k.data("bPopup")-1:null);b.undelegate(".bClose, ."+a.closeClass,"click."+e,r).data("bPopup",null);clearTimeout(H);G();return!1}function I(d){y=k.height();w=k.width();h=D();if(h.x||h.y)clearTimeout(J),J=setTimeout(function(){C();d=d||a.followSpeed;var e={};h.x&&(e.left=a.follow[0]?m(!0):"auto");h.y&&(e.top=a.follow[1]?p(!0):"auto");b.dequeue().each(function(){g?c(this).css({left:x,top:z}):c(this).animate(e,d,a.followEasing)})},50)}function F(d){var c=d.width(),e=d.height(),f={};a.contentContainer.css({height:e,width:c});e>=b.height()&&(f.height=b.height());c>=b.width()&&(f.width=b.width());t=b.outerHeight(!0);u=b.outerWidth(!0);C();a.contentContainer.css({height:"auto",width:"auto"});f.left=m(!(!a.follow[0]&&n||g));f.top=p(!(!a.follow[1]&&q||g));b.animate(f,250,function(){d.show();h=D()})}function M(){k.data("bPopup",v);b.delegate(".bClose, ."+a.closeClass,"click."+e,r);a.modalClose&&c(".b-modal."+e).css("cursor","pointer").bind("click",r);N||!a.follow[0]&&!a.follow[1]||k.bind("scroll."+e,function(){if(h.x||h.y){var d={};h.x&&(d.left=a.follow[0]?m(!g):"auto");h.y&&(d.top=a.follow[1]?p(!g):"auto");b.dequeue().animate(d,a.followSpeed,a.followEasing)}}).bind("resize."+e,function(){I()});a.escClose&&f.bind("keydown."+e,function(a){27==a.which&&r()})}function G(d){function c(e){b.css({display:"block",opacity:1}).animate(e,a.speed,a.easing,function(){K(d)})}switch(d?a.transition:a.transitionClose||a.transition){case "slideIn":c({left:d?m(!(!a.follow[0]&&n||g)):f.scrollLeft()-(u||b.outerWidth(!0))-200});break;case "slideBack":c({left:d?m(!(!a.follow[0]&&n||g)):f.scrollLeft()+w+200});break;case "slideDown":c({top:d?p(!(!a.follow[1]&&q||g)):f.scrollTop()-(t||b.outerHeight(!0))-200});break;case "slideUp":c({top:d?p(!(!a.follow[1]&&q||g)):f.scrollTop()+y+200});break;default:b.stop().fadeTo(a.speed,d?1:0,function(){K(d)})}}function K(d){d?(M(),l(E),a.autoClose&&(H=setTimeout(r,a.autoClose))):(b.hide(),l(a.onClose),a.loadUrl&&(a.contentContainer.empty(),b.css({height:"auto",width:"auto"})))}function m(a){return a?x+f.scrollLeft():x}function p(a){return a?z+f.scrollTop():z}function l(a,e){c.isFunction(a)&&a.call(b,e)}function C(){z=q?a.position[1]:Math.max(0,(y-b.outerHeight(!0))/2-a.amsl);x=n?a.position[0]:(w-b.outerWidth(!0))/2;h=D()}function D(){return{x:w>b.outerWidth(!0),y:y>b.outerHeight(!0)}}c.isFunction(A)&&(E=A,A=null);var a=c.extend({},c.fn.bPopup.defaults,A);a.scrollBar||c("html").css("overflow","hidden");var b=this,f=c(document),k=c(window),y=k.height(),w=k.width(),N=/OS 6(_\d)+/i.test(navigator.userAgent),v=0,e,h,q,n,g,z,x,t,u,J,H;b.close=function(){r()};b.reposition=function(a){I(a)};return b.each(function(){c(this).data("bPopup")||(l(a.onOpen),v=(k.data("bPopup")||0)+1,e="__b-popup"+v+"__",q="auto"!==a.position[1],n="auto"!==a.position[0],g="fixed"===a.positionStyle,t=b.outerHeight(!0),u=b.outerWidth(!0),a.loadUrl?L():B())})};c.fn.bPopup.defaults={amsl:50,appending:!0,appendTo:"body",autoClose:!1,closeClass:"b-close",content:"ajax",contentContainer:!1,easing:"swing",escClose:!0,follow:[!0,!0],followEasing:"swing",followSpeed:500,iframeAttr:'scrolling="no" frameborder="0"',loadCallback:!1,loadData:!1,loadUrl:!1,modal:!0,modalClose:!0,modalColor:"#000",onClose:!1,onOpen:!1,opacity:.7,position:["auto","auto"],positionStyle:"absolute",scrollBar:!0,speed:250,transition:"fadeIn",transitionClose:!1,zIndex:9997}})(jQuery);
skin/frontend/rwd/default/js/ve/ve/jquery-1.10.2.js ADDED
@@ -0,0 +1,9789 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jQuery JavaScript Library v1.10.2
3
+ * http://jquery.com/
4
+ *
5
+ * Includes Sizzle.js
6
+ * http://sizzlejs.com/
7
+ *
8
+ * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors
9
+ * Released under the MIT license
10
+ * http://jquery.org/license
11
+ *
12
+ * Date: 2013-07-03T13:48Z
13
+ */
14
+ (function( window, undefined ) {
15
+
16
+ // Can't do this because several apps including ASP.NET trace
17
+ // the stack via arguments.caller.callee and Firefox dies if
18
+ // you try to trace through "use strict" call chains. (#13335)
19
+ // Support: Firefox 18+
20
+ //"use strict";
21
+ var
22
+ // The deferred used on DOM ready
23
+ readyList,
24
+
25
+ // A central reference to the root jQuery(document)
26
+ rootjQuery,
27
+
28
+ // Support: IE<10
29
+ // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined`
30
+ core_strundefined = typeof undefined,
31
+
32
+ // Use the correct document accordingly with window argument (sandbox)
33
+ location = window.location,
34
+ document = window.document,
35
+ docElem = document.documentElement,
36
+
37
+ // Map over jQuery in case of overwrite
38
+ _jQuery = window.jQuery,
39
+
40
+ // Map over the $ in case of overwrite
41
+ _$ = window.$,
42
+
43
+ // [[Class]] -> type pairs
44
+ class2type = {},
45
+
46
+ // List of deleted data cache ids, so we can reuse them
47
+ core_deletedIds = [],
48
+
49
+ core_version = "1.10.2",
50
+
51
+ // Save a reference to some core methods
52
+ core_concat = core_deletedIds.concat,
53
+ core_push = core_deletedIds.push,
54
+ core_slice = core_deletedIds.slice,
55
+ core_indexOf = core_deletedIds.indexOf,
56
+ core_toString = class2type.toString,
57
+ core_hasOwn = class2type.hasOwnProperty,
58
+ core_trim = core_version.trim,
59
+
60
+ // Define a local copy of jQuery
61
+ jQuery = function( selector, context ) {
62
+ // The jQuery object is actually just the init constructor 'enhanced'
63
+ return new jQuery.fn.init( selector, context, rootjQuery );
64
+ },
65
+
66
+ // Used for matching numbers
67
+ core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
68
+
69
+ // Used for splitting on whitespace
70
+ core_rnotwhite = /\S+/g,
71
+
72
+ // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
73
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
74
+
75
+ // A simple way to check for HTML strings
76
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
77
+ // Strict HTML recognition (#11290: must start with <)
78
+ rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
79
+
80
+ // Match a standalone tag
81
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
82
+
83
+ // JSON RegExp
84
+ rvalidchars = /^[\],:{}\s]*$/,
85
+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
86
+ rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
87
+ rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,
88
+
89
+ // Matches dashed string for camelizing
90
+ rmsPrefix = /^-ms-/,
91
+ rdashAlpha = /-([\da-z])/gi,
92
+
93
+ // Used by jQuery.camelCase as callback to replace()
94
+ fcamelCase = function( all, letter ) {
95
+ return letter.toUpperCase();
96
+ },
97
+
98
+ // The ready event handler
99
+ completed = function( event ) {
100
+
101
+ // readyState === "complete" is good enough for us to call the dom ready in oldIE
102
+ if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
103
+ detach();
104
+ jQuery.ready();
105
+ }
106
+ },
107
+ // Clean-up method for dom ready events
108
+ detach = function() {
109
+ if ( document.addEventListener ) {
110
+ document.removeEventListener( "DOMContentLoaded", completed, false );
111
+ window.removeEventListener( "load", completed, false );
112
+
113
+ } else {
114
+ document.detachEvent( "onreadystatechange", completed );
115
+ window.detachEvent( "onload", completed );
116
+ }
117
+ };
118
+
119
+ jQuery.fn = jQuery.prototype = {
120
+ // The current version of jQuery being used
121
+ jquery: core_version,
122
+
123
+ constructor: jQuery,
124
+ init: function( selector, context, rootjQuery ) {
125
+ var match, elem;
126
+
127
+ // HANDLE: $(""), $(null), $(undefined), $(false)
128
+ if ( !selector ) {
129
+ return this;
130
+ }
131
+
132
+ // Handle HTML strings
133
+ if ( typeof selector === "string" ) {
134
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
135
+ // Assume that strings that start and end with <> are HTML and skip the regex check
136
+ match = [ null, selector, null ];
137
+
138
+ } else {
139
+ match = rquickExpr.exec( selector );
140
+ }
141
+
142
+ // Match html or make sure no context is specified for #id
143
+ if ( match && (match[1] || !context) ) {
144
+
145
+ // HANDLE: $(html) -> $(array)
146
+ if ( match[1] ) {
147
+ context = context instanceof jQuery ? context[0] : context;
148
+
149
+ // scripts is true for back-compat
150
+ jQuery.merge( this, jQuery.parseHTML(
151
+ match[1],
152
+ context && context.nodeType ? context.ownerDocument || context : document,
153
+ true
154
+ ) );
155
+
156
+ // HANDLE: $(html, props)
157
+ if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
158
+ for ( match in context ) {
159
+ // Properties of context are called as methods if possible
160
+ if ( jQuery.isFunction( this[ match ] ) ) {
161
+ this[ match ]( context[ match ] );
162
+
163
+ // ...and otherwise set as attributes
164
+ } else {
165
+ this.attr( match, context[ match ] );
166
+ }
167
+ }
168
+ }
169
+
170
+ return this;
171
+
172
+ // HANDLE: $(#id)
173
+ } else {
174
+ elem = document.getElementById( match[2] );
175
+
176
+ // Check parentNode to catch when Blackberry 4.6 returns
177
+ // nodes that are no longer in the document #6963
178
+ if ( elem && elem.parentNode ) {
179
+ // Handle the case where IE and Opera return items
180
+ // by name instead of ID
181
+ if ( elem.id !== match[2] ) {
182
+ return rootjQuery.find( selector );
183
+ }
184
+
185
+ // Otherwise, we inject the element directly into the jQuery object
186
+ this.length = 1;
187
+ this[0] = elem;
188
+ }
189
+
190
+ this.context = document;
191
+ this.selector = selector;
192
+ return this;
193
+ }
194
+
195
+ // HANDLE: $(expr, $(...))
196
+ } else if ( !context || context.jquery ) {
197
+ return ( context || rootjQuery ).find( selector );
198
+
199
+ // HANDLE: $(expr, context)
200
+ // (which is just equivalent to: $(context).find(expr)
201
+ } else {
202
+ return this.constructor( context ).find( selector );
203
+ }
204
+
205
+ // HANDLE: $(DOMElement)
206
+ } else if ( selector.nodeType ) {
207
+ this.context = this[0] = selector;
208
+ this.length = 1;
209
+ return this;
210
+
211
+ // HANDLE: $(function)
212
+ // Shortcut for document ready
213
+ } else if ( jQuery.isFunction( selector ) ) {
214
+ return rootjQuery.ready( selector );
215
+ }
216
+
217
+ if ( selector.selector !== undefined ) {
218
+ this.selector = selector.selector;
219
+ this.context = selector.context;
220
+ }
221
+
222
+ return jQuery.makeArray( selector, this );
223
+ },
224
+
225
+ // Start with an empty selector
226
+ selector: "",
227
+
228
+ // The default length of a jQuery object is 0
229
+ length: 0,
230
+
231
+ toArray: function() {
232
+ return core_slice.call( this );
233
+ },
234
+
235
+ // Get the Nth element in the matched element set OR
236
+ // Get the whole matched element set as a clean array
237
+ get: function( num ) {
238
+ return num == null ?
239
+
240
+ // Return a 'clean' array
241
+ this.toArray() :
242
+
243
+ // Return just the object
244
+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
245
+ },
246
+
247
+ // Take an array of elements and push it onto the stack
248
+ // (returning the new matched element set)
249
+ pushStack: function( elems ) {
250
+
251
+ // Build a new jQuery matched element set
252
+ var ret = jQuery.merge( this.constructor(), elems );
253
+
254
+ // Add the old object onto the stack (as a reference)
255
+ ret.prevObject = this;
256
+ ret.context = this.context;
257
+
258
+ // Return the newly-formed element set
259
+ return ret;
260
+ },
261
+
262
+ // Execute a callback for every element in the matched set.
263
+ // (You can seed the arguments with an array of args, but this is
264
+ // only used internally.)
265
+ each: function( callback, args ) {
266
+ return jQuery.each( this, callback, args );
267
+ },
268
+
269
+ ready: function( fn ) {
270
+ // Add the callback
271
+ jQuery.ready.promise().done( fn );
272
+
273
+ return this;
274
+ },
275
+
276
+ slice: function() {
277
+ return this.pushStack( core_slice.apply( this, arguments ) );
278
+ },
279
+
280
+ first: function() {
281
+ return this.eq( 0 );
282
+ },
283
+
284
+ last: function() {
285
+ return this.eq( -1 );
286
+ },
287
+
288
+ eq: function( i ) {
289
+ var len = this.length,
290
+ j = +i + ( i < 0 ? len : 0 );
291
+ return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
292
+ },
293
+
294
+ map: function( callback ) {
295
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
296
+ return callback.call( elem, i, elem );
297
+ }));
298
+ },
299
+
300
+ end: function() {
301
+ return this.prevObject || this.constructor(null);
302
+ },
303
+
304
+ // For internal use only.
305
+ // Behaves like an Array's method, not like a jQuery method.
306
+ push: core_push,
307
+ sort: [].sort,
308
+ splice: [].splice
309
+ };
310
+
311
+ // Give the init function the jQuery prototype for later instantiation
312
+ jQuery.fn.init.prototype = jQuery.fn;
313
+
314
+ jQuery.extend = jQuery.fn.extend = function() {
315
+ var src, copyIsArray, copy, name, options, clone,
316
+ target = arguments[0] || {},
317
+ i = 1,
318
+ length = arguments.length,
319
+ deep = false;
320
+
321
+ // Handle a deep copy situation
322
+ if ( typeof target === "boolean" ) {
323
+ deep = target;
324
+ target = arguments[1] || {};
325
+ // skip the boolean and the target
326
+ i = 2;
327
+ }
328
+
329
+ // Handle case when target is a string or something (possible in deep copy)
330
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
331
+ target = {};
332
+ }
333
+
334
+ // extend jQuery itself if only one argument is passed
335
+ if ( length === i ) {
336
+ target = this;
337
+ --i;
338
+ }
339
+
340
+ for ( ; i < length; i++ ) {
341
+ // Only deal with non-null/undefined values
342
+ if ( (options = arguments[ i ]) != null ) {
343
+ // Extend the base object
344
+ for ( name in options ) {
345
+ src = target[ name ];
346
+ copy = options[ name ];
347
+
348
+ // Prevent never-ending loop
349
+ if ( target === copy ) {
350
+ continue;
351
+ }
352
+
353
+ // Recurse if we're merging plain objects or arrays
354
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
355
+ if ( copyIsArray ) {
356
+ copyIsArray = false;
357
+ clone = src && jQuery.isArray(src) ? src : [];
358
+
359
+ } else {
360
+ clone = src && jQuery.isPlainObject(src) ? src : {};
361
+ }
362
+
363
+ // Never move original objects, clone them
364
+ target[ name ] = jQuery.extend( deep, clone, copy );
365
+
366
+ // Don't bring in undefined values
367
+ } else if ( copy !== undefined ) {
368
+ target[ name ] = copy;
369
+ }
370
+ }
371
+ }
372
+ }
373
+
374
+ // Return the modified object
375
+ return target;
376
+ };
377
+
378
+ jQuery.extend({
379
+ // Unique for each copy of jQuery on the page
380
+ // Non-digits removed to match rinlinejQuery
381
+ expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
382
+
383
+ noConflict: function( deep ) {
384
+ if ( window.$ === jQuery ) {
385
+ window.$ = _$;
386
+ }
387
+
388
+ if ( deep && window.jQuery === jQuery ) {
389
+ window.jQuery = _jQuery;
390
+ }
391
+
392
+ return jQuery;
393
+ },
394
+
395
+ // Is the DOM ready to be used? Set to true once it occurs.
396
+ isReady: false,
397
+
398
+ // A counter to track how many items to wait for before
399
+ // the ready event fires. See #6781
400
+ readyWait: 1,
401
+
402
+ // Hold (or release) the ready event
403
+ holdReady: function( hold ) {
404
+ if ( hold ) {
405
+ jQuery.readyWait++;
406
+ } else {
407
+ jQuery.ready( true );
408
+ }
409
+ },
410
+
411
+ // Handle when the DOM is ready
412
+ ready: function( wait ) {
413
+
414
+ // Abort if there are pending holds or we're already ready
415
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
416
+ return;
417
+ }
418
+
419
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
420
+ if ( !document.body ) {
421
+ return setTimeout( jQuery.ready );
422
+ }
423
+
424
+ // Remember that the DOM is ready
425
+ jQuery.isReady = true;
426
+
427
+ // If a normal DOM Ready event fired, decrement, and wait if need be
428
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
429
+ return;
430
+ }
431
+
432
+ // If there are functions bound, to execute
433
+ readyList.resolveWith( document, [ jQuery ] );
434
+
435
+ // Trigger any bound ready events
436
+ if ( jQuery.fn.trigger ) {
437
+ jQuery( document ).trigger("ready").off("ready");
438
+ }
439
+ },
440
+
441
+ // See test/unit/core.js for details concerning isFunction.
442
+ // Since version 1.3, DOM methods and functions like alert
443
+ // aren't supported. They return false on IE (#2968).
444
+ isFunction: function( obj ) {
445
+ return jQuery.type(obj) === "function";
446
+ },
447
+
448
+ isArray: Array.isArray || function( obj ) {
449
+ return jQuery.type(obj) === "array";
450
+ },
451
+
452
+ isWindow: function( obj ) {
453
+ /* jshint eqeqeq: false */
454
+ return obj != null && obj == obj.window;
455
+ },
456
+
457
+ isNumeric: function( obj ) {
458
+ return !isNaN( parseFloat(obj) ) && isFinite( obj );
459
+ },
460
+
461
+ type: function( obj ) {
462
+ if ( obj == null ) {
463
+ return String( obj );
464
+ }
465
+ return typeof obj === "object" || typeof obj === "function" ?
466
+ class2type[ core_toString.call(obj) ] || "object" :
467
+ typeof obj;
468
+ },
469
+
470
+ isPlainObject: function( obj ) {
471
+ var key;
472
+
473
+ // Must be an Object.
474
+ // Because of IE, we also have to check the presence of the constructor property.
475
+ // Make sure that DOM nodes and window objects don't pass through, as well
476
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
477
+ return false;
478
+ }
479
+
480
+ try {
481
+ // Not own constructor property must be Object
482
+ if ( obj.constructor &&
483
+ !core_hasOwn.call(obj, "constructor") &&
484
+ !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
485
+ return false;
486
+ }
487
+ } catch ( e ) {
488
+ // IE8,9 Will throw exceptions on certain host objects #9897
489
+ return false;
490
+ }
491
+
492
+ // Support: IE<9
493
+ // Handle iteration over inherited properties before own properties.
494
+ if ( jQuery.support.ownLast ) {
495
+ for ( key in obj ) {
496
+ return core_hasOwn.call( obj, key );
497
+ }
498
+ }
499
+
500
+ // Own properties are enumerated firstly, so to speed up,
501
+ // if last one is own, then all properties are own.
502
+ for ( key in obj ) {}
503
+
504
+ return key === undefined || core_hasOwn.call( obj, key );
505
+ },
506
+
507
+ isEmptyObject: function( obj ) {
508
+ var name;
509
+ for ( name in obj ) {
510
+ return false;
511
+ }
512
+ return true;
513
+ },
514
+
515
+ error: function( msg ) {
516
+ throw new Error( msg );
517
+ },
518
+
519
+ // data: string of html
520
+ // context (optional): If specified, the fragment will be created in this context, defaults to document
521
+ // keepScripts (optional): If true, will include scripts passed in the html string
522
+ parseHTML: function( data, context, keepScripts ) {
523
+ if ( !data || typeof data !== "string" ) {
524
+ return null;
525
+ }
526
+ if ( typeof context === "boolean" ) {
527
+ keepScripts = context;
528
+ context = false;
529
+ }
530
+ context = context || document;
531
+
532
+ var parsed = rsingleTag.exec( data ),
533
+ scripts = !keepScripts && [];
534
+
535
+ // Single tag
536
+ if ( parsed ) {
537
+ return [ context.createElement( parsed[1] ) ];
538
+ }
539
+
540
+ parsed = jQuery.buildFragment( [ data ], context, scripts );
541
+ if ( scripts ) {
542
+ jQuery( scripts ).remove();
543
+ }
544
+ return jQuery.merge( [], parsed.childNodes );
545
+ },
546
+
547
+ parseJSON: function( data ) {
548
+ // Attempt to parse using the native JSON parser first
549
+ if ( window.JSON && window.JSON.parse ) {
550
+ return window.JSON.parse( data );
551
+ }
552
+
553
+ if ( data === null ) {
554
+ return data;
555
+ }
556
+
557
+ if ( typeof data === "string" ) {
558
+
559
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
560
+ data = jQuery.trim( data );
561
+
562
+ if ( data ) {
563
+ // Make sure the incoming data is actual JSON
564
+ // Logic borrowed from http://json.org/json2.js
565
+ if ( rvalidchars.test( data.replace( rvalidescape, "@" )
566
+ .replace( rvalidtokens, "]" )
567
+ .replace( rvalidbraces, "")) ) {
568
+
569
+ return ( new Function( "return " + data ) )();
570
+ }
571
+ }
572
+ }
573
+
574
+ jQuery.error( "Invalid JSON: " + data );
575
+ },
576
+
577
+ // Cross-browser xml parsing
578
+ parseXML: function( data ) {
579
+ var xml, tmp;
580
+ if ( !data || typeof data !== "string" ) {
581
+ return null;
582
+ }
583
+ try {
584
+ if ( window.DOMParser ) { // Standard
585
+ tmp = new DOMParser();
586
+ xml = tmp.parseFromString( data , "text/xml" );
587
+ } else { // IE
588
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
589
+ xml.async = "false";
590
+ xml.loadXML( data );
591
+ }
592
+ } catch( e ) {
593
+ xml = undefined;
594
+ }
595
+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
596
+ jQuery.error( "Invalid XML: " + data );
597
+ }
598
+ return xml;
599
+ },
600
+
601
+ noop: function() {},
602
+
603
+ // Evaluates a script in a global context
604
+ // Workarounds based on findings by Jim Driscoll
605
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
606
+ globalEval: function( data ) {
607
+ if ( data && jQuery.trim( data ) ) {
608
+ // We use execScript on Internet Explorer
609
+ // We use an anonymous function so that context is window
610
+ // rather than jQuery in Firefox
611
+ ( window.execScript || function( data ) {
612
+ window[ "eval" ].call( window, data );
613
+ } )( data );
614
+ }
615
+ },
616
+
617
+ // Convert dashed to camelCase; used by the css and data modules
618
+ // Microsoft forgot to hump their vendor prefix (#9572)
619
+ camelCase: function( string ) {
620
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
621
+ },
622
+
623
+ nodeName: function( elem, name ) {
624
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
625
+ },
626
+
627
+ // args is for internal usage only
628
+ each: function( obj, callback, args ) {
629
+ var value,
630
+ i = 0,
631
+ length = obj.length,
632
+ isArray = isArraylike( obj );
633
+
634
+ if ( args ) {
635
+ if ( isArray ) {
636
+ for ( ; i < length; i++ ) {
637
+ value = callback.apply( obj[ i ], args );
638
+
639
+ if ( value === false ) {
640
+ break;
641
+ }
642
+ }
643
+ } else {
644
+ for ( i in obj ) {
645
+ value = callback.apply( obj[ i ], args );
646
+
647
+ if ( value === false ) {
648
+ break;
649
+ }
650
+ }
651
+ }
652
+
653
+ // A special, fast, case for the most common use of each
654
+ } else {
655
+ if ( isArray ) {
656
+ for ( ; i < length; i++ ) {
657
+ value = callback.call( obj[ i ], i, obj[ i ] );
658
+
659
+ if ( value === false ) {
660
+ break;
661
+ }
662
+ }
663
+ } else {
664
+ for ( i in obj ) {
665
+ value = callback.call( obj[ i ], i, obj[ i ] );
666
+
667
+ if ( value === false ) {
668
+ break;
669
+ }
670
+ }
671
+ }
672
+ }
673
+
674
+ return obj;
675
+ },
676
+
677
+ // Use native String.trim function wherever possible
678
+ trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
679
+ function( text ) {
680
+ return text == null ?
681
+ "" :
682
+ core_trim.call( text );
683
+ } :
684
+
685
+ // Otherwise use our own trimming functionality
686
+ function( text ) {
687
+ return text == null ?
688
+ "" :
689
+ ( text + "" ).replace( rtrim, "" );
690
+ },
691
+
692
+ // results is for internal usage only
693
+ makeArray: function( arr, results ) {
694
+ var ret = results || [];
695
+
696
+ if ( arr != null ) {
697
+ if ( isArraylike( Object(arr) ) ) {
698
+ jQuery.merge( ret,
699
+ typeof arr === "string" ?
700
+ [ arr ] : arr
701
+ );
702
+ } else {
703
+ core_push.call( ret, arr );
704
+ }
705
+ }
706
+
707
+ return ret;
708
+ },
709
+
710
+ inArray: function( elem, arr, i ) {
711
+ var len;
712
+
713
+ if ( arr ) {
714
+ if ( core_indexOf ) {
715
+ return core_indexOf.call( arr, elem, i );
716
+ }
717
+
718
+ len = arr.length;
719
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
720
+
721
+ for ( ; i < len; i++ ) {
722
+ // Skip accessing in sparse arrays
723
+ if ( i in arr && arr[ i ] === elem ) {
724
+ return i;
725
+ }
726
+ }
727
+ }
728
+
729
+ return -1;
730
+ },
731
+
732
+ merge: function( first, second ) {
733
+ var l = second.length,
734
+ i = first.length,
735
+ j = 0;
736
+
737
+ if ( typeof l === "number" ) {
738
+ for ( ; j < l; j++ ) {
739
+ first[ i++ ] = second[ j ];
740
+ }
741
+ } else {
742
+ while ( second[j] !== undefined ) {
743
+ first[ i++ ] = second[ j++ ];
744
+ }
745
+ }
746
+
747
+ first.length = i;
748
+
749
+ return first;
750
+ },
751
+
752
+ grep: function( elems, callback, inv ) {
753
+ var retVal,
754
+ ret = [],
755
+ i = 0,
756
+ length = elems.length;
757
+ inv = !!inv;
758
+
759
+ // Go through the array, only saving the items
760
+ // that pass the validator function
761
+ for ( ; i < length; i++ ) {
762
+ retVal = !!callback( elems[ i ], i );
763
+ if ( inv !== retVal ) {
764
+ ret.push( elems[ i ] );
765
+ }
766
+ }
767
+
768
+ return ret;
769
+ },
770
+
771
+ // arg is for internal usage only
772
+ map: function( elems, callback, arg ) {
773
+ var value,
774
+ i = 0,
775
+ length = elems.length,
776
+ isArray = isArraylike( elems ),
777
+ ret = [];
778
+
779
+ // Go through the array, translating each of the items to their
780
+ if ( isArray ) {
781
+ for ( ; i < length; i++ ) {
782
+ value = callback( elems[ i ], i, arg );
783
+
784
+ if ( value != null ) {
785
+ ret[ ret.length ] = value;
786
+ }
787
+ }
788
+
789
+ // Go through every key on the object,
790
+ } else {
791
+ for ( i in elems ) {
792
+ value = callback( elems[ i ], i, arg );
793
+
794
+ if ( value != null ) {
795
+ ret[ ret.length ] = value;
796
+ }
797
+ }
798
+ }
799
+
800
+ // Flatten any nested arrays
801
+ return core_concat.apply( [], ret );
802
+ },
803
+
804
+ // A global GUID counter for objects
805
+ guid: 1,
806
+
807
+ // Bind a function to a context, optionally partially applying any
808
+ // arguments.
809
+ proxy: function( fn, context ) {
810
+ var args, proxy, tmp;
811
+
812
+ if ( typeof context === "string" ) {
813
+ tmp = fn[ context ];
814
+ context = fn;
815
+ fn = tmp;
816
+ }
817
+
818
+ // Quick check to determine if target is callable, in the spec
819
+ // this throws a TypeError, but we will just return undefined.
820
+ if ( !jQuery.isFunction( fn ) ) {
821
+ return undefined;
822
+ }
823
+
824
+ // Simulated bind
825
+ args = core_slice.call( arguments, 2 );
826
+ proxy = function() {
827
+ return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
828
+ };
829
+
830
+ // Set the guid of unique handler to the same of original handler, so it can be removed
831
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
832
+
833
+ return proxy;
834
+ },
835
+
836
+ // Multifunctional method to get and set values of a collection
837
+ // The value/s can optionally be executed if it's a function
838
+ access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
839
+ var i = 0,
840
+ length = elems.length,
841
+ bulk = key == null;
842
+
843
+ // Sets many values
844
+ if ( jQuery.type( key ) === "object" ) {
845
+ chainable = true;
846
+ for ( i in key ) {
847
+ jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
848
+ }
849
+
850
+ // Sets one value
851
+ } else if ( value !== undefined ) {
852
+ chainable = true;
853
+
854
+ if ( !jQuery.isFunction( value ) ) {
855
+ raw = true;
856
+ }
857
+
858
+ if ( bulk ) {
859
+ // Bulk operations run against the entire set
860
+ if ( raw ) {
861
+ fn.call( elems, value );
862
+ fn = null;
863
+
864
+ // ...except when executing function values
865
+ } else {
866
+ bulk = fn;
867
+ fn = function( elem, key, value ) {
868
+ return bulk.call( jQuery( elem ), value );
869
+ };
870
+ }
871
+ }
872
+
873
+ if ( fn ) {
874
+ for ( ; i < length; i++ ) {
875
+ fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
876
+ }
877
+ }
878
+ }
879
+
880
+ return chainable ?
881
+ elems :
882
+
883
+ // Gets
884
+ bulk ?
885
+ fn.call( elems ) :
886
+ length ? fn( elems[0], key ) : emptyGet;
887
+ },
888
+
889
+ now: function() {
890
+ return ( new Date() ).getTime();
891
+ },
892
+
893
+ // A method for quickly swapping in/out CSS properties to get correct calculations.
894
+ // Note: this method belongs to the css module but it's needed here for the support module.
895
+ // If support gets modularized, this method should be moved back to the css module.
896
+ swap: function( elem, options, callback, args ) {
897
+ var ret, name,
898
+ old = {};
899
+
900
+ // Remember the old values, and insert the new ones
901
+ for ( name in options ) {
902
+ old[ name ] = elem.style[ name ];
903
+ elem.style[ name ] = options[ name ];
904
+ }
905
+
906
+ ret = callback.apply( elem, args || [] );
907
+
908
+ // Revert the old values
909
+ for ( name in options ) {
910
+ elem.style[ name ] = old[ name ];
911
+ }
912
+
913
+ return ret;
914
+ }
915
+ });
916
+
917
+ jQuery.ready.promise = function( obj ) {
918
+ if ( !readyList ) {
919
+
920
+ readyList = jQuery.Deferred();
921
+
922
+ // Catch cases where $(document).ready() is called after the browser event has already occurred.
923
+ // we once tried to use readyState "interactive" here, but it caused issues like the one
924
+ // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
925
+ if ( document.readyState === "complete" ) {
926
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
927
+ setTimeout( jQuery.ready );
928
+
929
+ // Standards-based browsers support DOMContentLoaded
930
+ } else if ( document.addEventListener ) {
931
+ // Use the handy event callback
932
+ document.addEventListener( "DOMContentLoaded", completed, false );
933
+
934
+ // A fallback to window.onload, that will always work
935
+ window.addEventListener( "load", completed, false );
936
+
937
+ // If IE event model is used
938
+ } else {
939
+ // Ensure firing before onload, maybe late but safe also for iframes
940
+ document.attachEvent( "onreadystatechange", completed );
941
+
942
+ // A fallback to window.onload, that will always work
943
+ window.attachEvent( "onload", completed );
944
+
945
+ // If IE and not a frame
946
+ // continually check to see if the document is ready
947
+ var top = false;
948
+
949
+ try {
950
+ top = window.frameElement == null && document.documentElement;
951
+ } catch(e) {}
952
+
953
+ if ( top && top.doScroll ) {
954
+ (function doScrollCheck() {
955
+ if ( !jQuery.isReady ) {
956
+
957
+ try {
958
+ // Use the trick by Diego Perini
959
+ // http://javascript.nwbox.com/IEContentLoaded/
960
+ top.doScroll("left");
961
+ } catch(e) {
962
+ return setTimeout( doScrollCheck, 50 );
963
+ }
964
+
965
+ // detach all dom ready events
966
+ detach();
967
+
968
+ // and execute any waiting functions
969
+ jQuery.ready();
970
+ }
971
+ })();
972
+ }
973
+ }
974
+ }
975
+ return readyList.promise( obj );
976
+ };
977
+
978
+ // Populate the class2type map
979
+ jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
980
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
981
+ });
982
+
983
+ function isArraylike( obj ) {
984
+ var length = obj.length,
985
+ type = jQuery.type( obj );
986
+
987
+ if ( jQuery.isWindow( obj ) ) {
988
+ return false;
989
+ }
990
+
991
+ if ( obj.nodeType === 1 && length ) {
992
+ return true;
993
+ }
994
+
995
+ return type === "array" || type !== "function" &&
996
+ ( length === 0 ||
997
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj );
998
+ }
999
+
1000
+ // All jQuery objects should point back to these
1001
+ rootjQuery = jQuery(document);
1002
+ /*!
1003
+ * Sizzle CSS Selector Engine v1.10.2
1004
+ * http://sizzlejs.com/
1005
+ *
1006
+ * Copyright 2013 jQuery Foundation, Inc. and other contributors
1007
+ * Released under the MIT license
1008
+ * http://jquery.org/license
1009
+ *
1010
+ * Date: 2013-07-03
1011
+ */
1012
+ (function( window, undefined ) {
1013
+
1014
+ var i,
1015
+ support,
1016
+ cachedruns,
1017
+ Expr,
1018
+ getText,
1019
+ isXML,
1020
+ compile,
1021
+ outermostContext,
1022
+ sortInput,
1023
+
1024
+ // Local document vars
1025
+ setDocument,
1026
+ document,
1027
+ docElem,
1028
+ documentIsHTML,
1029
+ rbuggyQSA,
1030
+ rbuggyMatches,
1031
+ matches,
1032
+ contains,
1033
+
1034
+ // Instance-specific data
1035
+ expando = "sizzle" + -(new Date()),
1036
+ preferredDoc = window.document,
1037
+ dirruns = 0,
1038
+ done = 0,
1039
+ classCache = createCache(),
1040
+ tokenCache = createCache(),
1041
+ compilerCache = createCache(),
1042
+ hasDuplicate = false,
1043
+ sortOrder = function( a, b ) {
1044
+ if ( a === b ) {
1045
+ hasDuplicate = true;
1046
+ return 0;
1047
+ }
1048
+ return 0;
1049
+ },
1050
+
1051
+ // General-purpose constants
1052
+ strundefined = typeof undefined,
1053
+ MAX_NEGATIVE = 1 << 31,
1054
+
1055
+ // Instance methods
1056
+ hasOwn = ({}).hasOwnProperty,
1057
+ arr = [],
1058
+ pop = arr.pop,
1059
+ push_native = arr.push,
1060
+ push = arr.push,
1061
+ slice = arr.slice,
1062
+ // Use a stripped-down indexOf if we can't use a native one
1063
+ indexOf = arr.indexOf || function( elem ) {
1064
+ var i = 0,
1065
+ len = this.length;
1066
+ for ( ; i < len; i++ ) {
1067
+ if ( this[i] === elem ) {
1068
+ return i;
1069
+ }
1070
+ }
1071
+ return -1;
1072
+ },
1073
+
1074
+ booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
1075
+
1076
+ // Regular expressions
1077
+
1078
+ // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
1079
+ whitespace = "[\\x20\\t\\r\\n\\f]",
1080
+ // http://www.w3.org/TR/css3-syntax/#characters
1081
+ characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
1082
+
1083
+ // Loosely modeled on CSS identifier characters
1084
+ // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
1085
+ // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
1086
+ identifier = characterEncoding.replace( "w", "w#" ),
1087
+
1088
+ // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
1089
+ attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
1090
+ "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
1091
+
1092
+ // Prefer arguments quoted,
1093
+ // then not containing pseudos/brackets,
1094
+ // then attribute selectors/non-parenthetical expressions,
1095
+ // then anything else
1096
+ // These preferences are here to reduce the number of selectors
1097
+ // needing tokenize in the PSEUDO preFilter
1098
+ pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
1099
+
1100
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
1101
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
1102
+
1103
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
1104
+ rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
1105
+
1106
+ rsibling = new RegExp( whitespace + "*[+~]" ),
1107
+ rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ),
1108
+
1109
+ rpseudo = new RegExp( pseudos ),
1110
+ ridentifier = new RegExp( "^" + identifier + "$" ),
1111
+
1112
+ matchExpr = {
1113
+ "ID": new RegExp( "^#(" + characterEncoding + ")" ),
1114
+ "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
1115
+ "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
1116
+ "ATTR": new RegExp( "^" + attributes ),
1117
+ "PSEUDO": new RegExp( "^" + pseudos ),
1118
+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
1119
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
1120
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
1121
+ "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
1122
+ // For use in libraries implementing .is()
1123
+ // We use this for POS matching in `select`
1124
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
1125
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
1126
+ },
1127
+
1128
+ rnative = /^[^{]+\{\s*\[native \w/,
1129
+
1130
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
1131
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
1132
+
1133
+ rinputs = /^(?:input|select|textarea|button)$/i,
1134
+ rheader = /^h\d$/i,
1135
+
1136
+ rescape = /'|\\/g,
1137
+
1138
+ // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
1139
+ runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
1140
+ funescape = function( _, escaped, escapedWhitespace ) {
1141
+ var high = "0x" + escaped - 0x10000;
1142
+ // NaN means non-codepoint
1143
+ // Support: Firefox
1144
+ // Workaround erroneous numeric interpretation of +"0x"
1145
+ return high !== high || escapedWhitespace ?
1146
+ escaped :
1147
+ // BMP codepoint
1148
+ high < 0 ?
1149
+ String.fromCharCode( high + 0x10000 ) :
1150
+ // Supplemental Plane codepoint (surrogate pair)
1151
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
1152
+ };
1153
+
1154
+ // Optimize for push.apply( _, NodeList )
1155
+ try {
1156
+ push.apply(
1157
+ (arr = slice.call( preferredDoc.childNodes )),
1158
+ preferredDoc.childNodes
1159
+ );
1160
+ // Support: Android<4.0
1161
+ // Detect silently failing push.apply
1162
+ arr[ preferredDoc.childNodes.length ].nodeType;
1163
+ } catch ( e ) {
1164
+ push = { apply: arr.length ?
1165
+
1166
+ // Leverage slice if possible
1167
+ function( target, els ) {
1168
+ push_native.apply( target, slice.call(els) );
1169
+ } :
1170
+
1171
+ // Support: IE<9
1172
+ // Otherwise append directly
1173
+ function( target, els ) {
1174
+ var j = target.length,
1175
+ i = 0;
1176
+ // Can't trust NodeList.length
1177
+ while ( (target[j++] = els[i++]) ) {}
1178
+ target.length = j - 1;
1179
+ }
1180
+ };
1181
+ }
1182
+
1183
+ function Sizzle( selector, context, results, seed ) {
1184
+ var match, elem, m, nodeType,
1185
+ // QSA vars
1186
+ i, groups, old, nid, newContext, newSelector;
1187
+
1188
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
1189
+ setDocument( context );
1190
+ }
1191
+
1192
+ context = context || document;
1193
+ results = results || [];
1194
+
1195
+ if ( !selector || typeof selector !== "string" ) {
1196
+ return results;
1197
+ }
1198
+
1199
+ if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
1200
+ return [];
1201
+ }
1202
+
1203
+ if ( documentIsHTML && !seed ) {
1204
+
1205
+ // Shortcuts
1206
+ if ( (match = rquickExpr.exec( selector )) ) {
1207
+ // Speed-up: Sizzle("#ID")
1208
+ if ( (m = match[1]) ) {
1209
+ if ( nodeType === 9 ) {
1210
+ elem = context.getElementById( m );
1211
+ // Check parentNode to catch when Blackberry 4.6 returns
1212
+ // nodes that are no longer in the document #6963
1213
+ if ( elem && elem.parentNode ) {
1214
+ // Handle the case where IE, Opera, and Webkit return items
1215
+ // by name instead of ID
1216
+ if ( elem.id === m ) {
1217
+ results.push( elem );
1218
+ return results;
1219
+ }
1220
+ } else {
1221
+ return results;
1222
+ }
1223
+ } else {
1224
+ // Context is not a document
1225
+ if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
1226
+ contains( context, elem ) && elem.id === m ) {
1227
+ results.push( elem );
1228
+ return results;
1229
+ }
1230
+ }
1231
+
1232
+ // Speed-up: Sizzle("TAG")
1233
+ } else if ( match[2] ) {
1234
+ push.apply( results, context.getElementsByTagName( selector ) );
1235
+ return results;
1236
+
1237
+ // Speed-up: Sizzle(".CLASS")
1238
+ } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
1239
+ push.apply( results, context.getElementsByClassName( m ) );
1240
+ return results;
1241
+ }
1242
+ }
1243
+
1244
+ // QSA path
1245
+ if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
1246
+ nid = old = expando;
1247
+ newContext = context;
1248
+ newSelector = nodeType === 9 && selector;
1249
+
1250
+ // qSA works strangely on Element-rooted queries
1251
+ // We can work around this by specifying an extra ID on the root
1252
+ // and working up from there (Thanks to Andrew Dupont for the technique)
1253
+ // IE 8 doesn't work on object elements
1254
+ if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
1255
+ groups = tokenize( selector );
1256
+
1257
+ if ( (old = context.getAttribute("id")) ) {
1258
+ nid = old.replace( rescape, "\\$&" );
1259
+ } else {
1260
+ context.setAttribute( "id", nid );
1261
+ }
1262
+ nid = "[id='" + nid + "'] ";
1263
+
1264
+ i = groups.length;
1265
+ while ( i-- ) {
1266
+ groups[i] = nid + toSelector( groups[i] );
1267
+ }
1268
+ newContext = rsibling.test( selector ) && context.parentNode || context;
1269
+ newSelector = groups.join(",");
1270
+ }
1271
+
1272
+ if ( newSelector ) {
1273
+ try {
1274
+ push.apply( results,
1275
+ newContext.querySelectorAll( newSelector )
1276
+ );
1277
+ return results;
1278
+ } catch(qsaError) {
1279
+ } finally {
1280
+ if ( !old ) {
1281
+ context.removeAttribute("id");
1282
+ }
1283
+ }
1284
+ }
1285
+ }
1286
+ }
1287
+
1288
+ // All others
1289
+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
1290
+ }
1291
+
1292
+ /**
1293
+ * Create key-value caches of limited size
1294
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
1295
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
1296
+ * deleting the oldest entry
1297
+ */
1298
+ function createCache() {
1299
+ var keys = [];
1300
+
1301
+ function cache( key, value ) {
1302
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
1303
+ if ( keys.push( key += " " ) > Expr.cacheLength ) {
1304
+ // Only keep the most recent entries
1305
+ delete cache[ keys.shift() ];
1306
+ }
1307
+ return (cache[ key ] = value);
1308
+ }
1309
+ return cache;
1310
+ }
1311
+
1312
+ /**
1313
+ * Mark a function for special use by Sizzle
1314
+ * @param {Function} fn The function to mark
1315
+ */
1316
+ function markFunction( fn ) {
1317
+ fn[ expando ] = true;
1318
+ return fn;
1319
+ }
1320
+
1321
+ /**
1322
+ * Support testing using an element
1323
+ * @param {Function} fn Passed the created div and expects a boolean result
1324
+ */
1325
+ function assert( fn ) {
1326
+ var div = document.createElement("div");
1327
+
1328
+ try {
1329
+ return !!fn( div );
1330
+ } catch (e) {
1331
+ return false;
1332
+ } finally {
1333
+ // Remove from its parent by default
1334
+ if ( div.parentNode ) {
1335
+ div.parentNode.removeChild( div );
1336
+ }
1337
+ // release memory in IE
1338
+ div = null;
1339
+ }
1340
+ }
1341
+
1342
+ /**
1343
+ * Adds the same handler for all of the specified attrs
1344
+ * @param {String} attrs Pipe-separated list of attributes
1345
+ * @param {Function} handler The method that will be applied
1346
+ */
1347
+ function addHandle( attrs, handler ) {
1348
+ var arr = attrs.split("|"),
1349
+ i = attrs.length;
1350
+
1351
+ while ( i-- ) {
1352
+ Expr.attrHandle[ arr[i] ] = handler;
1353
+ }
1354
+ }
1355
+
1356
+ /**
1357
+ * Checks document order of two siblings
1358
+ * @param {Element} a
1359
+ * @param {Element} b
1360
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
1361
+ */
1362
+ function siblingCheck( a, b ) {
1363
+ var cur = b && a,
1364
+ diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
1365
+ ( ~b.sourceIndex || MAX_NEGATIVE ) -
1366
+ ( ~a.sourceIndex || MAX_NEGATIVE );
1367
+
1368
+ // Use IE sourceIndex if available on both nodes
1369
+ if ( diff ) {
1370
+ return diff;
1371
+ }
1372
+
1373
+ // Check if b follows a
1374
+ if ( cur ) {
1375
+ while ( (cur = cur.nextSibling) ) {
1376
+ if ( cur === b ) {
1377
+ return -1;
1378
+ }
1379
+ }
1380
+ }
1381
+
1382
+ return a ? 1 : -1;
1383
+ }
1384
+
1385
+ /**
1386
+ * Returns a function to use in pseudos for input types
1387
+ * @param {String} type
1388
+ */
1389
+ function createInputPseudo( type ) {
1390
+ return function( elem ) {
1391
+ var name = elem.nodeName.toLowerCase();
1392
+ return name === "input" && elem.type === type;
1393
+ };
1394
+ }
1395
+
1396
+ /**
1397
+ * Returns a function to use in pseudos for buttons
1398
+ * @param {String} type
1399
+ */
1400
+ function createButtonPseudo( type ) {
1401
+ return function( elem ) {
1402
+ var name = elem.nodeName.toLowerCase();
1403
+ return (name === "input" || name === "button") && elem.type === type;
1404
+ };
1405
+ }
1406
+
1407
+ /**
1408
+ * Returns a function to use in pseudos for positionals
1409
+ * @param {Function} fn
1410
+ */
1411
+ function createPositionalPseudo( fn ) {
1412
+ return markFunction(function( argument ) {
1413
+ argument = +argument;
1414
+ return markFunction(function( seed, matches ) {
1415
+ var j,
1416
+ matchIndexes = fn( [], seed.length, argument ),
1417
+ i = matchIndexes.length;
1418
+
1419
+ // Match elements found at the specified indexes
1420
+ while ( i-- ) {
1421
+ if ( seed[ (j = matchIndexes[i]) ] ) {
1422
+ seed[j] = !(matches[j] = seed[j]);
1423
+ }
1424
+ }
1425
+ });
1426
+ });
1427
+ }
1428
+
1429
+ /**
1430
+ * Detect xml
1431
+ * @param {Element|Object} elem An element or a document
1432
+ */
1433
+ isXML = Sizzle.isXML = function( elem ) {
1434
+ // documentElement is verified for cases where it doesn't yet exist
1435
+ // (such as loading iframes in IE - #4833)
1436
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
1437
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
1438
+ };
1439
+
1440
+ // Expose support vars for convenience
1441
+ support = Sizzle.support = {};
1442
+
1443
+ /**
1444
+ * Sets document-related variables once based on the current document
1445
+ * @param {Element|Object} [doc] An element or document object to use to set the document
1446
+ * @returns {Object} Returns the current document
1447
+ */
1448
+ setDocument = Sizzle.setDocument = function( node ) {
1449
+ var doc = node ? node.ownerDocument || node : preferredDoc,
1450
+ parent = doc.defaultView;
1451
+
1452
+ // If no document and documentElement is available, return
1453
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
1454
+ return document;
1455
+ }
1456
+
1457
+ // Set our document
1458
+ document = doc;
1459
+ docElem = doc.documentElement;
1460
+
1461
+ // Support tests
1462
+ documentIsHTML = !isXML( doc );
1463
+
1464
+ // Support: IE>8
1465
+ // If iframe document is assigned to "document" variable and if iframe has been reloaded,
1466
+ // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
1467
+ // IE6-8 do not support the defaultView property so parent will be undefined
1468
+ if ( parent && parent.attachEvent && parent !== parent.top ) {
1469
+ parent.attachEvent( "onbeforeunload", function() {
1470
+ setDocument();
1471
+ });
1472
+ }
1473
+
1474
+ /* Attributes
1475
+ ---------------------------------------------------------------------- */
1476
+
1477
+ // Support: IE<8
1478
+ // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
1479
+ support.attributes = assert(function( div ) {
1480
+ div.className = "i";
1481
+ return !div.getAttribute("className");
1482
+ });
1483
+
1484
+ /* getElement(s)By*
1485
+ ---------------------------------------------------------------------- */
1486
+
1487
+ // Check if getElementsByTagName("*") returns only elements
1488
+ support.getElementsByTagName = assert(function( div ) {
1489
+ div.appendChild( doc.createComment("") );
1490
+ return !div.getElementsByTagName("*").length;
1491
+ });
1492
+
1493
+ // Check if getElementsByClassName can be trusted
1494
+ support.getElementsByClassName = assert(function( div ) {
1495
+ div.innerHTML = "<div class='a'></div><div class='a i'></div>";
1496
+
1497
+ // Support: Safari<4
1498
+ // Catch class over-caching
1499
+ div.firstChild.className = "i";
1500
+ // Support: Opera<10
1501
+ // Catch gEBCN failure to find non-leading classes
1502
+ return div.getElementsByClassName("i").length === 2;
1503
+ });
1504
+
1505
+ // Support: IE<10
1506
+ // Check if getElementById returns elements by name
1507
+ // The broken getElementById methods don't pick up programatically-set names,
1508
+ // so use a roundabout getElementsByName test
1509
+ support.getById = assert(function( div ) {
1510
+ docElem.appendChild( div ).id = expando;
1511
+ return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
1512
+ });
1513
+
1514
+ // ID find and filter
1515
+ if ( support.getById ) {
1516
+ Expr.find["ID"] = function( id, context ) {
1517
+ if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
1518
+ var m = context.getElementById( id );
1519
+ // Check parentNode to catch when Blackberry 4.6 returns
1520
+ // nodes that are no longer in the document #6963
1521
+ return m && m.parentNode ? [m] : [];
1522
+ }
1523
+ };
1524
+ Expr.filter["ID"] = function( id ) {
1525
+ var attrId = id.replace( runescape, funescape );
1526
+ return function( elem ) {
1527
+ return elem.getAttribute("id") === attrId;
1528
+ };
1529
+ };
1530
+ } else {
1531
+ // Support: IE6/7
1532
+ // getElementById is not reliable as a find shortcut
1533
+ delete Expr.find["ID"];
1534
+
1535
+ Expr.filter["ID"] = function( id ) {
1536
+ var attrId = id.replace( runescape, funescape );
1537
+ return function( elem ) {
1538
+ var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
1539
+ return node && node.value === attrId;
1540
+ };
1541
+ };
1542
+ }
1543
+
1544
+ // Tag
1545
+ Expr.find["TAG"] = support.getElementsByTagName ?
1546
+ function( tag, context ) {
1547
+ if ( typeof context.getElementsByTagName !== strundefined ) {
1548
+ return context.getElementsByTagName( tag );
1549
+ }
1550
+ } :
1551
+ function( tag, context ) {
1552
+ var elem,
1553
+ tmp = [],
1554
+ i = 0,
1555
+ results = context.getElementsByTagName( tag );
1556
+
1557
+ // Filter out possible comments
1558
+ if ( tag === "*" ) {
1559
+ while ( (elem = results[i++]) ) {
1560
+ if ( elem.nodeType === 1 ) {
1561
+ tmp.push( elem );
1562
+ }
1563
+ }
1564
+
1565
+ return tmp;
1566
+ }
1567
+ return results;
1568
+ };
1569
+
1570
+ // Class
1571
+ Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
1572
+ if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
1573
+ return context.getElementsByClassName( className );
1574
+ }
1575
+ };
1576
+
1577
+ /* QSA/matchesSelector
1578
+ ---------------------------------------------------------------------- */
1579
+
1580
+ // QSA and matchesSelector support
1581
+
1582
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
1583
+ rbuggyMatches = [];
1584
+
1585
+ // qSa(:focus) reports false when true (Chrome 21)
1586
+ // We allow this because of a bug in IE8/9 that throws an error
1587
+ // whenever `document.activeElement` is accessed on an iframe
1588
+ // So, we allow :focus to pass through QSA all the time to avoid the IE error
1589
+ // See http://bugs.jquery.com/ticket/13378
1590
+ rbuggyQSA = [];
1591
+
1592
+ if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
1593
+ // Build QSA regex
1594
+ // Regex strategy adopted from Diego Perini
1595
+ assert(function( div ) {
1596
+ // Select is set to empty string on purpose
1597
+ // This is to test IE's treatment of not explicitly
1598
+ // setting a boolean content attribute,
1599
+ // since its presence should be enough
1600
+ // http://bugs.jquery.com/ticket/12359
1601
+ div.innerHTML = "<select><option selected=''></option></select>";
1602
+
1603
+ // Support: IE8
1604
+ // Boolean attributes and "value" are not treated correctly
1605
+ if ( !div.querySelectorAll("[selected]").length ) {
1606
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
1607
+ }
1608
+
1609
+ // Webkit/Opera - :checked should return selected option elements
1610
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
1611
+ // IE8 throws error here and will not see later tests
1612
+ if ( !div.querySelectorAll(":checked").length ) {
1613
+ rbuggyQSA.push(":checked");
1614
+ }
1615
+ });
1616
+
1617
+ assert(function( div ) {
1618
+
1619
+ // Support: Opera 10-12/IE8
1620
+ // ^= $= *= and empty values
1621
+ // Should not select anything
1622
+ // Support: Windows 8 Native Apps
1623
+ // The type attribute is restricted during .innerHTML assignment
1624
+ var input = doc.createElement("input");
1625
+ input.setAttribute( "type", "hidden" );
1626
+ div.appendChild( input ).setAttribute( "t", "" );
1627
+
1628
+ if ( div.querySelectorAll("[t^='']").length ) {
1629
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
1630
+ }
1631
+
1632
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
1633
+ // IE8 throws error here and will not see later tests
1634
+ if ( !div.querySelectorAll(":enabled").length ) {
1635
+ rbuggyQSA.push( ":enabled", ":disabled" );
1636
+ }
1637
+
1638
+ // Opera 10-11 does not throw on post-comma invalid pseudos
1639
+ div.querySelectorAll("*,:x");
1640
+ rbuggyQSA.push(",.*:");
1641
+ });
1642
+ }
1643
+
1644
+ if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector ||
1645
+ docElem.mozMatchesSelector ||
1646
+ docElem.oMatchesSelector ||
1647
+ docElem.msMatchesSelector) )) ) {
1648
+
1649
+ assert(function( div ) {
1650
+ // Check to see if it's possible to do matchesSelector
1651
+ // on a disconnected node (IE 9)
1652
+ support.disconnectedMatch = matches.call( div, "div" );
1653
+
1654
+ // This should fail with an exception
1655
+ // Gecko does not error, returns false instead
1656
+ matches.call( div, "[s!='']:x" );
1657
+ rbuggyMatches.push( "!=", pseudos );
1658
+ });
1659
+ }
1660
+
1661
+ rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
1662
+ rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
1663
+
1664
+ /* Contains
1665
+ ---------------------------------------------------------------------- */
1666
+
1667
+ // Element contains another
1668
+ // Purposefully does not implement inclusive descendent
1669
+ // As in, an element does not contain itself
1670
+ contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ?
1671
+ function( a, b ) {
1672
+ var adown = a.nodeType === 9 ? a.documentElement : a,
1673
+ bup = b && b.parentNode;
1674
+ return a === bup || !!( bup && bup.nodeType === 1 && (
1675
+ adown.contains ?
1676
+ adown.contains( bup ) :
1677
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
1678
+ ));
1679
+ } :
1680
+ function( a, b ) {
1681
+ if ( b ) {
1682
+ while ( (b = b.parentNode) ) {
1683
+ if ( b === a ) {
1684
+ return true;
1685
+ }
1686
+ }
1687
+ }
1688
+ return false;
1689
+ };
1690
+
1691
+ /* Sorting
1692
+ ---------------------------------------------------------------------- */
1693
+
1694
+ // Document order sorting
1695
+ sortOrder = docElem.compareDocumentPosition ?
1696
+ function( a, b ) {
1697
+
1698
+ // Flag for duplicate removal
1699
+ if ( a === b ) {
1700
+ hasDuplicate = true;
1701
+ return 0;
1702
+ }
1703
+
1704
+ var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b );
1705
+
1706
+ if ( compare ) {
1707
+ // Disconnected nodes
1708
+ if ( compare & 1 ||
1709
+ (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
1710
+
1711
+ // Choose the first element that is related to our preferred document
1712
+ if ( a === doc || contains(preferredDoc, a) ) {
1713
+ return -1;
1714
+ }
1715
+ if ( b === doc || contains(preferredDoc, b) ) {
1716
+ return 1;
1717
+ }
1718
+
1719
+ // Maintain original order
1720
+ return sortInput ?
1721
+ ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
1722
+ 0;
1723
+ }
1724
+
1725
+ return compare & 4 ? -1 : 1;
1726
+ }
1727
+
1728
+ // Not directly comparable, sort on existence of method
1729
+ return a.compareDocumentPosition ? -1 : 1;
1730
+ } :
1731
+ function( a, b ) {
1732
+ var cur,
1733
+ i = 0,
1734
+ aup = a.parentNode,
1735
+ bup = b.parentNode,
1736
+ ap = [ a ],
1737
+ bp = [ b ];
1738
+
1739
+ // Exit early if the nodes are identical
1740
+ if ( a === b ) {
1741
+ hasDuplicate = true;
1742
+ return 0;
1743
+
1744
+ // Parentless nodes are either documents or disconnected
1745
+ } else if ( !aup || !bup ) {
1746
+ return a === doc ? -1 :
1747
+ b === doc ? 1 :
1748
+ aup ? -1 :
1749
+ bup ? 1 :
1750
+ sortInput ?
1751
+ ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
1752
+ 0;
1753
+
1754
+ // If the nodes are siblings, we can do a quick check
1755
+ } else if ( aup === bup ) {
1756
+ return siblingCheck( a, b );
1757
+ }
1758
+
1759
+ // Otherwise we need full lists of their ancestors for comparison
1760
+ cur = a;
1761
+ while ( (cur = cur.parentNode) ) {
1762
+ ap.unshift( cur );
1763
+ }
1764
+ cur = b;
1765
+ while ( (cur = cur.parentNode) ) {
1766
+ bp.unshift( cur );
1767
+ }
1768
+
1769
+ // Walk down the tree looking for a discrepancy
1770
+ while ( ap[i] === bp[i] ) {
1771
+ i++;
1772
+ }
1773
+
1774
+ return i ?
1775
+ // Do a sibling check if the nodes have a common ancestor
1776
+ siblingCheck( ap[i], bp[i] ) :
1777
+
1778
+ // Otherwise nodes in our document sort first
1779
+ ap[i] === preferredDoc ? -1 :
1780
+ bp[i] === preferredDoc ? 1 :
1781
+ 0;
1782
+ };
1783
+
1784
+ return doc;
1785
+ };
1786
+
1787
+ Sizzle.matches = function( expr, elements ) {
1788
+ return Sizzle( expr, null, null, elements );
1789
+ };
1790
+
1791
+ Sizzle.matchesSelector = function( elem, expr ) {
1792
+ // Set document vars if needed
1793
+ if ( ( elem.ownerDocument || elem ) !== document ) {
1794
+ setDocument( elem );
1795
+ }
1796
+
1797
+ // Make sure that attribute selectors are quoted
1798
+ expr = expr.replace( rattributeQuotes, "='$1']" );
1799
+
1800
+ if ( support.matchesSelector && documentIsHTML &&
1801
+ ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
1802
+ ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
1803
+
1804
+ try {
1805
+ var ret = matches.call( elem, expr );
1806
+
1807
+ // IE 9's matchesSelector returns false on disconnected nodes
1808
+ if ( ret || support.disconnectedMatch ||
1809
+ // As well, disconnected nodes are said to be in a document
1810
+ // fragment in IE 9
1811
+ elem.document && elem.document.nodeType !== 11 ) {
1812
+ return ret;
1813
+ }
1814
+ } catch(e) {}
1815
+ }
1816
+
1817
+ return Sizzle( expr, document, null, [elem] ).length > 0;
1818
+ };
1819
+
1820
+ Sizzle.contains = function( context, elem ) {
1821
+ // Set document vars if needed
1822
+ if ( ( context.ownerDocument || context ) !== document ) {
1823
+ setDocument( context );
1824
+ }
1825
+ return contains( context, elem );
1826
+ };
1827
+
1828
+ Sizzle.attr = function( elem, name ) {
1829
+ // Set document vars if needed
1830
+ if ( ( elem.ownerDocument || elem ) !== document ) {
1831
+ setDocument( elem );
1832
+ }
1833
+
1834
+ var fn = Expr.attrHandle[ name.toLowerCase() ],
1835
+ // Don't get fooled by Object.prototype properties (jQuery #13807)
1836
+ val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
1837
+ fn( elem, name, !documentIsHTML ) :
1838
+ undefined;
1839
+
1840
+ return val === undefined ?
1841
+ support.attributes || !documentIsHTML ?
1842
+ elem.getAttribute( name ) :
1843
+ (val = elem.getAttributeNode(name)) && val.specified ?
1844
+ val.value :
1845
+ null :
1846
+ val;
1847
+ };
1848
+
1849
+ Sizzle.error = function( msg ) {
1850
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
1851
+ };
1852
+
1853
+ /**
1854
+ * Document sorting and removing duplicates
1855
+ * @param {ArrayLike} results
1856
+ */
1857
+ Sizzle.uniqueSort = function( results ) {
1858
+ var elem,
1859
+ duplicates = [],
1860
+ j = 0,
1861
+ i = 0;
1862
+
1863
+ // Unless we *know* we can detect duplicates, assume their presence
1864
+ hasDuplicate = !support.detectDuplicates;
1865
+ sortInput = !support.sortStable && results.slice( 0 );
1866
+ results.sort( sortOrder );
1867
+
1868
+ if ( hasDuplicate ) {
1869
+ while ( (elem = results[i++]) ) {
1870
+ if ( elem === results[ i ] ) {
1871
+ j = duplicates.push( i );
1872
+ }
1873
+ }
1874
+ while ( j-- ) {
1875
+ results.splice( duplicates[ j ], 1 );
1876
+ }
1877
+ }
1878
+
1879
+ return results;
1880
+ };
1881
+
1882
+ /**
1883
+ * Utility function for retrieving the text value of an array of DOM nodes
1884
+ * @param {Array|Element} elem
1885
+ */
1886
+ getText = Sizzle.getText = function( elem ) {
1887
+ var node,
1888
+ ret = "",
1889
+ i = 0,
1890
+ nodeType = elem.nodeType;
1891
+
1892
+ if ( !nodeType ) {
1893
+ // If no nodeType, this is expected to be an array
1894
+ for ( ; (node = elem[i]); i++ ) {
1895
+ // Do not traverse comment nodes
1896
+ ret += getText( node );
1897
+ }
1898
+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
1899
+ // Use textContent for elements
1900
+ // innerText usage removed for consistency of new lines (see #11153)
1901
+ if ( typeof elem.textContent === "string" ) {
1902
+ return elem.textContent;
1903
+ } else {
1904
+ // Traverse its children
1905
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
1906
+ ret += getText( elem );
1907
+ }
1908
+ }
1909
+ } else if ( nodeType === 3 || nodeType === 4 ) {
1910
+ return elem.nodeValue;
1911
+ }
1912
+ // Do not include comment or processing instruction nodes
1913
+
1914
+ return ret;
1915
+ };
1916
+
1917
+ Expr = Sizzle.selectors = {
1918
+
1919
+ // Can be adjusted by the user
1920
+ cacheLength: 50,
1921
+
1922
+ createPseudo: markFunction,
1923
+
1924
+ match: matchExpr,
1925
+
1926
+ attrHandle: {},
1927
+
1928
+ find: {},
1929
+
1930
+ relative: {
1931
+ ">": { dir: "parentNode", first: true },
1932
+ " ": { dir: "parentNode" },
1933
+ "+": { dir: "previousSibling", first: true },
1934
+ "~": { dir: "previousSibling" }
1935
+ },
1936
+
1937
+ preFilter: {
1938
+ "ATTR": function( match ) {
1939
+ match[1] = match[1].replace( runescape, funescape );
1940
+
1941
+ // Move the given value to match[3] whether quoted or unquoted
1942
+ match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
1943
+
1944
+ if ( match[2] === "~=" ) {
1945
+ match[3] = " " + match[3] + " ";
1946
+ }
1947
+
1948
+ return match.slice( 0, 4 );
1949
+ },
1950
+
1951
+ "CHILD": function( match ) {
1952
+ /* matches from matchExpr["CHILD"]
1953
+ 1 type (only|nth|...)
1954
+ 2 what (child|of-type)
1955
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
1956
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
1957
+ 5 sign of xn-component
1958
+ 6 x of xn-component
1959
+ 7 sign of y-component
1960
+ 8 y of y-component
1961
+ */
1962
+ match[1] = match[1].toLowerCase();
1963
+
1964
+ if ( match[1].slice( 0, 3 ) === "nth" ) {
1965
+ // nth-* requires argument
1966
+ if ( !match[3] ) {
1967
+ Sizzle.error( match[0] );
1968
+ }
1969
+
1970
+ // numeric x and y parameters for Expr.filter.CHILD
1971
+ // remember that false/true cast respectively to 0/1
1972
+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
1973
+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
1974
+
1975
+ // other types prohibit arguments
1976
+ } else if ( match[3] ) {
1977
+ Sizzle.error( match[0] );
1978
+ }
1979
+
1980
+ return match;
1981
+ },
1982
+
1983
+ "PSEUDO": function( match ) {
1984
+ var excess,
1985
+ unquoted = !match[5] && match[2];
1986
+
1987
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
1988
+ return null;
1989
+ }
1990
+
1991
+ // Accept quoted arguments as-is
1992
+ if ( match[3] && match[4] !== undefined ) {
1993
+ match[2] = match[4];
1994
+
1995
+ // Strip excess characters from unquoted arguments
1996
+ } else if ( unquoted && rpseudo.test( unquoted ) &&
1997
+ // Get excess from tokenize (recursively)
1998
+ (excess = tokenize( unquoted, true )) &&
1999
+ // advance to the next closing parenthesis
2000
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
2001
+
2002
+ // excess is a negative index
2003
+ match[0] = match[0].slice( 0, excess );
2004
+ match[2] = unquoted.slice( 0, excess );
2005
+ }
2006
+
2007
+ // Return only captures needed by the pseudo filter method (type and argument)
2008
+ return match.slice( 0, 3 );
2009
+ }
2010
+ },
2011
+
2012
+ filter: {
2013
+
2014
+ "TAG": function( nodeNameSelector ) {
2015
+ var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
2016
+ return nodeNameSelector === "*" ?
2017
+ function() { return true; } :
2018
+ function( elem ) {
2019
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
2020
+ };
2021
+ },
2022
+
2023
+ "CLASS": function( className ) {
2024
+ var pattern = classCache[ className + " " ];
2025
+
2026
+ return pattern ||
2027
+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
2028
+ classCache( className, function( elem ) {
2029
+ return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
2030
+ });
2031
+ },
2032
+
2033
+ "ATTR": function( name, operator, check ) {
2034
+ return function( elem ) {
2035
+ var result = Sizzle.attr( elem, name );
2036
+
2037
+ if ( result == null ) {
2038
+ return operator === "!=";
2039
+ }
2040
+ if ( !operator ) {
2041
+ return true;
2042
+ }
2043
+
2044
+ result += "";
2045
+
2046
+ return operator === "=" ? result === check :
2047
+ operator === "!=" ? result !== check :
2048
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
2049
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
2050
+ operator === "$=" ? check && result.slice( -check.length ) === check :
2051
+ operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
2052
+ operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
2053
+ false;
2054
+ };
2055
+ },
2056
+
2057
+ "CHILD": function( type, what, argument, first, last ) {
2058
+ var simple = type.slice( 0, 3 ) !== "nth",
2059
+ forward = type.slice( -4 ) !== "last",
2060
+ ofType = what === "of-type";
2061
+
2062
+ return first === 1 && last === 0 ?
2063
+
2064
+ // Shortcut for :nth-*(n)
2065
+ function( elem ) {
2066
+ return !!elem.parentNode;
2067
+ } :
2068
+
2069
+ function( elem, context, xml ) {
2070
+ var cache, outerCache, node, diff, nodeIndex, start,
2071
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
2072
+ parent = elem.parentNode,
2073
+ name = ofType && elem.nodeName.toLowerCase(),
2074
+ useCache = !xml && !ofType;
2075
+
2076
+ if ( parent ) {
2077
+
2078
+ // :(first|last|only)-(child|of-type)
2079
+ if ( simple ) {
2080
+ while ( dir ) {
2081
+ node = elem;
2082
+ while ( (node = node[ dir ]) ) {
2083
+ if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
2084
+ return false;
2085
+ }
2086
+ }
2087
+ // Reverse direction for :only-* (if we haven't yet done so)
2088
+ start = dir = type === "only" && !start && "nextSibling";
2089
+ }
2090
+ return true;
2091
+ }
2092
+
2093
+ start = [ forward ? parent.firstChild : parent.lastChild ];
2094
+
2095
+ // non-xml :nth-child(...) stores cache data on `parent`
2096
+ if ( forward && useCache ) {
2097
+ // Seek `elem` from a previously-cached index
2098
+ outerCache = parent[ expando ] || (parent[ expando ] = {});
2099
+ cache = outerCache[ type ] || [];
2100
+ nodeIndex = cache[0] === dirruns && cache[1];
2101
+ diff = cache[0] === dirruns && cache[2];
2102
+ node = nodeIndex && parent.childNodes[ nodeIndex ];
2103
+
2104
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
2105
+
2106
+ // Fallback to seeking `elem` from the start
2107
+ (diff = nodeIndex = 0) || start.pop()) ) {
2108
+
2109
+ // When found, cache indexes on `parent` and break
2110
+ if ( node.nodeType === 1 && ++diff && node === elem ) {
2111
+ outerCache[ type ] = [ dirruns, nodeIndex, diff ];
2112
+ break;
2113
+ }
2114
+ }
2115
+
2116
+ // Use previously-cached element index if available
2117
+ } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
2118
+ diff = cache[1];
2119
+
2120
+ // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
2121
+ } else {
2122
+ // Use the same loop as above to seek `elem` from the start
2123
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
2124
+ (diff = nodeIndex = 0) || start.pop()) ) {
2125
+
2126
+ if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
2127
+ // Cache the index of each encountered element
2128
+ if ( useCache ) {
2129
+ (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
2130
+ }
2131
+
2132
+ if ( node === elem ) {
2133
+ break;
2134
+ }
2135
+ }
2136
+ }
2137
+ }
2138
+
2139
+ // Incorporate the offset, then check against cycle size
2140
+ diff -= last;
2141
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
2142
+ }
2143
+ };
2144
+ },
2145
+
2146
+ "PSEUDO": function( pseudo, argument ) {
2147
+ // pseudo-class names are case-insensitive
2148
+ // http://www.w3.org/TR/selectors/#pseudo-classes
2149
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
2150
+ // Remember that setFilters inherits from pseudos
2151
+ var args,
2152
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
2153
+ Sizzle.error( "unsupported pseudo: " + pseudo );
2154
+
2155
+ // The user may use createPseudo to indicate that
2156
+ // arguments are needed to create the filter function
2157
+ // just as Sizzle does
2158
+ if ( fn[ expando ] ) {
2159
+ return fn( argument );
2160
+ }
2161
+
2162
+ // But maintain support for old signatures
2163
+ if ( fn.length > 1 ) {
2164
+ args = [ pseudo, pseudo, "", argument ];
2165
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
2166
+ markFunction(function( seed, matches ) {
2167
+ var idx,
2168
+ matched = fn( seed, argument ),
2169
+ i = matched.length;
2170
+ while ( i-- ) {
2171
+ idx = indexOf.call( seed, matched[i] );
2172
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
2173
+ }
2174
+ }) :
2175
+ function( elem ) {
2176
+ return fn( elem, 0, args );
2177
+ };
2178
+ }
2179
+
2180
+ return fn;
2181
+ }
2182
+ },
2183
+
2184
+ pseudos: {
2185
+ // Potentially complex pseudos
2186
+ "not": markFunction(function( selector ) {
2187
+ // Trim the selector passed to compile
2188
+ // to avoid treating leading and trailing
2189
+ // spaces as combinators
2190
+ var input = [],
2191
+ results = [],
2192
+ matcher = compile( selector.replace( rtrim, "$1" ) );
2193
+
2194
+ return matcher[ expando ] ?
2195
+ markFunction(function( seed, matches, context, xml ) {
2196
+ var elem,
2197
+ unmatched = matcher( seed, null, xml, [] ),
2198
+ i = seed.length;
2199
+
2200
+ // Match elements unmatched by `matcher`
2201
+ while ( i-- ) {
2202
+ if ( (elem = unmatched[i]) ) {
2203
+ seed[i] = !(matches[i] = elem);
2204
+ }
2205
+ }
2206
+ }) :
2207
+ function( elem, context, xml ) {
2208
+ input[0] = elem;
2209
+ matcher( input, null, xml, results );
2210
+ return !results.pop();
2211
+ };
2212
+ }),
2213
+
2214
+ "has": markFunction(function( selector ) {
2215
+ return function( elem ) {
2216
+ return Sizzle( selector, elem ).length > 0;
2217
+ };
2218
+ }),
2219
+
2220
+ "contains": markFunction(function( text ) {
2221
+ return function( elem ) {
2222
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
2223
+ };
2224
+ }),
2225
+
2226
+ // "Whether an element is represented by a :lang() selector
2227
+ // is based solely on the element's language value
2228
+ // being equal to the identifier C,
2229
+ // or beginning with the identifier C immediately followed by "-".
2230
+ // The matching of C against the element's language value is performed case-insensitively.
2231
+ // The identifier C does not have to be a valid language name."
2232
+ // http://www.w3.org/TR/selectors/#lang-pseudo
2233
+ "lang": markFunction( function( lang ) {
2234
+ // lang value must be a valid identifier
2235
+ if ( !ridentifier.test(lang || "") ) {
2236
+ Sizzle.error( "unsupported lang: " + lang );
2237
+ }
2238
+ lang = lang.replace( runescape, funescape ).toLowerCase();
2239
+ return function( elem ) {
2240
+ var elemLang;
2241
+ do {
2242
+ if ( (elemLang = documentIsHTML ?
2243
+ elem.lang :
2244
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
2245
+
2246
+ elemLang = elemLang.toLowerCase();
2247
+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
2248
+ }
2249
+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
2250
+ return false;
2251
+ };
2252
+ }),
2253
+
2254
+ // Miscellaneous
2255
+ "target": function( elem ) {
2256
+ var hash = window.location && window.location.hash;
2257
+ return hash && hash.slice( 1 ) === elem.id;
2258
+ },
2259
+
2260
+ "root": function( elem ) {
2261
+ return elem === docElem;
2262
+ },
2263
+
2264
+ "focus": function( elem ) {
2265
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
2266
+ },
2267
+
2268
+ // Boolean properties
2269
+ "enabled": function( elem ) {
2270
+ return elem.disabled === false;
2271
+ },
2272
+
2273
+ "disabled": function( elem ) {
2274
+ return elem.disabled === true;
2275
+ },
2276
+
2277
+ "checked": function( elem ) {
2278
+ // In CSS3, :checked should return both checked and selected elements
2279
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
2280
+ var nodeName = elem.nodeName.toLowerCase();
2281
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
2282
+ },
2283
+
2284
+ "selected": function( elem ) {
2285
+ // Accessing this property makes selected-by-default
2286
+ // options in Safari work properly
2287
+ if ( elem.parentNode ) {
2288
+ elem.parentNode.selectedIndex;
2289
+ }
2290
+
2291
+ return elem.selected === true;
2292
+ },
2293
+
2294
+ // Contents
2295
+ "empty": function( elem ) {
2296
+ // http://www.w3.org/TR/selectors/#empty-pseudo
2297
+ // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
2298
+ // not comment, processing instructions, or others
2299
+ // Thanks to Diego Perini for the nodeName shortcut
2300
+ // Greater than "@" means alpha characters (specifically not starting with "#" or "?")
2301
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
2302
+ if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
2303
+ return false;
2304
+ }
2305
+ }
2306
+ return true;
2307
+ },
2308
+
2309
+ "parent": function( elem ) {
2310
+ return !Expr.pseudos["empty"]( elem );
2311
+ },
2312
+
2313
+ // Element/input types
2314
+ "header": function( elem ) {
2315
+ return rheader.test( elem.nodeName );
2316
+ },
2317
+
2318
+ "input": function( elem ) {
2319
+ return rinputs.test( elem.nodeName );
2320
+ },
2321
+
2322
+ "button": function( elem ) {
2323
+ var name = elem.nodeName.toLowerCase();
2324
+ return name === "input" && elem.type === "button" || name === "button";
2325
+ },
2326
+
2327
+ "text": function( elem ) {
2328
+ var attr;
2329
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
2330
+ // use getAttribute instead to test this case
2331
+ return elem.nodeName.toLowerCase() === "input" &&
2332
+ elem.type === "text" &&
2333
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
2334
+ },
2335
+
2336
+ // Position-in-collection
2337
+ "first": createPositionalPseudo(function() {
2338
+ return [ 0 ];
2339
+ }),
2340
+
2341
+ "last": createPositionalPseudo(function( matchIndexes, length ) {
2342
+ return [ length - 1 ];
2343
+ }),
2344
+
2345
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
2346
+ return [ argument < 0 ? argument + length : argument ];
2347
+ }),
2348
+
2349
+ "even": createPositionalPseudo(function( matchIndexes, length ) {
2350
+ var i = 0;
2351
+ for ( ; i < length; i += 2 ) {
2352
+ matchIndexes.push( i );
2353
+ }
2354
+ return matchIndexes;
2355
+ }),
2356
+
2357
+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
2358
+ var i = 1;
2359
+ for ( ; i < length; i += 2 ) {
2360
+ matchIndexes.push( i );
2361
+ }
2362
+ return matchIndexes;
2363
+ }),
2364
+
2365
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2366
+ var i = argument < 0 ? argument + length : argument;
2367
+ for ( ; --i >= 0; ) {
2368
+ matchIndexes.push( i );
2369
+ }
2370
+ return matchIndexes;
2371
+ }),
2372
+
2373
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
2374
+ var i = argument < 0 ? argument + length : argument;
2375
+ for ( ; ++i < length; ) {
2376
+ matchIndexes.push( i );
2377
+ }
2378
+ return matchIndexes;
2379
+ })
2380
+ }
2381
+ };
2382
+
2383
+ Expr.pseudos["nth"] = Expr.pseudos["eq"];
2384
+
2385
+ // Add button/input type pseudos
2386
+ for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
2387
+ Expr.pseudos[ i ] = createInputPseudo( i );
2388
+ }
2389
+ for ( i in { submit: true, reset: true } ) {
2390
+ Expr.pseudos[ i ] = createButtonPseudo( i );
2391
+ }
2392
+
2393
+ // Easy API for creating new setFilters
2394
+ function setFilters() {}
2395
+ setFilters.prototype = Expr.filters = Expr.pseudos;
2396
+ Expr.setFilters = new setFilters();
2397
+
2398
+ function tokenize( selector, parseOnly ) {
2399
+ var matched, match, tokens, type,
2400
+ soFar, groups, preFilters,
2401
+ cached = tokenCache[ selector + " " ];
2402
+
2403
+ if ( cached ) {
2404
+ return parseOnly ? 0 : cached.slice( 0 );
2405
+ }
2406
+
2407
+ soFar = selector;
2408
+ groups = [];
2409
+ preFilters = Expr.preFilter;
2410
+
2411
+ while ( soFar ) {
2412
+
2413
+ // Comma and first run
2414
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
2415
+ if ( match ) {
2416
+ // Don't consume trailing commas as valid
2417
+ soFar = soFar.slice( match[0].length ) || soFar;
2418
+ }
2419
+ groups.push( tokens = [] );
2420
+ }
2421
+
2422
+ matched = false;
2423
+
2424
+ // Combinators
2425
+ if ( (match = rcombinators.exec( soFar )) ) {
2426
+ matched = match.shift();
2427
+ tokens.push({
2428
+ value: matched,
2429
+ // Cast descendant combinators to space
2430
+ type: match[0].replace( rtrim, " " )
2431
+ });
2432
+ soFar = soFar.slice( matched.length );
2433
+ }
2434
+
2435
+ // Filters
2436
+ for ( type in Expr.filter ) {
2437
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
2438
+ (match = preFilters[ type ]( match ))) ) {
2439
+ matched = match.shift();
2440
+ tokens.push({
2441
+ value: matched,
2442
+ type: type,
2443
+ matches: match
2444
+ });
2445
+ soFar = soFar.slice( matched.length );
2446
+ }
2447
+ }
2448
+
2449
+ if ( !matched ) {
2450
+ break;
2451
+ }
2452
+ }
2453
+
2454
+ // Return the length of the invalid excess
2455
+ // if we're just parsing
2456
+ // Otherwise, throw an error or return tokens
2457
+ return parseOnly ?
2458
+ soFar.length :
2459
+ soFar ?
2460
+ Sizzle.error( selector ) :
2461
+ // Cache the tokens
2462
+ tokenCache( selector, groups ).slice( 0 );
2463
+ }
2464
+
2465
+ function toSelector( tokens ) {
2466
+ var i = 0,
2467
+ len = tokens.length,
2468
+ selector = "";
2469
+ for ( ; i < len; i++ ) {
2470
+ selector += tokens[i].value;
2471
+ }
2472
+ return selector;
2473
+ }
2474
+
2475
+ function addCombinator( matcher, combinator, base ) {
2476
+ var dir = combinator.dir,
2477
+ checkNonElements = base && dir === "parentNode",
2478
+ doneName = done++;
2479
+
2480
+ return combinator.first ?
2481
+ // Check against closest ancestor/preceding element
2482
+ function( elem, context, xml ) {
2483
+ while ( (elem = elem[ dir ]) ) {
2484
+ if ( elem.nodeType === 1 || checkNonElements ) {
2485
+ return matcher( elem, context, xml );
2486
+ }
2487
+ }
2488
+ } :
2489
+
2490
+ // Check against all ancestor/preceding elements
2491
+ function( elem, context, xml ) {
2492
+ var data, cache, outerCache,
2493
+ dirkey = dirruns + " " + doneName;
2494
+
2495
+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
2496
+ if ( xml ) {
2497
+ while ( (elem = elem[ dir ]) ) {
2498
+ if ( elem.nodeType === 1 || checkNonElements ) {
2499
+ if ( matcher( elem, context, xml ) ) {
2500
+ return true;
2501
+ }
2502
+ }
2503
+ }
2504
+ } else {
2505
+ while ( (elem = elem[ dir ]) ) {
2506
+ if ( elem.nodeType === 1 || checkNonElements ) {
2507
+ outerCache = elem[ expando ] || (elem[ expando ] = {});
2508
+ if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
2509
+ if ( (data = cache[1]) === true || data === cachedruns ) {
2510
+ return data === true;
2511
+ }
2512
+ } else {
2513
+ cache = outerCache[ dir ] = [ dirkey ];
2514
+ cache[1] = matcher( elem, context, xml ) || cachedruns;
2515
+ if ( cache[1] === true ) {
2516
+ return true;
2517
+ }
2518
+ }
2519
+ }
2520
+ }
2521
+ }
2522
+ };
2523
+ }
2524
+
2525
+ function elementMatcher( matchers ) {
2526
+ return matchers.length > 1 ?
2527
+ function( elem, context, xml ) {
2528
+ var i = matchers.length;
2529
+ while ( i-- ) {
2530
+ if ( !matchers[i]( elem, context, xml ) ) {
2531
+ return false;
2532
+ }
2533
+ }
2534
+ return true;
2535
+ } :
2536
+ matchers[0];
2537
+ }
2538
+
2539
+ function condense( unmatched, map, filter, context, xml ) {
2540
+ var elem,
2541
+ newUnmatched = [],
2542
+ i = 0,
2543
+ len = unmatched.length,
2544
+ mapped = map != null;
2545
+
2546
+ for ( ; i < len; i++ ) {
2547
+ if ( (elem = unmatched[i]) ) {
2548
+ if ( !filter || filter( elem, context, xml ) ) {
2549
+ newUnmatched.push( elem );
2550
+ if ( mapped ) {
2551
+ map.push( i );
2552
+ }
2553
+ }
2554
+ }
2555
+ }
2556
+
2557
+ return newUnmatched;
2558
+ }
2559
+
2560
+ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
2561
+ if ( postFilter && !postFilter[ expando ] ) {
2562
+ postFilter = setMatcher( postFilter );
2563
+ }
2564
+ if ( postFinder && !postFinder[ expando ] ) {
2565
+ postFinder = setMatcher( postFinder, postSelector );
2566
+ }
2567
+ return markFunction(function( seed, results, context, xml ) {
2568
+ var temp, i, elem,
2569
+ preMap = [],
2570
+ postMap = [],
2571
+ preexisting = results.length,
2572
+
2573
+ // Get initial elements from seed or context
2574
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
2575
+
2576
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
2577
+ matcherIn = preFilter && ( seed || !selector ) ?
2578
+ condense( elems, preMap, preFilter, context, xml ) :
2579
+ elems,
2580
+
2581
+ matcherOut = matcher ?
2582
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
2583
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
2584
+
2585
+ // ...intermediate processing is necessary
2586
+ [] :
2587
+
2588
+ // ...otherwise use results directly
2589
+ results :
2590
+ matcherIn;
2591
+
2592
+ // Find primary matches
2593
+ if ( matcher ) {
2594
+ matcher( matcherIn, matcherOut, context, xml );
2595
+ }
2596
+
2597
+ // Apply postFilter
2598
+ if ( postFilter ) {
2599
+ temp = condense( matcherOut, postMap );
2600
+ postFilter( temp, [], context, xml );
2601
+
2602
+ // Un-match failing elements by moving them back to matcherIn
2603
+ i = temp.length;
2604
+ while ( i-- ) {
2605
+ if ( (elem = temp[i]) ) {
2606
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
2607
+ }
2608
+ }
2609
+ }
2610
+
2611
+ if ( seed ) {
2612
+ if ( postFinder || preFilter ) {
2613
+ if ( postFinder ) {
2614
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
2615
+ temp = [];
2616
+ i = matcherOut.length;
2617
+ while ( i-- ) {
2618
+ if ( (elem = matcherOut[i]) ) {
2619
+ // Restore matcherIn since elem is not yet a final match
2620
+ temp.push( (matcherIn[i] = elem) );
2621
+ }
2622
+ }
2623
+ postFinder( null, (matcherOut = []), temp, xml );
2624
+ }
2625
+
2626
+ // Move matched elements from seed to results to keep them synchronized
2627
+ i = matcherOut.length;
2628
+ while ( i-- ) {
2629
+ if ( (elem = matcherOut[i]) &&
2630
+ (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
2631
+
2632
+ seed[temp] = !(results[temp] = elem);
2633
+ }
2634
+ }
2635
+ }
2636
+
2637
+ // Add elements to results, through postFinder if defined
2638
+ } else {
2639
+ matcherOut = condense(
2640
+ matcherOut === results ?
2641
+ matcherOut.splice( preexisting, matcherOut.length ) :
2642
+ matcherOut
2643
+ );
2644
+ if ( postFinder ) {
2645
+ postFinder( null, results, matcherOut, xml );
2646
+ } else {
2647
+ push.apply( results, matcherOut );
2648
+ }
2649
+ }
2650
+ });
2651
+ }
2652
+
2653
+ function matcherFromTokens( tokens ) {
2654
+ var checkContext, matcher, j,
2655
+ len = tokens.length,
2656
+ leadingRelative = Expr.relative[ tokens[0].type ],
2657
+ implicitRelative = leadingRelative || Expr.relative[" "],
2658
+ i = leadingRelative ? 1 : 0,
2659
+
2660
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
2661
+ matchContext = addCombinator( function( elem ) {
2662
+ return elem === checkContext;
2663
+ }, implicitRelative, true ),
2664
+ matchAnyContext = addCombinator( function( elem ) {
2665
+ return indexOf.call( checkContext, elem ) > -1;
2666
+ }, implicitRelative, true ),
2667
+ matchers = [ function( elem, context, xml ) {
2668
+ return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
2669
+ (checkContext = context).nodeType ?
2670
+ matchContext( elem, context, xml ) :
2671
+ matchAnyContext( elem, context, xml ) );
2672
+ } ];
2673
+
2674
+ for ( ; i < len; i++ ) {
2675
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
2676
+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
2677
+ } else {
2678
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
2679
+
2680
+ // Return special upon seeing a positional matcher
2681
+ if ( matcher[ expando ] ) {
2682
+ // Find the next relative operator (if any) for proper handling
2683
+ j = ++i;
2684
+ for ( ; j < len; j++ ) {
2685
+ if ( Expr.relative[ tokens[j].type ] ) {
2686
+ break;
2687
+ }
2688
+ }
2689
+ return setMatcher(
2690
+ i > 1 && elementMatcher( matchers ),
2691
+ i > 1 && toSelector(
2692
+ // If the preceding token was a descendant combinator, insert an implicit any-element `*`
2693
+ tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
2694
+ ).replace( rtrim, "$1" ),
2695
+ matcher,
2696
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
2697
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
2698
+ j < len && toSelector( tokens )
2699
+ );
2700
+ }
2701
+ matchers.push( matcher );
2702
+ }
2703
+ }
2704
+
2705
+ return elementMatcher( matchers );
2706
+ }
2707
+
2708
+ function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
2709
+ // A counter to specify which element is currently being matched
2710
+ var matcherCachedRuns = 0,
2711
+ bySet = setMatchers.length > 0,
2712
+ byElement = elementMatchers.length > 0,
2713
+ superMatcher = function( seed, context, xml, results, expandContext ) {
2714
+ var elem, j, matcher,
2715
+ setMatched = [],
2716
+ matchedCount = 0,
2717
+ i = "0",
2718
+ unmatched = seed && [],
2719
+ outermost = expandContext != null,
2720
+ contextBackup = outermostContext,
2721
+ // We must always have either seed elements or context
2722
+ elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
2723
+ // Use integer dirruns iff this is the outermost matcher
2724
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);
2725
+
2726
+ if ( outermost ) {
2727
+ outermostContext = context !== document && context;
2728
+ cachedruns = matcherCachedRuns;
2729
+ }
2730
+
2731
+ // Add elements passing elementMatchers directly to results
2732
+ // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
2733
+ for ( ; (elem = elems[i]) != null; i++ ) {
2734
+ if ( byElement && elem ) {
2735
+ j = 0;
2736
+ while ( (matcher = elementMatchers[j++]) ) {
2737
+ if ( matcher( elem, context, xml ) ) {
2738
+ results.push( elem );
2739
+ break;
2740
+ }
2741
+ }
2742
+ if ( outermost ) {
2743
+ dirruns = dirrunsUnique;
2744
+ cachedruns = ++matcherCachedRuns;
2745
+ }
2746
+ }
2747
+
2748
+ // Track unmatched elements for set filters
2749
+ if ( bySet ) {
2750
+ // They will have gone through all possible matchers
2751
+ if ( (elem = !matcher && elem) ) {
2752
+ matchedCount--;
2753
+ }
2754
+
2755
+ // Lengthen the array for every element, matched or not
2756
+ if ( seed ) {
2757
+ unmatched.push( elem );
2758
+ }
2759
+ }
2760
+ }
2761
+
2762
+ // Apply set filters to unmatched elements
2763
+ matchedCount += i;
2764
+ if ( bySet && i !== matchedCount ) {
2765
+ j = 0;
2766
+ while ( (matcher = setMatchers[j++]) ) {
2767
+ matcher( unmatched, setMatched, context, xml );
2768
+ }
2769
+
2770
+ if ( seed ) {
2771
+ // Reintegrate element matches to eliminate the need for sorting
2772
+ if ( matchedCount > 0 ) {
2773
+ while ( i-- ) {
2774
+ if ( !(unmatched[i] || setMatched[i]) ) {
2775
+ setMatched[i] = pop.call( results );
2776
+ }
2777
+ }
2778
+ }
2779
+
2780
+ // Discard index placeholder values to get only actual matches
2781
+ setMatched = condense( setMatched );
2782
+ }
2783
+
2784
+ // Add matches to results
2785
+ push.apply( results, setMatched );
2786
+
2787
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
2788
+ if ( outermost && !seed && setMatched.length > 0 &&
2789
+ ( matchedCount + setMatchers.length ) > 1 ) {
2790
+
2791
+ Sizzle.uniqueSort( results );
2792
+ }
2793
+ }
2794
+
2795
+ // Override manipulation of globals by nested matchers
2796
+ if ( outermost ) {
2797
+ dirruns = dirrunsUnique;
2798
+ outermostContext = contextBackup;
2799
+ }
2800
+
2801
+ return unmatched;
2802
+ };
2803
+
2804
+ return bySet ?
2805
+ markFunction( superMatcher ) :
2806
+ superMatcher;
2807
+ }
2808
+
2809
+ compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
2810
+ var i,
2811
+ setMatchers = [],
2812
+ elementMatchers = [],
2813
+ cached = compilerCache[ selector + " " ];
2814
+
2815
+ if ( !cached ) {
2816
+ // Generate a function of recursive functions that can be used to check each element
2817
+ if ( !group ) {
2818
+ group = tokenize( selector );
2819
+ }
2820
+ i = group.length;
2821
+ while ( i-- ) {
2822
+ cached = matcherFromTokens( group[i] );
2823
+ if ( cached[ expando ] ) {
2824
+ setMatchers.push( cached );
2825
+ } else {
2826
+ elementMatchers.push( cached );
2827
+ }
2828
+ }
2829
+
2830
+ // Cache the compiled function
2831
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
2832
+ }
2833
+ return cached;
2834
+ };
2835
+
2836
+ function multipleContexts( selector, contexts, results ) {
2837
+ var i = 0,
2838
+ len = contexts.length;
2839
+ for ( ; i < len; i++ ) {
2840
+ Sizzle( selector, contexts[i], results );
2841
+ }
2842
+ return results;
2843
+ }
2844
+
2845
+ function select( selector, context, results, seed ) {
2846
+ var i, tokens, token, type, find,
2847
+ match = tokenize( selector );
2848
+
2849
+ if ( !seed ) {
2850
+ // Try to minimize operations if there is only one group
2851
+ if ( match.length === 1 ) {
2852
+
2853
+ // Take a shortcut and set the context if the root selector is an ID
2854
+ tokens = match[0] = match[0].slice( 0 );
2855
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
2856
+ support.getById && context.nodeType === 9 && documentIsHTML &&
2857
+ Expr.relative[ tokens[1].type ] ) {
2858
+
2859
+ context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
2860
+ if ( !context ) {
2861
+ return results;
2862
+ }
2863
+ selector = selector.slice( tokens.shift().value.length );
2864
+ }
2865
+
2866
+ // Fetch a seed set for right-to-left matching
2867
+ i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
2868
+ while ( i-- ) {
2869
+ token = tokens[i];
2870
+
2871
+ // Abort if we hit a combinator
2872
+ if ( Expr.relative[ (type = token.type) ] ) {
2873
+ break;
2874
+ }
2875
+ if ( (find = Expr.find[ type ]) ) {
2876
+ // Search, expanding context for leading sibling combinators
2877
+ if ( (seed = find(
2878
+ token.matches[0].replace( runescape, funescape ),
2879
+ rsibling.test( tokens[0].type ) && context.parentNode || context
2880
+ )) ) {
2881
+
2882
+ // If seed is empty or no tokens remain, we can return early
2883
+ tokens.splice( i, 1 );
2884
+ selector = seed.length && toSelector( tokens );
2885
+ if ( !selector ) {
2886
+ push.apply( results, seed );
2887
+ return results;
2888
+ }
2889
+
2890
+ break;
2891
+ }
2892
+ }
2893
+ }
2894
+ }
2895
+ }
2896
+
2897
+ // Compile and execute a filtering function
2898
+ // Provide `match` to avoid retokenization if we modified the selector above
2899
+ compile( selector, match )(
2900
+ seed,
2901
+ context,
2902
+ !documentIsHTML,
2903
+ results,
2904
+ rsibling.test( selector )
2905
+ );
2906
+ return results;
2907
+ }
2908
+
2909
+ // One-time assignments
2910
+
2911
+ // Sort stability
2912
+ support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
2913
+
2914
+ // Support: Chrome<14
2915
+ // Always assume duplicates if they aren't passed to the comparison function
2916
+ support.detectDuplicates = hasDuplicate;
2917
+
2918
+ // Initialize against the default document
2919
+ setDocument();
2920
+
2921
+ // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
2922
+ // Detached nodes confoundingly follow *each other*
2923
+ support.sortDetached = assert(function( div1 ) {
2924
+ // Should return 1, but returns 4 (following)
2925
+ return div1.compareDocumentPosition( document.createElement("div") ) & 1;
2926
+ });
2927
+
2928
+ // Support: IE<8
2929
+ // Prevent attribute/property "interpolation"
2930
+ // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2931
+ if ( !assert(function( div ) {
2932
+ div.innerHTML = "<a href='#'></a>";
2933
+ return div.firstChild.getAttribute("href") === "#" ;
2934
+ }) ) {
2935
+ addHandle( "type|href|height|width", function( elem, name, isXML ) {
2936
+ if ( !isXML ) {
2937
+ return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
2938
+ }
2939
+ });
2940
+ }
2941
+
2942
+ // Support: IE<9
2943
+ // Use defaultValue in place of getAttribute("value")
2944
+ if ( !support.attributes || !assert(function( div ) {
2945
+ div.innerHTML = "<input/>";
2946
+ div.firstChild.setAttribute( "value", "" );
2947
+ return div.firstChild.getAttribute( "value" ) === "";
2948
+ }) ) {
2949
+ addHandle( "value", function( elem, name, isXML ) {
2950
+ if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
2951
+ return elem.defaultValue;
2952
+ }
2953
+ });
2954
+ }
2955
+
2956
+ // Support: IE<9
2957
+ // Use getAttributeNode to fetch booleans when getAttribute lies
2958
+ if ( !assert(function( div ) {
2959
+ return div.getAttribute("disabled") == null;
2960
+ }) ) {
2961
+ addHandle( booleans, function( elem, name, isXML ) {
2962
+ var val;
2963
+ if ( !isXML ) {
2964
+ return (val = elem.getAttributeNode( name )) && val.specified ?
2965
+ val.value :
2966
+ elem[ name ] === true ? name.toLowerCase() : null;
2967
+ }
2968
+ });
2969
+ }
2970
+
2971
+ jQuery.find = Sizzle;
2972
+ jQuery.expr = Sizzle.selectors;
2973
+ jQuery.expr[":"] = jQuery.expr.pseudos;
2974
+ jQuery.unique = Sizzle.uniqueSort;
2975
+ jQuery.text = Sizzle.getText;
2976
+ jQuery.isXMLDoc = Sizzle.isXML;
2977
+ jQuery.contains = Sizzle.contains;
2978
+
2979
+
2980
+ })( window );
2981
+ // String to Object options format cache
2982
+ var optionsCache = {};
2983
+
2984
+ // Convert String-formatted options into Object-formatted ones and store in cache
2985
+ function createOptions( options ) {
2986
+ var object = optionsCache[ options ] = {};
2987
+ jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
2988
+ object[ flag ] = true;
2989
+ });
2990
+ return object;
2991
+ }
2992
+
2993
+ /*
2994
+ * Create a callback list using the following parameters:
2995
+ *
2996
+ * options: an optional list of space-separated options that will change how
2997
+ * the callback list behaves or a more traditional option object
2998
+ *
2999
+ * By default a callback list will act like an event callback list and can be
3000
+ * "fired" multiple times.
3001
+ *
3002
+ * Possible options:
3003
+ *
3004
+ * once: will ensure the callback list can only be fired once (like a Deferred)
3005
+ *
3006
+ * memory: will keep track of previous values and will call any callback added
3007
+ * after the list has been fired right away with the latest "memorized"
3008
+ * values (like a Deferred)
3009
+ *
3010
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
3011
+ *
3012
+ * stopOnFalse: interrupt callings when a callback returns false
3013
+ *
3014
+ */
3015
+ jQuery.Callbacks = function( options ) {
3016
+
3017
+ // Convert options from String-formatted to Object-formatted if needed
3018
+ // (we check in cache first)
3019
+ options = typeof options === "string" ?
3020
+ ( optionsCache[ options ] || createOptions( options ) ) :
3021
+ jQuery.extend( {}, options );
3022
+
3023
+ var // Flag to know if list is currently firing
3024
+ firing,
3025
+ // Last fire value (for non-forgettable lists)
3026
+ memory,
3027
+ // Flag to know if list was already fired
3028
+ fired,
3029
+ // End of the loop when firing
3030
+ firingLength,
3031
+ // Index of currently firing callback (modified by remove if needed)
3032
+ firingIndex,
3033
+ // First callback to fire (used internally by add and fireWith)
3034
+ firingStart,
3035
+ // Actual callback list
3036
+ list = [],
3037
+ // Stack of fire calls for repeatable lists
3038
+ stack = !options.once && [],
3039
+ // Fire callbacks
3040
+ fire = function( data ) {
3041
+ memory = options.memory && data;
3042
+ fired = true;
3043
+ firingIndex = firingStart || 0;
3044
+ firingStart = 0;
3045
+ firingLength = list.length;
3046
+ firing = true;
3047
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
3048
+ if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
3049
+ memory = false; // To prevent further calls using add
3050
+ break;
3051
+ }
3052
+ }
3053
+ firing = false;
3054
+ if ( list ) {
3055
+ if ( stack ) {
3056
+ if ( stack.length ) {
3057
+ fire( stack.shift() );
3058
+ }
3059
+ } else if ( memory ) {
3060
+ list = [];
3061
+ } else {
3062
+ self.disable();
3063
+ }
3064
+ }
3065
+ },
3066
+ // Actual Callbacks object
3067
+ self = {
3068
+ // Add a callback or a collection of callbacks to the list
3069
+ add: function() {
3070
+ if ( list ) {
3071
+ // First, we save the current length
3072
+ var start = list.length;
3073
+ (function add( args ) {
3074
+ jQuery.each( args, function( _, arg ) {
3075
+ var type = jQuery.type( arg );
3076
+ if ( type === "function" ) {
3077
+ if ( !options.unique || !self.has( arg ) ) {
3078
+ list.push( arg );
3079
+ }
3080
+ } else if ( arg && arg.length && type !== "string" ) {
3081
+ // Inspect recursively
3082
+ add( arg );
3083
+ }
3084
+ });
3085
+ })( arguments );
3086
+ // Do we need to add the callbacks to the
3087
+ // current firing batch?
3088
+ if ( firing ) {
3089
+ firingLength = list.length;
3090
+ // With memory, if we're not firing then
3091
+ // we should call right away
3092
+ } else if ( memory ) {
3093
+ firingStart = start;
3094
+ fire( memory );
3095
+ }
3096
+ }
3097
+ return this;
3098
+ },
3099
+ // Remove a callback from the list
3100
+ remove: function() {
3101
+ if ( list ) {
3102
+ jQuery.each( arguments, function( _, arg ) {
3103
+ var index;
3104
+ while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
3105
+ list.splice( index, 1 );
3106
+ // Handle firing indexes
3107
+ if ( firing ) {
3108
+ if ( index <= firingLength ) {
3109
+ firingLength--;
3110
+ }
3111
+ if ( index <= firingIndex ) {
3112
+ firingIndex--;
3113
+ }
3114
+ }
3115
+ }
3116
+ });
3117
+ }
3118
+ return this;
3119
+ },
3120
+ // Check if a given callback is in the list.
3121
+ // If no argument is given, return whether or not list has callbacks attached.
3122
+ has: function( fn ) {
3123
+ return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
3124
+ },
3125
+ // Remove all callbacks from the list
3126
+ empty: function() {
3127
+ list = [];
3128
+ firingLength = 0;
3129
+ return this;
3130
+ },
3131
+ // Have the list do nothing anymore
3132
+ disable: function() {
3133
+ list = stack = memory = undefined;
3134
+ return this;
3135
+ },
3136
+ // Is it disabled?
3137
+ disabled: function() {
3138
+ return !list;
3139
+ },
3140
+ // Lock the list in its current state
3141
+ lock: function() {
3142
+ stack = undefined;
3143
+ if ( !memory ) {
3144
+ self.disable();
3145
+ }
3146
+ return this;
3147
+ },
3148
+ // Is it locked?
3149
+ locked: function() {
3150
+ return !stack;
3151
+ },
3152
+ // Call all callbacks with the given context and arguments
3153
+ fireWith: function( context, args ) {
3154
+ if ( list && ( !fired || stack ) ) {
3155
+ args = args || [];
3156
+ args = [ context, args.slice ? args.slice() : args ];
3157
+ if ( firing ) {
3158
+ stack.push( args );
3159
+ } else {
3160
+ fire( args );
3161
+ }
3162
+ }
3163
+ return this;
3164
+ },
3165
+ // Call all the callbacks with the given arguments
3166
+ fire: function() {
3167
+ self.fireWith( this, arguments );
3168
+ return this;
3169
+ },
3170
+ // To know if the callbacks have already been called at least once
3171
+ fired: function() {
3172
+ return !!fired;
3173
+ }
3174
+ };
3175
+
3176
+ return self;
3177
+ };
3178
+ jQuery.extend({
3179
+
3180
+ Deferred: function( func ) {
3181
+ var tuples = [
3182
+ // action, add listener, listener list, final state
3183
+ [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
3184
+ [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
3185
+ [ "notify", "progress", jQuery.Callbacks("memory") ]
3186
+ ],
3187
+ state = "pending",
3188
+ promise = {
3189
+ state: function() {
3190
+ return state;
3191
+ },
3192
+ always: function() {
3193
+ deferred.done( arguments ).fail( arguments );
3194
+ return this;
3195
+ },
3196
+ then: function( /* fnDone, fnFail, fnProgress */ ) {
3197
+ var fns = arguments;
3198
+ return jQuery.Deferred(function( newDefer ) {
3199
+ jQuery.each( tuples, function( i, tuple ) {
3200
+ var action = tuple[ 0 ],
3201
+ fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
3202
+ // deferred[ done | fail | progress ] for forwarding actions to newDefer
3203
+ deferred[ tuple[1] ](function() {
3204
+ var returned = fn && fn.apply( this, arguments );
3205
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
3206
+ returned.promise()
3207
+ .done( newDefer.resolve )
3208
+ .fail( newDefer.reject )
3209
+ .progress( newDefer.notify );
3210
+ } else {
3211
+ newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
3212
+ }
3213
+ });
3214
+ });
3215
+ fns = null;
3216
+ }).promise();
3217
+ },
3218
+ // Get a promise for this deferred
3219
+ // If obj is provided, the promise aspect is added to the object
3220
+ promise: function( obj ) {
3221
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
3222
+ }
3223
+ },
3224
+ deferred = {};
3225
+
3226
+ // Keep pipe for back-compat
3227
+ promise.pipe = promise.then;
3228
+
3229
+ // Add list-specific methods
3230
+ jQuery.each( tuples, function( i, tuple ) {
3231
+ var list = tuple[ 2 ],
3232
+ stateString = tuple[ 3 ];
3233
+
3234
+ // promise[ done | fail | progress ] = list.add
3235
+ promise[ tuple[1] ] = list.add;
3236
+
3237
+ // Handle state
3238
+ if ( stateString ) {
3239
+ list.add(function() {
3240
+ // state = [ resolved | rejected ]
3241
+ state = stateString;
3242
+
3243
+ // [ reject_list | resolve_list ].disable; progress_list.lock
3244
+ }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
3245
+ }
3246
+
3247
+ // deferred[ resolve | reject | notify ]
3248
+ deferred[ tuple[0] ] = function() {
3249
+ deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
3250
+ return this;
3251
+ };
3252
+ deferred[ tuple[0] + "With" ] = list.fireWith;
3253
+ });
3254
+
3255
+ // Make the deferred a promise
3256
+ promise.promise( deferred );
3257
+
3258
+ // Call given func if any
3259
+ if ( func ) {
3260
+ func.call( deferred, deferred );
3261
+ }
3262
+
3263
+ // All done!
3264
+ return deferred;
3265
+ },
3266
+
3267
+ // Deferred helper
3268
+ when: function( subordinate /* , ..., subordinateN */ ) {
3269
+ var i = 0,
3270
+ resolveValues = core_slice.call( arguments ),
3271
+ length = resolveValues.length,
3272
+
3273
+ // the count of uncompleted subordinates
3274
+ remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
3275
+
3276
+ // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
3277
+ deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
3278
+
3279
+ // Update function for both resolve and progress values
3280
+ updateFunc = function( i, contexts, values ) {
3281
+ return function( value ) {
3282
+ contexts[ i ] = this;
3283
+ values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
3284
+ if( values === progressValues ) {
3285
+ deferred.notifyWith( contexts, values );
3286
+ } else if ( !( --remaining ) ) {
3287
+ deferred.resolveWith( contexts, values );
3288
+ }
3289
+ };
3290
+ },
3291
+
3292
+ progressValues, progressContexts, resolveContexts;
3293
+
3294
+ // add listeners to Deferred subordinates; treat others as resolved
3295
+ if ( length > 1 ) {
3296
+ progressValues = new Array( length );
3297
+ progressContexts = new Array( length );
3298
+ resolveContexts = new Array( length );
3299
+ for ( ; i < length; i++ ) {
3300
+ if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
3301
+ resolveValues[ i ].promise()
3302
+ .done( updateFunc( i, resolveContexts, resolveValues ) )
3303
+ .fail( deferred.reject )
3304
+ .progress( updateFunc( i, progressContexts, progressValues ) );
3305
+ } else {
3306
+ --remaining;
3307
+ }
3308
+ }
3309
+ }
3310
+
3311
+ // if we're not waiting on anything, resolve the master
3312
+ if ( !remaining ) {
3313
+ deferred.resolveWith( resolveContexts, resolveValues );
3314
+ }
3315
+
3316
+ return deferred.promise();
3317
+ }
3318
+ });
3319
+ jQuery.support = (function( support ) {
3320
+
3321
+ var all, a, input, select, fragment, opt, eventName, isSupported, i,
3322
+ div = document.createElement("div");
3323
+
3324
+ // Setup
3325
+ div.setAttribute( "className", "t" );
3326
+ div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
3327
+
3328
+ // Finish early in limited (non-browser) environments
3329
+ all = div.getElementsByTagName("*") || [];
3330
+ a = div.getElementsByTagName("a")[ 0 ];
3331
+ if ( !a || !a.style || !all.length ) {
3332
+ return support;
3333
+ }
3334
+
3335
+ // First batch of tests
3336
+ select = document.createElement("select");
3337
+ opt = select.appendChild( document.createElement("option") );
3338
+ input = div.getElementsByTagName("input")[ 0 ];
3339
+
3340
+ a.style.cssText = "top:1px;float:left;opacity:.5";
3341
+
3342
+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
3343
+ support.getSetAttribute = div.className !== "t";
3344
+
3345
+ // IE strips leading whitespace when .innerHTML is used
3346
+ support.leadingWhitespace = div.firstChild.nodeType === 3;
3347
+
3348
+ // Make sure that tbody elements aren't automatically inserted
3349
+ // IE will insert them into empty tables
3350
+ support.tbody = !div.getElementsByTagName("tbody").length;
3351
+
3352
+ // Make sure that link elements get serialized correctly by innerHTML
3353
+ // This requires a wrapper element in IE
3354
+ support.htmlSerialize = !!div.getElementsByTagName("link").length;
3355
+
3356
+ // Get the style information from getAttribute
3357
+ // (IE uses .cssText instead)
3358
+ support.style = /top/.test( a.getAttribute("style") );
3359
+
3360
+ // Make sure that URLs aren't manipulated
3361
+ // (IE normalizes it by default)
3362
+ support.hrefNormalized = a.getAttribute("href") === "/a";
3363
+
3364
+ // Make sure that element opacity exists
3365
+ // (IE uses filter instead)
3366
+ // Use a regex to work around a WebKit issue. See #5145
3367
+ support.opacity = /^0.5/.test( a.style.opacity );
3368
+
3369
+ // Verify style float existence
3370
+ // (IE uses styleFloat instead of cssFloat)
3371
+ support.cssFloat = !!a.style.cssFloat;
3372
+
3373
+ // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
3374
+ support.checkOn = !!input.value;
3375
+
3376
+ // Make sure that a selected-by-default option has a working selected property.
3377
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
3378
+ support.optSelected = opt.selected;
3379
+
3380
+ // Tests for enctype support on a form (#6743)
3381
+ support.enctype = !!document.createElement("form").enctype;
3382
+
3383
+ // Makes sure cloning an html5 element does not cause problems
3384
+ // Where outerHTML is undefined, this still works
3385
+ support.html5Clone = document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>";
3386
+
3387
+ // Will be defined later
3388
+ support.inlineBlockNeedsLayout = false;
3389
+ support.shrinkWrapBlocks = false;
3390
+ support.pixelPosition = false;
3391
+ support.deleteExpando = true;
3392
+ support.noCloneEvent = true;
3393
+ support.reliableMarginRight = true;
3394
+ support.boxSizingReliable = true;
3395
+
3396
+ // Make sure checked status is properly cloned
3397
+ input.checked = true;
3398
+ support.noCloneChecked = input.cloneNode( true ).checked;
3399
+
3400
+ // Make sure that the options inside disabled selects aren't marked as disabled
3401
+ // (WebKit marks them as disabled)
3402
+ select.disabled = true;
3403
+ support.optDisabled = !opt.disabled;
3404
+
3405
+ // Support: IE<9
3406
+ try {
3407
+ delete div.test;
3408
+ } catch( e ) {
3409
+ support.deleteExpando = false;
3410
+ }
3411
+
3412
+ // Check if we can trust getAttribute("value")
3413
+ input = document.createElement("input");
3414
+ input.setAttribute( "value", "" );
3415
+ support.input = input.getAttribute( "value" ) === "";
3416
+
3417
+ // Check if an input maintains its value after becoming a radio
3418
+ input.value = "t";
3419
+ input.setAttribute( "type", "radio" );
3420
+ support.radioValue = input.value === "t";
3421
+
3422
+ // #11217 - WebKit loses check when the name is after the checked attribute
3423
+ input.setAttribute( "checked", "t" );
3424
+ input.setAttribute( "name", "t" );
3425
+
3426
+ fragment = document.createDocumentFragment();
3427
+ fragment.appendChild( input );
3428
+
3429
+ // Check if a disconnected checkbox will retain its checked
3430
+ // value of true after appended to the DOM (IE6/7)
3431
+ support.appendChecked = input.checked;
3432
+
3433
+ // WebKit doesn't clone checked state correctly in fragments
3434
+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
3435
+
3436
+ // Support: IE<9
3437
+ // Opera does not clone events (and typeof div.attachEvent === undefined).
3438
+ // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
3439
+ if ( div.attachEvent ) {
3440
+ div.attachEvent( "onclick", function() {
3441
+ support.noCloneEvent = false;
3442
+ });
3443
+
3444
+ div.cloneNode( true ).click();
3445
+ }
3446
+
3447
+ // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)
3448
+ // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
3449
+ for ( i in { submit: true, change: true, focusin: true }) {
3450
+ div.setAttribute( eventName = "on" + i, "t" );
3451
+
3452
+ support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false;
3453
+ }
3454
+
3455
+ div.style.backgroundClip = "content-box";
3456
+ div.cloneNode( true ).style.backgroundClip = "";
3457
+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
3458
+
3459
+ // Support: IE<9
3460
+ // Iteration over object's inherited properties before its own.
3461
+ for ( i in jQuery( support ) ) {
3462
+ break;
3463
+ }
3464
+ support.ownLast = i !== "0";
3465
+
3466
+ // Run tests that need a body at doc ready
3467
+ jQuery(function() {
3468
+ var container, marginDiv, tds,
3469
+ divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
3470
+ body = document.getElementsByTagName("body")[0];
3471
+
3472
+ if ( !body ) {
3473
+ // Return for frameset docs that don't have a body
3474
+ return;
3475
+ }
3476
+
3477
+ container = document.createElement("div");
3478
+ container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
3479
+
3480
+ body.appendChild( container ).appendChild( div );
3481
+
3482
+ // Support: IE8
3483
+ // Check if table cells still have offsetWidth/Height when they are set
3484
+ // to display:none and there are still other visible table cells in a
3485
+ // table row; if so, offsetWidth/Height are not reliable for use when
3486
+ // determining if an element has been hidden directly using
3487
+ // display:none (it is still safe to use offsets if a parent element is
3488
+ // hidden; don safety goggles and see bug #4512 for more information).
3489
+ div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
3490
+ tds = div.getElementsByTagName("td");
3491
+ tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
3492
+ isSupported = ( tds[ 0 ].offsetHeight === 0 );
3493
+
3494
+ tds[ 0 ].style.display = "";
3495
+ tds[ 1 ].style.display = "none";
3496
+
3497
+ // Support: IE8
3498
+ // Check if empty table cells still have offsetWidth/Height
3499
+ support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
3500
+
3501
+ // Check box-sizing and margin behavior.
3502
+ div.innerHTML = "";
3503
+ div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
3504
+
3505
+ // Workaround failing boxSizing test due to offsetWidth returning wrong value
3506
+ // with some non-1 values of body zoom, ticket #13543
3507
+ jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() {
3508
+ support.boxSizing = div.offsetWidth === 4;
3509
+ });
3510
+
3511
+ // Use window.getComputedStyle because jsdom on node.js will break without it.
3512
+ if ( window.getComputedStyle ) {
3513
+ support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
3514
+ support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
3515
+
3516
+ // Check if div with explicit width and no margin-right incorrectly
3517
+ // gets computed margin-right based on width of container. (#3333)
3518
+ // Fails in WebKit before Feb 2011 nightlies
3519
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
3520
+ marginDiv = div.appendChild( document.createElement("div") );
3521
+ marginDiv.style.cssText = div.style.cssText = divReset;
3522
+ marginDiv.style.marginRight = marginDiv.style.width = "0";
3523
+ div.style.width = "1px";
3524
+
3525
+ support.reliableMarginRight =
3526
+ !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
3527
+ }
3528
+
3529
+ if ( typeof div.style.zoom !== core_strundefined ) {
3530
+ // Support: IE<8
3531
+ // Check if natively block-level elements act like inline-block
3532
+ // elements when setting their display to 'inline' and giving
3533
+ // them layout
3534
+ div.innerHTML = "";
3535
+ div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
3536
+ support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
3537
+
3538
+ // Support: IE6
3539
+ // Check if elements with layout shrink-wrap their children
3540
+ div.style.display = "block";
3541
+ div.innerHTML = "<div></div>";
3542
+ div.firstChild.style.width = "5px";
3543
+ support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
3544
+
3545
+ if ( support.inlineBlockNeedsLayout ) {
3546
+ // Prevent IE 6 from affecting layout for positioned elements #11048
3547
+ // Prevent IE from shrinking the body in IE 7 mode #12869
3548
+ // Support: IE<8
3549
+ body.style.zoom = 1;
3550
+ }
3551
+ }
3552
+
3553
+ body.removeChild( container );
3554
+
3555
+ // Null elements to avoid leaks in IE
3556
+ container = div = tds = marginDiv = null;
3557
+ });
3558
+
3559
+ // Null elements to avoid leaks in IE
3560
+ all = select = fragment = opt = a = input = null;
3561
+
3562
+ return support;
3563
+ })({});
3564
+
3565
+ var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
3566
+ rmultiDash = /([A-Z])/g;
3567
+
3568
+ function internalData( elem, name, data, pvt /* Internal Use Only */ ){
3569
+ if ( !jQuery.acceptData( elem ) ) {
3570
+ return;
3571
+ }
3572
+
3573
+ var ret, thisCache,
3574
+ internalKey = jQuery.expando,
3575
+
3576
+ // We have to handle DOM nodes and JS objects differently because IE6-7
3577
+ // can't GC object references properly across the DOM-JS boundary
3578
+ isNode = elem.nodeType,
3579
+
3580
+ // Only DOM nodes need the global jQuery cache; JS object data is
3581
+ // attached directly to the object so GC can occur automatically
3582
+ cache = isNode ? jQuery.cache : elem,
3583
+
3584
+ // Only defining an ID for JS objects if its cache already exists allows
3585
+ // the code to shortcut on the same path as a DOM node with no cache
3586
+ id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
3587
+
3588
+ // Avoid doing any more work than we need to when trying to get data on an
3589
+ // object that has no data at all
3590
+ if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
3591
+ return;
3592
+ }
3593
+
3594
+ if ( !id ) {
3595
+ // Only DOM nodes need a new unique ID for each element since their data
3596
+ // ends up in the global cache
3597
+ if ( isNode ) {
3598
+ id = elem[ internalKey ] = core_deletedIds.pop() || jQuery.guid++;
3599
+ } else {
3600
+ id = internalKey;
3601
+ }
3602
+ }
3603
+
3604
+ if ( !cache[ id ] ) {
3605
+ // Avoid exposing jQuery metadata on plain JS objects when the object
3606
+ // is serialized using JSON.stringify
3607
+ cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
3608
+ }
3609
+
3610
+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
3611
+ // shallow copied over onto the existing cache
3612
+ if ( typeof name === "object" || typeof name === "function" ) {
3613
+ if ( pvt ) {
3614
+ cache[ id ] = jQuery.extend( cache[ id ], name );
3615
+ } else {
3616
+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
3617
+ }
3618
+ }
3619
+
3620
+ thisCache = cache[ id ];
3621
+
3622
+ // jQuery data() is stored in a separate object inside the object's internal data
3623
+ // cache in order to avoid key collisions between internal data and user-defined
3624
+ // data.
3625
+ if ( !pvt ) {
3626
+ if ( !thisCache.data ) {
3627
+ thisCache.data = {};
3628
+ }
3629
+
3630
+ thisCache = thisCache.data;
3631
+ }
3632
+
3633
+ if ( data !== undefined ) {
3634
+ thisCache[ jQuery.camelCase( name ) ] = data;
3635
+ }
3636
+
3637
+ // Check for both converted-to-camel and non-converted data property names
3638
+ // If a data property was specified
3639
+ if ( typeof name === "string" ) {
3640
+
3641
+ // First Try to find as-is property data
3642
+ ret = thisCache[ name ];
3643
+
3644
+ // Test for null|undefined property data
3645
+ if ( ret == null ) {
3646
+
3647
+ // Try to find the camelCased property
3648
+ ret = thisCache[ jQuery.camelCase( name ) ];
3649
+ }
3650
+ } else {
3651
+ ret = thisCache;
3652
+ }
3653
+
3654
+ return ret;
3655
+ }
3656
+
3657
+ function internalRemoveData( elem, name, pvt ) {
3658
+ if ( !jQuery.acceptData( elem ) ) {
3659
+ return;
3660
+ }
3661
+
3662
+ var thisCache, i,
3663
+ isNode = elem.nodeType,
3664
+
3665
+ // See jQuery.data for more information
3666
+ cache = isNode ? jQuery.cache : elem,
3667
+ id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
3668
+
3669
+ // If there is already no cache entry for this object, there is no
3670
+ // purpose in continuing
3671
+ if ( !cache[ id ] ) {
3672
+ return;
3673
+ }
3674
+
3675
+ if ( name ) {
3676
+
3677
+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
3678
+
3679
+ if ( thisCache ) {
3680
+
3681
+ // Support array or space separated string names for data keys
3682
+ if ( !jQuery.isArray( name ) ) {
3683
+
3684
+ // try the string as a key before any manipulation
3685
+ if ( name in thisCache ) {
3686
+ name = [ name ];
3687
+ } else {
3688
+
3689
+ // split the camel cased version by spaces unless a key with the spaces exists
3690
+ name = jQuery.camelCase( name );
3691
+ if ( name in thisCache ) {
3692
+ name = [ name ];
3693
+ } else {
3694
+ name = name.split(" ");
3695
+ }
3696
+ }
3697
+ } else {
3698
+ // If "name" is an array of keys...
3699
+ // When data is initially created, via ("key", "val") signature,
3700
+ // keys will be converted to camelCase.
3701
+ // Since there is no way to tell _how_ a key was added, remove
3702
+ // both plain key and camelCase key. #12786
3703
+ // This will only penalize the array argument path.
3704
+ name = name.concat( jQuery.map( name, jQuery.camelCase ) );
3705
+ }
3706
+
3707
+ i = name.length;
3708
+ while ( i-- ) {
3709
+ delete thisCache[ name[i] ];
3710
+ }
3711
+
3712
+ // If there is no data left in the cache, we want to continue
3713
+ // and let the cache object itself get destroyed
3714
+ if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
3715
+ return;
3716
+ }
3717
+ }
3718
+ }
3719
+
3720
+ // See jQuery.data for more information
3721
+ if ( !pvt ) {
3722
+ delete cache[ id ].data;
3723
+
3724
+ // Don't destroy the parent cache unless the internal data object
3725
+ // had been the only thing left in it
3726
+ if ( !isEmptyDataObject( cache[ id ] ) ) {
3727
+ return;
3728
+ }
3729
+ }
3730
+
3731
+ // Destroy the cache
3732
+ if ( isNode ) {
3733
+ jQuery.cleanData( [ elem ], true );
3734
+
3735
+ // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
3736
+ /* jshint eqeqeq: false */
3737
+ } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
3738
+ /* jshint eqeqeq: true */
3739
+ delete cache[ id ];
3740
+
3741
+ // When all else fails, null
3742
+ } else {
3743
+ cache[ id ] = null;
3744
+ }
3745
+ }
3746
+
3747
+ jQuery.extend({
3748
+ cache: {},
3749
+
3750
+ // The following elements throw uncatchable exceptions if you
3751
+ // attempt to add expando properties to them.
3752
+ noData: {
3753
+ "applet": true,
3754
+ "embed": true,
3755
+ // Ban all objects except for Flash (which handle expandos)
3756
+ "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
3757
+ },
3758
+
3759
+ hasData: function( elem ) {
3760
+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
3761
+ return !!elem && !isEmptyDataObject( elem );
3762
+ },
3763
+
3764
+ data: function( elem, name, data ) {
3765
+ return internalData( elem, name, data );
3766
+ },
3767
+
3768
+ removeData: function( elem, name ) {
3769
+ return internalRemoveData( elem, name );
3770
+ },
3771
+
3772
+ // For internal use only.
3773
+ _data: function( elem, name, data ) {
3774
+ return internalData( elem, name, data, true );
3775
+ },
3776
+
3777
+ _removeData: function( elem, name ) {
3778
+ return internalRemoveData( elem, name, true );
3779
+ },
3780
+
3781
+ // A method for determining if a DOM node can handle the data expando
3782
+ acceptData: function( elem ) {
3783
+ // Do not set data on non-element because it will not be cleared (#8335).
3784
+ if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {
3785
+ return false;
3786
+ }
3787
+
3788
+ var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
3789
+
3790
+ // nodes accept data unless otherwise specified; rejection can be conditional
3791
+ return !noData || noData !== true && elem.getAttribute("classid") === noData;
3792
+ }
3793
+ });
3794
+
3795
+ jQuery.fn.extend({
3796
+ data: function( key, value ) {
3797
+ var attrs, name,
3798
+ data = null,
3799
+ i = 0,
3800
+ elem = this[0];
3801
+
3802
+ // Special expections of .data basically thwart jQuery.access,
3803
+ // so implement the relevant behavior ourselves
3804
+
3805
+ // Gets all values
3806
+ if ( key === undefined ) {
3807
+ if ( this.length ) {
3808
+ data = jQuery.data( elem );
3809
+
3810
+ if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
3811
+ attrs = elem.attributes;
3812
+ for ( ; i < attrs.length; i++ ) {
3813
+ name = attrs[i].name;
3814
+
3815
+ if ( name.indexOf("data-") === 0 ) {
3816
+ name = jQuery.camelCase( name.slice(5) );
3817
+
3818
+ dataAttr( elem, name, data[ name ] );
3819
+ }
3820
+ }
3821
+ jQuery._data( elem, "parsedAttrs", true );
3822
+ }
3823
+ }
3824
+
3825
+ return data;
3826
+ }
3827
+
3828
+ // Sets multiple values
3829
+ if ( typeof key === "object" ) {
3830
+ return this.each(function() {
3831
+ jQuery.data( this, key );
3832
+ });
3833
+ }
3834
+
3835
+ return arguments.length > 1 ?
3836
+
3837
+ // Sets one value
3838
+ this.each(function() {
3839
+ jQuery.data( this, key, value );
3840
+ }) :
3841
+
3842
+ // Gets one value
3843
+ // Try to fetch any internally stored data first
3844
+ elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;
3845
+ },
3846
+
3847
+ removeData: function( key ) {
3848
+ return this.each(function() {
3849
+ jQuery.removeData( this, key );
3850
+ });
3851
+ }
3852
+ });
3853
+
3854
+ function dataAttr( elem, key, data ) {
3855
+ // If nothing was found internally, try to fetch any
3856
+ // data from the HTML5 data-* attribute
3857
+ if ( data === undefined && elem.nodeType === 1 ) {
3858
+
3859
+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
3860
+
3861
+ data = elem.getAttribute( name );
3862
+
3863
+ if ( typeof data === "string" ) {
3864
+ try {
3865
+ data = data === "true" ? true :
3866
+ data === "false" ? false :
3867
+ data === "null" ? null :
3868
+ // Only convert to a number if it doesn't change the string
3869
+ +data + "" === data ? +data :
3870
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
3871
+ data;
3872
+ } catch( e ) {}
3873
+
3874
+ // Make sure we set the data so it isn't changed later
3875
+ jQuery.data( elem, key, data );
3876
+
3877
+ } else {
3878
+ data = undefined;
3879
+ }
3880
+ }
3881
+
3882
+ return data;
3883
+ }
3884
+
3885
+ // checks a cache object for emptiness
3886
+ function isEmptyDataObject( obj ) {
3887
+ var name;
3888
+ for ( name in obj ) {
3889
+
3890
+ // if the public data object is empty, the private is still empty
3891
+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
3892
+ continue;
3893
+ }
3894
+ if ( name !== "toJSON" ) {
3895
+ return false;
3896
+ }
3897
+ }
3898
+
3899
+ return true;
3900
+ }
3901
+ jQuery.extend({
3902
+ queue: function( elem, type, data ) {
3903
+ var queue;
3904
+
3905
+ if ( elem ) {
3906
+ type = ( type || "fx" ) + "queue";
3907
+ queue = jQuery._data( elem, type );
3908
+
3909
+ // Speed up dequeue by getting out quickly if this is just a lookup
3910
+ if ( data ) {
3911
+ if ( !queue || jQuery.isArray(data) ) {
3912
+ queue = jQuery._data( elem, type, jQuery.makeArray(data) );
3913
+ } else {
3914
+ queue.push( data );
3915
+ }
3916
+ }
3917
+ return queue || [];
3918
+ }
3919
+ },
3920
+
3921
+ dequeue: function( elem, type ) {
3922
+ type = type || "fx";
3923
+
3924
+ var queue = jQuery.queue( elem, type ),
3925
+ startLength = queue.length,
3926
+ fn = queue.shift(),
3927
+ hooks = jQuery._queueHooks( elem, type ),
3928
+ next = function() {
3929
+ jQuery.dequeue( elem, type );
3930
+ };
3931
+
3932
+ // If the fx queue is dequeued, always remove the progress sentinel
3933
+ if ( fn === "inprogress" ) {
3934
+ fn = queue.shift();
3935
+ startLength--;
3936
+ }
3937
+
3938
+ if ( fn ) {
3939
+
3940
+ // Add a progress sentinel to prevent the fx queue from being
3941
+ // automatically dequeued
3942
+ if ( type === "fx" ) {
3943
+ queue.unshift( "inprogress" );
3944
+ }
3945
+
3946
+ // clear up the last queue stop function
3947
+ delete hooks.stop;
3948
+ fn.call( elem, next, hooks );
3949
+ }
3950
+
3951
+ if ( !startLength && hooks ) {
3952
+ hooks.empty.fire();
3953
+ }
3954
+ },
3955
+
3956
+ // not intended for public consumption - generates a queueHooks object, or returns the current one
3957
+ _queueHooks: function( elem, type ) {
3958
+ var key = type + "queueHooks";
3959
+ return jQuery._data( elem, key ) || jQuery._data( elem, key, {
3960
+ empty: jQuery.Callbacks("once memory").add(function() {
3961
+ jQuery._removeData( elem, type + "queue" );
3962
+ jQuery._removeData( elem, key );
3963
+ })
3964
+ });
3965
+ }
3966
+ });
3967
+
3968
+ jQuery.fn.extend({
3969
+ queue: function( type, data ) {
3970
+ var setter = 2;
3971
+
3972
+ if ( typeof type !== "string" ) {
3973
+ data = type;
3974
+ type = "fx";
3975
+ setter--;
3976
+ }
3977
+
3978
+ if ( arguments.length < setter ) {
3979
+ return jQuery.queue( this[0], type );
3980
+ }
3981
+
3982
+ return data === undefined ?
3983
+ this :
3984
+ this.each(function() {
3985
+ var queue = jQuery.queue( this, type, data );
3986
+
3987
+ // ensure a hooks for this queue
3988
+ jQuery._queueHooks( this, type );
3989
+
3990
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
3991
+ jQuery.dequeue( this, type );
3992
+ }
3993
+ });
3994
+ },
3995
+ dequeue: function( type ) {
3996
+ return this.each(function() {
3997
+ jQuery.dequeue( this, type );
3998
+ });
3999
+ },
4000
+ // Based off of the plugin by Clint Helfers, with permission.
4001
+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
4002
+ delay: function( time, type ) {
4003
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
4004
+ type = type || "fx";
4005
+
4006
+ return this.queue( type, function( next, hooks ) {
4007
+ var timeout = setTimeout( next, time );
4008
+ hooks.stop = function() {
4009
+ clearTimeout( timeout );
4010
+ };
4011
+ });
4012
+ },
4013
+ clearQueue: function( type ) {
4014
+ return this.queue( type || "fx", [] );
4015
+ },
4016
+ // Get a promise resolved when queues of a certain type
4017
+ // are emptied (fx is the type by default)
4018
+ promise: function( type, obj ) {
4019
+ var tmp,
4020
+ count = 1,
4021
+ defer = jQuery.Deferred(),
4022
+ elements = this,
4023
+ i = this.length,
4024
+ resolve = function() {
4025
+ if ( !( --count ) ) {
4026
+ defer.resolveWith( elements, [ elements ] );
4027
+ }
4028
+ };
4029
+
4030
+ if ( typeof type !== "string" ) {
4031
+ obj = type;
4032
+ type = undefined;
4033
+ }
4034
+ type = type || "fx";
4035
+
4036
+ while( i-- ) {
4037
+ tmp = jQuery._data( elements[ i ], type + "queueHooks" );
4038
+ if ( tmp && tmp.empty ) {
4039
+ count++;
4040
+ tmp.empty.add( resolve );
4041
+ }
4042
+ }
4043
+ resolve();
4044
+ return defer.promise( obj );
4045
+ }
4046
+ });
4047
+ var nodeHook, boolHook,
4048
+ rclass = /[\t\r\n\f]/g,
4049
+ rreturn = /\r/g,
4050
+ rfocusable = /^(?:input|select|textarea|button|object)$/i,
4051
+ rclickable = /^(?:a|area)$/i,
4052
+ ruseDefault = /^(?:checked|selected)$/i,
4053
+ getSetAttribute = jQuery.support.getSetAttribute,
4054
+ getSetInput = jQuery.support.input;
4055
+
4056
+ jQuery.fn.extend({
4057
+ attr: function( name, value ) {
4058
+ return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
4059
+ },
4060
+
4061
+ removeAttr: function( name ) {
4062
+ return this.each(function() {
4063
+ jQuery.removeAttr( this, name );
4064
+ });
4065
+ },
4066
+
4067
+ prop: function( name, value ) {
4068
+ return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
4069
+ },
4070
+
4071
+ removeProp: function( name ) {
4072
+ name = jQuery.propFix[ name ] || name;
4073
+ return this.each(function() {
4074
+ // try/catch handles cases where IE balks (such as removing a property on window)
4075
+ try {
4076
+ this[ name ] = undefined;
4077
+ delete this[ name ];
4078
+ } catch( e ) {}
4079
+ });
4080
+ },
4081
+
4082
+ addClass: function( value ) {
4083
+ var classes, elem, cur, clazz, j,
4084
+ i = 0,
4085
+ len = this.length,
4086
+ proceed = typeof value === "string" && value;
4087
+
4088
+ if ( jQuery.isFunction( value ) ) {
4089
+ return this.each(function( j ) {
4090
+ jQuery( this ).addClass( value.call( this, j, this.className ) );
4091
+ });
4092
+ }
4093
+
4094
+ if ( proceed ) {
4095
+ // The disjunction here is for better compressibility (see removeClass)
4096
+ classes = ( value || "" ).match( core_rnotwhite ) || [];
4097
+
4098
+ for ( ; i < len; i++ ) {
4099
+ elem = this[ i ];
4100
+ cur = elem.nodeType === 1 && ( elem.className ?
4101
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
4102
+ " "
4103
+ );
4104
+
4105
+ if ( cur ) {
4106
+ j = 0;
4107
+ while ( (clazz = classes[j++]) ) {
4108
+ if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
4109
+ cur += clazz + " ";
4110
+ }
4111
+ }
4112
+ elem.className = jQuery.trim( cur );
4113
+
4114
+ }
4115
+ }
4116
+ }
4117
+
4118
+ return this;
4119
+ },
4120
+
4121
+ removeClass: function( value ) {
4122
+ var classes, elem, cur, clazz, j,
4123
+ i = 0,
4124
+ len = this.length,
4125
+ proceed = arguments.length === 0 || typeof value === "string" && value;
4126
+
4127
+ if ( jQuery.isFunction( value ) ) {
4128
+ return this.each(function( j ) {
4129
+ jQuery( this ).removeClass( value.call( this, j, this.className ) );
4130
+ });
4131
+ }
4132
+ if ( proceed ) {
4133
+ classes = ( value || "" ).match( core_rnotwhite ) || [];
4134
+
4135
+ for ( ; i < len; i++ ) {
4136
+ elem = this[ i ];
4137
+ // This expression is here for better compressibility (see addClass)
4138
+ cur = elem.nodeType === 1 && ( elem.className ?
4139
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
4140
+ ""
4141
+ );
4142
+
4143
+ if ( cur ) {
4144
+ j = 0;
4145
+ while ( (clazz = classes[j++]) ) {
4146
+ // Remove *all* instances
4147
+ while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
4148
+ cur = cur.replace( " " + clazz + " ", " " );
4149
+ }
4150
+ }
4151
+ elem.className = value ? jQuery.trim( cur ) : "";
4152
+ }
4153
+ }
4154
+ }
4155
+
4156
+ return this;
4157
+ },
4158
+
4159
+ toggleClass: function( value, stateVal ) {
4160
+ var type = typeof value;
4161
+
4162
+ if ( typeof stateVal === "boolean" && type === "string" ) {
4163
+ return stateVal ? this.addClass( value ) : this.removeClass( value );
4164
+ }
4165
+
4166
+ if ( jQuery.isFunction( value ) ) {
4167
+ return this.each(function( i ) {
4168
+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
4169
+ });
4170
+ }
4171
+
4172
+ return this.each(function() {
4173
+ if ( type === "string" ) {
4174
+ // toggle individual class names
4175
+ var className,
4176
+ i = 0,
4177
+ self = jQuery( this ),
4178
+ classNames = value.match( core_rnotwhite ) || [];
4179
+
4180
+ while ( (className = classNames[ i++ ]) ) {
4181
+ // check each className given, space separated list
4182
+ if ( self.hasClass( className ) ) {
4183
+ self.removeClass( className );
4184
+ } else {
4185
+ self.addClass( className );
4186
+ }
4187
+ }
4188
+
4189
+ // Toggle whole class name
4190
+ } else if ( type === core_strundefined || type === "boolean" ) {
4191
+ if ( this.className ) {
4192
+ // store className if set
4193
+ jQuery._data( this, "__className__", this.className );
4194
+ }
4195
+
4196
+ // If the element has a class name or if we're passed "false",
4197
+ // then remove the whole classname (if there was one, the above saved it).
4198
+ // Otherwise bring back whatever was previously saved (if anything),
4199
+ // falling back to the empty string if nothing was stored.
4200
+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
4201
+ }
4202
+ });
4203
+ },
4204
+
4205
+ hasClass: function( selector ) {
4206
+ var className = " " + selector + " ",
4207
+ i = 0,
4208
+ l = this.length;
4209
+ for ( ; i < l; i++ ) {
4210
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
4211
+ return true;
4212
+ }
4213
+ }
4214
+
4215
+ return false;
4216
+ },
4217
+
4218
+ val: function( value ) {
4219
+ var ret, hooks, isFunction,
4220
+ elem = this[0];
4221
+
4222
+ if ( !arguments.length ) {
4223
+ if ( elem ) {
4224
+ hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
4225
+
4226
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
4227
+ return ret;
4228
+ }
4229
+
4230
+ ret = elem.value;
4231
+
4232
+ return typeof ret === "string" ?
4233
+ // handle most common string cases
4234
+ ret.replace(rreturn, "") :
4235
+ // handle cases where value is null/undef or number
4236
+ ret == null ? "" : ret;
4237
+ }
4238
+
4239
+ return;
4240
+ }
4241
+
4242
+ isFunction = jQuery.isFunction( value );
4243
+
4244
+ return this.each(function( i ) {
4245
+ var val;
4246
+
4247
+ if ( this.nodeType !== 1 ) {
4248
+ return;
4249
+ }
4250
+
4251
+ if ( isFunction ) {
4252
+ val = value.call( this, i, jQuery( this ).val() );
4253
+ } else {
4254
+ val = value;
4255
+ }
4256
+
4257
+ // Treat null/undefined as ""; convert numbers to string
4258
+ if ( val == null ) {
4259
+ val = "";
4260
+ } else if ( typeof val === "number" ) {
4261
+ val += "";
4262
+ } else if ( jQuery.isArray( val ) ) {
4263
+ val = jQuery.map(val, function ( value ) {
4264
+ return value == null ? "" : value + "";
4265
+ });
4266
+ }
4267
+
4268
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
4269
+
4270
+ // If set returns undefined, fall back to normal setting
4271
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
4272
+ this.value = val;
4273
+ }
4274
+ });
4275
+ }
4276
+ });
4277
+
4278
+ jQuery.extend({
4279
+ valHooks: {
4280
+ option: {
4281
+ get: function( elem ) {
4282
+ // Use proper attribute retrieval(#6932, #12072)
4283
+ var val = jQuery.find.attr( elem, "value" );
4284
+ return val != null ?
4285
+ val :
4286
+ elem.text;
4287
+ }
4288
+ },
4289
+ select: {
4290
+ get: function( elem ) {
4291
+ var value, option,
4292
+ options = elem.options,
4293
+ index = elem.selectedIndex,
4294
+ one = elem.type === "select-one" || index < 0,
4295
+ values = one ? null : [],
4296
+ max = one ? index + 1 : options.length,
4297
+ i = index < 0 ?
4298
+ max :
4299
+ one ? index : 0;
4300
+
4301
+ // Loop through all the selected options
4302
+ for ( ; i < max; i++ ) {
4303
+ option = options[ i ];
4304
+
4305
+ // oldIE doesn't update selected after form reset (#2551)
4306
+ if ( ( option.selected || i === index ) &&
4307
+ // Don't return options that are disabled or in a disabled optgroup
4308
+ ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
4309
+ ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
4310
+
4311
+ // Get the specific value for the option
4312
+ value = jQuery( option ).val();
4313
+
4314
+ // We don't need an array for one selects
4315
+ if ( one ) {
4316
+ return value;
4317
+ }
4318
+
4319
+ // Multi-Selects return an array
4320
+ values.push( value );
4321
+ }
4322
+ }
4323
+
4324
+ return values;
4325
+ },
4326
+
4327
+ set: function( elem, value ) {
4328
+ var optionSet, option,
4329
+ options = elem.options,
4330
+ values = jQuery.makeArray( value ),
4331
+ i = options.length;
4332
+
4333
+ while ( i-- ) {
4334
+ option = options[ i ];
4335
+ if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) {
4336
+ optionSet = true;
4337
+ }
4338
+ }
4339
+
4340
+ // force browsers to behave consistently when non-matching value is set
4341
+ if ( !optionSet ) {
4342
+ elem.selectedIndex = -1;
4343
+ }
4344
+ return values;
4345
+ }
4346
+ }
4347
+ },
4348
+
4349
+ attr: function( elem, name, value ) {
4350
+ var hooks, ret,
4351
+ nType = elem.nodeType;
4352
+
4353
+ // don't get/set attributes on text, comment and attribute nodes
4354
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
4355
+ return;
4356
+ }
4357
+
4358
+ // Fallback to prop when attributes are not supported
4359
+ if ( typeof elem.getAttribute === core_strundefined ) {
4360
+ return jQuery.prop( elem, name, value );
4361
+ }
4362
+
4363
+ // All attributes are lowercase
4364
+ // Grab necessary hook if one is defined
4365
+ if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
4366
+ name = name.toLowerCase();
4367
+ hooks = jQuery.attrHooks[ name ] ||
4368
+ ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
4369
+ }
4370
+
4371
+ if ( value !== undefined ) {
4372
+
4373
+ if ( value === null ) {
4374
+ jQuery.removeAttr( elem, name );
4375
+
4376
+ } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
4377
+ return ret;
4378
+
4379
+ } else {
4380
+ elem.setAttribute( name, value + "" );
4381
+ return value;
4382
+ }
4383
+
4384
+ } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
4385
+ return ret;
4386
+
4387
+ } else {
4388
+ ret = jQuery.find.attr( elem, name );
4389
+
4390
+ // Non-existent attributes return null, we normalize to undefined
4391
+ return ret == null ?
4392
+ undefined :
4393
+ ret;
4394
+ }
4395
+ },
4396
+
4397
+ removeAttr: function( elem, value ) {
4398
+ var name, propName,
4399
+ i = 0,
4400
+ attrNames = value && value.match( core_rnotwhite );
4401
+
4402
+ if ( attrNames && elem.nodeType === 1 ) {
4403
+ while ( (name = attrNames[i++]) ) {
4404
+ propName = jQuery.propFix[ name ] || name;
4405
+
4406
+ // Boolean attributes get special treatment (#10870)
4407
+ if ( jQuery.expr.match.bool.test( name ) ) {
4408
+ // Set corresponding property to false
4409
+ if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
4410
+ elem[ propName ] = false;
4411
+ // Support: IE<9
4412
+ // Also clear defaultChecked/defaultSelected (if appropriate)
4413
+ } else {
4414
+ elem[ jQuery.camelCase( "default-" + name ) ] =
4415
+ elem[ propName ] = false;
4416
+ }
4417
+
4418
+ // See #9699 for explanation of this approach (setting first, then removal)
4419
+ } else {
4420
+ jQuery.attr( elem, name, "" );
4421
+ }
4422
+
4423
+ elem.removeAttribute( getSetAttribute ? name : propName );
4424
+ }
4425
+ }
4426
+ },
4427
+
4428
+ attrHooks: {
4429
+ type: {
4430
+ set: function( elem, value ) {
4431
+ if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
4432
+ // Setting the type on a radio button after the value resets the value in IE6-9
4433
+ // Reset value to default in case type is set after value during creation
4434
+ var val = elem.value;
4435
+ elem.setAttribute( "type", value );
4436
+ if ( val ) {
4437
+ elem.value = val;
4438
+ }
4439
+ return value;
4440
+ }
4441
+ }
4442
+ }
4443
+ },
4444
+
4445
+ propFix: {
4446
+ "for": "htmlFor",
4447
+ "class": "className"
4448
+ },
4449
+
4450
+ prop: function( elem, name, value ) {
4451
+ var ret, hooks, notxml,
4452
+ nType = elem.nodeType;
4453
+
4454
+ // don't get/set properties on text, comment and attribute nodes
4455
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
4456
+ return;
4457
+ }
4458
+
4459
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
4460
+
4461
+ if ( notxml ) {
4462
+ // Fix name and attach hooks
4463
+ name = jQuery.propFix[ name ] || name;
4464
+ hooks = jQuery.propHooks[ name ];
4465
+ }
4466
+
4467
+ if ( value !== undefined ) {
4468
+ return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
4469
+ ret :
4470
+ ( elem[ name ] = value );
4471
+
4472
+ } else {
4473
+ return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
4474
+ ret :
4475
+ elem[ name ];
4476
+ }
4477
+ },
4478
+
4479
+ propHooks: {
4480
+ tabIndex: {
4481
+ get: function( elem ) {
4482
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
4483
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
4484
+ // Use proper attribute retrieval(#12072)
4485
+ var tabindex = jQuery.find.attr( elem, "tabindex" );
4486
+
4487
+ return tabindex ?
4488
+ parseInt( tabindex, 10 ) :
4489
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
4490
+ 0 :
4491
+ -1;
4492
+ }
4493
+ }
4494
+ }
4495
+ });
4496
+
4497
+ // Hooks for boolean attributes
4498
+ boolHook = {
4499
+ set: function( elem, value, name ) {
4500
+ if ( value === false ) {
4501
+ // Remove boolean attributes when set to false
4502
+ jQuery.removeAttr( elem, name );
4503
+ } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
4504
+ // IE<8 needs the *property* name
4505
+ elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
4506
+
4507
+ // Use defaultChecked and defaultSelected for oldIE
4508
+ } else {
4509
+ elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
4510
+ }
4511
+
4512
+ return name;
4513
+ }
4514
+ };
4515
+ jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
4516
+ var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr;
4517
+
4518
+ jQuery.expr.attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
4519
+ function( elem, name, isXML ) {
4520
+ var fn = jQuery.expr.attrHandle[ name ],
4521
+ ret = isXML ?
4522
+ undefined :
4523
+ /* jshint eqeqeq: false */
4524
+ (jQuery.expr.attrHandle[ name ] = undefined) !=
4525
+ getter( elem, name, isXML ) ?
4526
+
4527
+ name.toLowerCase() :
4528
+ null;
4529
+ jQuery.expr.attrHandle[ name ] = fn;
4530
+ return ret;
4531
+ } :
4532
+ function( elem, name, isXML ) {
4533
+ return isXML ?
4534
+ undefined :
4535
+ elem[ jQuery.camelCase( "default-" + name ) ] ?
4536
+ name.toLowerCase() :
4537
+ null;
4538
+ };
4539
+ });
4540
+
4541
+ // fix oldIE attroperties
4542
+ if ( !getSetInput || !getSetAttribute ) {
4543
+ jQuery.attrHooks.value = {
4544
+ set: function( elem, value, name ) {
4545
+ if ( jQuery.nodeName( elem, "input" ) ) {
4546
+ // Does not return so that setAttribute is also used
4547
+ elem.defaultValue = value;
4548
+ } else {
4549
+ // Use nodeHook if defined (#1954); otherwise setAttribute is fine
4550
+ return nodeHook && nodeHook.set( elem, value, name );
4551
+ }
4552
+ }
4553
+ };
4554
+ }
4555
+
4556
+ // IE6/7 do not support getting/setting some attributes with get/setAttribute
4557
+ if ( !getSetAttribute ) {
4558
+
4559
+ // Use this for any attribute in IE6/7
4560
+ // This fixes almost every IE6/7 issue
4561
+ nodeHook = {
4562
+ set: function( elem, value, name ) {
4563
+ // Set the existing or create a new attribute node
4564
+ var ret = elem.getAttributeNode( name );
4565
+ if ( !ret ) {
4566
+ elem.setAttributeNode(
4567
+ (ret = elem.ownerDocument.createAttribute( name ))
4568
+ );
4569
+ }
4570
+
4571
+ ret.value = value += "";
4572
+
4573
+ // Break association with cloned elements by also using setAttribute (#9646)
4574
+ return name === "value" || value === elem.getAttribute( name ) ?
4575
+ value :
4576
+ undefined;
4577
+ }
4578
+ };
4579
+ jQuery.expr.attrHandle.id = jQuery.expr.attrHandle.name = jQuery.expr.attrHandle.coords =
4580
+ // Some attributes are constructed with empty-string values when not defined
4581
+ function( elem, name, isXML ) {
4582
+ var ret;
4583
+ return isXML ?
4584
+ undefined :
4585
+ (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
4586
+ ret.value :
4587
+ null;
4588
+ };
4589
+ jQuery.valHooks.button = {
4590
+ get: function( elem, name ) {
4591
+ var ret = elem.getAttributeNode( name );
4592
+ return ret && ret.specified ?
4593
+ ret.value :
4594
+ undefined;
4595
+ },
4596
+ set: nodeHook.set
4597
+ };
4598
+
4599
+ // Set contenteditable to false on removals(#10429)
4600
+ // Setting to empty string throws an error as an invalid value
4601
+ jQuery.attrHooks.contenteditable = {
4602
+ set: function( elem, value, name ) {
4603
+ nodeHook.set( elem, value === "" ? false : value, name );
4604
+ }
4605
+ };
4606
+
4607
+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
4608
+ // This is for removals
4609
+ jQuery.each([ "width", "height" ], function( i, name ) {
4610
+ jQuery.attrHooks[ name ] = {
4611
+ set: function( elem, value ) {
4612
+ if ( value === "" ) {
4613
+ elem.setAttribute( name, "auto" );
4614
+ return value;
4615
+ }
4616
+ }
4617
+ };
4618
+ });
4619
+ }
4620
+
4621
+
4622
+ // Some attributes require a special call on IE
4623
+ // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
4624
+ if ( !jQuery.support.hrefNormalized ) {
4625
+ // href/src property should get the full normalized URL (#10299/#12915)
4626
+ jQuery.each([ "href", "src" ], function( i, name ) {
4627
+ jQuery.propHooks[ name ] = {
4628
+ get: function( elem ) {
4629
+ return elem.getAttribute( name, 4 );
4630
+ }
4631
+ };
4632
+ });
4633
+ }
4634
+
4635
+ if ( !jQuery.support.style ) {
4636
+ jQuery.attrHooks.style = {
4637
+ get: function( elem ) {
4638
+ // Return undefined in the case of empty string
4639
+ // Note: IE uppercases css property names, but if we were to .toLowerCase()
4640
+ // .cssText, that would destroy case senstitivity in URL's, like in "background"
4641
+ return elem.style.cssText || undefined;
4642
+ },
4643
+ set: function( elem, value ) {
4644
+ return ( elem.style.cssText = value + "" );
4645
+ }
4646
+ };
4647
+ }
4648
+
4649
+ // Safari mis-reports the default selected property of an option
4650
+ // Accessing the parent's selectedIndex property fixes it
4651
+ if ( !jQuery.support.optSelected ) {
4652
+ jQuery.propHooks.selected = {
4653
+ get: function( elem ) {
4654
+ var parent = elem.parentNode;
4655
+
4656
+ if ( parent ) {
4657
+ parent.selectedIndex;
4658
+
4659
+ // Make sure that it also works with optgroups, see #5701
4660
+ if ( parent.parentNode ) {
4661
+ parent.parentNode.selectedIndex;
4662
+ }
4663
+ }
4664
+ return null;
4665
+ }
4666
+ };
4667
+ }
4668
+
4669
+ jQuery.each([
4670
+ "tabIndex",
4671
+ "readOnly",
4672
+ "maxLength",
4673
+ "cellSpacing",
4674
+ "cellPadding",
4675
+ "rowSpan",
4676
+ "colSpan",
4677
+ "useMap",
4678
+ "frameBorder",
4679
+ "contentEditable"
4680
+ ], function() {
4681
+ jQuery.propFix[ this.toLowerCase() ] = this;
4682
+ });
4683
+
4684
+ // IE6/7 call enctype encoding
4685
+ if ( !jQuery.support.enctype ) {
4686
+ jQuery.propFix.enctype = "encoding";
4687
+ }
4688
+
4689
+ // Radios and checkboxes getter/setter
4690
+ jQuery.each([ "radio", "checkbox" ], function() {
4691
+ jQuery.valHooks[ this ] = {
4692
+ set: function( elem, value ) {
4693
+ if ( jQuery.isArray( value ) ) {
4694
+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
4695
+ }
4696
+ }
4697
+ };
4698
+ if ( !jQuery.support.checkOn ) {
4699
+ jQuery.valHooks[ this ].get = function( elem ) {
4700
+ // Support: Webkit
4701
+ // "" is returned instead of "on" if a value isn't specified
4702
+ return elem.getAttribute("value") === null ? "on" : elem.value;
4703
+ };
4704
+ }
4705
+ });
4706
+ var rformElems = /^(?:input|select|textarea)$/i,
4707
+ rkeyEvent = /^key/,
4708
+ rmouseEvent = /^(?:mouse|contextmenu)|click/,
4709
+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
4710
+ rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
4711
+
4712
+ function returnTrue() {
4713
+ return true;
4714
+ }
4715
+
4716
+ function returnFalse() {
4717
+ return false;
4718
+ }
4719
+
4720
+ function safeActiveElement() {
4721
+ try {
4722
+ return document.activeElement;
4723
+ } catch ( err ) { }
4724
+ }
4725
+
4726
+ /*
4727
+ * Helper functions for managing events -- not part of the public interface.
4728
+ * Props to Dean Edwards' addEvent library for many of the ideas.
4729
+ */
4730
+ jQuery.event = {
4731
+
4732
+ global: {},
4733
+
4734
+ add: function( elem, types, handler, data, selector ) {
4735
+ var tmp, events, t, handleObjIn,
4736
+ special, eventHandle, handleObj,
4737
+ handlers, type, namespaces, origType,
4738
+ elemData = jQuery._data( elem );
4739
+
4740
+ // Don't attach events to noData or text/comment nodes (but allow plain objects)
4741
+ if ( !elemData ) {
4742
+ return;
4743
+ }
4744
+
4745
+ // Caller can pass in an object of custom data in lieu of the handler
4746
+ if ( handler.handler ) {
4747
+ handleObjIn = handler;
4748
+ handler = handleObjIn.handler;
4749
+ selector = handleObjIn.selector;
4750
+ }
4751
+
4752
+ // Make sure that the handler has a unique ID, used to find/remove it later
4753
+ if ( !handler.guid ) {
4754
+ handler.guid = jQuery.guid++;
4755
+ }
4756
+
4757
+ // Init the element's event structure and main handler, if this is the first
4758
+ if ( !(events = elemData.events) ) {
4759
+ events = elemData.events = {};
4760
+ }
4761
+ if ( !(eventHandle = elemData.handle) ) {
4762
+ eventHandle = elemData.handle = function( e ) {
4763
+ // Discard the second event of a jQuery.event.trigger() and
4764
+ // when an event is called after a page has unloaded
4765
+ return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
4766
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
4767
+ undefined;
4768
+ };
4769
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
4770
+ eventHandle.elem = elem;
4771
+ }
4772
+
4773
+ // Handle multiple events separated by a space
4774
+ types = ( types || "" ).match( core_rnotwhite ) || [""];
4775
+ t = types.length;
4776
+ while ( t-- ) {
4777
+ tmp = rtypenamespace.exec( types[t] ) || [];
4778
+ type = origType = tmp[1];
4779
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
4780
+
4781
+ // There *must* be a type, no attaching namespace-only handlers
4782
+ if ( !type ) {
4783
+ continue;
4784
+ }
4785
+
4786
+ // If event changes its type, use the special event handlers for the changed type
4787
+ special = jQuery.event.special[ type ] || {};
4788
+
4789
+ // If selector defined, determine special event api type, otherwise given type
4790
+ type = ( selector ? special.delegateType : special.bindType ) || type;
4791
+
4792
+ // Update special based on newly reset type
4793
+ special = jQuery.event.special[ type ] || {};
4794
+
4795
+ // handleObj is passed to all event handlers
4796
+ handleObj = jQuery.extend({
4797
+ type: type,
4798
+ origType: origType,
4799
+ data: data,
4800
+ handler: handler,
4801
+ guid: handler.guid,
4802
+ selector: selector,
4803
+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
4804
+ namespace: namespaces.join(".")
4805
+ }, handleObjIn );
4806
+
4807
+ // Init the event handler queue if we're the first
4808
+ if ( !(handlers = events[ type ]) ) {
4809
+ handlers = events[ type ] = [];
4810
+ handlers.delegateCount = 0;
4811
+
4812
+ // Only use addEventListener/attachEvent if the special events handler returns false
4813
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
4814
+ // Bind the global event handler to the element
4815
+ if ( elem.addEventListener ) {
4816
+ elem.addEventListener( type, eventHandle, false );
4817
+
4818
+ } else if ( elem.attachEvent ) {
4819
+ elem.attachEvent( "on" + type, eventHandle );
4820
+ }
4821
+ }
4822
+ }
4823
+
4824
+ if ( special.add ) {
4825
+ special.add.call( elem, handleObj );
4826
+
4827
+ if ( !handleObj.handler.guid ) {
4828
+ handleObj.handler.guid = handler.guid;
4829
+ }
4830
+ }
4831
+
4832
+ // Add to the element's handler list, delegates in front
4833
+ if ( selector ) {
4834
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
4835
+ } else {
4836
+ handlers.push( handleObj );
4837
+ }
4838
+
4839
+ // Keep track of which events have ever been used, for event optimization
4840
+ jQuery.event.global[ type ] = true;
4841
+ }
4842
+
4843
+ // Nullify elem to prevent memory leaks in IE
4844
+ elem = null;
4845
+ },
4846
+
4847
+ // Detach an event or set of events from an element
4848
+ remove: function( elem, types, handler, selector, mappedTypes ) {
4849
+ var j, handleObj, tmp,
4850
+ origCount, t, events,
4851
+ special, handlers, type,
4852
+ namespaces, origType,
4853
+ elemData = jQuery.hasData( elem ) && jQuery._data( elem );
4854
+
4855
+ if ( !elemData || !(events = elemData.events) ) {
4856
+ return;
4857
+ }
4858
+
4859
+ // Once for each type.namespace in types; type may be omitted
4860
+ types = ( types || "" ).match( core_rnotwhite ) || [""];
4861
+ t = types.length;
4862
+ while ( t-- ) {
4863
+ tmp = rtypenamespace.exec( types[t] ) || [];
4864
+ type = origType = tmp[1];
4865
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
4866
+
4867
+ // Unbind all events (on this namespace, if provided) for the element
4868
+ if ( !type ) {
4869
+ for ( type in events ) {
4870
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
4871
+ }
4872
+ continue;
4873
+ }
4874
+
4875
+ special = jQuery.event.special[ type ] || {};
4876
+ type = ( selector ? special.delegateType : special.bindType ) || type;
4877
+ handlers = events[ type ] || [];
4878
+ tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
4879
+
4880
+ // Remove matching events
4881
+ origCount = j = handlers.length;
4882
+ while ( j-- ) {
4883
+ handleObj = handlers[ j ];
4884
+
4885
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
4886
+ ( !handler || handler.guid === handleObj.guid ) &&
4887
+ ( !tmp || tmp.test( handleObj.namespace ) ) &&
4888
+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
4889
+ handlers.splice( j, 1 );
4890
+
4891
+ if ( handleObj.selector ) {
4892
+ handlers.delegateCount--;
4893
+ }
4894
+ if ( special.remove ) {
4895
+ special.remove.call( elem, handleObj );
4896
+ }
4897
+ }
4898
+ }
4899
+
4900
+ // Remove generic event handler if we removed something and no more handlers exist
4901
+ // (avoids potential for endless recursion during removal of special event handlers)
4902
+ if ( origCount && !handlers.length ) {
4903
+ if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
4904
+ jQuery.removeEvent( elem, type, elemData.handle );
4905
+ }
4906
+
4907
+ delete events[ type ];
4908
+ }
4909
+ }
4910
+
4911
+ // Remove the expando if it's no longer used
4912
+ if ( jQuery.isEmptyObject( events ) ) {
4913
+ delete elemData.handle;
4914
+
4915
+ // removeData also checks for emptiness and clears the expando if empty
4916
+ // so use it instead of delete
4917
+ jQuery._removeData( elem, "events" );
4918
+ }
4919
+ },
4920
+
4921
+ trigger: function( event, data, elem, onlyHandlers ) {
4922
+ var handle, ontype, cur,
4923
+ bubbleType, special, tmp, i,
4924
+ eventPath = [ elem || document ],
4925
+ type = core_hasOwn.call( event, "type" ) ? event.type : event,
4926
+ namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
4927
+
4928
+ cur = tmp = elem = elem || document;
4929
+
4930
+ // Don't do events on text and comment nodes
4931
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
4932
+ return;
4933
+ }
4934
+
4935
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
4936
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
4937
+ return;
4938
+ }
4939
+
4940
+ if ( type.indexOf(".") >= 0 ) {
4941
+ // Namespaced trigger; create a regexp to match event type in handle()
4942
+ namespaces = type.split(".");
4943
+ type = namespaces.shift();
4944
+ namespaces.sort();
4945
+ }
4946
+ ontype = type.indexOf(":") < 0 && "on" + type;
4947
+
4948
+ // Caller can pass in a jQuery.Event object, Object, or just an event type string
4949
+ event = event[ jQuery.expando ] ?
4950
+ event :
4951
+ new jQuery.Event( type, typeof event === "object" && event );
4952
+
4953
+ // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
4954
+ event.isTrigger = onlyHandlers ? 2 : 3;
4955
+ event.namespace = namespaces.join(".");
4956
+ event.namespace_re = event.namespace ?
4957
+ new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
4958
+ null;
4959
+
4960
+ // Clean up the event in case it is being reused
4961
+ event.result = undefined;
4962
+ if ( !event.target ) {
4963
+ event.target = elem;
4964
+ }
4965
+
4966
+ // Clone any incoming data and prepend the event, creating the handler arg list
4967
+ data = data == null ?
4968
+ [ event ] :
4969
+ jQuery.makeArray( data, [ event ] );
4970
+
4971
+ // Allow special events to draw outside the lines
4972
+ special = jQuery.event.special[ type ] || {};
4973
+ if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
4974
+ return;
4975
+ }
4976
+
4977
+ // Determine event propagation path in advance, per W3C events spec (#9951)
4978
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
4979
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
4980
+
4981
+ bubbleType = special.delegateType || type;
4982
+ if ( !rfocusMorph.test( bubbleType + type ) ) {
4983
+ cur = cur.parentNode;
4984
+ }
4985
+ for ( ; cur; cur = cur.parentNode ) {
4986
+ eventPath.push( cur );
4987
+ tmp = cur;
4988
+ }
4989
+
4990
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
4991
+ if ( tmp === (elem.ownerDocument || document) ) {
4992
+ eventPath.push( tmp.defaultView || tmp.parentWindow || window );
4993
+ }
4994
+ }
4995
+
4996
+ // Fire handlers on the event path
4997
+ i = 0;
4998
+ while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
4999
+
5000
+ event.type = i > 1 ?
5001
+ bubbleType :
5002
+ special.bindType || type;
5003
+
5004
+ // jQuery handler
5005
+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
5006
+ if ( handle ) {
5007
+ handle.apply( cur, data );
5008
+ }
5009
+
5010
+ // Native handler
5011
+ handle = ontype && cur[ ontype ];
5012
+ if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
5013
+ event.preventDefault();
5014
+ }
5015
+ }
5016
+ event.type = type;
5017
+
5018
+ // If nobody prevented the default action, do it now
5019
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
5020
+
5021
+ if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
5022
+ jQuery.acceptData( elem ) ) {
5023
+
5024
+ // Call a native DOM method on the target with the same name name as the event.
5025
+ // Can't use an .isFunction() check here because IE6/7 fails that test.
5026
+ // Don't do default actions on window, that's where global variables be (#6170)
5027
+ if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
5028
+
5029
+ // Don't re-trigger an onFOO event when we call its FOO() method
5030
+ tmp = elem[ ontype ];
5031
+
5032
+ if ( tmp ) {
5033
+ elem[ ontype ] = null;
5034
+ }
5035
+
5036
+ // Prevent re-triggering of the same event, since we already bubbled it above
5037
+ jQuery.event.triggered = type;
5038
+ try {
5039
+ elem[ type ]();
5040
+ } catch ( e ) {
5041
+ // IE<9 dies on focus/blur to hidden element (#1486,#12518)
5042
+ // only reproducible on winXP IE8 native, not IE9 in IE8 mode
5043
+ }
5044
+ jQuery.event.triggered = undefined;
5045
+
5046
+ if ( tmp ) {
5047
+ elem[ ontype ] = tmp;
5048
+ }
5049
+ }
5050
+ }
5051
+ }
5052
+
5053
+ return event.result;
5054
+ },
5055
+
5056
+ dispatch: function( event ) {
5057
+
5058
+ // Make a writable jQuery.Event from the native event object
5059
+ event = jQuery.event.fix( event );
5060
+
5061
+ var i, ret, handleObj, matched, j,
5062
+ handlerQueue = [],
5063
+ args = core_slice.call( arguments ),
5064
+ handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
5065
+ special = jQuery.event.special[ event.type ] || {};
5066
+
5067
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
5068
+ args[0] = event;
5069
+ event.delegateTarget = this;
5070
+
5071
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
5072
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
5073
+ return;
5074
+ }
5075
+
5076
+ // Determine handlers
5077
+ handlerQueue = jQuery.event.handlers.call( this, event, handlers );
5078
+
5079
+ // Run delegates first; they may want to stop propagation beneath us
5080
+ i = 0;
5081
+ while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
5082
+ event.currentTarget = matched.elem;
5083
+
5084
+ j = 0;
5085
+ while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
5086
+
5087
+ // Triggered event must either 1) have no namespace, or
5088
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
5089
+ if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
5090
+
5091
+ event.handleObj = handleObj;
5092
+ event.data = handleObj.data;
5093
+
5094
+ ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
5095
+ .apply( matched.elem, args );
5096
+
5097
+ if ( ret !== undefined ) {
5098
+ if ( (event.result = ret) === false ) {
5099
+ event.preventDefault();
5100
+ event.stopPropagation();
5101
+ }
5102
+ }
5103
+ }
5104
+ }
5105
+ }
5106
+
5107
+ // Call the postDispatch hook for the mapped type
5108
+ if ( special.postDispatch ) {
5109
+ special.postDispatch.call( this, event );
5110
+ }
5111
+
5112
+ return event.result;
5113
+ },
5114
+
5115
+ handlers: function( event, handlers ) {
5116
+ var sel, handleObj, matches, i,
5117
+ handlerQueue = [],
5118
+ delegateCount = handlers.delegateCount,
5119
+ cur = event.target;
5120
+
5121
+ // Find delegate handlers
5122
+ // Black-hole SVG <use> instance trees (#13180)
5123
+ // Avoid non-left-click bubbling in Firefox (#3861)
5124
+ if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
5125
+
5126
+ /* jshint eqeqeq: false */
5127
+ for ( ; cur != this; cur = cur.parentNode || this ) {
5128
+ /* jshint eqeqeq: true */
5129
+
5130
+ // Don't check non-elements (#13208)
5131
+ // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
5132
+ if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
5133
+ matches = [];
5134
+ for ( i = 0; i < delegateCount; i++ ) {
5135
+ handleObj = handlers[ i ];
5136
+
5137
+ // Don't conflict with Object.prototype properties (#13203)
5138
+ sel = handleObj.selector + " ";
5139
+
5140
+ if ( matches[ sel ] === undefined ) {
5141
+ matches[ sel ] = handleObj.needsContext ?
5142
+ jQuery( sel, this ).index( cur ) >= 0 :
5143
+ jQuery.find( sel, this, null, [ cur ] ).length;
5144
+ }
5145
+ if ( matches[ sel ] ) {
5146
+ matches.push( handleObj );
5147
+ }
5148
+ }
5149
+ if ( matches.length ) {
5150
+ handlerQueue.push({ elem: cur, handlers: matches });
5151
+ }
5152
+ }
5153
+ }
5154
+ }
5155
+
5156
+ // Add the remaining (directly-bound) handlers
5157
+ if ( delegateCount < handlers.length ) {
5158
+ handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
5159
+ }
5160
+
5161
+ return handlerQueue;
5162
+ },
5163
+
5164
+ fix: function( event ) {
5165
+ if ( event[ jQuery.expando ] ) {
5166
+ return event;
5167
+ }
5168
+
5169
+ // Create a writable copy of the event object and normalize some properties
5170
+ var i, prop, copy,
5171
+ type = event.type,
5172
+ originalEvent = event,
5173
+ fixHook = this.fixHooks[ type ];
5174
+
5175
+ if ( !fixHook ) {
5176
+ this.fixHooks[ type ] = fixHook =
5177
+ rmouseEvent.test( type ) ? this.mouseHooks :
5178
+ rkeyEvent.test( type ) ? this.keyHooks :
5179
+ {};
5180
+ }
5181
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
5182
+
5183
+ event = new jQuery.Event( originalEvent );
5184
+
5185
+ i = copy.length;
5186
+ while ( i-- ) {
5187
+ prop = copy[ i ];
5188
+ event[ prop ] = originalEvent[ prop ];
5189
+ }
5190
+
5191
+ // Support: IE<9
5192
+ // Fix target property (#1925)
5193
+ if ( !event.target ) {
5194
+ event.target = originalEvent.srcElement || document;
5195
+ }
5196
+
5197
+ // Support: Chrome 23+, Safari?
5198
+ // Target should not be a text node (#504, #13143)
5199
+ if ( event.target.nodeType === 3 ) {
5200
+ event.target = event.target.parentNode;
5201
+ }
5202
+
5203
+ // Support: IE<9
5204
+ // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
5205
+ event.metaKey = !!event.metaKey;
5206
+
5207
+ return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
5208
+ },
5209
+
5210
+ // Includes some event props shared by KeyEvent and MouseEvent
5211
+ props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
5212
+
5213
+ fixHooks: {},
5214
+
5215
+ keyHooks: {
5216
+ props: "char charCode key keyCode".split(" "),
5217
+ filter: function( event, original ) {
5218
+
5219
+ // Add which for key events
5220
+ if ( event.which == null ) {
5221
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
5222
+ }
5223
+
5224
+ return event;
5225
+ }
5226
+ },
5227
+
5228
+ mouseHooks: {
5229
+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
5230
+ filter: function( event, original ) {
5231
+ var body, eventDoc, doc,
5232
+ button = original.button,
5233
+ fromElement = original.fromElement;
5234
+
5235
+ // Calculate pageX/Y if missing and clientX/Y available
5236
+ if ( event.pageX == null && original.clientX != null ) {
5237
+ eventDoc = event.target.ownerDocument || document;
5238
+ doc = eventDoc.documentElement;
5239
+ body = eventDoc.body;
5240
+
5241
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
5242
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
5243
+ }
5244
+
5245
+ // Add relatedTarget, if necessary
5246
+ if ( !event.relatedTarget && fromElement ) {
5247
+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
5248
+ }
5249
+
5250
+ // Add which for click: 1 === left; 2 === middle; 3 === right
5251
+ // Note: button is not normalized, so don't use it
5252
+ if ( !event.which && button !== undefined ) {
5253
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
5254
+ }
5255
+
5256
+ return event;
5257
+ }
5258
+ },
5259
+
5260
+ special: {
5261
+ load: {
5262
+ // Prevent triggered image.load events from bubbling to window.load
5263
+ noBubble: true
5264
+ },
5265
+ focus: {
5266
+ // Fire native event if possible so blur/focus sequence is correct
5267
+ trigger: function() {
5268
+ if ( this !== safeActiveElement() && this.focus ) {
5269
+ try {
5270
+ this.focus();
5271
+ return false;
5272
+ } catch ( e ) {
5273
+ // Support: IE<9
5274
+ // If we error on focus to hidden element (#1486, #12518),
5275
+ // let .trigger() run the handlers
5276
+ }
5277
+ }
5278
+ },
5279
+ delegateType: "focusin"
5280
+ },
5281
+ blur: {
5282
+ trigger: function() {
5283
+ if ( this === safeActiveElement() && this.blur ) {
5284
+ this.blur();
5285
+ return false;
5286
+ }
5287
+ },
5288
+ delegateType: "focusout"
5289
+ },
5290
+ click: {
5291
+ // For checkbox, fire native event so checked state will be right
5292
+ trigger: function() {
5293
+ if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
5294
+ this.click();
5295
+ return false;
5296
+ }
5297
+ },
5298
+
5299
+ // For cross-browser consistency, don't fire native .click() on links
5300
+ _default: function( event ) {
5301
+ return jQuery.nodeName( event.target, "a" );
5302
+ }
5303
+ },
5304
+
5305
+ beforeunload: {
5306
+ postDispatch: function( event ) {
5307
+
5308
+ // Even when returnValue equals to undefined Firefox will still show alert
5309
+ if ( event.result !== undefined ) {
5310
+ event.originalEvent.returnValue = event.result;
5311
+ }
5312
+ }
5313
+ }
5314
+ },
5315
+
5316
+ simulate: function( type, elem, event, bubble ) {
5317
+ // Piggyback on a donor event to simulate a different one.
5318
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
5319
+ // simulated event prevents default then we do the same on the donor.
5320
+ var e = jQuery.extend(
5321
+ new jQuery.Event(),
5322
+ event,
5323
+ {
5324
+ type: type,
5325
+ isSimulated: true,
5326
+ originalEvent: {}
5327
+ }
5328
+ );
5329
+ if ( bubble ) {
5330
+ jQuery.event.trigger( e, null, elem );
5331
+ } else {
5332
+ jQuery.event.dispatch.call( elem, e );
5333
+ }
5334
+ if ( e.isDefaultPrevented() ) {
5335
+ event.preventDefault();
5336
+ }
5337
+ }
5338
+ };
5339
+
5340
+ jQuery.removeEvent = document.removeEventListener ?
5341
+ function( elem, type, handle ) {
5342
+ if ( elem.removeEventListener ) {
5343
+ elem.removeEventListener( type, handle, false );
5344
+ }
5345
+ } :
5346
+ function( elem, type, handle ) {
5347
+ var name = "on" + type;
5348
+
5349
+ if ( elem.detachEvent ) {
5350
+
5351
+ // #8545, #7054, preventing memory leaks for custom events in IE6-8
5352
+ // detachEvent needed property on element, by name of that event, to properly expose it to GC
5353
+ if ( typeof elem[ name ] === core_strundefined ) {
5354
+ elem[ name ] = null;
5355
+ }
5356
+
5357
+ elem.detachEvent( name, handle );
5358
+ }
5359
+ };
5360
+
5361
+ jQuery.Event = function( src, props ) {
5362
+ // Allow instantiation without the 'new' keyword
5363
+ if ( !(this instanceof jQuery.Event) ) {
5364
+ return new jQuery.Event( src, props );
5365
+ }
5366
+
5367
+ // Event object
5368
+ if ( src && src.type ) {
5369
+ this.originalEvent = src;
5370
+ this.type = src.type;
5371
+
5372
+ // Events bubbling up the document may have been marked as prevented
5373
+ // by a handler lower down the tree; reflect the correct value.
5374
+ this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
5375
+ src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
5376
+
5377
+ // Event type
5378
+ } else {
5379
+ this.type = src;
5380
+ }
5381
+
5382
+ // Put explicitly provided properties onto the event object
5383
+ if ( props ) {
5384
+ jQuery.extend( this, props );
5385
+ }
5386
+
5387
+ // Create a timestamp if incoming event doesn't have one
5388
+ this.timeStamp = src && src.timeStamp || jQuery.now();
5389
+
5390
+ // Mark it as fixed
5391
+ this[ jQuery.expando ] = true;
5392
+ };
5393
+
5394
+ // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
5395
+ // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
5396
+ jQuery.Event.prototype = {
5397
+ isDefaultPrevented: returnFalse,
5398
+ isPropagationStopped: returnFalse,
5399
+ isImmediatePropagationStopped: returnFalse,
5400
+
5401
+ preventDefault: function() {
5402
+ var e = this.originalEvent;
5403
+
5404
+ this.isDefaultPrevented = returnTrue;
5405
+ if ( !e ) {
5406
+ return;
5407
+ }
5408
+
5409
+ // If preventDefault exists, run it on the original event
5410
+ if ( e.preventDefault ) {
5411
+ e.preventDefault();
5412
+
5413
+ // Support: IE
5414
+ // Otherwise set the returnValue property of the original event to false
5415
+ } else {
5416
+ e.returnValue = false;
5417
+ }
5418
+ },
5419
+ stopPropagation: function() {
5420
+ var e = this.originalEvent;
5421
+
5422
+ this.isPropagationStopped = returnTrue;
5423
+ if ( !e ) {
5424
+ return;
5425
+ }
5426
+ // If stopPropagation exists, run it on the original event
5427
+ if ( e.stopPropagation ) {
5428
+ e.stopPropagation();
5429
+ }
5430
+
5431
+ // Support: IE
5432
+ // Set the cancelBubble property of the original event to true
5433
+ e.cancelBubble = true;
5434
+ },
5435
+ stopImmediatePropagation: function() {
5436
+ this.isImmediatePropagationStopped = returnTrue;
5437
+ this.stopPropagation();
5438
+ }
5439
+ };
5440
+
5441
+ // Create mouseenter/leave events using mouseover/out and event-time checks
5442
+ jQuery.each({
5443
+ mouseenter: "mouseover",
5444
+ mouseleave: "mouseout"
5445
+ }, function( orig, fix ) {
5446
+ jQuery.event.special[ orig ] = {
5447
+ delegateType: fix,
5448
+ bindType: fix,
5449
+
5450
+ handle: function( event ) {
5451
+ var ret,
5452
+ target = this,
5453
+ related = event.relatedTarget,
5454
+ handleObj = event.handleObj;
5455
+
5456
+ // For mousenter/leave call the handler if related is outside the target.
5457
+ // NB: No relatedTarget if the mouse left/entered the browser window
5458
+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
5459
+ event.type = handleObj.origType;
5460
+ ret = handleObj.handler.apply( this, arguments );
5461
+ event.type = fix;
5462
+ }
5463
+ return ret;
5464
+ }
5465
+ };
5466
+ });
5467
+
5468
+ // IE submit delegation
5469
+ if ( !jQuery.support.submitBubbles ) {
5470
+
5471
+ jQuery.event.special.submit = {
5472
+ setup: function() {
5473
+ // Only need this for delegated form submit events
5474
+ if ( jQuery.nodeName( this, "form" ) ) {
5475
+ return false;
5476
+ }
5477
+
5478
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
5479
+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
5480
+ // Node name check avoids a VML-related crash in IE (#9807)
5481
+ var elem = e.target,
5482
+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
5483
+ if ( form && !jQuery._data( form, "submitBubbles" ) ) {
5484
+ jQuery.event.add( form, "submit._submit", function( event ) {
5485
+ event._submit_bubble = true;
5486
+ });
5487
+ jQuery._data( form, "submitBubbles", true );
5488
+ }
5489
+ });
5490
+ // return undefined since we don't need an event listener
5491
+ },
5492
+
5493
+ postDispatch: function( event ) {
5494
+ // If form was submitted by the user, bubble the event up the tree
5495
+ if ( event._submit_bubble ) {
5496
+ delete event._submit_bubble;
5497
+ if ( this.parentNode && !event.isTrigger ) {
5498
+ jQuery.event.simulate( "submit", this.parentNode, event, true );
5499
+ }
5500
+ }
5501
+ },
5502
+
5503
+ teardown: function() {
5504
+ // Only need this for delegated form submit events
5505
+ if ( jQuery.nodeName( this, "form" ) ) {
5506
+ return false;
5507
+ }
5508
+
5509
+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
5510
+ jQuery.event.remove( this, "._submit" );
5511
+ }
5512
+ };
5513
+ }
5514
+
5515
+ // IE change delegation and checkbox/radio fix
5516
+ if ( !jQuery.support.changeBubbles ) {
5517
+
5518
+ jQuery.event.special.change = {
5519
+
5520
+ setup: function() {
5521
+
5522
+ if ( rformElems.test( this.nodeName ) ) {
5523
+ // IE doesn't fire change on a check/radio until blur; trigger it on click
5524
+ // after a propertychange. Eat the blur-change in special.change.handle.
5525
+ // This still fires onchange a second time for check/radio after blur.
5526
+ if ( this.type === "checkbox" || this.type === "radio" ) {
5527
+ jQuery.event.add( this, "propertychange._change", function( event ) {
5528
+ if ( event.originalEvent.propertyName === "checked" ) {
5529
+ this._just_changed = true;
5530
+ }
5531
+ });
5532
+ jQuery.event.add( this, "click._change", function( event ) {
5533
+ if ( this._just_changed && !event.isTrigger ) {
5534
+ this._just_changed = false;
5535
+ }
5536
+ // Allow triggered, simulated change events (#11500)
5537
+ jQuery.event.simulate( "change", this, event, true );
5538
+ });
5539
+ }
5540
+ return false;
5541
+ }
5542
+ // Delegated event; lazy-add a change handler on descendant inputs
5543
+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
5544
+ var elem = e.target;
5545
+
5546
+ if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
5547
+ jQuery.event.add( elem, "change._change", function( event ) {
5548
+ if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
5549
+ jQuery.event.simulate( "change", this.parentNode, event, true );
5550
+ }
5551
+ });
5552
+ jQuery._data( elem, "changeBubbles", true );
5553
+ }
5554
+ });
5555
+ },
5556
+
5557
+ handle: function( event ) {
5558
+ var elem = event.target;
5559
+
5560
+ // Swallow native change events from checkbox/radio, we already triggered them above
5561
+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
5562
+ return event.handleObj.handler.apply( this, arguments );
5563
+ }
5564
+ },
5565
+
5566
+ teardown: function() {
5567
+ jQuery.event.remove( this, "._change" );
5568
+
5569
+ return !rformElems.test( this.nodeName );
5570
+ }
5571
+ };
5572
+ }
5573
+
5574
+ // Create "bubbling" focus and blur events
5575
+ if ( !jQuery.support.focusinBubbles ) {
5576
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
5577
+
5578
+ // Attach a single capturing handler while someone wants focusin/focusout
5579
+ var attaches = 0,
5580
+ handler = function( event ) {
5581
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
5582
+ };
5583
+
5584
+ jQuery.event.special[ fix ] = {
5585
+ setup: function() {
5586
+ if ( attaches++ === 0 ) {
5587
+ document.addEventListener( orig, handler, true );
5588
+ }
5589
+ },
5590
+ teardown: function() {
5591
+ if ( --attaches === 0 ) {
5592
+ document.removeEventListener( orig, handler, true );
5593
+ }
5594
+ }
5595
+ };
5596
+ });
5597
+ }
5598
+
5599
+ jQuery.fn.extend({
5600
+
5601
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
5602
+ var type, origFn;
5603
+
5604
+ // Types can be a map of types/handlers
5605
+ if ( typeof types === "object" ) {
5606
+ // ( types-Object, selector, data )
5607
+ if ( typeof selector !== "string" ) {
5608
+ // ( types-Object, data )
5609
+ data = data || selector;
5610
+ selector = undefined;
5611
+ }
5612
+ for ( type in types ) {
5613
+ this.on( type, selector, data, types[ type ], one );
5614
+ }
5615
+ return this;
5616
+ }
5617
+
5618
+ if ( data == null && fn == null ) {
5619
+ // ( types, fn )
5620
+ fn = selector;
5621
+ data = selector = undefined;
5622
+ } else if ( fn == null ) {
5623
+ if ( typeof selector === "string" ) {
5624
+ // ( types, selector, fn )
5625
+ fn = data;
5626
+ data = undefined;
5627
+ } else {
5628
+ // ( types, data, fn )
5629
+ fn = data;
5630
+ data = selector;
5631
+ selector = undefined;
5632
+ }
5633
+ }
5634
+ if ( fn === false ) {
5635
+ fn = returnFalse;
5636
+ } else if ( !fn ) {
5637
+ return this;
5638
+ }
5639
+
5640
+ if ( one === 1 ) {
5641
+ origFn = fn;
5642
+ fn = function( event ) {
5643
+ // Can use an empty set, since event contains the info
5644
+ jQuery().off( event );
5645
+ return origFn.apply( this, arguments );
5646
+ };
5647
+ // Use same guid so caller can remove using origFn
5648
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
5649
+ }
5650
+ return this.each( function() {
5651
+ jQuery.event.add( this, types, fn, data, selector );
5652
+ });
5653
+ },
5654
+ one: function( types, selector, data, fn ) {
5655
+ return this.on( types, selector, data, fn, 1 );
5656
+ },
5657
+ off: function( types, selector, fn ) {
5658
+ var handleObj, type;
5659
+ if ( types && types.preventDefault && types.handleObj ) {
5660
+ // ( event ) dispatched jQuery.Event
5661
+ handleObj = types.handleObj;
5662
+ jQuery( types.delegateTarget ).off(
5663
+ handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
5664
+ handleObj.selector,
5665
+ handleObj.handler
5666
+ );
5667
+ return this;
5668
+ }
5669
+ if ( typeof types === "object" ) {
5670
+ // ( types-object [, selector] )
5671
+ for ( type in types ) {
5672
+ this.off( type, selector, types[ type ] );
5673
+ }
5674
+ return this;
5675
+ }
5676
+ if ( selector === false || typeof selector === "function" ) {
5677
+ // ( types [, fn] )
5678
+ fn = selector;
5679
+ selector = undefined;
5680
+ }
5681
+ if ( fn === false ) {
5682
+ fn = returnFalse;
5683
+ }
5684
+ return this.each(function() {
5685
+ jQuery.event.remove( this, types, fn, selector );
5686
+ });
5687
+ },
5688
+
5689
+ trigger: function( type, data ) {
5690
+ return this.each(function() {
5691
+ jQuery.event.trigger( type, data, this );
5692
+ });
5693
+ },
5694
+ triggerHandler: function( type, data ) {
5695
+ var elem = this[0];
5696
+ if ( elem ) {
5697
+ return jQuery.event.trigger( type, data, elem, true );
5698
+ }
5699
+ }
5700
+ });
5701
+ var isSimple = /^.[^:#\[\.,]*$/,
5702
+ rparentsprev = /^(?:parents|prev(?:Until|All))/,
5703
+ rneedsContext = jQuery.expr.match.needsContext,
5704
+ // methods guaranteed to produce a unique set when starting from a unique set
5705
+ guaranteedUnique = {
5706
+ children: true,
5707
+ contents: true,
5708
+ next: true,
5709
+ prev: true
5710
+ };
5711
+
5712
+ jQuery.fn.extend({
5713
+ find: function( selector ) {
5714
+ var i,
5715
+ ret = [],
5716
+ self = this,
5717
+ len = self.length;
5718
+
5719
+ if ( typeof selector !== "string" ) {
5720
+ return this.pushStack( jQuery( selector ).filter(function() {
5721
+ for ( i = 0; i < len; i++ ) {
5722
+ if ( jQuery.contains( self[ i ], this ) ) {
5723
+ return true;
5724
+ }
5725
+ }
5726
+ }) );
5727
+ }
5728
+
5729
+ for ( i = 0; i < len; i++ ) {
5730
+ jQuery.find( selector, self[ i ], ret );
5731
+ }
5732
+
5733
+ // Needed because $( selector, context ) becomes $( context ).find( selector )
5734
+ ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
5735
+ ret.selector = this.selector ? this.selector + " " + selector : selector;
5736
+ return ret;
5737
+ },
5738
+
5739
+ has: function( target ) {
5740
+ var i,
5741
+ targets = jQuery( target, this ),
5742
+ len = targets.length;
5743
+
5744
+ return this.filter(function() {
5745
+ for ( i = 0; i < len; i++ ) {
5746
+ if ( jQuery.contains( this, targets[i] ) ) {
5747
+ return true;
5748
+ }
5749
+ }
5750
+ });
5751
+ },
5752
+
5753
+ not: function( selector ) {
5754
+ return this.pushStack( winnow(this, selector || [], true) );
5755
+ },
5756
+
5757
+ filter: function( selector ) {
5758
+ return this.pushStack( winnow(this, selector || [], false) );
5759
+ },
5760
+
5761
+ is: function( selector ) {
5762
+ return !!winnow(
5763
+ this,
5764
+
5765
+ // If this is a positional/relative selector, check membership in the returned set
5766
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
5767
+ typeof selector === "string" && rneedsContext.test( selector ) ?
5768
+ jQuery( selector ) :
5769
+ selector || [],
5770
+ false
5771
+ ).length;
5772
+ },
5773
+
5774
+ closest: function( selectors, context ) {
5775
+ var cur,
5776
+ i = 0,
5777
+ l = this.length,
5778
+ ret = [],
5779
+ pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
5780
+ jQuery( selectors, context || this.context ) :
5781
+ 0;
5782
+
5783
+ for ( ; i < l; i++ ) {
5784
+ for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
5785
+ // Always skip document fragments
5786
+ if ( cur.nodeType < 11 && (pos ?
5787
+ pos.index(cur) > -1 :
5788
+
5789
+ // Don't pass non-elements to Sizzle
5790
+ cur.nodeType === 1 &&
5791
+ jQuery.find.matchesSelector(cur, selectors)) ) {
5792
+
5793
+ cur = ret.push( cur );
5794
+ break;
5795
+ }
5796
+ }
5797
+ }
5798
+
5799
+ return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );
5800
+ },
5801
+
5802
+ // Determine the position of an element within
5803
+ // the matched set of elements
5804
+ index: function( elem ) {
5805
+
5806
+ // No argument, return index in parent
5807
+ if ( !elem ) {
5808
+ return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
5809
+ }
5810
+
5811
+ // index in selector
5812
+ if ( typeof elem === "string" ) {
5813
+ return jQuery.inArray( this[0], jQuery( elem ) );
5814
+ }
5815
+
5816
+ // Locate the position of the desired element
5817
+ return jQuery.inArray(
5818
+ // If it receives a jQuery object, the first element is used
5819
+ elem.jquery ? elem[0] : elem, this );
5820
+ },
5821
+
5822
+ add: function( selector, context ) {
5823
+ var set = typeof selector === "string" ?
5824
+ jQuery( selector, context ) :
5825
+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
5826
+ all = jQuery.merge( this.get(), set );
5827
+
5828
+ return this.pushStack( jQuery.unique(all) );
5829
+ },
5830
+
5831
+ addBack: function( selector ) {
5832
+ return this.add( selector == null ?
5833
+ this.prevObject : this.prevObject.filter(selector)
5834
+ );
5835
+ }
5836
+ });
5837
+
5838
+ function sibling( cur, dir ) {
5839
+ do {
5840
+ cur = cur[ dir ];
5841
+ } while ( cur && cur.nodeType !== 1 );
5842
+
5843
+ return cur;
5844
+ }
5845
+
5846
+ jQuery.each({
5847
+ parent: function( elem ) {
5848
+ var parent = elem.parentNode;
5849
+ return parent && parent.nodeType !== 11 ? parent : null;
5850
+ },
5851
+ parents: function( elem ) {
5852
+ return jQuery.dir( elem, "parentNode" );
5853
+ },
5854
+ parentsUntil: function( elem, i, until ) {
5855
+ return jQuery.dir( elem, "parentNode", until );
5856
+ },
5857
+ next: function( elem ) {
5858
+ return sibling( elem, "nextSibling" );
5859
+ },
5860
+ prev: function( elem ) {
5861
+ return sibling( elem, "previousSibling" );
5862
+ },
5863
+ nextAll: function( elem ) {
5864
+ return jQuery.dir( elem, "nextSibling" );
5865
+ },
5866
+ prevAll: function( elem ) {
5867
+ return jQuery.dir( elem, "previousSibling" );
5868
+ },
5869
+ nextUntil: function( elem, i, until ) {
5870
+ return jQuery.dir( elem, "nextSibling", until );
5871
+ },
5872
+ prevUntil: function( elem, i, until ) {
5873
+ return jQuery.dir( elem, "previousSibling", until );
5874
+ },
5875
+ siblings: function( elem ) {
5876
+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
5877
+ },
5878
+ children: function( elem ) {
5879
+ return jQuery.sibling( elem.firstChild );
5880
+ },
5881
+ contents: function( elem ) {
5882
+ return jQuery.nodeName( elem, "iframe" ) ?
5883
+ elem.contentDocument || elem.contentWindow.document :
5884
+ jQuery.merge( [], elem.childNodes );
5885
+ }
5886
+ }, function( name, fn ) {
5887
+ jQuery.fn[ name ] = function( until, selector ) {
5888
+ var ret = jQuery.map( this, fn, until );
5889
+
5890
+ if ( name.slice( -5 ) !== "Until" ) {
5891
+ selector = until;
5892
+ }
5893
+
5894
+ if ( selector && typeof selector === "string" ) {
5895
+ ret = jQuery.filter( selector, ret );
5896
+ }
5897
+
5898
+ if ( this.length > 1 ) {
5899
+ // Remove duplicates
5900
+ if ( !guaranteedUnique[ name ] ) {
5901
+ ret = jQuery.unique( ret );
5902
+ }
5903
+
5904
+ // Reverse order for parents* and prev-derivatives
5905
+ if ( rparentsprev.test( name ) ) {
5906
+ ret = ret.reverse();
5907
+ }
5908
+ }
5909
+
5910
+ return this.pushStack( ret );
5911
+ };
5912
+ });
5913
+
5914
+ jQuery.extend({
5915
+ filter: function( expr, elems, not ) {
5916
+ var elem = elems[ 0 ];
5917
+
5918
+ if ( not ) {
5919
+ expr = ":not(" + expr + ")";
5920
+ }
5921
+
5922
+ return elems.length === 1 && elem.nodeType === 1 ?
5923
+ jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
5924
+ jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
5925
+ return elem.nodeType === 1;
5926
+ }));
5927
+ },
5928
+
5929
+ dir: function( elem, dir, until ) {
5930
+ var matched = [],
5931
+ cur = elem[ dir ];
5932
+
5933
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
5934
+ if ( cur.nodeType === 1 ) {
5935
+ matched.push( cur );
5936
+ }
5937
+ cur = cur[dir];
5938
+ }
5939
+ return matched;
5940
+ },
5941
+
5942
+ sibling: function( n, elem ) {
5943
+ var r = [];
5944
+
5945
+ for ( ; n; n = n.nextSibling ) {
5946
+ if ( n.nodeType === 1 && n !== elem ) {
5947
+ r.push( n );
5948
+ }
5949
+ }
5950
+
5951
+ return r;
5952
+ }
5953
+ });
5954
+
5955
+ // Implement the identical functionality for filter and not
5956
+ function winnow( elements, qualifier, not ) {
5957
+ if ( jQuery.isFunction( qualifier ) ) {
5958
+ return jQuery.grep( elements, function( elem, i ) {
5959
+ /* jshint -W018 */
5960
+ return !!qualifier.call( elem, i, elem ) !== not;
5961
+ });
5962
+
5963
+ }
5964
+
5965
+ if ( qualifier.nodeType ) {
5966
+ return jQuery.grep( elements, function( elem ) {
5967
+ return ( elem === qualifier ) !== not;
5968
+ });
5969
+
5970
+ }
5971
+
5972
+ if ( typeof qualifier === "string" ) {
5973
+ if ( isSimple.test( qualifier ) ) {
5974
+ return jQuery.filter( qualifier, elements, not );
5975
+ }
5976
+
5977
+ qualifier = jQuery.filter( qualifier, elements );
5978
+ }
5979
+
5980
+ return jQuery.grep( elements, function( elem ) {
5981
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
5982
+ });
5983
+ }
5984
+ function createSafeFragment( document ) {
5985
+ var list = nodeNames.split( "|" ),
5986
+ safeFrag = document.createDocumentFragment();
5987
+
5988
+ if ( safeFrag.createElement ) {
5989
+ while ( list.length ) {
5990
+ safeFrag.createElement(
5991
+ list.pop()
5992
+ );
5993
+ }
5994
+ }
5995
+ return safeFrag;
5996
+ }
5997
+
5998
+ var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
5999
+ "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
6000
+ rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
6001
+ rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
6002
+ rleadingWhitespace = /^\s+/,
6003
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
6004
+ rtagName = /<([\w:]+)/,
6005
+ rtbody = /<tbody/i,
6006
+ rhtml = /<|&#?\w+;/,
6007
+ rnoInnerhtml = /<(?:script|style|link)/i,
6008
+ manipulation_rcheckableType = /^(?:checkbox|radio)$/i,
6009
+ // checked="checked" or checked
6010
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
6011
+ rscriptType = /^$|\/(?:java|ecma)script/i,
6012
+ rscriptTypeMasked = /^true\/(.*)/,
6013
+ rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
6014
+
6015
+ // We have to close these tags to support XHTML (#13200)
6016
+ wrapMap = {
6017
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
6018
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
6019
+ area: [ 1, "<map>", "</map>" ],
6020
+ param: [ 1, "<object>", "</object>" ],
6021
+ thead: [ 1, "<table>", "</table>" ],
6022
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
6023
+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
6024
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
6025
+
6026
+ // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
6027
+ // unless wrapped in a div with non-breaking characters in front of it.
6028
+ _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
6029
+ },
6030
+ safeFragment = createSafeFragment( document ),
6031
+ fragmentDiv = safeFragment.appendChild( document.createElement("div") );
6032
+
6033
+ wrapMap.optgroup = wrapMap.option;
6034
+ wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
6035
+ wrapMap.th = wrapMap.td;
6036
+
6037
+ jQuery.fn.extend({
6038
+ text: function( value ) {
6039
+ return jQuery.access( this, function( value ) {
6040
+ return value === undefined ?
6041
+ jQuery.text( this ) :
6042
+ this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
6043
+ }, null, value, arguments.length );
6044
+ },
6045
+
6046
+ append: function() {
6047
+ return this.domManip( arguments, function( elem ) {
6048
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6049
+ var target = manipulationTarget( this, elem );
6050
+ target.appendChild( elem );
6051
+ }
6052
+ });
6053
+ },
6054
+
6055
+ prepend: function() {
6056
+ return this.domManip( arguments, function( elem ) {
6057
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
6058
+ var target = manipulationTarget( this, elem );
6059
+ target.insertBefore( elem, target.firstChild );
6060
+ }
6061
+ });
6062
+ },
6063
+
6064
+ before: function() {
6065
+ return this.domManip( arguments, function( elem ) {
6066
+ if ( this.parentNode ) {
6067
+ this.parentNode.insertBefore( elem, this );
6068
+ }
6069
+ });
6070
+ },
6071
+
6072
+ after: function() {
6073
+ return this.domManip( arguments, function( elem ) {
6074
+ if ( this.parentNode ) {
6075
+ this.parentNode.insertBefore( elem, this.nextSibling );
6076
+ }
6077
+ });
6078
+ },
6079
+
6080
+ // keepData is for internal use only--do not document
6081
+ remove: function( selector, keepData ) {
6082
+ var elem,
6083
+ elems = selector ? jQuery.filter( selector, this ) : this,
6084
+ i = 0;
6085
+
6086
+ for ( ; (elem = elems[i]) != null; i++ ) {
6087
+
6088
+ if ( !keepData && elem.nodeType === 1 ) {
6089
+ jQuery.cleanData( getAll( elem ) );
6090
+ }
6091
+
6092
+ if ( elem.parentNode ) {
6093
+ if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
6094
+ setGlobalEval( getAll( elem, "script" ) );
6095
+ }
6096
+ elem.parentNode.removeChild( elem );
6097
+ }
6098
+ }
6099
+
6100
+ return this;
6101
+ },
6102
+
6103
+ empty: function() {
6104
+ var elem,
6105
+ i = 0;
6106
+
6107
+ for ( ; (elem = this[i]) != null; i++ ) {
6108
+ // Remove element nodes and prevent memory leaks
6109
+ if ( elem.nodeType === 1 ) {
6110
+ jQuery.cleanData( getAll( elem, false ) );
6111
+ }
6112
+
6113
+ // Remove any remaining nodes
6114
+ while ( elem.firstChild ) {
6115
+ elem.removeChild( elem.firstChild );
6116
+ }
6117
+
6118
+ // If this is a select, ensure that it displays empty (#12336)
6119
+ // Support: IE<9
6120
+ if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
6121
+ elem.options.length = 0;
6122
+ }
6123
+ }
6124
+
6125
+ return this;
6126
+ },
6127
+
6128
+ clone: function( dataAndEvents, deepDataAndEvents ) {
6129
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
6130
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
6131
+
6132
+ return this.map( function () {
6133
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
6134
+ });
6135
+ },
6136
+
6137
+ html: function( value ) {
6138
+ return jQuery.access( this, function( value ) {
6139
+ var elem = this[0] || {},
6140
+ i = 0,
6141
+ l = this.length;
6142
+
6143
+ if ( value === undefined ) {
6144
+ return elem.nodeType === 1 ?
6145
+ elem.innerHTML.replace( rinlinejQuery, "" ) :
6146
+ undefined;
6147
+ }
6148
+
6149
+ // See if we can take a shortcut and just use innerHTML
6150
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
6151
+ ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
6152
+ ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
6153
+ !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
6154
+
6155
+ value = value.replace( rxhtmlTag, "<$1></$2>" );
6156
+
6157
+ try {
6158
+ for (; i < l; i++ ) {
6159
+ // Remove element nodes and prevent memory leaks
6160
+ elem = this[i] || {};
6161
+ if ( elem.nodeType === 1 ) {
6162
+ jQuery.cleanData( getAll( elem, false ) );
6163
+ elem.innerHTML = value;
6164
+ }
6165
+ }
6166
+
6167
+ elem = 0;
6168
+
6169
+ // If using innerHTML throws an exception, use the fallback method
6170
+ } catch(e) {}
6171
+ }
6172
+
6173
+ if ( elem ) {
6174
+ this.empty().append( value );
6175
+ }
6176
+ }, null, value, arguments.length );
6177
+ },
6178
+
6179
+ replaceWith: function() {
6180
+ var
6181
+ // Snapshot the DOM in case .domManip sweeps something relevant into its fragment
6182
+ args = jQuery.map( this, function( elem ) {
6183
+ return [ elem.nextSibling, elem.parentNode ];
6184
+ }),
6185
+ i = 0;
6186
+
6187
+ // Make the changes, replacing each context element with the new content
6188
+ this.domManip( arguments, function( elem ) {
6189
+ var next = args[ i++ ],
6190
+ parent = args[ i++ ];
6191
+
6192
+ if ( parent ) {
6193
+ // Don't use the snapshot next if it has moved (#13810)
6194
+ if ( next && next.parentNode !== parent ) {
6195
+ next = this.nextSibling;
6196
+ }
6197
+ jQuery( this ).remove();
6198
+ parent.insertBefore( elem, next );
6199
+ }
6200
+ // Allow new content to include elements from the context set
6201
+ }, true );
6202
+
6203
+ // Force removal if there was no new content (e.g., from empty arguments)
6204
+ return i ? this : this.remove();
6205
+ },
6206
+
6207
+ detach: function( selector ) {
6208
+ return this.remove( selector, true );
6209
+ },
6210
+
6211
+ domManip: function( args, callback, allowIntersection ) {
6212
+
6213
+ // Flatten any nested arrays
6214
+ args = core_concat.apply( [], args );
6215
+
6216
+ var first, node, hasScripts,
6217
+ scripts, doc, fragment,
6218
+ i = 0,
6219
+ l = this.length,
6220
+ set = this,
6221
+ iNoClone = l - 1,
6222
+ value = args[0],
6223
+ isFunction = jQuery.isFunction( value );
6224
+
6225
+ // We can't cloneNode fragments that contain checked, in WebKit
6226
+ if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {
6227
+ return this.each(function( index ) {
6228
+ var self = set.eq( index );
6229
+ if ( isFunction ) {
6230
+ args[0] = value.call( this, index, self.html() );
6231
+ }
6232
+ self.domManip( args, callback, allowIntersection );
6233
+ });
6234
+ }
6235
+
6236
+ if ( l ) {
6237
+ fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this );
6238
+ first = fragment.firstChild;
6239
+
6240
+ if ( fragment.childNodes.length === 1 ) {
6241
+ fragment = first;
6242
+ }
6243
+
6244
+ if ( first ) {
6245
+ scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
6246
+ hasScripts = scripts.length;
6247
+
6248
+ // Use the original fragment for the last item instead of the first because it can end up
6249
+ // being emptied incorrectly in certain situations (#8070).
6250
+ for ( ; i < l; i++ ) {
6251
+ node = fragment;
6252
+
6253
+ if ( i !== iNoClone ) {
6254
+ node = jQuery.clone( node, true, true );
6255
+
6256
+ // Keep references to cloned scripts for later restoration
6257
+ if ( hasScripts ) {
6258
+ jQuery.merge( scripts, getAll( node, "script" ) );
6259
+ }
6260
+ }
6261
+
6262
+ callback.call( this[i], node, i );
6263
+ }
6264
+
6265
+ if ( hasScripts ) {
6266
+ doc = scripts[ scripts.length - 1 ].ownerDocument;
6267
+
6268
+ // Reenable scripts
6269
+ jQuery.map( scripts, restoreScript );
6270
+
6271
+ // Evaluate executable scripts on first document insertion
6272
+ for ( i = 0; i < hasScripts; i++ ) {
6273
+ node = scripts[ i ];
6274
+ if ( rscriptType.test( node.type || "" ) &&
6275
+ !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
6276
+
6277
+ if ( node.src ) {
6278
+ // Hope ajax is available...
6279
+ jQuery._evalUrl( node.src );
6280
+ } else {
6281
+ jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
6282
+ }
6283
+ }
6284
+ }
6285
+ }
6286
+
6287
+ // Fix #11809: Avoid leaking memory
6288
+ fragment = first = null;
6289
+ }
6290
+ }
6291
+
6292
+ return this;
6293
+ }
6294
+ });
6295
+
6296
+ // Support: IE<8
6297
+ // Manipulating tables requires a tbody
6298
+ function manipulationTarget( elem, content ) {
6299
+ return jQuery.nodeName( elem, "table" ) &&
6300
+ jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ?
6301
+
6302
+ elem.getElementsByTagName("tbody")[0] ||
6303
+ elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
6304
+ elem;
6305
+ }
6306
+
6307
+ // Replace/restore the type attribute of script elements for safe DOM manipulation
6308
+ function disableScript( elem ) {
6309
+ elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type;
6310
+ return elem;
6311
+ }
6312
+ function restoreScript( elem ) {
6313
+ var match = rscriptTypeMasked.exec( elem.type );
6314
+ if ( match ) {
6315
+ elem.type = match[1];
6316
+ } else {
6317
+ elem.removeAttribute("type");
6318
+ }
6319
+ return elem;
6320
+ }
6321
+
6322
+ // Mark scripts as having already been evaluated
6323
+ function setGlobalEval( elems, refElements ) {
6324
+ var elem,
6325
+ i = 0;
6326
+ for ( ; (elem = elems[i]) != null; i++ ) {
6327
+ jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
6328
+ }
6329
+ }
6330
+
6331
+ function cloneCopyEvent( src, dest ) {
6332
+
6333
+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
6334
+ return;
6335
+ }
6336
+
6337
+ var type, i, l,
6338
+ oldData = jQuery._data( src ),
6339
+ curData = jQuery._data( dest, oldData ),
6340
+ events = oldData.events;
6341
+
6342
+ if ( events ) {
6343
+ delete curData.handle;
6344
+ curData.events = {};
6345
+
6346
+ for ( type in events ) {
6347
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
6348
+ jQuery.event.add( dest, type, events[ type ][ i ] );
6349
+ }
6350
+ }
6351
+ }
6352
+
6353
+ // make the cloned public data object a copy from the original
6354
+ if ( curData.data ) {
6355
+ curData.data = jQuery.extend( {}, curData.data );
6356
+ }
6357
+ }
6358
+
6359
+ function fixCloneNodeIssues( src, dest ) {
6360
+ var nodeName, e, data;
6361
+
6362
+ // We do not need to do anything for non-Elements
6363
+ if ( dest.nodeType !== 1 ) {
6364
+ return;
6365
+ }
6366
+
6367
+ nodeName = dest.nodeName.toLowerCase();
6368
+
6369
+ // IE6-8 copies events bound via attachEvent when using cloneNode.
6370
+ if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {
6371
+ data = jQuery._data( dest );
6372
+
6373
+ for ( e in data.events ) {
6374
+ jQuery.removeEvent( dest, e, data.handle );
6375
+ }
6376
+
6377
+ // Event data gets referenced instead of copied if the expando gets copied too
6378
+ dest.removeAttribute( jQuery.expando );
6379
+ }
6380
+
6381
+ // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
6382
+ if ( nodeName === "script" && dest.text !== src.text ) {
6383
+ disableScript( dest ).text = src.text;
6384
+ restoreScript( dest );
6385
+
6386
+ // IE6-10 improperly clones children of object elements using classid.
6387
+ // IE10 throws NoModificationAllowedError if parent is null, #12132.
6388
+ } else if ( nodeName === "object" ) {
6389
+ if ( dest.parentNode ) {
6390
+ dest.outerHTML = src.outerHTML;
6391
+ }
6392
+
6393
+ // This path appears unavoidable for IE9. When cloning an object
6394
+ // element in IE9, the outerHTML strategy above is not sufficient.
6395
+ // If the src has innerHTML and the destination does not,
6396
+ // copy the src.innerHTML into the dest.innerHTML. #10324
6397
+ if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
6398
+ dest.innerHTML = src.innerHTML;
6399
+ }
6400
+
6401
+ } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) {
6402
+ // IE6-8 fails to persist the checked state of a cloned checkbox
6403
+ // or radio button. Worse, IE6-7 fail to give the cloned element
6404
+ // a checked appearance if the defaultChecked value isn't also set
6405
+
6406
+ dest.defaultChecked = dest.checked = src.checked;
6407
+
6408
+ // IE6-7 get confused and end up setting the value of a cloned
6409
+ // checkbox/radio button to an empty string instead of "on"
6410
+ if ( dest.value !== src.value ) {
6411
+ dest.value = src.value;
6412
+ }
6413
+
6414
+ // IE6-8 fails to return the selected option to the default selected
6415
+ // state when cloning options
6416
+ } else if ( nodeName === "option" ) {
6417
+ dest.defaultSelected = dest.selected = src.defaultSelected;
6418
+
6419
+ // IE6-8 fails to set the defaultValue to the correct value when
6420
+ // cloning other types of input fields
6421
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
6422
+ dest.defaultValue = src.defaultValue;
6423
+ }
6424
+ }
6425
+
6426
+ jQuery.each({
6427
+ appendTo: "append",
6428
+ prependTo: "prepend",
6429
+ insertBefore: "before",
6430
+ insertAfter: "after",
6431
+ replaceAll: "replaceWith"
6432
+ }, function( name, original ) {
6433
+ jQuery.fn[ name ] = function( selector ) {
6434
+ var elems,
6435
+ i = 0,
6436
+ ret = [],
6437
+ insert = jQuery( selector ),
6438
+ last = insert.length - 1;
6439
+
6440
+ for ( ; i <= last; i++ ) {
6441
+ elems = i === last ? this : this.clone(true);
6442
+ jQuery( insert[i] )[ original ]( elems );
6443
+
6444
+ // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
6445
+ core_push.apply( ret, elems.get() );
6446
+ }
6447
+
6448
+ return this.pushStack( ret );
6449
+ };
6450
+ });
6451
+
6452
+ function getAll( context, tag ) {
6453
+ var elems, elem,
6454
+ i = 0,
6455
+ found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) :
6456
+ typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) :
6457
+ undefined;
6458
+
6459
+ if ( !found ) {
6460
+ for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
6461
+ if ( !tag || jQuery.nodeName( elem, tag ) ) {
6462
+ found.push( elem );
6463
+ } else {
6464
+ jQuery.merge( found, getAll( elem, tag ) );
6465
+ }
6466
+ }
6467
+ }
6468
+
6469
+ return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
6470
+ jQuery.merge( [ context ], found ) :
6471
+ found;
6472
+ }
6473
+
6474
+ // Used in buildFragment, fixes the defaultChecked property
6475
+ function fixDefaultChecked( elem ) {
6476
+ if ( manipulation_rcheckableType.test( elem.type ) ) {
6477
+ elem.defaultChecked = elem.checked;
6478
+ }
6479
+ }
6480
+
6481
+ jQuery.extend({
6482
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
6483
+ var destElements, node, clone, i, srcElements,
6484
+ inPage = jQuery.contains( elem.ownerDocument, elem );
6485
+
6486
+ if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
6487
+ clone = elem.cloneNode( true );
6488
+
6489
+ // IE<=8 does not properly clone detached, unknown element nodes
6490
+ } else {
6491
+ fragmentDiv.innerHTML = elem.outerHTML;
6492
+ fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
6493
+ }
6494
+
6495
+ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
6496
+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
6497
+
6498
+ // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
6499
+ destElements = getAll( clone );
6500
+ srcElements = getAll( elem );
6501
+
6502
+ // Fix all IE cloning issues
6503
+ for ( i = 0; (node = srcElements[i]) != null; ++i ) {
6504
+ // Ensure that the destination node is not null; Fixes #9587
6505
+ if ( destElements[i] ) {
6506
+ fixCloneNodeIssues( node, destElements[i] );
6507
+ }
6508
+ }
6509
+ }
6510
+
6511
+ // Copy the events from the original to the clone
6512
+ if ( dataAndEvents ) {
6513
+ if ( deepDataAndEvents ) {
6514
+ srcElements = srcElements || getAll( elem );
6515
+ destElements = destElements || getAll( clone );
6516
+
6517
+ for ( i = 0; (node = srcElements[i]) != null; i++ ) {
6518
+ cloneCopyEvent( node, destElements[i] );
6519
+ }
6520
+ } else {
6521
+ cloneCopyEvent( elem, clone );
6522
+ }
6523
+ }
6524
+
6525
+ // Preserve script evaluation history
6526
+ destElements = getAll( clone, "script" );
6527
+ if ( destElements.length > 0 ) {
6528
+ setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
6529
+ }
6530
+
6531
+ destElements = srcElements = node = null;
6532
+
6533
+ // Return the cloned set
6534
+ return clone;
6535
+ },
6536
+
6537
+ buildFragment: function( elems, context, scripts, selection ) {
6538
+ var j, elem, contains,
6539
+ tmp, tag, tbody, wrap,
6540
+ l = elems.length,
6541
+
6542
+ // Ensure a safe fragment
6543
+ safe = createSafeFragment( context ),
6544
+
6545
+ nodes = [],
6546
+ i = 0;
6547
+
6548
+ for ( ; i < l; i++ ) {
6549
+ elem = elems[ i ];
6550
+
6551
+ if ( elem || elem === 0 ) {
6552
+
6553
+ // Add nodes directly
6554
+ if ( jQuery.type( elem ) === "object" ) {
6555
+ jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
6556
+
6557
+ // Convert non-html into a text node
6558
+ } else if ( !rhtml.test( elem ) ) {
6559
+ nodes.push( context.createTextNode( elem ) );
6560
+
6561
+ // Convert html into DOM nodes
6562
+ } else {
6563
+ tmp = tmp || safe.appendChild( context.createElement("div") );
6564
+
6565
+ // Deserialize a standard representation
6566
+ tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
6567
+ wrap = wrapMap[ tag ] || wrapMap._default;
6568
+
6569
+ tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
6570
+
6571
+ // Descend through wrappers to the right content
6572
+ j = wrap[0];
6573
+ while ( j-- ) {
6574
+ tmp = tmp.lastChild;
6575
+ }
6576
+
6577
+ // Manually add leading whitespace removed by IE
6578
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
6579
+ nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
6580
+ }
6581
+
6582
+ // Remove IE's autoinserted <tbody> from table fragments
6583
+ if ( !jQuery.support.tbody ) {
6584
+
6585
+ // String was a <table>, *may* have spurious <tbody>
6586
+ elem = tag === "table" && !rtbody.test( elem ) ?
6587
+ tmp.firstChild :
6588
+
6589
+ // String was a bare <thead> or <tfoot>
6590
+ wrap[1] === "<table>" && !rtbody.test( elem ) ?
6591
+ tmp :
6592
+ 0;
6593
+
6594
+ j = elem && elem.childNodes.length;
6595
+ while ( j-- ) {
6596
+ if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
6597
+ elem.removeChild( tbody );
6598
+ }
6599
+ }
6600
+ }
6601
+
6602
+ jQuery.merge( nodes, tmp.childNodes );
6603
+
6604
+ // Fix #12392 for WebKit and IE > 9
6605
+ tmp.textContent = "";
6606
+
6607
+ // Fix #12392 for oldIE
6608
+ while ( tmp.firstChild ) {
6609
+ tmp.removeChild( tmp.firstChild );
6610
+ }
6611
+
6612
+ // Remember the top-level container for proper cleanup
6613
+ tmp = safe.lastChild;
6614
+ }
6615
+ }
6616
+ }
6617
+
6618
+ // Fix #11356: Clear elements from fragment
6619
+ if ( tmp ) {
6620
+ safe.removeChild( tmp );
6621
+ }
6622
+
6623
+ // Reset defaultChecked for any radios and checkboxes
6624
+ // about to be appended to the DOM in IE 6/7 (#8060)
6625
+ if ( !jQuery.support.appendChecked ) {
6626
+ jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
6627
+ }
6628
+
6629
+ i = 0;
6630
+ while ( (elem = nodes[ i++ ]) ) {
6631
+
6632
+ // #4087 - If origin and destination elements are the same, and this is
6633
+ // that element, do not do anything
6634
+ if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
6635
+ continue;
6636
+ }
6637
+
6638
+ contains = jQuery.contains( elem.ownerDocument, elem );
6639
+
6640
+ // Append to fragment
6641
+ tmp = getAll( safe.appendChild( elem ), "script" );
6642
+
6643
+ // Preserve script evaluation history
6644
+ if ( contains ) {
6645
+ setGlobalEval( tmp );
6646
+ }
6647
+
6648
+ // Capture executables
6649
+ if ( scripts ) {
6650
+ j = 0;
6651
+ while ( (elem = tmp[ j++ ]) ) {
6652
+ if ( rscriptType.test( elem.type || "" ) ) {
6653
+ scripts.push( elem );
6654
+ }
6655
+ }
6656
+ }
6657
+ }
6658
+
6659
+ tmp = null;
6660
+
6661
+ return safe;
6662
+ },
6663
+
6664
+ cleanData: function( elems, /* internal */ acceptData ) {
6665
+ var elem, type, id, data,
6666
+ i = 0,
6667
+ internalKey = jQuery.expando,
6668
+ cache = jQuery.cache,
6669
+ deleteExpando = jQuery.support.deleteExpando,
6670
+ special = jQuery.event.special;
6671
+
6672
+ for ( ; (elem = elems[i]) != null; i++ ) {
6673
+
6674
+ if ( acceptData || jQuery.acceptData( elem ) ) {
6675
+
6676
+ id = elem[ internalKey ];
6677
+ data = id && cache[ id ];
6678
+
6679
+ if ( data ) {
6680
+ if ( data.events ) {
6681
+ for ( type in data.events ) {
6682
+ if ( special[ type ] ) {
6683
+ jQuery.event.remove( elem, type );
6684
+
6685
+ // This is a shortcut to avoid jQuery.event.remove's overhead
6686
+ } else {
6687
+ jQuery.removeEvent( elem, type, data.handle );
6688
+ }
6689
+ }
6690
+ }
6691
+
6692
+ // Remove cache only if it was not already removed by jQuery.event.remove
6693
+ if ( cache[ id ] ) {
6694
+
6695
+ delete cache[ id ];
6696
+
6697
+ // IE does not allow us to delete expando properties from nodes,
6698
+ // nor does it have a removeAttribute function on Document nodes;
6699
+ // we must handle all of these cases
6700
+ if ( deleteExpando ) {
6701
+ delete elem[ internalKey ];
6702
+
6703
+ } else if ( typeof elem.removeAttribute !== core_strundefined ) {
6704
+ elem.removeAttribute( internalKey );
6705
+
6706
+ } else {
6707
+ elem[ internalKey ] = null;
6708
+ }
6709
+
6710
+ core_deletedIds.push( id );
6711
+ }
6712
+ }
6713
+ }
6714
+ }
6715
+ },
6716
+
6717
+ _evalUrl: function( url ) {
6718
+ return jQuery.ajax({
6719
+ url: url,
6720
+ type: "GET",
6721
+ dataType: "script",
6722
+ async: false,
6723
+ global: false,
6724
+ "throws": true
6725
+ });
6726
+ }
6727
+ });
6728
+ jQuery.fn.extend({
6729
+ wrapAll: function( html ) {
6730
+ if ( jQuery.isFunction( html ) ) {
6731
+ return this.each(function(i) {
6732
+ jQuery(this).wrapAll( html.call(this, i) );
6733
+ });
6734
+ }
6735
+
6736
+ if ( this[0] ) {
6737
+ // The elements to wrap the target around
6738
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
6739
+
6740
+ if ( this[0].parentNode ) {
6741
+ wrap.insertBefore( this[0] );
6742
+ }
6743
+
6744
+ wrap.map(function() {
6745
+ var elem = this;
6746
+
6747
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
6748
+ elem = elem.firstChild;
6749
+ }
6750
+
6751
+ return elem;
6752
+ }).append( this );
6753
+ }
6754
+
6755
+ return this;
6756
+ },
6757
+
6758
+ wrapInner: function( html ) {
6759
+ if ( jQuery.isFunction( html ) ) {
6760
+ return this.each(function(i) {
6761
+ jQuery(this).wrapInner( html.call(this, i) );
6762
+ });
6763
+ }
6764
+
6765
+ return this.each(function() {
6766
+ var self = jQuery( this ),
6767
+ contents = self.contents();
6768
+
6769
+ if ( contents.length ) {
6770
+ contents.wrapAll( html );
6771
+
6772
+ } else {
6773
+ self.append( html );
6774
+ }
6775
+ });
6776
+ },
6777
+
6778
+ wrap: function( html ) {
6779
+ var isFunction = jQuery.isFunction( html );
6780
+
6781
+ return this.each(function(i) {
6782
+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
6783
+ });
6784
+ },
6785
+
6786
+ unwrap: function() {
6787
+ return this.parent().each(function() {
6788
+ if ( !jQuery.nodeName( this, "body" ) ) {
6789
+ jQuery( this ).replaceWith( this.childNodes );
6790
+ }
6791
+ }).end();
6792
+ }
6793
+ });
6794
+ var iframe, getStyles, curCSS,
6795
+ ralpha = /alpha\([^)]*\)/i,
6796
+ ropacity = /opacity\s*=\s*([^)]*)/,
6797
+ rposition = /^(top|right|bottom|left)$/,
6798
+ // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
6799
+ // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6800
+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6801
+ rmargin = /^margin/,
6802
+ rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
6803
+ rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
6804
+ rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ),
6805
+ elemdisplay = { BODY: "block" },
6806
+
6807
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6808
+ cssNormalTransform = {
6809
+ letterSpacing: 0,
6810
+ fontWeight: 400
6811
+ },
6812
+
6813
+ cssExpand = [ "Top", "Right", "Bottom", "Left" ],
6814
+ cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
6815
+
6816
+ // return a css property mapped to a potentially vendor prefixed property
6817
+ function vendorPropName( style, name ) {
6818
+
6819
+ // shortcut for names that are not vendor prefixed
6820
+ if ( name in style ) {
6821
+ return name;
6822
+ }
6823
+
6824
+ // check for vendor prefixed names
6825
+ var capName = name.charAt(0).toUpperCase() + name.slice(1),
6826
+ origName = name,
6827
+ i = cssPrefixes.length;
6828
+
6829
+ while ( i-- ) {
6830
+ name = cssPrefixes[ i ] + capName;
6831
+ if ( name in style ) {
6832
+ return name;
6833
+ }
6834
+ }
6835
+
6836
+ return origName;
6837
+ }
6838
+
6839
+ function isHidden( elem, el ) {
6840
+ // isHidden might be called from jQuery#filter function;
6841
+ // in that case, element will be second argument
6842
+ elem = el || elem;
6843
+ return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
6844
+ }
6845
+
6846
+ function showHide( elements, show ) {
6847
+ var display, elem, hidden,
6848
+ values = [],
6849
+ index = 0,
6850
+ length = elements.length;
6851
+
6852
+ for ( ; index < length; index++ ) {
6853
+ elem = elements[ index ];
6854
+ if ( !elem.style ) {
6855
+ continue;
6856
+ }
6857
+
6858
+ values[ index ] = jQuery._data( elem, "olddisplay" );
6859
+ display = elem.style.display;
6860
+ if ( show ) {
6861
+ // Reset the inline display of this element to learn if it is
6862
+ // being hidden by cascaded rules or not
6863
+ if ( !values[ index ] && display === "none" ) {
6864
+ elem.style.display = "";
6865
+ }
6866
+
6867
+ // Set elements which have been overridden with display: none
6868
+ // in a stylesheet to whatever the default browser style is
6869
+ // for such an element
6870
+ if ( elem.style.display === "" && isHidden( elem ) ) {
6871
+ values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
6872
+ }
6873
+ } else {
6874
+
6875
+ if ( !values[ index ] ) {
6876
+ hidden = isHidden( elem );
6877
+
6878
+ if ( display && display !== "none" || !hidden ) {
6879
+ jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
6880
+ }
6881
+ }
6882
+ }
6883
+ }
6884
+
6885
+ // Set the display of most of the elements in a second loop
6886
+ // to avoid the constant reflow
6887
+ for ( index = 0; index < length; index++ ) {
6888
+ elem = elements[ index ];
6889
+ if ( !elem.style ) {
6890
+ continue;
6891
+ }
6892
+ if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
6893
+ elem.style.display = show ? values[ index ] || "" : "none";
6894
+ }
6895
+ }
6896
+
6897
+ return elements;
6898
+ }
6899
+
6900
+ jQuery.fn.extend({
6901
+ css: function( name, value ) {
6902
+ return jQuery.access( this, function( elem, name, value ) {
6903
+ var len, styles,
6904
+ map = {},
6905
+ i = 0;
6906
+
6907
+ if ( jQuery.isArray( name ) ) {
6908
+ styles = getStyles( elem );
6909
+ len = name.length;
6910
+
6911
+ for ( ; i < len; i++ ) {
6912
+ map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6913
+ }
6914
+
6915
+ return map;
6916
+ }
6917
+
6918
+ return value !== undefined ?
6919
+ jQuery.style( elem, name, value ) :
6920
+ jQuery.css( elem, name );
6921
+ }, name, value, arguments.length > 1 );
6922
+ },
6923
+ show: function() {
6924
+ return showHide( this, true );
6925
+ },
6926
+ hide: function() {
6927
+ return showHide( this );
6928
+ },
6929
+ toggle: function( state ) {
6930
+ if ( typeof state === "boolean" ) {
6931
+ return state ? this.show() : this.hide();
6932
+ }
6933
+
6934
+ return this.each(function() {
6935
+ if ( isHidden( this ) ) {
6936
+ jQuery( this ).show();
6937
+ } else {
6938
+ jQuery( this ).hide();
6939
+ }
6940
+ });
6941
+ }
6942
+ });
6943
+
6944
+ jQuery.extend({
6945
+ // Add in style property hooks for overriding the default
6946
+ // behavior of getting and setting a style property
6947
+ cssHooks: {
6948
+ opacity: {
6949
+ get: function( elem, computed ) {
6950
+ if ( computed ) {
6951
+ // We should always get a number back from opacity
6952
+ var ret = curCSS( elem, "opacity" );
6953
+ return ret === "" ? "1" : ret;
6954
+ }
6955
+ }
6956
+ }
6957
+ },
6958
+
6959
+ // Don't automatically add "px" to these possibly-unitless properties
6960
+ cssNumber: {
6961
+ "columnCount": true,
6962
+ "fillOpacity": true,
6963
+ "fontWeight": true,
6964
+ "lineHeight": true,
6965
+ "opacity": true,
6966
+ "order": true,
6967
+ "orphans": true,
6968
+ "widows": true,
6969
+ "zIndex": true,
6970
+ "zoom": true
6971
+ },
6972
+
6973
+ // Add in properties whose names you wish to fix before
6974
+ // setting or getting the value
6975
+ cssProps: {
6976
+ // normalize float css property
6977
+ "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
6978
+ },
6979
+
6980
+ // Get and set the style property on a DOM Node
6981
+ style: function( elem, name, value, extra ) {
6982
+ // Don't set styles on text and comment nodes
6983
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6984
+ return;
6985
+ }
6986
+
6987
+ // Make sure that we're working with the right name
6988
+ var ret, type, hooks,
6989
+ origName = jQuery.camelCase( name ),
6990
+ style = elem.style;
6991
+
6992
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
6993
+
6994
+ // gets hook for the prefixed version
6995
+ // followed by the unprefixed version
6996
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6997
+
6998
+ // Check if we're setting a value
6999
+ if ( value !== undefined ) {
7000
+ type = typeof value;
7001
+
7002
+ // convert relative number strings (+= or -=) to relative numbers. #7345
7003
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
7004
+ value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
7005
+ // Fixes bug #9237
7006
+ type = "number";
7007
+ }
7008
+
7009
+ // Make sure that NaN and null values aren't set. See: #7116
7010
+ if ( value == null || type === "number" && isNaN( value ) ) {
7011
+ return;
7012
+ }
7013
+
7014
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
7015
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
7016
+ value += "px";
7017
+ }
7018
+
7019
+ // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
7020
+ // but it would mean to define eight (for every problematic property) identical functions
7021
+ if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
7022
+ style[ name ] = "inherit";
7023
+ }
7024
+
7025
+ // If a hook was provided, use that value, otherwise just set the specified value
7026
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
7027
+
7028
+ // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
7029
+ // Fixes bug #5509
7030
+ try {
7031
+ style[ name ] = value;
7032
+ } catch(e) {}
7033
+ }
7034
+
7035
+ } else {
7036
+ // If a hook was provided get the non-computed value from there
7037
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
7038
+ return ret;
7039
+ }
7040
+
7041
+ // Otherwise just get the value from the style object
7042
+ return style[ name ];
7043
+ }
7044
+ },
7045
+
7046
+ css: function( elem, name, extra, styles ) {
7047
+ var num, val, hooks,
7048
+ origName = jQuery.camelCase( name );
7049
+
7050
+ // Make sure that we're working with the right name
7051
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
7052
+
7053
+ // gets hook for the prefixed version
7054
+ // followed by the unprefixed version
7055
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
7056
+
7057
+ // If a hook was provided get the computed value from there
7058
+ if ( hooks && "get" in hooks ) {
7059
+ val = hooks.get( elem, true, extra );
7060
+ }
7061
+
7062
+ // Otherwise, if a way to get the computed value exists, use that
7063
+ if ( val === undefined ) {
7064
+ val = curCSS( elem, name, styles );
7065
+ }
7066
+
7067
+ //convert "normal" to computed value
7068
+ if ( val === "normal" && name in cssNormalTransform ) {
7069
+ val = cssNormalTransform[ name ];
7070
+ }
7071
+
7072
+ // Return, converting to number if forced or a qualifier was provided and val looks numeric
7073
+ if ( extra === "" || extra ) {
7074
+ num = parseFloat( val );
7075
+ return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
7076
+ }
7077
+ return val;
7078
+ }
7079
+ });
7080
+
7081
+ // NOTE: we've included the "window" in window.getComputedStyle
7082
+ // because jsdom on node.js will break without it.
7083
+ if ( window.getComputedStyle ) {
7084
+ getStyles = function( elem ) {
7085
+ return window.getComputedStyle( elem, null );
7086
+ };
7087
+
7088
+ curCSS = function( elem, name, _computed ) {
7089
+ var width, minWidth, maxWidth,
7090
+ computed = _computed || getStyles( elem ),
7091
+
7092
+ // getPropertyValue is only needed for .css('filter') in IE9, see #12537
7093
+ ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,
7094
+ style = elem.style;
7095
+
7096
+ if ( computed ) {
7097
+
7098
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
7099
+ ret = jQuery.style( elem, name );
7100
+ }
7101
+
7102
+ // A tribute to the "awesome hack by Dean Edwards"
7103
+ // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
7104
+ // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
7105
+ // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
7106
+ if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
7107
+
7108
+ // Remember the original values
7109
+ width = style.width;
7110
+ minWidth = style.minWidth;
7111
+ maxWidth = style.maxWidth;
7112
+
7113
+ // Put in the new values to get a computed value out
7114
+ style.minWidth = style.maxWidth = style.width = ret;
7115
+ ret = computed.width;
7116
+
7117
+ // Revert the changed values
7118
+ style.width = width;
7119
+ style.minWidth = minWidth;
7120
+ style.maxWidth = maxWidth;
7121
+ }
7122
+ }
7123
+
7124
+ return ret;
7125
+ };
7126
+ } else if ( document.documentElement.currentStyle ) {
7127
+ getStyles = function( elem ) {
7128
+ return elem.currentStyle;
7129
+ };
7130
+
7131
+ curCSS = function( elem, name, _computed ) {
7132
+ var left, rs, rsLeft,
7133
+ computed = _computed || getStyles( elem ),
7134
+ ret = computed ? computed[ name ] : undefined,
7135
+ style = elem.style;
7136
+
7137
+ // Avoid setting ret to empty string here
7138
+ // so we don't default to auto
7139
+ if ( ret == null && style && style[ name ] ) {
7140
+ ret = style[ name ];
7141
+ }
7142
+
7143
+ // From the awesome hack by Dean Edwards
7144
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
7145
+
7146
+ // If we're not dealing with a regular pixel number
7147
+ // but a number that has a weird ending, we need to convert it to pixels
7148
+ // but not position css attributes, as those are proportional to the parent element instead
7149
+ // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
7150
+ if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
7151
+
7152
+ // Remember the original values
7153
+ left = style.left;
7154
+ rs = elem.runtimeStyle;
7155
+ rsLeft = rs && rs.left;
7156
+
7157
+ // Put in the new values to get a computed value out
7158
+ if ( rsLeft ) {
7159
+ rs.left = elem.currentStyle.left;
7160
+ }
7161
+ style.left = name === "fontSize" ? "1em" : ret;
7162
+ ret = style.pixelLeft + "px";
7163
+
7164
+ // Revert the changed values
7165
+ style.left = left;
7166
+ if ( rsLeft ) {
7167
+ rs.left = rsLeft;
7168
+ }
7169
+ }
7170
+
7171
+ return ret === "" ? "auto" : ret;
7172
+ };
7173
+ }
7174
+
7175
+ function setPositiveNumber( elem, value, subtract ) {
7176
+ var matches = rnumsplit.exec( value );
7177
+ return matches ?
7178
+ // Guard against undefined "subtract", e.g., when used as in cssHooks
7179
+ Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
7180
+ value;
7181
+ }
7182
+
7183
+ function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
7184
+ var i = extra === ( isBorderBox ? "border" : "content" ) ?
7185
+ // If we already have the right measurement, avoid augmentation
7186
+ 4 :
7187
+ // Otherwise initialize for horizontal or vertical properties
7188
+ name === "width" ? 1 : 0,
7189
+
7190
+ val = 0;
7191
+
7192
+ for ( ; i < 4; i += 2 ) {
7193
+ // both box models exclude margin, so add it if we want it
7194
+ if ( extra === "margin" ) {
7195
+ val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
7196
+ }
7197
+
7198
+ if ( isBorderBox ) {
7199
+ // border-box includes padding, so remove it if we want content
7200
+ if ( extra === "content" ) {
7201
+ val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7202
+ }
7203
+
7204
+ // at this point, extra isn't border nor margin, so remove border
7205
+ if ( extra !== "margin" ) {
7206
+ val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7207
+ }
7208
+ } else {
7209
+ // at this point, extra isn't content, so add padding
7210
+ val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7211
+
7212
+ // at this point, extra isn't content nor padding, so add border
7213
+ if ( extra !== "padding" ) {
7214
+ val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7215
+ }
7216
+ }
7217
+ }
7218
+
7219
+ return val;
7220
+ }
7221
+
7222
+ function getWidthOrHeight( elem, name, extra ) {
7223
+
7224
+ // Start with offset property, which is equivalent to the border-box value
7225
+ var valueIsBorderBox = true,
7226
+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
7227
+ styles = getStyles( elem ),
7228
+ isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
7229
+
7230
+ // some non-html elements return undefined for offsetWidth, so check for null/undefined
7231
+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
7232
+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
7233
+ if ( val <= 0 || val == null ) {
7234
+ // Fall back to computed then uncomputed css if necessary
7235
+ val = curCSS( elem, name, styles );
7236
+ if ( val < 0 || val == null ) {
7237
+ val = elem.style[ name ];
7238
+ }
7239
+
7240
+ // Computed unit is not pixels. Stop here and return.
7241
+ if ( rnumnonpx.test(val) ) {
7242
+ return val;
7243
+ }
7244
+
7245
+ // we need the check for style in case a browser which returns unreliable values
7246
+ // for getComputedStyle silently falls back to the reliable elem.style
7247
+ valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
7248
+
7249
+ // Normalize "", auto, and prepare for extra
7250
+ val = parseFloat( val ) || 0;
7251
+ }
7252
+
7253
+ // use the active box-sizing model to add/subtract irrelevant styles
7254
+ return ( val +
7255
+ augmentWidthOrHeight(
7256
+ elem,
7257
+ name,
7258
+ extra || ( isBorderBox ? "border" : "content" ),
7259
+ valueIsBorderBox,
7260
+ styles
7261
+ )
7262
+ ) + "px";
7263
+ }
7264
+
7265
+ // Try to determine the default display value of an element
7266
+ function css_defaultDisplay( nodeName ) {
7267
+ var doc = document,
7268
+ display = elemdisplay[ nodeName ];
7269
+
7270
+ if ( !display ) {
7271
+ display = actualDisplay( nodeName, doc );
7272
+
7273
+ // If the simple way fails, read from inside an iframe
7274
+ if ( display === "none" || !display ) {
7275
+ // Use the already-created iframe if possible
7276
+ iframe = ( iframe ||
7277
+ jQuery("<iframe frameborder='0' width='0' height='0'/>")
7278
+ .css( "cssText", "display:block !important" )
7279
+ ).appendTo( doc.documentElement );
7280
+
7281
+ // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
7282
+ doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
7283
+ doc.write("<!doctype html><html><body>");
7284
+ doc.close();
7285
+
7286
+ display = actualDisplay( nodeName, doc );
7287
+ iframe.detach();
7288
+ }
7289
+
7290
+ // Store the correct default display
7291
+ elemdisplay[ nodeName ] = display;
7292
+ }
7293
+
7294
+ return display;
7295
+ }
7296
+
7297
+ // Called ONLY from within css_defaultDisplay
7298
+ function actualDisplay( name, doc ) {
7299
+ var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
7300
+ display = jQuery.css( elem[0], "display" );
7301
+ elem.remove();
7302
+ return display;
7303
+ }
7304
+
7305
+ jQuery.each([ "height", "width" ], function( i, name ) {
7306
+ jQuery.cssHooks[ name ] = {
7307
+ get: function( elem, computed, extra ) {
7308
+ if ( computed ) {
7309
+ // certain elements can have dimension info if we invisibly show them
7310
+ // however, it must have a current display style that would benefit from this
7311
+ return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
7312
+ jQuery.swap( elem, cssShow, function() {
7313
+ return getWidthOrHeight( elem, name, extra );
7314
+ }) :
7315
+ getWidthOrHeight( elem, name, extra );
7316
+ }
7317
+ },
7318
+
7319
+ set: function( elem, value, extra ) {
7320
+ var styles = extra && getStyles( elem );
7321
+ return setPositiveNumber( elem, value, extra ?
7322
+ augmentWidthOrHeight(
7323
+ elem,
7324
+ name,
7325
+ extra,
7326
+ jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
7327
+ styles
7328
+ ) : 0
7329
+ );
7330
+ }
7331
+ };
7332
+ });
7333
+
7334
+ if ( !jQuery.support.opacity ) {
7335
+ jQuery.cssHooks.opacity = {
7336
+ get: function( elem, computed ) {
7337
+ // IE uses filters for opacity
7338
+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
7339
+ ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
7340
+ computed ? "1" : "";
7341
+ },
7342
+
7343
+ set: function( elem, value ) {
7344
+ var style = elem.style,
7345
+ currentStyle = elem.currentStyle,
7346
+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
7347
+ filter = currentStyle && currentStyle.filter || style.filter || "";
7348
+
7349
+ // IE has trouble with opacity if it does not have layout
7350
+ // Force it by setting the zoom level
7351
+ style.zoom = 1;
7352
+
7353
+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
7354
+ // if value === "", then remove inline opacity #12685
7355
+ if ( ( value >= 1 || value === "" ) &&
7356
+ jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
7357
+ style.removeAttribute ) {
7358
+
7359
+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
7360
+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
7361
+ // style.removeAttribute is IE Only, but so apparently is this code path...
7362
+ style.removeAttribute( "filter" );
7363
+
7364
+ // if there is no filter style applied in a css rule or unset inline opacity, we are done
7365
+ if ( value === "" || currentStyle && !currentStyle.filter ) {
7366
+ return;
7367
+ }
7368
+ }
7369
+
7370
+ // otherwise, set new filter values
7371
+ style.filter = ralpha.test( filter ) ?
7372
+ filter.replace( ralpha, opacity ) :
7373
+ filter + " " + opacity;
7374
+ }
7375
+ };
7376
+ }
7377
+
7378
+ // These hooks cannot be added until DOM ready because the support test
7379
+ // for it is not run until after DOM ready
7380
+ jQuery(function() {
7381
+ if ( !jQuery.support.reliableMarginRight ) {
7382
+ jQuery.cssHooks.marginRight = {
7383
+ get: function( elem, computed ) {
7384
+ if ( computed ) {
7385
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
7386
+ // Work around by temporarily setting element display to inline-block
7387
+ return jQuery.swap( elem, { "display": "inline-block" },
7388
+ curCSS, [ elem, "marginRight" ] );
7389
+ }
7390
+ }
7391
+ };
7392
+ }
7393
+
7394
+ // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
7395
+ // getComputedStyle returns percent when specified for top/left/bottom/right
7396
+ // rather than make the css module depend on the offset module, we just check for it here
7397
+ if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
7398
+ jQuery.each( [ "top", "left" ], function( i, prop ) {
7399
+ jQuery.cssHooks[ prop ] = {
7400
+ get: function( elem, computed ) {
7401
+ if ( computed ) {
7402
+ computed = curCSS( elem, prop );
7403
+ // if curCSS returns percentage, fallback to offset
7404
+ return rnumnonpx.test( computed ) ?
7405
+ jQuery( elem ).position()[ prop ] + "px" :
7406
+ computed;
7407
+ }
7408
+ }
7409
+ };
7410
+ });
7411
+ }
7412
+
7413
+ });
7414
+
7415
+ if ( jQuery.expr && jQuery.expr.filters ) {
7416
+ jQuery.expr.filters.hidden = function( elem ) {
7417
+ // Support: Opera <= 12.12
7418
+ // Opera reports offsetWidths and offsetHeights less than zero on some elements
7419
+ return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
7420
+ (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
7421
+ };
7422
+
7423
+ jQuery.expr.filters.visible = function( elem ) {
7424
+ return !jQuery.expr.filters.hidden( elem );
7425
+ };
7426
+ }
7427
+
7428
+ // These hooks are used by animate to expand properties
7429
+ jQuery.each({
7430
+ margin: "",
7431
+ padding: "",
7432
+ border: "Width"
7433
+ }, function( prefix, suffix ) {
7434
+ jQuery.cssHooks[ prefix + suffix ] = {
7435
+ expand: function( value ) {
7436
+ var i = 0,
7437
+ expanded = {},
7438
+
7439
+ // assumes a single number if not a string
7440
+ parts = typeof value === "string" ? value.split(" ") : [ value ];
7441
+
7442
+ for ( ; i < 4; i++ ) {
7443
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
7444
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
7445
+ }
7446
+
7447
+ return expanded;
7448
+ }
7449
+ };
7450
+
7451
+ if ( !rmargin.test( prefix ) ) {
7452
+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
7453
+ }
7454
+ });
7455
+ var r20 = /%20/g,
7456
+ rbracket = /\[\]$/,
7457
+ rCRLF = /\r?\n/g,
7458
+ rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
7459
+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
7460
+
7461
+ jQuery.fn.extend({
7462
+ serialize: function() {
7463
+ return jQuery.param( this.serializeArray() );
7464
+ },
7465
+ serializeArray: function() {
7466
+ return this.map(function(){
7467
+ // Can add propHook for "elements" to filter or add form elements
7468
+ var elements = jQuery.prop( this, "elements" );
7469
+ return elements ? jQuery.makeArray( elements ) : this;
7470
+ })
7471
+ .filter(function(){
7472
+ var type = this.type;
7473
+ // Use .is(":disabled") so that fieldset[disabled] works
7474
+ return this.name && !jQuery( this ).is( ":disabled" ) &&
7475
+ rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
7476
+ ( this.checked || !manipulation_rcheckableType.test( type ) );
7477
+ })
7478
+ .map(function( i, elem ){
7479
+ var val = jQuery( this ).val();
7480
+
7481
+ return val == null ?
7482
+ null :
7483
+ jQuery.isArray( val ) ?
7484
+ jQuery.map( val, function( val ){
7485
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7486
+ }) :
7487
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7488
+ }).get();
7489
+ }
7490
+ });
7491
+
7492
+ //Serialize an array of form elements or a set of
7493
+ //key/values into a query string
7494
+ jQuery.param = function( a, traditional ) {
7495
+ var prefix,
7496
+ s = [],
7497
+ add = function( key, value ) {
7498
+ // If value is a function, invoke it and return its value
7499
+ value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
7500
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
7501
+ };
7502
+
7503
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
7504
+ if ( traditional === undefined ) {
7505
+ traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
7506
+ }
7507
+
7508
+ // If an array was passed in, assume that it is an array of form elements.
7509
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
7510
+ // Serialize the form elements
7511
+ jQuery.each( a, function() {
7512
+ add( this.name, this.value );
7513
+ });
7514
+
7515
+ } else {
7516
+ // If traditional, encode the "old" way (the way 1.3.2 or older
7517
+ // did it), otherwise encode params recursively.
7518
+ for ( prefix in a ) {
7519
+ buildParams( prefix, a[ prefix ], traditional, add );
7520
+ }
7521
+ }
7522
+
7523
+ // Return the resulting serialization
7524
+ return s.join( "&" ).replace( r20, "+" );
7525
+ };
7526
+
7527
+ function buildParams( prefix, obj, traditional, add ) {
7528
+ var name;
7529
+
7530
+ if ( jQuery.isArray( obj ) ) {
7531
+ // Serialize array item.
7532
+ jQuery.each( obj, function( i, v ) {
7533
+ if ( traditional || rbracket.test( prefix ) ) {
7534
+ // Treat each array item as a scalar.
7535
+ add( prefix, v );
7536
+
7537
+ } else {
7538
+ // Item is non-scalar (array or object), encode its numeric index.
7539
+ buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
7540
+ }
7541
+ });
7542
+
7543
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
7544
+ // Serialize object item.
7545
+ for ( name in obj ) {
7546
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
7547
+ }
7548
+
7549
+ } else {
7550
+ // Serialize scalar item.
7551
+ add( prefix, obj );
7552
+ }
7553
+ }
7554
+ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
7555
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
7556
+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
7557
+
7558
+ // Handle event binding
7559
+ jQuery.fn[ name ] = function( data, fn ) {
7560
+ return arguments.length > 0 ?
7561
+ this.on( name, null, data, fn ) :
7562
+ this.trigger( name );
7563
+ };
7564
+ });
7565
+
7566
+ jQuery.fn.extend({
7567
+ hover: function( fnOver, fnOut ) {
7568
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
7569
+ },
7570
+
7571
+ bind: function( types, data, fn ) {
7572
+ return this.on( types, null, data, fn );
7573
+ },
7574
+ unbind: function( types, fn ) {
7575
+ return this.off( types, null, fn );
7576
+ },
7577
+
7578
+ delegate: function( selector, types, data, fn ) {
7579
+ return this.on( types, selector, data, fn );
7580
+ },
7581
+ undelegate: function( selector, types, fn ) {
7582
+ // ( namespace ) or ( selector, types [, fn] )
7583
+ return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
7584
+ }
7585
+ });
7586
+ var
7587
+ // Document location
7588
+ ajaxLocParts,
7589
+ ajaxLocation,
7590
+ ajax_nonce = jQuery.now(),
7591
+
7592
+ ajax_rquery = /\?/,
7593
+ rhash = /#.*$/,
7594
+ rts = /([?&])_=[^&]*/,
7595
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
7596
+ // #7653, #8125, #8152: local protocol detection
7597
+ rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
7598
+ rnoContent = /^(?:GET|HEAD)$/,
7599
+ rprotocol = /^\/\//,
7600
+ rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
7601
+
7602
+ // Keep a copy of the old load method
7603
+ _load = jQuery.fn.load,
7604
+
7605
+ /* Prefilters
7606
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
7607
+ * 2) These are called:
7608
+ * - BEFORE asking for a transport
7609
+ * - AFTER param serialization (s.data is a string if s.processData is true)
7610
+ * 3) key is the dataType
7611
+ * 4) the catchall symbol "*" can be used
7612
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
7613
+ */
7614
+ prefilters = {},
7615
+
7616
+ /* Transports bindings
7617
+ * 1) key is the dataType
7618
+ * 2) the catchall symbol "*" can be used
7619
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
7620
+ */
7621
+ transports = {},
7622
+
7623
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
7624
+ allTypes = "*/".concat("*");
7625
+
7626
+ // #8138, IE may throw an exception when accessing
7627
+ // a field from window.location if document.domain has been set
7628
+ try {
7629
+ ajaxLocation = location.href;
7630
+ } catch( e ) {
7631
+ // Use the href attribute of an A element
7632
+ // since IE will modify it given document.location
7633
+ ajaxLocation = document.createElement( "a" );
7634
+ ajaxLocation.href = "";
7635
+ ajaxLocation = ajaxLocation.href;
7636
+ }
7637
+
7638
+ // Segment location into parts
7639
+ ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
7640
+
7641
+ // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
7642
+ function addToPrefiltersOrTransports( structure ) {
7643
+
7644
+ // dataTypeExpression is optional and defaults to "*"
7645
+ return function( dataTypeExpression, func ) {
7646
+
7647
+ if ( typeof dataTypeExpression !== "string" ) {
7648
+ func = dataTypeExpression;
7649
+ dataTypeExpression = "*";
7650
+ }
7651
+
7652
+ var dataType,
7653
+ i = 0,
7654
+ dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];
7655
+
7656
+ if ( jQuery.isFunction( func ) ) {
7657
+ // For each dataType in the dataTypeExpression
7658
+ while ( (dataType = dataTypes[i++]) ) {
7659
+ // Prepend if requested
7660
+ if ( dataType[0] === "+" ) {
7661
+ dataType = dataType.slice( 1 ) || "*";
7662
+ (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
7663
+
7664
+ // Otherwise append
7665
+ } else {
7666
+ (structure[ dataType ] = structure[ dataType ] || []).push( func );
7667
+ }
7668
+ }
7669
+ }
7670
+ };
7671
+ }
7672
+
7673
+ // Base inspection function for prefilters and transports
7674
+ function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
7675
+
7676
+ var inspected = {},
7677
+ seekingTransport = ( structure === transports );
7678
+
7679
+ function inspect( dataType ) {
7680
+ var selected;
7681
+ inspected[ dataType ] = true;
7682
+ jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
7683
+ var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
7684
+ if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
7685
+ options.dataTypes.unshift( dataTypeOrTransport );
7686
+ inspect( dataTypeOrTransport );
7687
+ return false;
7688
+ } else if ( seekingTransport ) {
7689
+ return !( selected = dataTypeOrTransport );
7690
+ }
7691
+ });
7692
+ return selected;
7693
+ }
7694
+
7695
+ return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
7696
+ }
7697
+
7698
+ // A special extend for ajax options
7699
+ // that takes "flat" options (not to be deep extended)
7700
+ // Fixes #9887
7701
+ function ajaxExtend( target, src ) {
7702
+ var deep, key,
7703
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
7704
+
7705
+ for ( key in src ) {
7706
+ if ( src[ key ] !== undefined ) {
7707
+ ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
7708
+ }
7709
+ }
7710
+ if ( deep ) {
7711
+ jQuery.extend( true, target, deep );
7712
+ }
7713
+
7714
+ return target;
7715
+ }
7716
+
7717
+ jQuery.fn.load = function( url, params, callback ) {
7718
+ if ( typeof url !== "string" && _load ) {
7719
+ return _load.apply( this, arguments );
7720
+ }
7721
+
7722
+ var selector, response, type,
7723
+ self = this,
7724
+ off = url.indexOf(" ");
7725
+
7726
+ if ( off >= 0 ) {
7727
+ selector = url.slice( off, url.length );
7728
+ url = url.slice( 0, off );
7729
+ }
7730
+
7731
+ // If it's a function
7732
+ if ( jQuery.isFunction( params ) ) {
7733
+
7734
+ // We assume that it's the callback
7735
+ callback = params;
7736
+ params = undefined;
7737
+
7738
+ // Otherwise, build a param string
7739
+ } else if ( params && typeof params === "object" ) {
7740
+ type = "POST";
7741
+ }
7742
+
7743
+ // If we have elements to modify, make the request
7744
+ if ( self.length > 0 ) {
7745
+ jQuery.ajax({
7746
+ url: url,
7747
+
7748
+ // if "type" variable is undefined, then "GET" method will be used
7749
+ type: type,
7750
+ dataType: "html",
7751
+ data: params
7752
+ }).done(function( responseText ) {
7753
+
7754
+ // Save response for use in complete callback
7755
+ response = arguments;
7756
+
7757
+ self.html( selector ?
7758
+
7759
+ // If a selector was specified, locate the right elements in a dummy div
7760
+ // Exclude scripts to avoid IE 'Permission Denied' errors
7761
+ jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
7762
+
7763
+ // Otherwise use the full result
7764
+ responseText );
7765
+
7766
+ }).complete( callback && function( jqXHR, status ) {
7767
+ self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
7768
+ });
7769
+ }
7770
+
7771
+ return this;
7772
+ };
7773
+
7774
+ // Attach a bunch of functions for handling common AJAX events
7775
+ jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
7776
+ jQuery.fn[ type ] = function( fn ){
7777
+ return this.on( type, fn );
7778
+ };
7779
+ });
7780
+
7781
+ jQuery.extend({
7782
+
7783
+ // Counter for holding the number of active queries
7784
+ active: 0,
7785
+
7786
+ // Last-Modified header cache for next request
7787
+ lastModified: {},
7788
+ etag: {},
7789
+
7790
+ ajaxSettings: {
7791
+ url: ajaxLocation,
7792
+ type: "GET",
7793
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
7794
+ global: true,
7795
+ processData: true,
7796
+ async: true,
7797
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
7798
+ /*
7799
+ timeout: 0,
7800
+ data: null,
7801
+ dataType: null,
7802
+ username: null,
7803
+ password: null,
7804
+ cache: null,
7805
+ throws: false,
7806
+ traditional: false,
7807
+ headers: {},
7808
+ */
7809
+
7810
+ accepts: {
7811
+ "*": allTypes,
7812
+ text: "text/plain",
7813
+ html: "text/html",
7814
+ xml: "application/xml, text/xml",
7815
+ json: "application/json, text/javascript"
7816
+ },
7817
+
7818
+ contents: {
7819
+ xml: /xml/,
7820
+ html: /html/,
7821
+ json: /json/
7822
+ },
7823
+
7824
+ responseFields: {
7825
+ xml: "responseXML",
7826
+ text: "responseText",
7827
+ json: "responseJSON"
7828
+ },
7829
+
7830
+ // Data converters
7831
+ // Keys separate source (or catchall "*") and destination types with a single space
7832
+ converters: {
7833
+
7834
+ // Convert anything to text
7835
+ "* text": String,
7836
+
7837
+ // Text to html (true = no transformation)
7838
+ "text html": true,
7839
+
7840
+ // Evaluate text as a json expression
7841
+ "text json": jQuery.parseJSON,
7842
+
7843
+ // Parse text as xml
7844
+ "text xml": jQuery.parseXML
7845
+ },
7846
+
7847
+ // For options that shouldn't be deep extended:
7848
+ // you can add your own custom options here if
7849
+ // and when you create one that shouldn't be
7850
+ // deep extended (see ajaxExtend)
7851
+ flatOptions: {
7852
+ url: true,
7853
+ context: true
7854
+ }
7855
+ },
7856
+
7857
+ // Creates a full fledged settings object into target
7858
+ // with both ajaxSettings and settings fields.
7859
+ // If target is omitted, writes into ajaxSettings.
7860
+ ajaxSetup: function( target, settings ) {
7861
+ return settings ?
7862
+
7863
+ // Building a settings object
7864
+ ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
7865
+
7866
+ // Extending ajaxSettings
7867
+ ajaxExtend( jQuery.ajaxSettings, target );
7868
+ },
7869
+
7870
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
7871
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
7872
+
7873
+ // Main method
7874
+ ajax: function( url, options ) {
7875
+
7876
+ // If url is an object, simulate pre-1.5 signature
7877
+ if ( typeof url === "object" ) {
7878
+ options = url;
7879
+ url = undefined;
7880
+ }
7881
+
7882
+ // Force options to be an object
7883
+ options = options || {};
7884
+
7885
+ var // Cross-domain detection vars
7886
+ parts,
7887
+ // Loop variable
7888
+ i,
7889
+ // URL without anti-cache param
7890
+ cacheURL,
7891
+ // Response headers as string
7892
+ responseHeadersString,
7893
+ // timeout handle
7894
+ timeoutTimer,
7895
+
7896
+ // To know if global events are to be dispatched
7897
+ fireGlobals,
7898
+
7899
+ transport,
7900
+ // Response headers
7901
+ responseHeaders,
7902
+ // Create the final options object
7903
+ s = jQuery.ajaxSetup( {}, options ),
7904
+ // Callbacks context
7905
+ callbackContext = s.context || s,
7906
+ // Context for global events is callbackContext if it is a DOM node or jQuery collection
7907
+ globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
7908
+ jQuery( callbackContext ) :
7909
+ jQuery.event,
7910
+ // Deferreds
7911
+ deferred = jQuery.Deferred(),
7912
+ completeDeferred = jQuery.Callbacks("once memory"),
7913
+ // Status-dependent callbacks
7914
+ statusCode = s.statusCode || {},
7915
+ // Headers (they are sent all at once)
7916
+ requestHeaders = {},
7917
+ requestHeadersNames = {},
7918
+ // The jqXHR state
7919
+ state = 0,
7920
+ // Default abort message
7921
+ strAbort = "canceled",
7922
+ // Fake xhr
7923
+ jqXHR = {
7924
+ readyState: 0,
7925
+
7926
+ // Builds headers hashtable if needed
7927
+ getResponseHeader: function( key ) {
7928
+ var match;
7929
+ if ( state === 2 ) {
7930
+ if ( !responseHeaders ) {
7931
+ responseHeaders = {};
7932
+ while ( (match = rheaders.exec( responseHeadersString )) ) {
7933
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
7934
+ }
7935
+ }
7936
+ match = responseHeaders[ key.toLowerCase() ];
7937
+ }
7938
+ return match == null ? null : match;
7939
+ },
7940
+
7941
+ // Raw string
7942
+ getAllResponseHeaders: function() {
7943
+ return state === 2 ? responseHeadersString : null;
7944
+ },
7945
+
7946
+ // Caches the header
7947
+ setRequestHeader: function( name, value ) {
7948
+ var lname = name.toLowerCase();
7949
+ if ( !state ) {
7950
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
7951
+ requestHeaders[ name ] = value;
7952
+ }
7953
+ return this;
7954
+ },
7955
+
7956
+ // Overrides response content-type header
7957
+ overrideMimeType: function( type ) {
7958
+ if ( !state ) {
7959
+ s.mimeType = type;
7960
+ }
7961
+ return this;
7962
+ },
7963
+
7964
+ // Status-dependent callbacks
7965
+ statusCode: function( map ) {
7966
+ var code;
7967
+ if ( map ) {
7968
+ if ( state < 2 ) {
7969
+ for ( code in map ) {
7970
+ // Lazy-add the new callback in a way that preserves old ones
7971
+ statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
7972
+ }
7973
+ } else {
7974
+ // Execute the appropriate callbacks
7975
+ jqXHR.always( map[ jqXHR.status ] );
7976
+ }
7977
+ }
7978
+ return this;
7979
+ },
7980
+
7981
+ // Cancel the request
7982
+ abort: function( statusText ) {
7983
+ var finalText = statusText || strAbort;
7984
+ if ( transport ) {
7985
+ transport.abort( finalText );
7986
+ }
7987
+ done( 0, finalText );
7988
+ return this;
7989
+ }
7990
+ };
7991
+
7992
+ // Attach deferreds
7993
+ deferred.promise( jqXHR ).complete = completeDeferred.add;
7994
+ jqXHR.success = jqXHR.done;
7995
+ jqXHR.error = jqXHR.fail;
7996
+
7997
+ // Remove hash character (#7531: and string promotion)
7998
+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
7999
+ // Handle falsy url in the settings object (#10093: consistency with old signature)
8000
+ // We also use the url parameter if available
8001
+ s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
8002
+
8003
+ // Alias method option to type as per ticket #12004
8004
+ s.type = options.method || options.type || s.method || s.type;
8005
+
8006
+ // Extract dataTypes list
8007
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
8008
+
8009
+ // A cross-domain request is in order when we have a protocol:host:port mismatch
8010
+ if ( s.crossDomain == null ) {
8011
+ parts = rurl.exec( s.url.toLowerCase() );
8012
+ s.crossDomain = !!( parts &&
8013
+ ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
8014
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
8015
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
8016
+ );
8017
+ }
8018
+
8019
+ // Convert data if not already a string
8020
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
8021
+ s.data = jQuery.param( s.data, s.traditional );
8022
+ }
8023
+
8024
+ // Apply prefilters
8025
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
8026
+
8027
+ // If request was aborted inside a prefilter, stop there
8028
+ if ( state === 2 ) {
8029
+ return jqXHR;
8030
+ }
8031
+
8032
+ // We can fire global events as of now if asked to
8033
+ fireGlobals = s.global;
8034
+
8035
+ // Watch for a new set of requests
8036
+ if ( fireGlobals && jQuery.active++ === 0 ) {
8037
+ jQuery.event.trigger("ajaxStart");
8038
+ }
8039
+
8040
+ // Uppercase the type
8041
+ s.type = s.type.toUpperCase();
8042
+
8043
+ // Determine if request has content
8044
+ s.hasContent = !rnoContent.test( s.type );
8045
+
8046
+ // Save the URL in case we're toying with the If-Modified-Since
8047
+ // and/or If-None-Match header later on
8048
+ cacheURL = s.url;
8049
+
8050
+ // More options handling for requests with no content
8051
+ if ( !s.hasContent ) {
8052
+
8053
+ // If data is available, append data to url
8054
+ if ( s.data ) {
8055
+ cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
8056
+ // #9682: remove data so that it's not used in an eventual retry
8057
+ delete s.data;
8058
+ }
8059
+
8060
+ // Add anti-cache in url if needed
8061
+ if ( s.cache === false ) {
8062
+ s.url = rts.test( cacheURL ) ?
8063
+
8064
+ // If there is already a '_' parameter, set its value
8065
+ cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
8066
+
8067
+ // Otherwise add one to the end
8068
+ cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
8069
+ }
8070
+ }
8071
+
8072
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8073
+ if ( s.ifModified ) {
8074
+ if ( jQuery.lastModified[ cacheURL ] ) {
8075
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
8076
+ }
8077
+ if ( jQuery.etag[ cacheURL ] ) {
8078
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
8079
+ }
8080
+ }
8081
+
8082
+ // Set the correct header, if data is being sent
8083
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
8084
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
8085
+ }
8086
+
8087
+ // Set the Accepts header for the server, depending on the dataType
8088
+ jqXHR.setRequestHeader(
8089
+ "Accept",
8090
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
8091
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
8092
+ s.accepts[ "*" ]
8093
+ );
8094
+
8095
+ // Check for headers option
8096
+ for ( i in s.headers ) {
8097
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
8098
+ }
8099
+
8100
+ // Allow custom headers/mimetypes and early abort
8101
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
8102
+ // Abort if not done already and return
8103
+ return jqXHR.abort();
8104
+ }
8105
+
8106
+ // aborting is no longer a cancellation
8107
+ strAbort = "abort";
8108
+
8109
+ // Install callbacks on deferreds
8110
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
8111
+ jqXHR[ i ]( s[ i ] );
8112
+ }
8113
+
8114
+ // Get transport
8115
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
8116
+
8117
+ // If no transport, we auto-abort
8118
+ if ( !transport ) {
8119
+ done( -1, "No Transport" );
8120
+ } else {
8121
+ jqXHR.readyState = 1;
8122
+
8123
+ // Send global event
8124
+ if ( fireGlobals ) {
8125
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
8126
+ }
8127
+ // Timeout
8128
+ if ( s.async && s.timeout > 0 ) {
8129
+ timeoutTimer = setTimeout(function() {
8130
+ jqXHR.abort("timeout");
8131
+ }, s.timeout );
8132
+ }
8133
+
8134
+ try {
8135
+ state = 1;
8136
+ transport.send( requestHeaders, done );
8137
+ } catch ( e ) {
8138
+ // Propagate exception as error if not done
8139
+ if ( state < 2 ) {
8140
+ done( -1, e );
8141
+ // Simply rethrow otherwise
8142
+ } else {
8143
+ throw e;
8144
+ }
8145
+ }
8146
+ }
8147
+
8148
+ // Callback for when everything is done
8149
+ function done( status, nativeStatusText, responses, headers ) {
8150
+ var isSuccess, success, error, response, modified,
8151
+ statusText = nativeStatusText;
8152
+
8153
+ // Called once
8154
+ if ( state === 2 ) {
8155
+ return;
8156
+ }
8157
+
8158
+ // State is "done" now
8159
+ state = 2;
8160
+
8161
+ // Clear timeout if it exists
8162
+ if ( timeoutTimer ) {
8163
+ clearTimeout( timeoutTimer );
8164
+ }
8165
+
8166
+ // Dereference transport for early garbage collection
8167
+ // (no matter how long the jqXHR object will be used)
8168
+ transport = undefined;
8169
+
8170
+ // Cache response headers
8171
+ responseHeadersString = headers || "";
8172
+
8173
+ // Set readyState
8174
+ jqXHR.readyState = status > 0 ? 4 : 0;
8175
+
8176
+ // Determine if successful
8177
+ isSuccess = status >= 200 && status < 300 || status === 304;
8178
+
8179
+ // Get response data
8180
+ if ( responses ) {
8181
+ response = ajaxHandleResponses( s, jqXHR, responses );
8182
+ }
8183
+
8184
+ // Convert no matter what (that way responseXXX fields are always set)
8185
+ response = ajaxConvert( s, response, jqXHR, isSuccess );
8186
+
8187
+ // If successful, handle type chaining
8188
+ if ( isSuccess ) {
8189
+
8190
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8191
+ if ( s.ifModified ) {
8192
+ modified = jqXHR.getResponseHeader("Last-Modified");
8193
+ if ( modified ) {
8194
+ jQuery.lastModified[ cacheURL ] = modified;
8195
+ }
8196
+ modified = jqXHR.getResponseHeader("etag");
8197
+ if ( modified ) {
8198
+ jQuery.etag[ cacheURL ] = modified;
8199
+ }
8200
+ }
8201
+
8202
+ // if no content
8203
+ if ( status === 204 || s.type === "HEAD" ) {
8204
+ statusText = "nocontent";
8205
+
8206
+ // if not modified
8207
+ } else if ( status === 304 ) {
8208
+ statusText = "notmodified";
8209
+
8210
+ // If we have data, let's convert it
8211
+ } else {
8212
+ statusText = response.state;
8213
+ success = response.data;
8214
+ error = response.error;
8215
+ isSuccess = !error;
8216
+ }
8217
+ } else {
8218
+ // We extract error from statusText
8219
+ // then normalize statusText and status for non-aborts
8220
+ error = statusText;
8221
+ if ( status || !statusText ) {
8222
+ statusText = "error";
8223
+ if ( status < 0 ) {
8224
+ status = 0;
8225
+ }
8226
+ }
8227
+ }
8228
+
8229
+ // Set data for the fake xhr object
8230
+ jqXHR.status = status;
8231
+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
8232
+
8233
+ // Success/Error
8234
+ if ( isSuccess ) {
8235
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
8236
+ } else {
8237
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
8238
+ }
8239
+
8240
+ // Status-dependent callbacks
8241
+ jqXHR.statusCode( statusCode );
8242
+ statusCode = undefined;
8243
+
8244
+ if ( fireGlobals ) {
8245
+ globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
8246
+ [ jqXHR, s, isSuccess ? success : error ] );
8247
+ }
8248
+
8249
+ // Complete
8250
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
8251
+
8252
+ if ( fireGlobals ) {
8253
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
8254
+ // Handle the global AJAX counter
8255
+ if ( !( --jQuery.active ) ) {
8256
+ jQuery.event.trigger("ajaxStop");
8257
+ }
8258
+ }
8259
+ }
8260
+
8261
+ return jqXHR;
8262
+ },
8263
+
8264
+ getJSON: function( url, data, callback ) {
8265
+ return jQuery.get( url, data, callback, "json" );
8266
+ },
8267
+
8268
+ getScript: function( url, callback ) {
8269
+ return jQuery.get( url, undefined, callback, "script" );
8270
+ }
8271
+ });
8272
+
8273
+ jQuery.each( [ "get", "post" ], function( i, method ) {
8274
+ jQuery[ method ] = function( url, data, callback, type ) {
8275
+ // shift arguments if data argument was omitted
8276
+ if ( jQuery.isFunction( data ) ) {
8277
+ type = type || callback;
8278
+ callback = data;
8279
+ data = undefined;
8280
+ }
8281
+
8282
+ return jQuery.ajax({
8283
+ url: url,
8284
+ type: method,
8285
+ dataType: type,
8286
+ data: data,
8287
+ success: callback
8288
+ });
8289
+ };
8290
+ });
8291
+
8292
+ /* Handles responses to an ajax request:
8293
+ * - finds the right dataType (mediates between content-type and expected dataType)
8294
+ * - returns the corresponding response
8295
+ */
8296
+ function ajaxHandleResponses( s, jqXHR, responses ) {
8297
+ var firstDataType, ct, finalDataType, type,
8298
+ contents = s.contents,
8299
+ dataTypes = s.dataTypes;
8300
+
8301
+ // Remove auto dataType and get content-type in the process
8302
+ while( dataTypes[ 0 ] === "*" ) {
8303
+ dataTypes.shift();
8304
+ if ( ct === undefined ) {
8305
+ ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
8306
+ }
8307
+ }
8308
+
8309
+ // Check if we're dealing with a known content-type
8310
+ if ( ct ) {
8311
+ for ( type in contents ) {
8312
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
8313
+ dataTypes.unshift( type );
8314
+ break;
8315
+ }
8316
+ }
8317
+ }
8318
+
8319
+ // Check to see if we have a response for the expected dataType
8320
+ if ( dataTypes[ 0 ] in responses ) {
8321
+ finalDataType = dataTypes[ 0 ];
8322
+ } else {
8323
+ // Try convertible dataTypes
8324
+ for ( type in responses ) {
8325
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
8326
+ finalDataType = type;
8327
+ break;
8328
+ }
8329
+ if ( !firstDataType ) {
8330
+ firstDataType = type;
8331
+ }
8332
+ }
8333
+ // Or just use first one
8334
+ finalDataType = finalDataType || firstDataType;
8335
+ }
8336
+
8337
+ // If we found a dataType
8338
+ // We add the dataType to the list if needed
8339
+ // and return the corresponding response
8340
+ if ( finalDataType ) {
8341
+ if ( finalDataType !== dataTypes[ 0 ] ) {
8342
+ dataTypes.unshift( finalDataType );
8343
+ }
8344
+ return responses[ finalDataType ];
8345
+ }
8346
+ }
8347
+
8348
+ /* Chain conversions given the request and the original response
8349
+ * Also sets the responseXXX fields on the jqXHR instance
8350
+ */
8351
+ function ajaxConvert( s, response, jqXHR, isSuccess ) {
8352
+ var conv2, current, conv, tmp, prev,
8353
+ converters = {},
8354
+ // Work with a copy of dataTypes in case we need to modify it for conversion
8355
+ dataTypes = s.dataTypes.slice();
8356
+
8357
+ // Create converters map with lowercased keys
8358
+ if ( dataTypes[ 1 ] ) {
8359
+ for ( conv in s.converters ) {
8360
+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
8361
+ }
8362
+ }
8363
+
8364
+ current = dataTypes.shift();
8365
+
8366
+ // Convert to each sequential dataType
8367
+ while ( current ) {
8368
+
8369
+ if ( s.responseFields[ current ] ) {
8370
+ jqXHR[ s.responseFields[ current ] ] = response;
8371
+ }
8372
+
8373
+ // Apply the dataFilter if provided
8374
+ if ( !prev && isSuccess && s.dataFilter ) {
8375
+ response = s.dataFilter( response, s.dataType );
8376
+ }
8377
+
8378
+ prev = current;
8379
+ current = dataTypes.shift();
8380
+
8381
+ if ( current ) {
8382
+
8383
+ // There's only work to do if current dataType is non-auto
8384
+ if ( current === "*" ) {
8385
+
8386
+ current = prev;
8387
+
8388
+ // Convert response if prev dataType is non-auto and differs from current
8389
+ } else if ( prev !== "*" && prev !== current ) {
8390
+
8391
+ // Seek a direct converter
8392
+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
8393
+
8394
+ // If none found, seek a pair
8395
+ if ( !conv ) {
8396
+ for ( conv2 in converters ) {
8397
+
8398
+ // If conv2 outputs current
8399
+ tmp = conv2.split( " " );
8400
+ if ( tmp[ 1 ] === current ) {
8401
+
8402
+ // If prev can be converted to accepted input
8403
+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
8404
+ converters[ "* " + tmp[ 0 ] ];
8405
+ if ( conv ) {
8406
+ // Condense equivalence converters
8407
+ if ( conv === true ) {
8408
+ conv = converters[ conv2 ];
8409
+
8410
+ // Otherwise, insert the intermediate dataType
8411
+ } else if ( converters[ conv2 ] !== true ) {
8412
+ current = tmp[ 0 ];
8413
+ dataTypes.unshift( tmp[ 1 ] );
8414
+ }
8415
+ break;
8416
+ }
8417
+ }
8418
+ }
8419
+ }
8420
+
8421
+ // Apply converter (if not an equivalence)
8422
+ if ( conv !== true ) {
8423
+
8424
+ // Unless errors are allowed to bubble, catch and return them
8425
+ if ( conv && s[ "throws" ] ) {
8426
+ response = conv( response );
8427
+ } else {
8428
+ try {
8429
+ response = conv( response );
8430
+ } catch ( e ) {
8431
+ return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
8432
+ }
8433
+ }
8434
+ }
8435
+ }
8436
+ }
8437
+ }
8438
+
8439
+ return { state: "success", data: response };
8440
+ }
8441
+ // Install script dataType
8442
+ jQuery.ajaxSetup({
8443
+ accepts: {
8444
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
8445
+ },
8446
+ contents: {
8447
+ script: /(?:java|ecma)script/
8448
+ },
8449
+ converters: {
8450
+ "text script": function( text ) {
8451
+ jQuery.globalEval( text );
8452
+ return text;
8453
+ }
8454
+ }
8455
+ });
8456
+
8457
+ // Handle cache's special case and global
8458
+ jQuery.ajaxPrefilter( "script", function( s ) {
8459
+ if ( s.cache === undefined ) {
8460
+ s.cache = false;
8461
+ }
8462
+ if ( s.crossDomain ) {
8463
+ s.type = "GET";
8464
+ s.global = false;
8465
+ }
8466
+ });
8467
+
8468
+ // Bind script tag hack transport
8469
+ jQuery.ajaxTransport( "script", function(s) {
8470
+
8471
+ // This transport only deals with cross domain requests
8472
+ if ( s.crossDomain ) {
8473
+
8474
+ var script,
8475
+ head = document.head || jQuery("head")[0] || document.documentElement;
8476
+
8477
+ return {
8478
+
8479
+ send: function( _, callback ) {
8480
+
8481
+ script = document.createElement("script");
8482
+
8483
+ script.async = true;
8484
+
8485
+ if ( s.scriptCharset ) {
8486
+ script.charset = s.scriptCharset;
8487
+ }
8488
+
8489
+ script.src = s.url;
8490
+
8491
+ // Attach handlers for all browsers
8492
+ script.onload = script.onreadystatechange = function( _, isAbort ) {
8493
+
8494
+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
8495
+
8496
+ // Handle memory leak in IE
8497
+ script.onload = script.onreadystatechange = null;
8498
+
8499
+ // Remove the script
8500
+ if ( script.parentNode ) {
8501
+ script.parentNode.removeChild( script );
8502
+ }
8503
+
8504
+ // Dereference the script
8505
+ script = null;
8506
+
8507
+ // Callback if not abort
8508
+ if ( !isAbort ) {
8509
+ callback( 200, "success" );
8510
+ }
8511
+ }
8512
+ };
8513
+
8514
+ // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
8515
+ // Use native DOM manipulation to avoid our domManip AJAX trickery
8516
+ head.insertBefore( script, head.firstChild );
8517
+ },
8518
+
8519
+ abort: function() {
8520
+ if ( script ) {
8521
+ script.onload( undefined, true );
8522
+ }
8523
+ }
8524
+ };
8525
+ }
8526
+ });
8527
+ var oldCallbacks = [],
8528
+ rjsonp = /(=)\?(?=&|$)|\?\?/;
8529
+
8530
+ // Default jsonp settings
8531
+ jQuery.ajaxSetup({
8532
+ jsonp: "callback",
8533
+ jsonpCallback: function() {
8534
+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
8535
+ this[ callback ] = true;
8536
+ return callback;
8537
+ }
8538
+ });
8539
+
8540
+ // Detect, normalize options and install callbacks for jsonp requests
8541
+ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
8542
+
8543
+ var callbackName, overwritten, responseContainer,
8544
+ jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
8545
+ "url" :
8546
+ typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
8547
+ );
8548
+
8549
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
8550
+ if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
8551
+
8552
+ // Get callback name, remembering preexisting value associated with it
8553
+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
8554
+ s.jsonpCallback() :
8555
+ s.jsonpCallback;
8556
+
8557
+ // Insert callback into url or form data
8558
+ if ( jsonProp ) {
8559
+ s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
8560
+ } else if ( s.jsonp !== false ) {
8561
+ s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
8562
+ }
8563
+
8564
+ // Use data converter to retrieve json after script execution
8565
+ s.converters["script json"] = function() {
8566
+ if ( !responseContainer ) {
8567
+ jQuery.error( callbackName + " was not called" );
8568
+ }
8569
+ return responseContainer[ 0 ];
8570
+ };
8571
+
8572
+ // force json dataType
8573
+ s.dataTypes[ 0 ] = "json";
8574
+
8575
+ // Install callback
8576
+ overwritten = window[ callbackName ];
8577
+ window[ callbackName ] = function() {
8578
+ responseContainer = arguments;
8579
+ };
8580
+
8581
+ // Clean-up function (fires after converters)
8582
+ jqXHR.always(function() {
8583
+ // Restore preexisting value
8584
+ window[ callbackName ] = overwritten;
8585
+
8586
+ // Save back as free
8587
+ if ( s[ callbackName ] ) {
8588
+ // make sure that re-using the options doesn't screw things around
8589
+ s.jsonpCallback = originalSettings.jsonpCallback;
8590
+
8591
+ // save the callback name for future use
8592
+ oldCallbacks.push( callbackName );
8593
+ }
8594
+
8595
+ // Call if it was a function and we have a response
8596
+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
8597
+ overwritten( responseContainer[ 0 ] );
8598
+ }
8599
+
8600
+ responseContainer = overwritten = undefined;
8601
+ });
8602
+
8603
+ // Delegate to script
8604
+ return "script";
8605
+ }
8606
+ });
8607
+ var xhrCallbacks, xhrSupported,
8608
+ xhrId = 0,
8609
+ // #5280: Internet Explorer will keep connections alive if we don't abort on unload
8610
+ xhrOnUnloadAbort = window.ActiveXObject && function() {
8611
+ // Abort all pending requests
8612
+ var key;
8613
+ for ( key in xhrCallbacks ) {
8614
+ xhrCallbacks[ key ]( undefined, true );
8615
+ }
8616
+ };
8617
+
8618
+ // Functions to create xhrs
8619
+ function createStandardXHR() {
8620
+ try {
8621
+ return new window.XMLHttpRequest();
8622
+ } catch( e ) {}
8623
+ }
8624
+
8625
+ function createActiveXHR() {
8626
+ try {
8627
+ return new window.ActiveXObject("Microsoft.XMLHTTP");
8628
+ } catch( e ) {}
8629
+ }
8630
+
8631
+ // Create the request object
8632
+ // (This is still attached to ajaxSettings for backward compatibility)
8633
+ jQuery.ajaxSettings.xhr = window.ActiveXObject ?
8634
+ /* Microsoft failed to properly
8635
+ * implement the XMLHttpRequest in IE7 (can't request local files),
8636
+ * so we use the ActiveXObject when it is available
8637
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
8638
+ * we need a fallback.
8639
+ */
8640
+ function() {
8641
+ return !this.isLocal && createStandardXHR() || createActiveXHR();
8642
+ } :
8643
+ // For all other browsers, use the standard XMLHttpRequest object
8644
+ createStandardXHR;
8645
+
8646
+ // Determine support properties
8647
+ xhrSupported = jQuery.ajaxSettings.xhr();
8648
+ jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
8649
+ xhrSupported = jQuery.support.ajax = !!xhrSupported;
8650
+
8651
+ // Create transport if the browser can provide an xhr
8652
+ if ( xhrSupported ) {
8653
+
8654
+ jQuery.ajaxTransport(function( s ) {
8655
+ // Cross domain only allowed if supported through XMLHttpRequest
8656
+ if ( !s.crossDomain || jQuery.support.cors ) {
8657
+
8658
+ var callback;
8659
+
8660
+ return {
8661
+ send: function( headers, complete ) {
8662
+
8663
+ // Get a new xhr
8664
+ var handle, i,
8665
+ xhr = s.xhr();
8666
+
8667
+ // Open the socket
8668
+ // Passing null username, generates a login popup on Opera (#2865)
8669
+ if ( s.username ) {
8670
+ xhr.open( s.type, s.url, s.async, s.username, s.password );
8671
+ } else {
8672
+ xhr.open( s.type, s.url, s.async );
8673
+ }
8674
+
8675
+ // Apply custom fields if provided
8676
+ if ( s.xhrFields ) {
8677
+ for ( i in s.xhrFields ) {
8678
+ xhr[ i ] = s.xhrFields[ i ];
8679
+ }
8680
+ }
8681
+
8682
+ // Override mime type if needed
8683
+ if ( s.mimeType && xhr.overrideMimeType ) {
8684
+ xhr.overrideMimeType( s.mimeType );
8685
+ }
8686
+
8687
+ // X-Requested-With header
8688
+ // For cross-domain requests, seeing as conditions for a preflight are
8689
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
8690
+ // (it can always be set on a per-request basis or even using ajaxSetup)
8691
+ // For same-domain requests, won't change header if already provided.
8692
+ if ( !s.crossDomain && !headers["X-Requested-With"] ) {
8693
+ headers["X-Requested-With"] = "XMLHttpRequest";
8694
+ }
8695
+
8696
+ // Need an extra try/catch for cross domain requests in Firefox 3
8697
+ try {
8698
+ for ( i in headers ) {
8699
+ xhr.setRequestHeader( i, headers[ i ] );
8700
+ }
8701
+ } catch( err ) {}
8702
+
8703
+ // Do send the request
8704
+ // This may raise an exception which is actually
8705
+ // handled in jQuery.ajax (so no try/catch here)
8706
+ xhr.send( ( s.hasContent && s.data ) || null );
8707
+
8708
+ // Listener
8709
+ callback = function( _, isAbort ) {
8710
+ var status, responseHeaders, statusText, responses;
8711
+
8712
+ // Firefox throws exceptions when accessing properties
8713
+ // of an xhr when a network error occurred
8714
+ // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
8715
+ try {
8716
+
8717
+ // Was never called and is aborted or complete
8718
+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
8719
+
8720
+ // Only called once
8721
+ callback = undefined;
8722
+
8723
+ // Do not keep as active anymore
8724
+ if ( handle ) {
8725
+ xhr.onreadystatechange = jQuery.noop;
8726
+ if ( xhrOnUnloadAbort ) {
8727
+ delete xhrCallbacks[ handle ];
8728
+ }
8729
+ }
8730
+
8731
+ // If it's an abort
8732
+ if ( isAbort ) {
8733
+ // Abort it manually if needed
8734
+ if ( xhr.readyState !== 4 ) {
8735
+ xhr.abort();
8736
+ }
8737
+ } else {
8738
+ responses = {};
8739
+ status = xhr.status;
8740
+ responseHeaders = xhr.getAllResponseHeaders();
8741
+
8742
+ // When requesting binary data, IE6-9 will throw an exception
8743
+ // on any attempt to access responseText (#11426)
8744
+ if ( typeof xhr.responseText === "string" ) {
8745
+ responses.text = xhr.responseText;
8746
+ }
8747
+
8748
+ // Firefox throws an exception when accessing
8749
+ // statusText for faulty cross-domain requests
8750
+ try {
8751
+ statusText = xhr.statusText;
8752
+ } catch( e ) {
8753
+ // We normalize with Webkit giving an empty statusText
8754
+ statusText = "";
8755
+ }
8756
+
8757
+ // Filter status for non standard behaviors
8758
+
8759
+ // If the request is local and we have data: assume a success
8760
+ // (success with no data won't get notified, that's the best we
8761
+ // can do given current implementations)
8762
+ if ( !status && s.isLocal && !s.crossDomain ) {
8763
+ status = responses.text ? 200 : 404;
8764
+ // IE - #1450: sometimes returns 1223 when it should be 204
8765
+ } else if ( status === 1223 ) {
8766
+ status = 204;
8767
+ }
8768
+ }
8769
+ }
8770
+ } catch( firefoxAccessException ) {
8771
+ if ( !isAbort ) {
8772
+ complete( -1, firefoxAccessException );
8773
+ }
8774
+ }
8775
+
8776
+ // Call complete if needed
8777
+ if ( responses ) {
8778
+ complete( status, statusText, responses, responseHeaders );
8779
+ }
8780
+ };
8781
+
8782
+ if ( !s.async ) {
8783
+ // if we're in sync mode we fire the callback
8784
+ callback();
8785
+ } else if ( xhr.readyState === 4 ) {
8786
+ // (IE6 & IE7) if it's in cache and has been
8787
+ // retrieved directly we need to fire the callback
8788
+ setTimeout( callback );
8789
+ } else {
8790
+ handle = ++xhrId;
8791
+ if ( xhrOnUnloadAbort ) {
8792
+ // Create the active xhrs callbacks list if needed
8793
+ // and attach the unload handler
8794
+ if ( !xhrCallbacks ) {
8795
+ xhrCallbacks = {};
8796
+ jQuery( window ).unload( xhrOnUnloadAbort );
8797
+ }
8798
+ // Add to list of active xhrs callbacks
8799
+ xhrCallbacks[ handle ] = callback;
8800
+ }
8801
+ xhr.onreadystatechange = callback;
8802
+ }
8803
+ },
8804
+
8805
+ abort: function() {
8806
+ if ( callback ) {
8807
+ callback( undefined, true );
8808
+ }
8809
+ }
8810
+ };
8811
+ }
8812
+ });
8813
+ }
8814
+ var fxNow, timerId,
8815
+ rfxtypes = /^(?:toggle|show|hide)$/,
8816
+ rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
8817
+ rrun = /queueHooks$/,
8818
+ animationPrefilters = [ defaultPrefilter ],
8819
+ tweeners = {
8820
+ "*": [function( prop, value ) {
8821
+ var tween = this.createTween( prop, value ),
8822
+ target = tween.cur(),
8823
+ parts = rfxnum.exec( value ),
8824
+ unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
8825
+
8826
+ // Starting value computation is required for potential unit mismatches
8827
+ start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
8828
+ rfxnum.exec( jQuery.css( tween.elem, prop ) ),
8829
+ scale = 1,
8830
+ maxIterations = 20;
8831
+
8832
+ if ( start && start[ 3 ] !== unit ) {
8833
+ // Trust units reported by jQuery.css
8834
+ unit = unit || start[ 3 ];
8835
+
8836
+ // Make sure we update the tween properties later on
8837
+ parts = parts || [];
8838
+
8839
+ // Iteratively approximate from a nonzero starting point
8840
+ start = +target || 1;
8841
+
8842
+ do {
8843
+ // If previous iteration zeroed out, double until we get *something*
8844
+ // Use a string for doubling factor so we don't accidentally see scale as unchanged below
8845
+ scale = scale || ".5";
8846
+
8847
+ // Adjust and apply
8848
+ start = start / scale;
8849
+ jQuery.style( tween.elem, prop, start + unit );
8850
+
8851
+ // Update scale, tolerating zero or NaN from tween.cur()
8852
+ // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
8853
+ } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
8854
+ }
8855
+
8856
+ // Update tween properties
8857
+ if ( parts ) {
8858
+ start = tween.start = +start || +target || 0;
8859
+ tween.unit = unit;
8860
+ // If a +=/-= token was provided, we're doing a relative animation
8861
+ tween.end = parts[ 1 ] ?
8862
+ start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
8863
+ +parts[ 2 ];
8864
+ }
8865
+
8866
+ return tween;
8867
+ }]
8868
+ };
8869
+
8870
+ // Animations created synchronously will run synchronously
8871
+ function createFxNow() {
8872
+ setTimeout(function() {
8873
+ fxNow = undefined;
8874
+ });
8875
+ return ( fxNow = jQuery.now() );
8876
+ }
8877
+
8878
+ function createTween( value, prop, animation ) {
8879
+ var tween,
8880
+ collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
8881
+ index = 0,
8882
+ length = collection.length;
8883
+ for ( ; index < length; index++ ) {
8884
+ if ( (tween = collection[ index ].call( animation, prop, value )) ) {
8885
+
8886
+ // we're done with this property
8887
+ return tween;
8888
+ }
8889
+ }
8890
+ }
8891
+
8892
+ function Animation( elem, properties, options ) {
8893
+ var result,
8894
+ stopped,
8895
+ index = 0,
8896
+ length = animationPrefilters.length,
8897
+ deferred = jQuery.Deferred().always( function() {
8898
+ // don't match elem in the :animated selector
8899
+ delete tick.elem;
8900
+ }),
8901
+ tick = function() {
8902
+ if ( stopped ) {
8903
+ return false;
8904
+ }
8905
+ var currentTime = fxNow || createFxNow(),
8906
+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
8907
+ // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
8908
+ temp = remaining / animation.duration || 0,
8909
+ percent = 1 - temp,
8910
+ index = 0,
8911
+ length = animation.tweens.length;
8912
+
8913
+ for ( ; index < length ; index++ ) {
8914
+ animation.tweens[ index ].run( percent );
8915
+ }
8916
+
8917
+ deferred.notifyWith( elem, [ animation, percent, remaining ]);
8918
+
8919
+ if ( percent < 1 && length ) {
8920
+ return remaining;
8921
+ } else {
8922
+ deferred.resolveWith( elem, [ animation ] );
8923
+ return false;
8924
+ }
8925
+ },
8926
+ animation = deferred.promise({
8927
+ elem: elem,
8928
+ props: jQuery.extend( {}, properties ),
8929
+ opts: jQuery.extend( true, { specialEasing: {} }, options ),
8930
+ originalProperties: properties,
8931
+ originalOptions: options,
8932
+ startTime: fxNow || createFxNow(),
8933
+ duration: options.duration,
8934
+ tweens: [],
8935
+ createTween: function( prop, end ) {
8936
+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
8937
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
8938
+ animation.tweens.push( tween );
8939
+ return tween;
8940
+ },
8941
+ stop: function( gotoEnd ) {
8942
+ var index = 0,
8943
+ // if we are going to the end, we want to run all the tweens
8944
+ // otherwise we skip this part
8945
+ length = gotoEnd ? animation.tweens.length : 0;
8946
+ if ( stopped ) {
8947
+ return this;
8948
+ }
8949
+ stopped = true;
8950
+ for ( ; index < length ; index++ ) {
8951
+ animation.tweens[ index ].run( 1 );
8952
+ }
8953
+
8954
+ // resolve when we played the last frame
8955
+ // otherwise, reject
8956
+ if ( gotoEnd ) {
8957
+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
8958
+ } else {
8959
+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
8960
+ }
8961
+ return this;
8962
+ }
8963
+ }),
8964
+ props = animation.props;
8965
+
8966
+ propFilter( props, animation.opts.specialEasing );
8967
+
8968
+ for ( ; index < length ; index++ ) {
8969
+ result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
8970
+ if ( result ) {
8971
+ return result;
8972
+ }
8973
+ }
8974
+
8975
+ jQuery.map( props, createTween, animation );
8976
+
8977
+ if ( jQuery.isFunction( animation.opts.start ) ) {
8978
+ animation.opts.start.call( elem, animation );
8979
+ }
8980
+
8981
+ jQuery.fx.timer(
8982
+ jQuery.extend( tick, {
8983
+ elem: elem,
8984
+ anim: animation,
8985
+ queue: animation.opts.queue
8986
+ })
8987
+ );
8988
+
8989
+ // attach callbacks from options
8990
+ return animation.progress( animation.opts.progress )
8991
+ .done( animation.opts.done, animation.opts.complete )
8992
+ .fail( animation.opts.fail )
8993
+ .always( animation.opts.always );
8994
+ }
8995
+
8996
+ function propFilter( props, specialEasing ) {
8997
+ var index, name, easing, value, hooks;
8998
+
8999
+ // camelCase, specialEasing and expand cssHook pass
9000
+ for ( index in props ) {
9001
+ name = jQuery.camelCase( index );
9002
+ easing = specialEasing[ name ];
9003
+ value = props[ index ];
9004
+ if ( jQuery.isArray( value ) ) {
9005
+ easing = value[ 1 ];
9006
+ value = props[ index ] = value[ 0 ];
9007
+ }
9008
+
9009
+ if ( index !== name ) {
9010
+ props[ name ] = value;
9011
+ delete props[ index ];
9012
+ }
9013
+
9014
+ hooks = jQuery.cssHooks[ name ];
9015
+ if ( hooks && "expand" in hooks ) {
9016
+ value = hooks.expand( value );
9017
+ delete props[ name ];
9018
+
9019
+ // not quite $.extend, this wont overwrite keys already present.
9020
+ // also - reusing 'index' from above because we have the correct "name"
9021
+ for ( index in value ) {
9022
+ if ( !( index in props ) ) {
9023
+ props[ index ] = value[ index ];
9024
+ specialEasing[ index ] = easing;
9025
+ }
9026
+ }
9027
+ } else {
9028
+ specialEasing[ name ] = easing;
9029
+ }
9030
+ }
9031
+ }
9032
+
9033
+ jQuery.Animation = jQuery.extend( Animation, {
9034
+
9035
+ tweener: function( props, callback ) {
9036
+ if ( jQuery.isFunction( props ) ) {
9037
+ callback = props;
9038
+ props = [ "*" ];
9039
+ } else {
9040
+ props = props.split(" ");
9041
+ }
9042
+
9043
+ var prop,
9044
+ index = 0,
9045
+ length = props.length;
9046
+
9047
+ for ( ; index < length ; index++ ) {
9048
+ prop = props[ index ];
9049
+ tweeners[ prop ] = tweeners[ prop ] || [];
9050
+ tweeners[ prop ].unshift( callback );
9051
+ }
9052
+ },
9053
+
9054
+ prefilter: function( callback, prepend ) {
9055
+ if ( prepend ) {
9056
+ animationPrefilters.unshift( callback );
9057
+ } else {
9058
+ animationPrefilters.push( callback );
9059
+ }
9060
+ }
9061
+ });
9062
+
9063
+ function defaultPrefilter( elem, props, opts ) {
9064
+ /* jshint validthis: true */
9065
+ var prop, value, toggle, tween, hooks, oldfire,
9066
+ anim = this,
9067
+ orig = {},
9068
+ style = elem.style,
9069
+ hidden = elem.nodeType && isHidden( elem ),
9070
+ dataShow = jQuery._data( elem, "fxshow" );
9071
+
9072
+ // handle queue: false promises
9073
+ if ( !opts.queue ) {
9074
+ hooks = jQuery._queueHooks( elem, "fx" );
9075
+ if ( hooks.unqueued == null ) {
9076
+ hooks.unqueued = 0;
9077
+ oldfire = hooks.empty.fire;
9078
+ hooks.empty.fire = function() {
9079
+ if ( !hooks.unqueued ) {
9080
+ oldfire();
9081
+ }
9082
+ };
9083
+ }
9084
+ hooks.unqueued++;
9085
+
9086
+ anim.always(function() {
9087
+ // doing this makes sure that the complete handler will be called
9088
+ // before this completes
9089
+ anim.always(function() {
9090
+ hooks.unqueued--;
9091
+ if ( !jQuery.queue( elem, "fx" ).length ) {
9092
+ hooks.empty.fire();
9093
+ }
9094
+ });
9095
+ });
9096
+ }
9097
+
9098
+ // height/width overflow pass
9099
+ if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
9100
+ // Make sure that nothing sneaks out
9101
+ // Record all 3 overflow attributes because IE does not
9102
+ // change the overflow attribute when overflowX and
9103
+ // overflowY are set to the same value
9104
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
9105
+
9106
+ // Set display property to inline-block for height/width
9107
+ // animations on inline elements that are having width/height animated
9108
+ if ( jQuery.css( elem, "display" ) === "inline" &&
9109
+ jQuery.css( elem, "float" ) === "none" ) {
9110
+
9111
+ // inline-level elements accept inline-block;
9112
+ // block-level elements need to be inline with layout
9113
+ if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
9114
+ style.display = "inline-block";
9115
+
9116
+ } else {
9117
+ style.zoom = 1;
9118
+ }
9119
+ }
9120
+ }
9121
+
9122
+ if ( opts.overflow ) {
9123
+ style.overflow = "hidden";
9124
+ if ( !jQuery.support.shrinkWrapBlocks ) {
9125
+ anim.always(function() {
9126
+ style.overflow = opts.overflow[ 0 ];
9127
+ style.overflowX = opts.overflow[ 1 ];
9128
+ style.overflowY = opts.overflow[ 2 ];
9129
+ });
9130
+ }
9131
+ }
9132
+
9133
+
9134
+ // show/hide pass
9135
+ for ( prop in props ) {
9136
+ value = props[ prop ];
9137
+ if ( rfxtypes.exec( value ) ) {
9138
+ delete props[ prop ];
9139
+ toggle = toggle || value === "toggle";
9140
+ if ( value === ( hidden ? "hide" : "show" ) ) {
9141
+ continue;
9142
+ }
9143
+ orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
9144
+ }
9145
+ }
9146
+
9147
+ if ( !jQuery.isEmptyObject( orig ) ) {
9148
+ if ( dataShow ) {
9149
+ if ( "hidden" in dataShow ) {
9150
+ hidden = dataShow.hidden;
9151
+ }
9152
+ } else {
9153
+ dataShow = jQuery._data( elem, "fxshow", {} );
9154
+ }
9155
+
9156
+ // store state if its toggle - enables .stop().toggle() to "reverse"
9157
+ if ( toggle ) {
9158
+ dataShow.hidden = !hidden;
9159
+ }
9160
+ if ( hidden ) {
9161
+ jQuery( elem ).show();
9162
+ } else {
9163
+ anim.done(function() {
9164
+ jQuery( elem ).hide();
9165
+ });
9166
+ }
9167
+ anim.done(function() {
9168
+ var prop;
9169
+ jQuery._removeData( elem, "fxshow" );
9170
+ for ( prop in orig ) {
9171
+ jQuery.style( elem, prop, orig[ prop ] );
9172
+ }
9173
+ });
9174
+ for ( prop in orig ) {
9175
+ tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
9176
+
9177
+ if ( !( prop in dataShow ) ) {
9178
+ dataShow[ prop ] = tween.start;
9179
+ if ( hidden ) {
9180
+ tween.end = tween.start;
9181
+ tween.start = prop === "width" || prop === "height" ? 1 : 0;
9182
+ }
9183
+ }
9184
+ }
9185
+ }
9186
+ }
9187
+
9188
+ function Tween( elem, options, prop, end, easing ) {
9189
+ return new Tween.prototype.init( elem, options, prop, end, easing );
9190
+ }
9191
+ jQuery.Tween = Tween;
9192
+
9193
+ Tween.prototype = {
9194
+ constructor: Tween,
9195
+ init: function( elem, options, prop, end, easing, unit ) {
9196
+ this.elem = elem;
9197
+ this.prop = prop;
9198
+ this.easing = easing || "swing";
9199
+ this.options = options;
9200
+ this.start = this.now = this.cur();
9201
+ this.end = end;
9202
+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
9203
+ },
9204
+ cur: function() {
9205
+ var hooks = Tween.propHooks[ this.prop ];
9206
+
9207
+ return hooks && hooks.get ?
9208
+ hooks.get( this ) :
9209
+ Tween.propHooks._default.get( this );
9210
+ },
9211
+ run: function( percent ) {
9212
+ var eased,
9213
+ hooks = Tween.propHooks[ this.prop ];
9214
+
9215
+ if ( this.options.duration ) {
9216
+ this.pos = eased = jQuery.easing[ this.easing ](
9217
+ percent, this.options.duration * percent, 0, 1, this.options.duration
9218
+ );
9219
+ } else {
9220
+ this.pos = eased = percent;
9221
+ }
9222
+ this.now = ( this.end - this.start ) * eased + this.start;
9223
+
9224
+ if ( this.options.step ) {
9225
+ this.options.step.call( this.elem, this.now, this );
9226
+ }
9227
+
9228
+ if ( hooks && hooks.set ) {
9229
+ hooks.set( this );
9230
+ } else {
9231
+ Tween.propHooks._default.set( this );
9232
+ }
9233
+ return this;
9234
+ }
9235
+ };
9236
+
9237
+ Tween.prototype.init.prototype = Tween.prototype;
9238
+
9239
+ Tween.propHooks = {
9240
+ _default: {
9241
+ get: function( tween ) {
9242
+ var result;
9243
+
9244
+ if ( tween.elem[ tween.prop ] != null &&
9245
+ (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
9246
+ return tween.elem[ tween.prop ];
9247
+ }
9248
+
9249
+ // passing an empty string as a 3rd parameter to .css will automatically
9250
+ // attempt a parseFloat and fallback to a string if the parse fails
9251
+ // so, simple values such as "10px" are parsed to Float.
9252
+ // complex values such as "rotate(1rad)" are returned as is.
9253
+ result = jQuery.css( tween.elem, tween.prop, "" );
9254
+ // Empty strings, null, undefined and "auto" are converted to 0.
9255
+ return !result || result === "auto" ? 0 : result;
9256
+ },
9257
+ set: function( tween ) {
9258
+ // use step hook for back compat - use cssHook if its there - use .style if its
9259
+ // available and use plain properties where available
9260
+ if ( jQuery.fx.step[ tween.prop ] ) {
9261
+ jQuery.fx.step[ tween.prop ]( tween );
9262
+ } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
9263
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
9264
+ } else {
9265
+ tween.elem[ tween.prop ] = tween.now;
9266
+ }
9267
+ }
9268
+ }
9269
+ };
9270
+
9271
+ // Support: IE <=9
9272
+ // Panic based approach to setting things on disconnected nodes
9273
+
9274
+ Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
9275
+ set: function( tween ) {
9276
+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
9277
+ tween.elem[ tween.prop ] = tween.now;
9278
+ }
9279
+ }
9280
+ };
9281
+
9282
+ jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
9283
+ var cssFn = jQuery.fn[ name ];
9284
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
9285
+ return speed == null || typeof speed === "boolean" ?
9286
+ cssFn.apply( this, arguments ) :
9287
+ this.animate( genFx( name, true ), speed, easing, callback );
9288
+ };
9289
+ });
9290
+
9291
+ jQuery.fn.extend({
9292
+ fadeTo: function( speed, to, easing, callback ) {
9293
+
9294
+ // show any hidden elements after setting opacity to 0
9295
+ return this.filter( isHidden ).css( "opacity", 0 ).show()
9296
+
9297
+ // animate to the value specified
9298
+ .end().animate({ opacity: to }, speed, easing, callback );
9299
+ },
9300
+ animate: function( prop, speed, easing, callback ) {
9301
+ var empty = jQuery.isEmptyObject( prop ),
9302
+ optall = jQuery.speed( speed, easing, callback ),
9303
+ doAnimation = function() {
9304
+ // Operate on a copy of prop so per-property easing won't be lost
9305
+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
9306
+
9307
+ // Empty animations, or finishing resolves immediately
9308
+ if ( empty || jQuery._data( this, "finish" ) ) {
9309
+ anim.stop( true );
9310
+ }
9311
+ };
9312
+ doAnimation.finish = doAnimation;
9313
+
9314
+ return empty || optall.queue === false ?
9315
+ this.each( doAnimation ) :
9316
+ this.queue( optall.queue, doAnimation );
9317
+ },
9318
+ stop: function( type, clearQueue, gotoEnd ) {
9319
+ var stopQueue = function( hooks ) {
9320
+ var stop = hooks.stop;
9321
+ delete hooks.stop;
9322
+ stop( gotoEnd );
9323
+ };
9324
+
9325
+ if ( typeof type !== "string" ) {
9326
+ gotoEnd = clearQueue;
9327
+ clearQueue = type;
9328
+ type = undefined;
9329
+ }
9330
+ if ( clearQueue && type !== false ) {
9331
+ this.queue( type || "fx", [] );
9332
+ }
9333
+
9334
+ return this.each(function() {
9335
+ var dequeue = true,
9336
+ index = type != null && type + "queueHooks",
9337
+ timers = jQuery.timers,
9338
+ data = jQuery._data( this );
9339
+
9340
+ if ( index ) {
9341
+ if ( data[ index ] && data[ index ].stop ) {
9342
+ stopQueue( data[ index ] );
9343
+ }
9344
+ } else {
9345
+ for ( index in data ) {
9346
+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
9347
+ stopQueue( data[ index ] );
9348
+ }
9349
+ }
9350
+ }
9351
+
9352
+ for ( index = timers.length; index--; ) {
9353
+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
9354
+ timers[ index ].anim.stop( gotoEnd );
9355
+ dequeue = false;
9356
+ timers.splice( index, 1 );
9357
+ }
9358
+ }
9359
+
9360
+ // start the next in the queue if the last step wasn't forced
9361
+ // timers currently will call their complete callbacks, which will dequeue
9362
+ // but only if they were gotoEnd
9363
+ if ( dequeue || !gotoEnd ) {
9364
+ jQuery.dequeue( this, type );
9365
+ }
9366
+ });
9367
+ },
9368
+ finish: function( type ) {
9369
+ if ( type !== false ) {
9370
+ type = type || "fx";
9371
+ }
9372
+ return this.each(function() {
9373
+ var index,
9374
+ data = jQuery._data( this ),
9375
+ queue = data[ type + "queue" ],
9376
+ hooks = data[ type + "queueHooks" ],
9377
+ timers = jQuery.timers,
9378
+ length = queue ? queue.length : 0;
9379
+
9380
+ // enable finishing flag on private data
9381
+ data.finish = true;
9382
+
9383
+ // empty the queue first
9384
+ jQuery.queue( this, type, [] );
9385
+
9386
+ if ( hooks && hooks.stop ) {
9387
+ hooks.stop.call( this, true );
9388
+ }
9389
+
9390
+ // look for any active animations, and finish them
9391
+ for ( index = timers.length; index--; ) {
9392
+ if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
9393
+ timers[ index ].anim.stop( true );
9394
+ timers.splice( index, 1 );
9395
+ }
9396
+ }
9397
+
9398
+ // look for any animations in the old queue and finish them
9399
+ for ( index = 0; index < length; index++ ) {
9400
+ if ( queue[ index ] && queue[ index ].finish ) {
9401
+ queue[ index ].finish.call( this );
9402
+ }
9403
+ }
9404
+
9405
+ // turn off finishing flag
9406
+ delete data.finish;
9407
+ });
9408
+ }
9409
+ });
9410
+
9411
+ // Generate parameters to create a standard animation
9412
+ function genFx( type, includeWidth ) {
9413
+ var which,
9414
+ attrs = { height: type },
9415
+ i = 0;
9416
+
9417
+ // if we include width, step value is 1 to do all cssExpand values,
9418
+ // if we don't include width, step value is 2 to skip over Left and Right
9419
+ includeWidth = includeWidth? 1 : 0;
9420
+ for( ; i < 4 ; i += 2 - includeWidth ) {
9421
+ which = cssExpand[ i ];
9422
+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
9423
+ }
9424
+
9425
+ if ( includeWidth ) {
9426
+ attrs.opacity = attrs.width = type;
9427
+ }
9428
+
9429
+ return attrs;
9430
+ }
9431
+
9432
+ // Generate shortcuts for custom animations
9433
+ jQuery.each({
9434
+ slideDown: genFx("show"),
9435
+ slideUp: genFx("hide"),
9436
+ slideToggle: genFx("toggle"),
9437
+ fadeIn: { opacity: "show" },
9438
+ fadeOut: { opacity: "hide" },
9439
+ fadeToggle: { opacity: "toggle" }
9440
+ }, function( name, props ) {
9441
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
9442
+ return this.animate( props, speed, easing, callback );
9443
+ };
9444
+ });
9445
+
9446
+ jQuery.speed = function( speed, easing, fn ) {
9447
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
9448
+ complete: fn || !fn && easing ||
9449
+ jQuery.isFunction( speed ) && speed,
9450
+ duration: speed,
9451
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
9452
+ };
9453
+
9454
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
9455
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
9456
+
9457
+ // normalize opt.queue - true/undefined/null -> "fx"
9458
+ if ( opt.queue == null || opt.queue === true ) {
9459
+ opt.queue = "fx";
9460
+ }
9461
+
9462
+ // Queueing
9463
+ opt.old = opt.complete;
9464
+
9465
+ opt.complete = function() {
9466
+ if ( jQuery.isFunction( opt.old ) ) {
9467
+ opt.old.call( this );
9468
+ }
9469
+
9470
+ if ( opt.queue ) {
9471
+ jQuery.dequeue( this, opt.queue );
9472
+ }
9473
+ };
9474
+
9475
+ return opt;
9476
+ };
9477
+
9478
+ jQuery.easing = {
9479
+ linear: function( p ) {
9480
+ return p;
9481
+ },
9482
+ swing: function( p ) {
9483
+ return 0.5 - Math.cos( p*Math.PI ) / 2;
9484
+ }
9485
+ };
9486
+
9487
+ jQuery.timers = [];
9488
+ jQuery.fx = Tween.prototype.init;
9489
+ jQuery.fx.tick = function() {
9490
+ var timer,
9491
+ timers = jQuery.timers,
9492
+ i = 0;
9493
+
9494
+ fxNow = jQuery.now();
9495
+
9496
+ for ( ; i < timers.length; i++ ) {
9497
+ timer = timers[ i ];
9498
+ // Checks the timer has not already been removed
9499
+ if ( !timer() && timers[ i ] === timer ) {
9500
+ timers.splice( i--, 1 );
9501
+ }
9502
+ }
9503
+
9504
+ if ( !timers.length ) {
9505
+ jQuery.fx.stop();
9506
+ }
9507
+ fxNow = undefined;
9508
+ };
9509
+
9510
+ jQuery.fx.timer = function( timer ) {
9511
+ if ( timer() && jQuery.timers.push( timer ) ) {
9512
+ jQuery.fx.start();
9513
+ }
9514
+ };
9515
+
9516
+ jQuery.fx.interval = 13;
9517
+
9518
+ jQuery.fx.start = function() {
9519
+ if ( !timerId ) {
9520
+ timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
9521
+ }
9522
+ };
9523
+
9524
+ jQuery.fx.stop = function() {
9525
+ clearInterval( timerId );
9526
+ timerId = null;
9527
+ };
9528
+
9529
+ jQuery.fx.speeds = {
9530
+ slow: 600,
9531
+ fast: 200,
9532
+ // Default speed
9533
+ _default: 400
9534
+ };
9535
+
9536
+ // Back Compat <1.8 extension point
9537
+ jQuery.fx.step = {};
9538
+
9539
+ if ( jQuery.expr && jQuery.expr.filters ) {
9540
+ jQuery.expr.filters.animated = function( elem ) {
9541
+ return jQuery.grep(jQuery.timers, function( fn ) {
9542
+ return elem === fn.elem;
9543
+ }).length;
9544
+ };
9545
+ }
9546
+ jQuery.fn.offset = function( options ) {
9547
+ if ( arguments.length ) {
9548
+ return options === undefined ?
9549
+ this :
9550
+ this.each(function( i ) {
9551
+ jQuery.offset.setOffset( this, options, i );
9552
+ });
9553
+ }
9554
+
9555
+ var docElem, win,
9556
+ box = { top: 0, left: 0 },
9557
+ elem = this[ 0 ],
9558
+ doc = elem && elem.ownerDocument;
9559
+
9560
+ if ( !doc ) {
9561
+ return;
9562
+ }
9563
+
9564
+ docElem = doc.documentElement;
9565
+
9566
+ // Make sure it's not a disconnected DOM node
9567
+ if ( !jQuery.contains( docElem, elem ) ) {
9568
+ return box;
9569
+ }
9570
+
9571
+ // If we don't have gBCR, just use 0,0 rather than error
9572
+ // BlackBerry 5, iOS 3 (original iPhone)
9573
+ if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
9574
+ box = elem.getBoundingClientRect();
9575
+ }
9576
+ win = getWindow( doc );
9577
+ return {
9578
+ top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
9579
+ left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
9580
+ };
9581
+ };
9582
+
9583
+ jQuery.offset = {
9584
+
9585
+ setOffset: function( elem, options, i ) {
9586
+ var position = jQuery.css( elem, "position" );
9587
+
9588
+ // set position first, in-case top/left are set even on static elem
9589
+ if ( position === "static" ) {
9590
+ elem.style.position = "relative";
9591
+ }
9592
+
9593
+ var curElem = jQuery( elem ),
9594
+ curOffset = curElem.offset(),
9595
+ curCSSTop = jQuery.css( elem, "top" ),
9596
+ curCSSLeft = jQuery.css( elem, "left" ),
9597
+ calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
9598
+ props = {}, curPosition = {}, curTop, curLeft;
9599
+
9600
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
9601
+ if ( calculatePosition ) {
9602
+ curPosition = curElem.position();
9603
+ curTop = curPosition.top;
9604
+ curLeft = curPosition.left;
9605
+ } else {
9606
+ curTop = parseFloat( curCSSTop ) || 0;
9607
+ curLeft = parseFloat( curCSSLeft ) || 0;
9608
+ }
9609
+
9610
+ if ( jQuery.isFunction( options ) ) {
9611
+ options = options.call( elem, i, curOffset );
9612
+ }
9613
+
9614
+ if ( options.top != null ) {
9615
+ props.top = ( options.top - curOffset.top ) + curTop;
9616
+ }
9617
+ if ( options.left != null ) {
9618
+ props.left = ( options.left - curOffset.left ) + curLeft;
9619
+ }
9620
+
9621
+ if ( "using" in options ) {
9622
+ options.using.call( elem, props );
9623
+ } else {
9624
+ curElem.css( props );
9625
+ }
9626
+ }
9627
+ };
9628
+
9629
+
9630
+ jQuery.fn.extend({
9631
+
9632
+ position: function() {
9633
+ if ( !this[ 0 ] ) {
9634
+ return;
9635
+ }
9636
+
9637
+ var offsetParent, offset,
9638
+ parentOffset = { top: 0, left: 0 },
9639
+ elem = this[ 0 ];
9640
+
9641
+ // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
9642
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
9643
+ // we assume that getBoundingClientRect is available when computed position is fixed
9644
+ offset = elem.getBoundingClientRect();
9645
+ } else {
9646
+ // Get *real* offsetParent
9647
+ offsetParent = this.offsetParent();
9648
+
9649
+ // Get correct offsets
9650
+ offset = this.offset();
9651
+ if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
9652
+ parentOffset = offsetParent.offset();
9653
+ }
9654
+
9655
+ // Add offsetParent borders
9656
+ parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
9657
+ parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
9658
+ }
9659
+
9660
+ // Subtract parent offsets and element margins
9661
+ // note: when an element has margin: auto the offsetLeft and marginLeft
9662
+ // are the same in Safari causing offset.left to incorrectly be 0
9663
+ return {
9664
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
9665
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
9666
+ };
9667
+ },
9668
+
9669
+ offsetParent: function() {
9670
+ return this.map(function() {
9671
+ var offsetParent = this.offsetParent || docElem;
9672
+ while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
9673
+ offsetParent = offsetParent.offsetParent;
9674
+ }
9675
+ return offsetParent || docElem;
9676
+ });
9677
+ }
9678
+ });
9679
+
9680
+
9681
+ // Create scrollLeft and scrollTop methods
9682
+ jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
9683
+ var top = /Y/.test( prop );
9684
+
9685
+ jQuery.fn[ method ] = function( val ) {
9686
+ return jQuery.access( this, function( elem, method, val ) {
9687
+ var win = getWindow( elem );
9688
+
9689
+ if ( val === undefined ) {
9690
+ return win ? (prop in win) ? win[ prop ] :
9691
+ win.document.documentElement[ method ] :
9692
+ elem[ method ];
9693
+ }
9694
+
9695
+ if ( win ) {
9696
+ win.scrollTo(
9697
+ !top ? val : jQuery( win ).scrollLeft(),
9698
+ top ? val : jQuery( win ).scrollTop()
9699
+ );
9700
+
9701
+ } else {
9702
+ elem[ method ] = val;
9703
+ }
9704
+ }, method, val, arguments.length, null );
9705
+ };
9706
+ });
9707
+
9708
+ function getWindow( elem ) {
9709
+ return jQuery.isWindow( elem ) ?
9710
+ elem :
9711
+ elem.nodeType === 9 ?
9712
+ elem.defaultView || elem.parentWindow :
9713
+ false;
9714
+ }
9715
+ // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
9716
+ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
9717
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
9718
+ // margin is only for outerHeight, outerWidth
9719
+ jQuery.fn[ funcName ] = function( margin, value ) {
9720
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
9721
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
9722
+
9723
+ return jQuery.access( this, function( elem, type, value ) {
9724
+ var doc;
9725
+
9726
+ if ( jQuery.isWindow( elem ) ) {
9727
+ // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
9728
+ // isn't a whole lot we can do. See pull request at this URL for discussion:
9729
+ // https://github.com/jquery/jquery/pull/764
9730
+ return elem.document.documentElement[ "client" + name ];
9731
+ }
9732
+
9733
+ // Get document width or height
9734
+ if ( elem.nodeType === 9 ) {
9735
+ doc = elem.documentElement;
9736
+
9737
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
9738
+ // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
9739
+ return Math.max(
9740
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
9741
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
9742
+ doc[ "client" + name ]
9743
+ );
9744
+ }
9745
+
9746
+ return value === undefined ?
9747
+ // Get width or height on the element, requesting but not forcing parseFloat
9748
+ jQuery.css( elem, type, extra ) :
9749
+
9750
+ // Set width or height on the element
9751
+ jQuery.style( elem, type, value, extra );
9752
+ }, type, chainable ? margin : undefined, chainable, null );
9753
+ };
9754
+ });
9755
+ });
9756
+ // Limit scope pollution from any deprecated API
9757
+ // (function() {
9758
+
9759
+ // The number of elements contained in the matched element set
9760
+ jQuery.fn.size = function() {
9761
+ return this.length;
9762
+ };
9763
+
9764
+ jQuery.fn.andSelf = jQuery.fn.addBack;
9765
+
9766
+ // })();
9767
+ if ( typeof module === "object" && module && typeof module.exports === "object" ) {
9768
+ // Expose jQuery as module.exports in loaders that implement the Node
9769
+ // module pattern (including browserify). Do not create the global, since
9770
+ // the user will be storing it themselves locally, and globals are frowned
9771
+ // upon in the Node module world.
9772
+ module.exports = jQuery;
9773
+ } else {
9774
+ // Otherwise expose jQuery to the global object as usual
9775
+ window.jQuery = window.$ = jQuery;
9776
+
9777
+ // Register as a named AMD module, since jQuery can be concatenated with other
9778
+ // files that may use define, but not via a proper concatenation script that
9779
+ // understands anonymous AMD modules. A named AMD is safest and most robust
9780
+ // way to register. Lowercase jquery is used because AMD module names are
9781
+ // derived from file names, and jQuery is normally delivered in a lowercase
9782
+ // file name. Do this after creating the global so that if an AMD module wants
9783
+ // to call noConflict to hide this version of jQuery, it will work.
9784
+ if ( typeof define === "function" && define.amd ) {
9785
+ define( "jquery", [], function () { return jQuery; } );
9786
+ }
9787
+ }
9788
+
9789
+ })( window );
skin/frontend/rwd/default/js/ve/ve/jquery-ui.js ADDED
@@ -0,0 +1,16617 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! jQuery UI - v1.11.4 - 2015-03-11
2
+ * http://jqueryui.com
3
+ * Includes: core.js, widget.js, mouse.js, position.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, draggable.js, droppable.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js, menu.js, progressbar.js, resizable.js, selectable.js, selectmenu.js, slider.js, sortable.js, spinner.js, tabs.js, tooltip.js
4
+ * Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */
5
+
6
+ (function( factory ) {
7
+ if ( typeof define === "function" && define.amd ) {
8
+
9
+ // AMD. Register as an anonymous module.
10
+ define([ "jquery" ], factory );
11
+ } else {
12
+
13
+ // Browser globals
14
+ factory( jQuery );
15
+ }
16
+ }(function( $ ) {
17
+ /*!
18
+ * jQuery UI Core 1.11.4
19
+ * http://jqueryui.com
20
+ *
21
+ * Copyright jQuery Foundation and other contributors
22
+ * Released under the MIT license.
23
+ * http://jquery.org/license
24
+ *
25
+ * http://api.jqueryui.com/category/ui-core/
26
+ */
27
+
28
+
29
+ // $.ui might exist from components with no dependencies, e.g., $.ui.position
30
+ $.ui = $.ui || {};
31
+
32
+ $.extend( $.ui, {
33
+ version: "1.11.4",
34
+
35
+ keyCode: {
36
+ BACKSPACE: 8,
37
+ COMMA: 188,
38
+ DELETE: 46,
39
+ DOWN: 40,
40
+ END: 35,
41
+ ENTER: 13,
42
+ ESCAPE: 27,
43
+ HOME: 36,
44
+ LEFT: 37,
45
+ PAGE_DOWN: 34,
46
+ PAGE_UP: 33,
47
+ PERIOD: 190,
48
+ RIGHT: 39,
49
+ SPACE: 32,
50
+ TAB: 9,
51
+ UP: 38
52
+ }
53
+ });
54
+
55
+ // plugins
56
+ $.fn.extend({
57
+ scrollParent: function( includeHidden ) {
58
+ var position = this.css( "position" ),
59
+ excludeStaticParent = position === "absolute",
60
+ overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
61
+ scrollParent = this.parents().filter( function() {
62
+ var parent = $( this );
63
+ if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
64
+ return false;
65
+ }
66
+ return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) );
67
+ }).eq( 0 );
68
+
69
+ return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;
70
+ },
71
+
72
+ uniqueId: (function() {
73
+ var uuid = 0;
74
+
75
+ return function() {
76
+ return this.each(function() {
77
+ if ( !this.id ) {
78
+ this.id = "ui-id-" + ( ++uuid );
79
+ }
80
+ });
81
+ };
82
+ })(),
83
+
84
+ removeUniqueId: function() {
85
+ return this.each(function() {
86
+ if ( /^ui-id-\d+$/.test( this.id ) ) {
87
+ $( this ).removeAttr( "id" );
88
+ }
89
+ });
90
+ }
91
+ });
92
+
93
+ // selectors
94
+ function focusable( element, isTabIndexNotNaN ) {
95
+ var map, mapName, img,
96
+ nodeName = element.nodeName.toLowerCase();
97
+ if ( "area" === nodeName ) {
98
+ map = element.parentNode;
99
+ mapName = map.name;
100
+ if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
101
+ return false;
102
+ }
103
+ img = $( "img[usemap='#" + mapName + "']" )[ 0 ];
104
+ return !!img && visible( img );
105
+ }
106
+ return ( /^(input|select|textarea|button|object)$/.test( nodeName ) ?
107
+ !element.disabled :
108
+ "a" === nodeName ?
109
+ element.href || isTabIndexNotNaN :
110
+ isTabIndexNotNaN) &&
111
+ // the element and all of its ancestors must be visible
112
+ visible( element );
113
+ }
114
+
115
+ function visible( element ) {
116
+ return $.expr.filters.visible( element ) &&
117
+ !$( element ).parents().addBack().filter(function() {
118
+ return $.css( this, "visibility" ) === "hidden";
119
+ }).length;
120
+ }
121
+
122
+ $.extend( $.expr[ ":" ], {
123
+ data: $.expr.createPseudo ?
124
+ $.expr.createPseudo(function( dataName ) {
125
+ return function( elem ) {
126
+ return !!$.data( elem, dataName );
127
+ };
128
+ }) :
129
+ // support: jQuery <1.8
130
+ function( elem, i, match ) {
131
+ return !!$.data( elem, match[ 3 ] );
132
+ },
133
+
134
+ focusable: function( element ) {
135
+ return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
136
+ },
137
+
138
+ tabbable: function( element ) {
139
+ var tabIndex = $.attr( element, "tabindex" ),
140
+ isTabIndexNaN = isNaN( tabIndex );
141
+ return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
142
+ }
143
+ });
144
+
145
+ // support: jQuery <1.8
146
+ if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
147
+ $.each( [ "Width", "Height" ], function( i, name ) {
148
+ var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
149
+ type = name.toLowerCase(),
150
+ orig = {
151
+ innerWidth: $.fn.innerWidth,
152
+ innerHeight: $.fn.innerHeight,
153
+ outerWidth: $.fn.outerWidth,
154
+ outerHeight: $.fn.outerHeight
155
+ };
156
+
157
+ function reduce( elem, size, border, margin ) {
158
+ $.each( side, function() {
159
+ size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
160
+ if ( border ) {
161
+ size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
162
+ }
163
+ if ( margin ) {
164
+ size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
165
+ }
166
+ });
167
+ return size;
168
+ }
169
+
170
+ $.fn[ "inner" + name ] = function( size ) {
171
+ if ( size === undefined ) {
172
+ return orig[ "inner" + name ].call( this );
173
+ }
174
+
175
+ return this.each(function() {
176
+ $( this ).css( type, reduce( this, size ) + "px" );
177
+ });
178
+ };
179
+
180
+ $.fn[ "outer" + name] = function( size, margin ) {
181
+ if ( typeof size !== "number" ) {
182
+ return orig[ "outer" + name ].call( this, size );
183
+ }
184
+
185
+ return this.each(function() {
186
+ $( this).css( type, reduce( this, size, true, margin ) + "px" );
187
+ });
188
+ };
189
+ });
190
+ }
191
+
192
+ // support: jQuery <1.8
193
+ if ( !$.fn.addBack ) {
194
+ $.fn.addBack = function( selector ) {
195
+ return this.add( selector == null ?
196
+ this.prevObject : this.prevObject.filter( selector )
197
+ );
198
+ };
199
+ }
200
+
201
+ // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
202
+ if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
203
+ $.fn.removeData = (function( removeData ) {
204
+ return function( key ) {
205
+ if ( arguments.length ) {
206
+ return removeData.call( this, $.camelCase( key ) );
207
+ } else {
208
+ return removeData.call( this );
209
+ }
210
+ };
211
+ })( $.fn.removeData );
212
+ }
213
+
214
+ // deprecated
215
+ $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
216
+
217
+ $.fn.extend({
218
+ focus: (function( orig ) {
219
+ return function( delay, fn ) {
220
+ return typeof delay === "number" ?
221
+ this.each(function() {
222
+ var elem = this;
223
+ setTimeout(function() {
224
+ $( elem ).focus();
225
+ if ( fn ) {
226
+ fn.call( elem );
227
+ }
228
+ }, delay );
229
+ }) :
230
+ orig.apply( this, arguments );
231
+ };
232
+ })( $.fn.focus ),
233
+
234
+ disableSelection: (function() {
235
+ var eventType = "onselectstart" in document.createElement( "div" ) ?
236
+ "selectstart" :
237
+ "mousedown";
238
+
239
+ return function() {
240
+ return this.bind( eventType + ".ui-disableSelection", function( event ) {
241
+ event.preventDefault();
242
+ });
243
+ };
244
+ })(),
245
+
246
+ enableSelection: function() {
247
+ return this.unbind( ".ui-disableSelection" );
248
+ },
249
+
250
+ zIndex: function( zIndex ) {
251
+ if ( zIndex !== undefined ) {
252
+ return this.css( "zIndex", zIndex );
253
+ }
254
+
255
+ if ( this.length ) {
256
+ var elem = $( this[ 0 ] ), position, value;
257
+ while ( elem.length && elem[ 0 ] !== document ) {
258
+ // Ignore z-index if position is set to a value where z-index is ignored by the browser
259
+ // This makes behavior of this function consistent across browsers
260
+ // WebKit always returns auto if the element is positioned
261
+ position = elem.css( "position" );
262
+ if ( position === "absolute" || position === "relative" || position === "fixed" ) {
263
+ // IE returns 0 when zIndex is not specified
264
+ // other browsers return a string
265
+ // we ignore the case of nested elements with an explicit value of 0
266
+ // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
267
+ value = parseInt( elem.css( "zIndex" ), 10 );
268
+ if ( !isNaN( value ) && value !== 0 ) {
269
+ return value;
270
+ }
271
+ }
272
+ elem = elem.parent();
273
+ }
274
+ }
275
+
276
+ return 0;
277
+ }
278
+ });
279
+
280
+ // $.ui.plugin is deprecated. Use $.widget() extensions instead.
281
+ $.ui.plugin = {
282
+ add: function( module, option, set ) {
283
+ var i,
284
+ proto = $.ui[ module ].prototype;
285
+ for ( i in set ) {
286
+ proto.plugins[ i ] = proto.plugins[ i ] || [];
287
+ proto.plugins[ i ].push( [ option, set[ i ] ] );
288
+ }
289
+ },
290
+ call: function( instance, name, args, allowDisconnected ) {
291
+ var i,
292
+ set = instance.plugins[ name ];
293
+
294
+ if ( !set ) {
295
+ return;
296
+ }
297
+
298
+ if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
299
+ return;
300
+ }
301
+
302
+ for ( i = 0; i < set.length; i++ ) {
303
+ if ( instance.options[ set[ i ][ 0 ] ] ) {
304
+ set[ i ][ 1 ].apply( instance.element, args );
305
+ }
306
+ }
307
+ }
308
+ };
309
+
310
+
311
+ /*!
312
+ * jQuery UI Widget 1.11.4
313
+ * http://jqueryui.com
314
+ *
315
+ * Copyright jQuery Foundation and other contributors
316
+ * Released under the MIT license.
317
+ * http://jquery.org/license
318
+ *
319
+ * http://api.jqueryui.com/jQuery.widget/
320
+ */
321
+
322
+
323
+ var widget_uuid = 0,
324
+ widget_slice = Array.prototype.slice;
325
+
326
+ $.cleanData = (function( orig ) {
327
+ return function( elems ) {
328
+ var events, elem, i;
329
+ for ( i = 0; (elem = elems[i]) != null; i++ ) {
330
+ try {
331
+
332
+ // Only trigger remove when necessary to save time
333
+ events = $._data( elem, "events" );
334
+ if ( events && events.remove ) {
335
+ $( elem ).triggerHandler( "remove" );
336
+ }
337
+
338
+ // http://bugs.jquery.com/ticket/8235
339
+ } catch ( e ) {}
340
+ }
341
+ orig( elems );
342
+ };
343
+ })( $.cleanData );
344
+
345
+ $.widget = function( name, base, prototype ) {
346
+ var fullName, existingConstructor, constructor, basePrototype,
347
+ // proxiedPrototype allows the provided prototype to remain unmodified
348
+ // so that it can be used as a mixin for multiple widgets (#8876)
349
+ proxiedPrototype = {},
350
+ namespace = name.split( "." )[ 0 ];
351
+
352
+ name = name.split( "." )[ 1 ];
353
+ fullName = namespace + "-" + name;
354
+
355
+ if ( !prototype ) {
356
+ prototype = base;
357
+ base = $.Widget;
358
+ }
359
+
360
+ // create selector for plugin
361
+ $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
362
+ return !!$.data( elem, fullName );
363
+ };
364
+
365
+ $[ namespace ] = $[ namespace ] || {};
366
+ existingConstructor = $[ namespace ][ name ];
367
+ constructor = $[ namespace ][ name ] = function( options, element ) {
368
+ // allow instantiation without "new" keyword
369
+ if ( !this._createWidget ) {
370
+ return new constructor( options, element );
371
+ }
372
+
373
+ // allow instantiation without initializing for simple inheritance
374
+ // must use "new" keyword (the code above always passes args)
375
+ if ( arguments.length ) {
376
+ this._createWidget( options, element );
377
+ }
378
+ };
379
+ // extend with the existing constructor to carry over any static properties
380
+ $.extend( constructor, existingConstructor, {
381
+ version: prototype.version,
382
+ // copy the object used to create the prototype in case we need to
383
+ // redefine the widget later
384
+ _proto: $.extend( {}, prototype ),
385
+ // track widgets that inherit from this widget in case this widget is
386
+ // redefined after a widget inherits from it
387
+ _childConstructors: []
388
+ });
389
+
390
+ basePrototype = new base();
391
+ // we need to make the options hash a property directly on the new instance
392
+ // otherwise we'll modify the options hash on the prototype that we're
393
+ // inheriting from
394
+ basePrototype.options = $.widget.extend( {}, basePrototype.options );
395
+ $.each( prototype, function( prop, value ) {
396
+ if ( !$.isFunction( value ) ) {
397
+ proxiedPrototype[ prop ] = value;
398
+ return;
399
+ }
400
+ proxiedPrototype[ prop ] = (function() {
401
+ var _super = function() {
402
+ return base.prototype[ prop ].apply( this, arguments );
403
+ },
404
+ _superApply = function( args ) {
405
+ return base.prototype[ prop ].apply( this, args );
406
+ };
407
+ return function() {
408
+ var __super = this._super,
409
+ __superApply = this._superApply,
410
+ returnValue;
411
+
412
+ this._super = _super;
413
+ this._superApply = _superApply;
414
+
415
+ returnValue = value.apply( this, arguments );
416
+
417
+ this._super = __super;
418
+ this._superApply = __superApply;
419
+
420
+ return returnValue;
421
+ };
422
+ })();
423
+ });
424
+ constructor.prototype = $.widget.extend( basePrototype, {
425
+ // TODO: remove support for widgetEventPrefix
426
+ // always use the name + a colon as the prefix, e.g., draggable:start
427
+ // don't prefix for widgets that aren't DOM-based
428
+ widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
429
+ }, proxiedPrototype, {
430
+ constructor: constructor,
431
+ namespace: namespace,
432
+ widgetName: name,
433
+ widgetFullName: fullName
434
+ });
435
+
436
+ // If this widget is being redefined then we need to find all widgets that
437
+ // are inheriting from it and redefine all of them so that they inherit from
438
+ // the new version of this widget. We're essentially trying to replace one
439
+ // level in the prototype chain.
440
+ if ( existingConstructor ) {
441
+ $.each( existingConstructor._childConstructors, function( i, child ) {
442
+ var childPrototype = child.prototype;
443
+
444
+ // redefine the child widget using the same prototype that was
445
+ // originally used, but inherit from the new version of the base
446
+ $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
447
+ });
448
+ // remove the list of existing child constructors from the old constructor
449
+ // so the old child constructors can be garbage collected
450
+ delete existingConstructor._childConstructors;
451
+ } else {
452
+ base._childConstructors.push( constructor );
453
+ }
454
+
455
+ $.widget.bridge( name, constructor );
456
+
457
+ return constructor;
458
+ };
459
+
460
+ $.widget.extend = function( target ) {
461
+ var input = widget_slice.call( arguments, 1 ),
462
+ inputIndex = 0,
463
+ inputLength = input.length,
464
+ key,
465
+ value;
466
+ for ( ; inputIndex < inputLength; inputIndex++ ) {
467
+ for ( key in input[ inputIndex ] ) {
468
+ value = input[ inputIndex ][ key ];
469
+ if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
470
+ // Clone objects
471
+ if ( $.isPlainObject( value ) ) {
472
+ target[ key ] = $.isPlainObject( target[ key ] ) ?
473
+ $.widget.extend( {}, target[ key ], value ) :
474
+ // Don't extend strings, arrays, etc. with objects
475
+ $.widget.extend( {}, value );
476
+ // Copy everything else by reference
477
+ } else {
478
+ target[ key ] = value;
479
+ }
480
+ }
481
+ }
482
+ }
483
+ return target;
484
+ };
485
+
486
+ $.widget.bridge = function( name, object ) {
487
+ var fullName = object.prototype.widgetFullName || name;
488
+ $.fn[ name ] = function( options ) {
489
+ var isMethodCall = typeof options === "string",
490
+ args = widget_slice.call( arguments, 1 ),
491
+ returnValue = this;
492
+
493
+ if ( isMethodCall ) {
494
+ this.each(function() {
495
+ var methodValue,
496
+ instance = $.data( this, fullName );
497
+ if ( options === "instance" ) {
498
+ returnValue = instance;
499
+ return false;
500
+ }
501
+ if ( !instance ) {
502
+ return $.error( "cannot call methods on " + name + " prior to initialization; " +
503
+ "attempted to call method '" + options + "'" );
504
+ }
505
+ if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
506
+ return $.error( "no such method '" + options + "' for " + name + " widget instance" );
507
+ }
508
+ methodValue = instance[ options ].apply( instance, args );
509
+ if ( methodValue !== instance && methodValue !== undefined ) {
510
+ returnValue = methodValue && methodValue.jquery ?
511
+ returnValue.pushStack( methodValue.get() ) :
512
+ methodValue;
513
+ return false;
514
+ }
515
+ });
516
+ } else {
517
+
518
+ // Allow multiple hashes to be passed on init
519
+ if ( args.length ) {
520
+ options = $.widget.extend.apply( null, [ options ].concat(args) );
521
+ }
522
+
523
+ this.each(function() {
524
+ var instance = $.data( this, fullName );
525
+ if ( instance ) {
526
+ instance.option( options || {} );
527
+ if ( instance._init ) {
528
+ instance._init();
529
+ }
530
+ } else {
531
+ $.data( this, fullName, new object( options, this ) );
532
+ }
533
+ });
534
+ }
535
+
536
+ return returnValue;
537
+ };
538
+ };
539
+
540
+ $.Widget = function( /* options, element */ ) {};
541
+ $.Widget._childConstructors = [];
542
+
543
+ $.Widget.prototype = {
544
+ widgetName: "widget",
545
+ widgetEventPrefix: "",
546
+ defaultElement: "<div>",
547
+ options: {
548
+ disabled: false,
549
+
550
+ // callbacks
551
+ create: null
552
+ },
553
+ _createWidget: function( options, element ) {
554
+ element = $( element || this.defaultElement || this )[ 0 ];
555
+ this.element = $( element );
556
+ this.uuid = widget_uuid++;
557
+ this.eventNamespace = "." + this.widgetName + this.uuid;
558
+
559
+ this.bindings = $();
560
+ this.hoverable = $();
561
+ this.focusable = $();
562
+
563
+ if ( element !== this ) {
564
+ $.data( element, this.widgetFullName, this );
565
+ this._on( true, this.element, {
566
+ remove: function( event ) {
567
+ if ( event.target === element ) {
568
+ this.destroy();
569
+ }
570
+ }
571
+ });
572
+ this.document = $( element.style ?
573
+ // element within the document
574
+ element.ownerDocument :
575
+ // element is window or document
576
+ element.document || element );
577
+ this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
578
+ }
579
+
580
+ this.options = $.widget.extend( {},
581
+ this.options,
582
+ this._getCreateOptions(),
583
+ options );
584
+
585
+ this._create();
586
+ this._trigger( "create", null, this._getCreateEventData() );
587
+ this._init();
588
+ },
589
+ _getCreateOptions: $.noop,
590
+ _getCreateEventData: $.noop,
591
+ _create: $.noop,
592
+ _init: $.noop,
593
+
594
+ destroy: function() {
595
+ this._destroy();
596
+ // we can probably remove the unbind calls in 2.0
597
+ // all event bindings should go through this._on()
598
+ this.element
599
+ .unbind( this.eventNamespace )
600
+ .removeData( this.widgetFullName )
601
+ // support: jquery <1.6.3
602
+ // http://bugs.jquery.com/ticket/9413
603
+ .removeData( $.camelCase( this.widgetFullName ) );
604
+ this.widget()
605
+ .unbind( this.eventNamespace )
606
+ .removeAttr( "aria-disabled" )
607
+ .removeClass(
608
+ this.widgetFullName + "-disabled " +
609
+ "ui-state-disabled" );
610
+
611
+ // clean up events and states
612
+ this.bindings.unbind( this.eventNamespace );
613
+ this.hoverable.removeClass( "ui-state-hover" );
614
+ this.focusable.removeClass( "ui-state-focus" );
615
+ },
616
+ _destroy: $.noop,
617
+
618
+ widget: function() {
619
+ return this.element;
620
+ },
621
+
622
+ option: function( key, value ) {
623
+ var options = key,
624
+ parts,
625
+ curOption,
626
+ i;
627
+
628
+ if ( arguments.length === 0 ) {
629
+ // don't return a reference to the internal hash
630
+ return $.widget.extend( {}, this.options );
631
+ }
632
+
633
+ if ( typeof key === "string" ) {
634
+ // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
635
+ options = {};
636
+ parts = key.split( "." );
637
+ key = parts.shift();
638
+ if ( parts.length ) {
639
+ curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
640
+ for ( i = 0; i < parts.length - 1; i++ ) {
641
+ curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
642
+ curOption = curOption[ parts[ i ] ];
643
+ }
644
+ key = parts.pop();
645
+ if ( arguments.length === 1 ) {
646
+ return curOption[ key ] === undefined ? null : curOption[ key ];
647
+ }
648
+ curOption[ key ] = value;
649
+ } else {
650
+ if ( arguments.length === 1 ) {
651
+ return this.options[ key ] === undefined ? null : this.options[ key ];
652
+ }
653
+ options[ key ] = value;
654
+ }
655
+ }
656
+
657
+ this._setOptions( options );
658
+
659
+ return this;
660
+ },
661
+ _setOptions: function( options ) {
662
+ var key;
663
+
664
+ for ( key in options ) {
665
+ this._setOption( key, options[ key ] );
666
+ }
667
+
668
+ return this;
669
+ },
670
+ _setOption: function( key, value ) {
671
+ this.options[ key ] = value;
672
+
673
+ if ( key === "disabled" ) {
674
+ this.widget()
675
+ .toggleClass( this.widgetFullName + "-disabled", !!value );
676
+
677
+ // If the widget is becoming disabled, then nothing is interactive
678
+ if ( value ) {
679
+ this.hoverable.removeClass( "ui-state-hover" );
680
+ this.focusable.removeClass( "ui-state-focus" );
681
+ }
682
+ }
683
+
684
+ return this;
685
+ },
686
+
687
+ enable: function() {
688
+ return this._setOptions({ disabled: false });
689
+ },
690
+ disable: function() {
691
+ return this._setOptions({ disabled: true });
692
+ },
693
+
694
+ _on: function( suppressDisabledCheck, element, handlers ) {
695
+ var delegateElement,
696
+ instance = this;
697
+
698
+ // no suppressDisabledCheck flag, shuffle arguments
699
+ if ( typeof suppressDisabledCheck !== "boolean" ) {
700
+ handlers = element;
701
+ element = suppressDisabledCheck;
702
+ suppressDisabledCheck = false;
703
+ }
704
+
705
+ // no element argument, shuffle and use this.element
706
+ if ( !handlers ) {
707
+ handlers = element;
708
+ element = this.element;
709
+ delegateElement = this.widget();
710
+ } else {
711
+ element = delegateElement = $( element );
712
+ this.bindings = this.bindings.add( element );
713
+ }
714
+
715
+ $.each( handlers, function( event, handler ) {
716
+ function handlerProxy() {
717
+ // allow widgets to customize the disabled handling
718
+ // - disabled as an array instead of boolean
719
+ // - disabled class as method for disabling individual parts
720
+ if ( !suppressDisabledCheck &&
721
+ ( instance.options.disabled === true ||
722
+ $( this ).hasClass( "ui-state-disabled" ) ) ) {
723
+ return;
724
+ }
725
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
726
+ .apply( instance, arguments );
727
+ }
728
+
729
+ // copy the guid so direct unbinding works
730
+ if ( typeof handler !== "string" ) {
731
+ handlerProxy.guid = handler.guid =
732
+ handler.guid || handlerProxy.guid || $.guid++;
733
+ }
734
+
735
+ var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
736
+ eventName = match[1] + instance.eventNamespace,
737
+ selector = match[2];
738
+ if ( selector ) {
739
+ delegateElement.delegate( selector, eventName, handlerProxy );
740
+ } else {
741
+ element.bind( eventName, handlerProxy );
742
+ }
743
+ });
744
+ },
745
+
746
+ _off: function( element, eventName ) {
747
+ eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
748
+ this.eventNamespace;
749
+ element.unbind( eventName ).undelegate( eventName );
750
+
751
+ // Clear the stack to avoid memory leaks (#10056)
752
+ this.bindings = $( this.bindings.not( element ).get() );
753
+ this.focusable = $( this.focusable.not( element ).get() );
754
+ this.hoverable = $( this.hoverable.not( element ).get() );
755
+ },
756
+
757
+ _delay: function( handler, delay ) {
758
+ function handlerProxy() {
759
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
760
+ .apply( instance, arguments );
761
+ }
762
+ var instance = this;
763
+ return setTimeout( handlerProxy, delay || 0 );
764
+ },
765
+
766
+ _hoverable: function( element ) {
767
+ this.hoverable = this.hoverable.add( element );
768
+ this._on( element, {
769
+ mouseenter: function( event ) {
770
+ $( event.currentTarget ).addClass( "ui-state-hover" );
771
+ },
772
+ mouseleave: function( event ) {
773
+ $( event.currentTarget ).removeClass( "ui-state-hover" );
774
+ }
775
+ });
776
+ },
777
+
778
+ _focusable: function( element ) {
779
+ this.focusable = this.focusable.add( element );
780
+ this._on( element, {
781
+ focusin: function( event ) {
782
+ $( event.currentTarget ).addClass( "ui-state-focus" );
783
+ },
784
+ focusout: function( event ) {
785
+ $( event.currentTarget ).removeClass( "ui-state-focus" );
786
+ }
787
+ });
788
+ },
789
+
790
+ _trigger: function( type, event, data ) {
791
+ var prop, orig,
792
+ callback = this.options[ type ];
793
+
794
+ data = data || {};
795
+ event = $.Event( event );
796
+ event.type = ( type === this.widgetEventPrefix ?
797
+ type :
798
+ this.widgetEventPrefix + type ).toLowerCase();
799
+ // the original event may come from any element
800
+ // so we need to reset the target on the new event
801
+ event.target = this.element[ 0 ];
802
+
803
+ // copy original event properties over to the new event
804
+ orig = event.originalEvent;
805
+ if ( orig ) {
806
+ for ( prop in orig ) {
807
+ if ( !( prop in event ) ) {
808
+ event[ prop ] = orig[ prop ];
809
+ }
810
+ }
811
+ }
812
+
813
+ this.element.trigger( event, data );
814
+ return !( $.isFunction( callback ) &&
815
+ callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
816
+ event.isDefaultPrevented() );
817
+ }
818
+ };
819
+
820
+ $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
821
+ $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
822
+ if ( typeof options === "string" ) {
823
+ options = { effect: options };
824
+ }
825
+ var hasOptions,
826
+ effectName = !options ?
827
+ method :
828
+ options === true || typeof options === "number" ?
829
+ defaultEffect :
830
+ options.effect || defaultEffect;
831
+ options = options || {};
832
+ if ( typeof options === "number" ) {
833
+ options = { duration: options };
834
+ }
835
+ hasOptions = !$.isEmptyObject( options );
836
+ options.complete = callback;
837
+ if ( options.delay ) {
838
+ element.delay( options.delay );
839
+ }
840
+ if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
841
+ element[ method ]( options );
842
+ } else if ( effectName !== method && element[ effectName ] ) {
843
+ element[ effectName ]( options.duration, options.easing, callback );
844
+ } else {
845
+ element.queue(function( next ) {
846
+ $( this )[ method ]();
847
+ if ( callback ) {
848
+ callback.call( element[ 0 ] );
849
+ }
850
+ next();
851
+ });
852
+ }
853
+ };
854
+ });
855
+
856
+ var widget = $.widget;
857
+
858
+
859
+ /*!
860
+ * jQuery UI Mouse 1.11.4
861
+ * http://jqueryui.com
862
+ *
863
+ * Copyright jQuery Foundation and other contributors
864
+ * Released under the MIT license.
865
+ * http://jquery.org/license
866
+ *
867
+ * http://api.jqueryui.com/mouse/
868
+ */
869
+
870
+
871
+ var mouseHandled = false;
872
+ $( document ).mouseup( function() {
873
+ mouseHandled = false;
874
+ });
875
+
876
+ var mouse = $.widget("ui.mouse", {
877
+ version: "1.11.4",
878
+ options: {
879
+ cancel: "input,textarea,button,select,option",
880
+ distance: 1,
881
+ delay: 0
882
+ },
883
+ _mouseInit: function() {
884
+ var that = this;
885
+
886
+ this.element
887
+ .bind("mousedown." + this.widgetName, function(event) {
888
+ return that._mouseDown(event);
889
+ })
890
+ .bind("click." + this.widgetName, function(event) {
891
+ if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
892
+ $.removeData(event.target, that.widgetName + ".preventClickEvent");
893
+ event.stopImmediatePropagation();
894
+ return false;
895
+ }
896
+ });
897
+
898
+ this.started = false;
899
+ },
900
+
901
+ // TODO: make sure destroying one instance of mouse doesn't mess with
902
+ // other instances of mouse
903
+ _mouseDestroy: function() {
904
+ this.element.unbind("." + this.widgetName);
905
+ if ( this._mouseMoveDelegate ) {
906
+ this.document
907
+ .unbind("mousemove." + this.widgetName, this._mouseMoveDelegate)
908
+ .unbind("mouseup." + this.widgetName, this._mouseUpDelegate);
909
+ }
910
+ },
911
+
912
+ _mouseDown: function(event) {
913
+ // don't let more than one widget handle mouseStart
914
+ if ( mouseHandled ) {
915
+ return;
916
+ }
917
+
918
+ this._mouseMoved = false;
919
+
920
+ // we may have missed mouseup (out of window)
921
+ (this._mouseStarted && this._mouseUp(event));
922
+
923
+ this._mouseDownEvent = event;
924
+
925
+ var that = this,
926
+ btnIsLeft = (event.which === 1),
927
+ // event.target.nodeName works around a bug in IE 8 with
928
+ // disabled inputs (#7620)
929
+ elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
930
+ if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
931
+ return true;
932
+ }
933
+
934
+ this.mouseDelayMet = !this.options.delay;
935
+ if (!this.mouseDelayMet) {
936
+ this._mouseDelayTimer = setTimeout(function() {
937
+ that.mouseDelayMet = true;
938
+ }, this.options.delay);
939
+ }
940
+
941
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
942
+ this._mouseStarted = (this._mouseStart(event) !== false);
943
+ if (!this._mouseStarted) {
944
+ event.preventDefault();
945
+ return true;
946
+ }
947
+ }
948
+
949
+ // Click event may never have fired (Gecko & Opera)
950
+ if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
951
+ $.removeData(event.target, this.widgetName + ".preventClickEvent");
952
+ }
953
+
954
+ // these delegates are required to keep context
955
+ this._mouseMoveDelegate = function(event) {
956
+ return that._mouseMove(event);
957
+ };
958
+ this._mouseUpDelegate = function(event) {
959
+ return that._mouseUp(event);
960
+ };
961
+
962
+ this.document
963
+ .bind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
964
+ .bind( "mouseup." + this.widgetName, this._mouseUpDelegate );
965
+
966
+ event.preventDefault();
967
+
968
+ mouseHandled = true;
969
+ return true;
970
+ },
971
+
972
+ _mouseMove: function(event) {
973
+ // Only check for mouseups outside the document if you've moved inside the document
974
+ // at least once. This prevents the firing of mouseup in the case of IE<9, which will
975
+ // fire a mousemove event if content is placed under the cursor. See #7778
976
+ // Support: IE <9
977
+ if ( this._mouseMoved ) {
978
+ // IE mouseup check - mouseup happened when mouse was out of window
979
+ if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
980
+ return this._mouseUp(event);
981
+
982
+ // Iframe mouseup check - mouseup occurred in another document
983
+ } else if ( !event.which ) {
984
+ return this._mouseUp( event );
985
+ }
986
+ }
987
+
988
+ if ( event.which || event.button ) {
989
+ this._mouseMoved = true;
990
+ }
991
+
992
+ if (this._mouseStarted) {
993
+ this._mouseDrag(event);
994
+ return event.preventDefault();
995
+ }
996
+
997
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
998
+ this._mouseStarted =
999
+ (this._mouseStart(this._mouseDownEvent, event) !== false);
1000
+ (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
1001
+ }
1002
+
1003
+ return !this._mouseStarted;
1004
+ },
1005
+
1006
+ _mouseUp: function(event) {
1007
+ this.document
1008
+ .unbind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
1009
+ .unbind( "mouseup." + this.widgetName, this._mouseUpDelegate );
1010
+
1011
+ if (this._mouseStarted) {
1012
+ this._mouseStarted = false;
1013
+
1014
+ if (event.target === this._mouseDownEvent.target) {
1015
+ $.data(event.target, this.widgetName + ".preventClickEvent", true);
1016
+ }
1017
+
1018
+ this._mouseStop(event);
1019
+ }
1020
+
1021
+ mouseHandled = false;
1022
+ return false;
1023
+ },
1024
+
1025
+ _mouseDistanceMet: function(event) {
1026
+ return (Math.max(
1027
+ Math.abs(this._mouseDownEvent.pageX - event.pageX),
1028
+ Math.abs(this._mouseDownEvent.pageY - event.pageY)
1029
+ ) >= this.options.distance
1030
+ );
1031
+ },
1032
+
1033
+ _mouseDelayMet: function(/* event */) {
1034
+ return this.mouseDelayMet;
1035
+ },
1036
+
1037
+ // These are placeholder methods, to be overriden by extending plugin
1038
+ _mouseStart: function(/* event */) {},
1039
+ _mouseDrag: function(/* event */) {},
1040
+ _mouseStop: function(/* event */) {},
1041
+ _mouseCapture: function(/* event */) { return true; }
1042
+ });
1043
+
1044
+
1045
+ /*!
1046
+ * jQuery UI Position 1.11.4
1047
+ * http://jqueryui.com
1048
+ *
1049
+ * Copyright jQuery Foundation and other contributors
1050
+ * Released under the MIT license.
1051
+ * http://jquery.org/license
1052
+ *
1053
+ * http://api.jqueryui.com/position/
1054
+ */
1055
+
1056
+ (function() {
1057
+
1058
+ $.ui = $.ui || {};
1059
+
1060
+ var cachedScrollbarWidth, supportsOffsetFractions,
1061
+ max = Math.max,
1062
+ abs = Math.abs,
1063
+ round = Math.round,
1064
+ rhorizontal = /left|center|right/,
1065
+ rvertical = /top|center|bottom/,
1066
+ roffset = /[\+\-]\d+(\.[\d]+)?%?/,
1067
+ rposition = /^\w+/,
1068
+ rpercent = /%$/,
1069
+ _position = $.fn.position;
1070
+
1071
+ function getOffsets( offsets, width, height ) {
1072
+ return [
1073
+ parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
1074
+ parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
1075
+ ];
1076
+ }
1077
+
1078
+ function parseCss( element, property ) {
1079
+ return parseInt( $.css( element, property ), 10 ) || 0;
1080
+ }
1081
+
1082
+ function getDimensions( elem ) {
1083
+ var raw = elem[0];
1084
+ if ( raw.nodeType === 9 ) {
1085
+ return {
1086
+ width: elem.width(),
1087
+ height: elem.height(),
1088
+ offset: { top: 0, left: 0 }
1089
+ };
1090
+ }
1091
+ if ( $.isWindow( raw ) ) {
1092
+ return {
1093
+ width: elem.width(),
1094
+ height: elem.height(),
1095
+ offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
1096
+ };
1097
+ }
1098
+ if ( raw.preventDefault ) {
1099
+ return {
1100
+ width: 0,
1101
+ height: 0,
1102
+ offset: { top: raw.pageY, left: raw.pageX }
1103
+ };
1104
+ }
1105
+ return {
1106
+ width: elem.outerWidth(),
1107
+ height: elem.outerHeight(),
1108
+ offset: elem.offset()
1109
+ };
1110
+ }
1111
+
1112
+ $.position = {
1113
+ scrollbarWidth: function() {
1114
+ if ( cachedScrollbarWidth !== undefined ) {
1115
+ return cachedScrollbarWidth;
1116
+ }
1117
+ var w1, w2,
1118
+ div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
1119
+ innerDiv = div.children()[0];
1120
+
1121
+ $( "body" ).append( div );
1122
+ w1 = innerDiv.offsetWidth;
1123
+ div.css( "overflow", "scroll" );
1124
+
1125
+ w2 = innerDiv.offsetWidth;
1126
+
1127
+ if ( w1 === w2 ) {
1128
+ w2 = div[0].clientWidth;
1129
+ }
1130
+
1131
+ div.remove();
1132
+
1133
+ return (cachedScrollbarWidth = w1 - w2);
1134
+ },
1135
+ getScrollInfo: function( within ) {
1136
+ var overflowX = within.isWindow || within.isDocument ? "" :
1137
+ within.element.css( "overflow-x" ),
1138
+ overflowY = within.isWindow || within.isDocument ? "" :
1139
+ within.element.css( "overflow-y" ),
1140
+ hasOverflowX = overflowX === "scroll" ||
1141
+ ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
1142
+ hasOverflowY = overflowY === "scroll" ||
1143
+ ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
1144
+ return {
1145
+ width: hasOverflowY ? $.position.scrollbarWidth() : 0,
1146
+ height: hasOverflowX ? $.position.scrollbarWidth() : 0
1147
+ };
1148
+ },
1149
+ getWithinInfo: function( element ) {
1150
+ var withinElement = $( element || window ),
1151
+ isWindow = $.isWindow( withinElement[0] ),
1152
+ isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
1153
+ return {
1154
+ element: withinElement,
1155
+ isWindow: isWindow,
1156
+ isDocument: isDocument,
1157
+ offset: withinElement.offset() || { left: 0, top: 0 },
1158
+ scrollLeft: withinElement.scrollLeft(),
1159
+ scrollTop: withinElement.scrollTop(),
1160
+
1161
+ // support: jQuery 1.6.x
1162
+ // jQuery 1.6 doesn't support .outerWidth/Height() on documents or windows
1163
+ width: isWindow || isDocument ? withinElement.width() : withinElement.outerWidth(),
1164
+ height: isWindow || isDocument ? withinElement.height() : withinElement.outerHeight()
1165
+ };
1166
+ }
1167
+ };
1168
+
1169
+ $.fn.position = function( options ) {
1170
+ if ( !options || !options.of ) {
1171
+ return _position.apply( this, arguments );
1172
+ }
1173
+
1174
+ // make a copy, we don't want to modify arguments
1175
+ options = $.extend( {}, options );
1176
+
1177
+ var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
1178
+ target = $( options.of ),
1179
+ within = $.position.getWithinInfo( options.within ),
1180
+ scrollInfo = $.position.getScrollInfo( within ),
1181
+ collision = ( options.collision || "flip" ).split( " " ),
1182
+ offsets = {};
1183
+
1184
+ dimensions = getDimensions( target );
1185
+ if ( target[0].preventDefault ) {
1186
+ // force left top to allow flipping
1187
+ options.at = "left top";
1188
+ }
1189
+ targetWidth = dimensions.width;
1190
+ targetHeight = dimensions.height;
1191
+ targetOffset = dimensions.offset;
1192
+ // clone to reuse original targetOffset later
1193
+ basePosition = $.extend( {}, targetOffset );
1194
+
1195
+ // force my and at to have valid horizontal and vertical positions
1196
+ // if a value is missing or invalid, it will be converted to center
1197
+ $.each( [ "my", "at" ], function() {
1198
+ var pos = ( options[ this ] || "" ).split( " " ),
1199
+ horizontalOffset,
1200
+ verticalOffset;
1201
+
1202
+ if ( pos.length === 1) {
1203
+ pos = rhorizontal.test( pos[ 0 ] ) ?
1204
+ pos.concat( [ "center" ] ) :
1205
+ rvertical.test( pos[ 0 ] ) ?
1206
+ [ "center" ].concat( pos ) :
1207
+ [ "center", "center" ];
1208
+ }
1209
+ pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
1210
+ pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
1211
+
1212
+ // calculate offsets
1213
+ horizontalOffset = roffset.exec( pos[ 0 ] );
1214
+ verticalOffset = roffset.exec( pos[ 1 ] );
1215
+ offsets[ this ] = [
1216
+ horizontalOffset ? horizontalOffset[ 0 ] : 0,
1217
+ verticalOffset ? verticalOffset[ 0 ] : 0
1218
+ ];
1219
+
1220
+ // reduce to just the positions without the offsets
1221
+ options[ this ] = [
1222
+ rposition.exec( pos[ 0 ] )[ 0 ],
1223
+ rposition.exec( pos[ 1 ] )[ 0 ]
1224
+ ];
1225
+ });
1226
+
1227
+ // normalize collision option
1228
+ if ( collision.length === 1 ) {
1229
+ collision[ 1 ] = collision[ 0 ];
1230
+ }
1231
+
1232
+ if ( options.at[ 0 ] === "right" ) {
1233
+ basePosition.left += targetWidth;
1234
+ } else if ( options.at[ 0 ] === "center" ) {
1235
+ basePosition.left += targetWidth / 2;
1236
+ }
1237
+
1238
+ if ( options.at[ 1 ] === "bottom" ) {
1239
+ basePosition.top += targetHeight;
1240
+ } else if ( options.at[ 1 ] === "center" ) {
1241
+ basePosition.top += targetHeight / 2;
1242
+ }
1243
+
1244
+ atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
1245
+ basePosition.left += atOffset[ 0 ];
1246
+ basePosition.top += atOffset[ 1 ];
1247
+
1248
+ return this.each(function() {
1249
+ var collisionPosition, using,
1250
+ elem = $( this ),
1251
+ elemWidth = elem.outerWidth(),
1252
+ elemHeight = elem.outerHeight(),
1253
+ marginLeft = parseCss( this, "marginLeft" ),
1254
+ marginTop = parseCss( this, "marginTop" ),
1255
+ collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
1256
+ collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
1257
+ position = $.extend( {}, basePosition ),
1258
+ myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1259
+
1260
+ if ( options.my[ 0 ] === "right" ) {
1261
+ position.left -= elemWidth;
1262
+ } else if ( options.my[ 0 ] === "center" ) {
1263
+ position.left -= elemWidth / 2;
1264
+ }
1265
+
1266
+ if ( options.my[ 1 ] === "bottom" ) {
1267
+ position.top -= elemHeight;
1268
+ } else if ( options.my[ 1 ] === "center" ) {
1269
+ position.top -= elemHeight / 2;
1270
+ }
1271
+
1272
+ position.left += myOffset[ 0 ];
1273
+ position.top += myOffset[ 1 ];
1274
+
1275
+ // if the browser doesn't support fractions, then round for consistent results
1276
+ if ( !supportsOffsetFractions ) {
1277
+ position.left = round( position.left );
1278
+ position.top = round( position.top );
1279
+ }
1280
+
1281
+ collisionPosition = {
1282
+ marginLeft: marginLeft,
1283
+ marginTop: marginTop
1284
+ };
1285
+
1286
+ $.each( [ "left", "top" ], function( i, dir ) {
1287
+ if ( $.ui.position[ collision[ i ] ] ) {
1288
+ $.ui.position[ collision[ i ] ][ dir ]( position, {
1289
+ targetWidth: targetWidth,
1290
+ targetHeight: targetHeight,
1291
+ elemWidth: elemWidth,
1292
+ elemHeight: elemHeight,
1293
+ collisionPosition: collisionPosition,
1294
+ collisionWidth: collisionWidth,
1295
+ collisionHeight: collisionHeight,
1296
+ offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1297
+ my: options.my,
1298
+ at: options.at,
1299
+ within: within,
1300
+ elem: elem
1301
+ });
1302
+ }
1303
+ });
1304
+
1305
+ if ( options.using ) {
1306
+ // adds feedback as second argument to using callback, if present
1307
+ using = function( props ) {
1308
+ var left = targetOffset.left - position.left,
1309
+ right = left + targetWidth - elemWidth,
1310
+ top = targetOffset.top - position.top,
1311
+ bottom = top + targetHeight - elemHeight,
1312
+ feedback = {
1313
+ target: {
1314
+ element: target,
1315
+ left: targetOffset.left,
1316
+ top: targetOffset.top,
1317
+ width: targetWidth,
1318
+ height: targetHeight
1319
+ },
1320
+ element: {
1321
+ element: elem,
1322
+ left: position.left,
1323
+ top: position.top,
1324
+ width: elemWidth,
1325
+ height: elemHeight
1326
+ },
1327
+ horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1328
+ vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1329
+ };
1330
+ if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1331
+ feedback.horizontal = "center";
1332
+ }
1333
+ if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1334
+ feedback.vertical = "middle";
1335
+ }
1336
+ if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1337
+ feedback.important = "horizontal";
1338
+ } else {
1339
+ feedback.important = "vertical";
1340
+ }
1341
+ options.using.call( this, props, feedback );
1342
+ };
1343
+ }
1344
+
1345
+ elem.offset( $.extend( position, { using: using } ) );
1346
+ });
1347
+ };
1348
+
1349
+ $.ui.position = {
1350
+ fit: {
1351
+ left: function( position, data ) {
1352
+ var within = data.within,
1353
+ withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1354
+ outerWidth = within.width,
1355
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1356
+ overLeft = withinOffset - collisionPosLeft,
1357
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1358
+ newOverRight;
1359
+
1360
+ // element is wider than within
1361
+ if ( data.collisionWidth > outerWidth ) {
1362
+ // element is initially over the left side of within
1363
+ if ( overLeft > 0 && overRight <= 0 ) {
1364
+ newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
1365
+ position.left += overLeft - newOverRight;
1366
+ // element is initially over right side of within
1367
+ } else if ( overRight > 0 && overLeft <= 0 ) {
1368
+ position.left = withinOffset;
1369
+ // element is initially over both left and right sides of within
1370
+ } else {
1371
+ if ( overLeft > overRight ) {
1372
+ position.left = withinOffset + outerWidth - data.collisionWidth;
1373
+ } else {
1374
+ position.left = withinOffset;
1375
+ }
1376
+ }
1377
+ // too far left -> align with left edge
1378
+ } else if ( overLeft > 0 ) {
1379
+ position.left += overLeft;
1380
+ // too far right -> align with right edge
1381
+ } else if ( overRight > 0 ) {
1382
+ position.left -= overRight;
1383
+ // adjust based on position and margin
1384
+ } else {
1385
+ position.left = max( position.left - collisionPosLeft, position.left );
1386
+ }
1387
+ },
1388
+ top: function( position, data ) {
1389
+ var within = data.within,
1390
+ withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1391
+ outerHeight = data.within.height,
1392
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
1393
+ overTop = withinOffset - collisionPosTop,
1394
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1395
+ newOverBottom;
1396
+
1397
+ // element is taller than within
1398
+ if ( data.collisionHeight > outerHeight ) {
1399
+ // element is initially over the top of within
1400
+ if ( overTop > 0 && overBottom <= 0 ) {
1401
+ newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
1402
+ position.top += overTop - newOverBottom;
1403
+ // element is initially over bottom of within
1404
+ } else if ( overBottom > 0 && overTop <= 0 ) {
1405
+ position.top = withinOffset;
1406
+ // element is initially over both top and bottom of within
1407
+ } else {
1408
+ if ( overTop > overBottom ) {
1409
+ position.top = withinOffset + outerHeight - data.collisionHeight;
1410
+ } else {
1411
+ position.top = withinOffset;
1412
+ }
1413
+ }
1414
+ // too far up -> align with top
1415
+ } else if ( overTop > 0 ) {
1416
+ position.top += overTop;
1417
+ // too far down -> align with bottom edge
1418
+ } else if ( overBottom > 0 ) {
1419
+ position.top -= overBottom;
1420
+ // adjust based on position and margin
1421
+ } else {
1422
+ position.top = max( position.top - collisionPosTop, position.top );
1423
+ }
1424
+ }
1425
+ },
1426
+ flip: {
1427
+ left: function( position, data ) {
1428
+ var within = data.within,
1429
+ withinOffset = within.offset.left + within.scrollLeft,
1430
+ outerWidth = within.width,
1431
+ offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1432
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1433
+ overLeft = collisionPosLeft - offsetLeft,
1434
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1435
+ myOffset = data.my[ 0 ] === "left" ?
1436
+ -data.elemWidth :
1437
+ data.my[ 0 ] === "right" ?
1438
+ data.elemWidth :
1439
+ 0,
1440
+ atOffset = data.at[ 0 ] === "left" ?
1441
+ data.targetWidth :
1442
+ data.at[ 0 ] === "right" ?
1443
+ -data.targetWidth :
1444
+ 0,
1445
+ offset = -2 * data.offset[ 0 ],
1446
+ newOverRight,
1447
+ newOverLeft;
1448
+
1449
+ if ( overLeft < 0 ) {
1450
+ newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
1451
+ if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1452
+ position.left += myOffset + atOffset + offset;
1453
+ }
1454
+ } else if ( overRight > 0 ) {
1455
+ newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
1456
+ if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1457
+ position.left += myOffset + atOffset + offset;
1458
+ }
1459
+ }
1460
+ },
1461
+ top: function( position, data ) {
1462
+ var within = data.within,
1463
+ withinOffset = within.offset.top + within.scrollTop,
1464
+ outerHeight = within.height,
1465
+ offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1466
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
1467
+ overTop = collisionPosTop - offsetTop,
1468
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1469
+ top = data.my[ 1 ] === "top",
1470
+ myOffset = top ?
1471
+ -data.elemHeight :
1472
+ data.my[ 1 ] === "bottom" ?
1473
+ data.elemHeight :
1474
+ 0,
1475
+ atOffset = data.at[ 1 ] === "top" ?
1476
+ data.targetHeight :
1477
+ data.at[ 1 ] === "bottom" ?
1478
+ -data.targetHeight :
1479
+ 0,
1480
+ offset = -2 * data.offset[ 1 ],
1481
+ newOverTop,
1482
+ newOverBottom;
1483
+ if ( overTop < 0 ) {
1484
+ newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
1485
+ if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1486
+ position.top += myOffset + atOffset + offset;
1487
+ }
1488
+ } else if ( overBottom > 0 ) {
1489
+ newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
1490
+ if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1491
+ position.top += myOffset + atOffset + offset;
1492
+ }
1493
+ }
1494
+ }
1495
+ },
1496
+ flipfit: {
1497
+ left: function() {
1498
+ $.ui.position.flip.left.apply( this, arguments );
1499
+ $.ui.position.fit.left.apply( this, arguments );
1500
+ },
1501
+ top: function() {
1502
+ $.ui.position.flip.top.apply( this, arguments );
1503
+ $.ui.position.fit.top.apply( this, arguments );
1504
+ }
1505
+ }
1506
+ };
1507
+
1508
+ // fraction support test
1509
+ (function() {
1510
+ var testElement, testElementParent, testElementStyle, offsetLeft, i,
1511
+ body = document.getElementsByTagName( "body" )[ 0 ],
1512
+ div = document.createElement( "div" );
1513
+
1514
+ //Create a "fake body" for testing based on method used in jQuery.support
1515
+ testElement = document.createElement( body ? "div" : "body" );
1516
+ testElementStyle = {
1517
+ visibility: "hidden",
1518
+ width: 0,
1519
+ height: 0,
1520
+ border: 0,
1521
+ margin: 0,
1522
+ background: "none"
1523
+ };
1524
+ if ( body ) {
1525
+ $.extend( testElementStyle, {
1526
+ position: "absolute",
1527
+ left: "-1000px",
1528
+ top: "-1000px"
1529
+ });
1530
+ }
1531
+ for ( i in testElementStyle ) {
1532
+ testElement.style[ i ] = testElementStyle[ i ];
1533
+ }
1534
+ testElement.appendChild( div );
1535
+ testElementParent = body || document.documentElement;
1536
+ testElementParent.insertBefore( testElement, testElementParent.firstChild );
1537
+
1538
+ div.style.cssText = "position: absolute; left: 10.7432222px;";
1539
+
1540
+ offsetLeft = $( div ).offset().left;
1541
+ supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11;
1542
+
1543
+ testElement.innerHTML = "";
1544
+ testElementParent.removeChild( testElement );
1545
+ })();
1546
+
1547
+ })();
1548
+
1549
+ var position = $.ui.position;
1550
+
1551
+
1552
+ /*!
1553
+ * jQuery UI Accordion 1.11.4
1554
+ * http://jqueryui.com
1555
+ *
1556
+ * Copyright jQuery Foundation and other contributors
1557
+ * Released under the MIT license.
1558
+ * http://jquery.org/license
1559
+ *
1560
+ * http://api.jqueryui.com/accordion/
1561
+ */
1562
+
1563
+
1564
+ var accordion = $.widget( "ui.accordion", {
1565
+ version: "1.11.4",
1566
+ options: {
1567
+ active: 0,
1568
+ animate: {},
1569
+ collapsible: false,
1570
+ event: "click",
1571
+ header: "> li > :first-child,> :not(li):even",
1572
+ heightStyle: "auto",
1573
+ icons: {
1574
+ activeHeader: "ui-icon-triangle-1-s",
1575
+ header: "ui-icon-triangle-1-e"
1576
+ },
1577
+
1578
+ // callbacks
1579
+ activate: null,
1580
+ beforeActivate: null
1581
+ },
1582
+
1583
+ hideProps: {
1584
+ borderTopWidth: "hide",
1585
+ borderBottomWidth: "hide",
1586
+ paddingTop: "hide",
1587
+ paddingBottom: "hide",
1588
+ height: "hide"
1589
+ },
1590
+
1591
+ showProps: {
1592
+ borderTopWidth: "show",
1593
+ borderBottomWidth: "show",
1594
+ paddingTop: "show",
1595
+ paddingBottom: "show",
1596
+ height: "show"
1597
+ },
1598
+
1599
+ _create: function() {
1600
+ var options = this.options;
1601
+ this.prevShow = this.prevHide = $();
1602
+ this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
1603
+ // ARIA
1604
+ .attr( "role", "tablist" );
1605
+
1606
+ // don't allow collapsible: false and active: false / null
1607
+ if ( !options.collapsible && (options.active === false || options.active == null) ) {
1608
+ options.active = 0;
1609
+ }
1610
+
1611
+ this._processPanels();
1612
+ // handle negative values
1613
+ if ( options.active < 0 ) {
1614
+ options.active += this.headers.length;
1615
+ }
1616
+ this._refresh();
1617
+ },
1618
+
1619
+ _getCreateEventData: function() {
1620
+ return {
1621
+ header: this.active,
1622
+ panel: !this.active.length ? $() : this.active.next()
1623
+ };
1624
+ },
1625
+
1626
+ _createIcons: function() {
1627
+ var icons = this.options.icons;
1628
+ if ( icons ) {
1629
+ $( "<span>" )
1630
+ .addClass( "ui-accordion-header-icon ui-icon " + icons.header )
1631
+ .prependTo( this.headers );
1632
+ this.active.children( ".ui-accordion-header-icon" )
1633
+ .removeClass( icons.header )
1634
+ .addClass( icons.activeHeader );
1635
+ this.headers.addClass( "ui-accordion-icons" );
1636
+ }
1637
+ },
1638
+
1639
+ _destroyIcons: function() {
1640
+ this.headers
1641
+ .removeClass( "ui-accordion-icons" )
1642
+ .children( ".ui-accordion-header-icon" )
1643
+ .remove();
1644
+ },
1645
+
1646
+ _destroy: function() {
1647
+ var contents;
1648
+
1649
+ // clean up main element
1650
+ this.element
1651
+ .removeClass( "ui-accordion ui-widget ui-helper-reset" )
1652
+ .removeAttr( "role" );
1653
+
1654
+ // clean up headers
1655
+ this.headers
1656
+ .removeClass( "ui-accordion-header ui-accordion-header-active ui-state-default " +
1657
+ "ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
1658
+ .removeAttr( "role" )
1659
+ .removeAttr( "aria-expanded" )
1660
+ .removeAttr( "aria-selected" )
1661
+ .removeAttr( "aria-controls" )
1662
+ .removeAttr( "tabIndex" )
1663
+ .removeUniqueId();
1664
+
1665
+ this._destroyIcons();
1666
+
1667
+ // clean up content panels
1668
+ contents = this.headers.next()
1669
+ .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom " +
1670
+ "ui-accordion-content ui-accordion-content-active ui-state-disabled" )
1671
+ .css( "display", "" )
1672
+ .removeAttr( "role" )
1673
+ .removeAttr( "aria-hidden" )
1674
+ .removeAttr( "aria-labelledby" )
1675
+ .removeUniqueId();
1676
+
1677
+ if ( this.options.heightStyle !== "content" ) {
1678
+ contents.css( "height", "" );
1679
+ }
1680
+ },
1681
+
1682
+ _setOption: function( key, value ) {
1683
+ if ( key === "active" ) {
1684
+ // _activate() will handle invalid values and update this.options
1685
+ this._activate( value );
1686
+ return;
1687
+ }
1688
+
1689
+ if ( key === "event" ) {
1690
+ if ( this.options.event ) {
1691
+ this._off( this.headers, this.options.event );
1692
+ }
1693
+ this._setupEvents( value );
1694
+ }
1695
+
1696
+ this._super( key, value );
1697
+
1698
+ // setting collapsible: false while collapsed; open first panel
1699
+ if ( key === "collapsible" && !value && this.options.active === false ) {
1700
+ this._activate( 0 );
1701
+ }
1702
+
1703
+ if ( key === "icons" ) {
1704
+ this._destroyIcons();
1705
+ if ( value ) {
1706
+ this._createIcons();
1707
+ }
1708
+ }
1709
+
1710
+ // #5332 - opacity doesn't cascade to positioned elements in IE
1711
+ // so we need to add the disabled class to the headers and panels
1712
+ if ( key === "disabled" ) {
1713
+ this.element
1714
+ .toggleClass( "ui-state-disabled", !!value )
1715
+ .attr( "aria-disabled", value );
1716
+ this.headers.add( this.headers.next() )
1717
+ .toggleClass( "ui-state-disabled", !!value );
1718
+ }
1719
+ },
1720
+
1721
+ _keydown: function( event ) {
1722
+ if ( event.altKey || event.ctrlKey ) {
1723
+ return;
1724
+ }
1725
+
1726
+ var keyCode = $.ui.keyCode,
1727
+ length = this.headers.length,
1728
+ currentIndex = this.headers.index( event.target ),
1729
+ toFocus = false;
1730
+
1731
+ switch ( event.keyCode ) {
1732
+ case keyCode.RIGHT:
1733
+ case keyCode.DOWN:
1734
+ toFocus = this.headers[ ( currentIndex + 1 ) % length ];
1735
+ break;
1736
+ case keyCode.LEFT:
1737
+ case keyCode.UP:
1738
+ toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
1739
+ break;
1740
+ case keyCode.SPACE:
1741
+ case keyCode.ENTER:
1742
+ this._eventHandler( event );
1743
+ break;
1744
+ case keyCode.HOME:
1745
+ toFocus = this.headers[ 0 ];
1746
+ break;
1747
+ case keyCode.END:
1748
+ toFocus = this.headers[ length - 1 ];
1749
+ break;
1750
+ }
1751
+
1752
+ if ( toFocus ) {
1753
+ $( event.target ).attr( "tabIndex", -1 );
1754
+ $( toFocus ).attr( "tabIndex", 0 );
1755
+ toFocus.focus();
1756
+ event.preventDefault();
1757
+ }
1758
+ },
1759
+
1760
+ _panelKeyDown: function( event ) {
1761
+ if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
1762
+ $( event.currentTarget ).prev().focus();
1763
+ }
1764
+ },
1765
+
1766
+ refresh: function() {
1767
+ var options = this.options;
1768
+ this._processPanels();
1769
+
1770
+ // was collapsed or no panel
1771
+ if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
1772
+ options.active = false;
1773
+ this.active = $();
1774
+ // active false only when collapsible is true
1775
+ } else if ( options.active === false ) {
1776
+ this._activate( 0 );
1777
+ // was active, but active panel is gone
1778
+ } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
1779
+ // all remaining panel are disabled
1780
+ if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
1781
+ options.active = false;
1782
+ this.active = $();
1783
+ // activate previous panel
1784
+ } else {
1785
+ this._activate( Math.max( 0, options.active - 1 ) );
1786
+ }
1787
+ // was active, active panel still exists
1788
+ } else {
1789
+ // make sure active index is correct
1790
+ options.active = this.headers.index( this.active );
1791
+ }
1792
+
1793
+ this._destroyIcons();
1794
+
1795
+ this._refresh();
1796
+ },
1797
+
1798
+ _processPanels: function() {
1799
+ var prevHeaders = this.headers,
1800
+ prevPanels = this.panels;
1801
+
1802
+ this.headers = this.element.find( this.options.header )
1803
+ .addClass( "ui-accordion-header ui-state-default ui-corner-all" );
1804
+
1805
+ this.panels = this.headers.next()
1806
+ .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
1807
+ .filter( ":not(.ui-accordion-content-active)" )
1808
+ .hide();
1809
+
1810
+ // Avoid memory leaks (#10056)
1811
+ if ( prevPanels ) {
1812
+ this._off( prevHeaders.not( this.headers ) );
1813
+ this._off( prevPanels.not( this.panels ) );
1814
+ }
1815
+ },
1816
+
1817
+ _refresh: function() {
1818
+ var maxHeight,
1819
+ options = this.options,
1820
+ heightStyle = options.heightStyle,
1821
+ parent = this.element.parent();
1822
+
1823
+ this.active = this._findActive( options.active )
1824
+ .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )
1825
+ .removeClass( "ui-corner-all" );
1826
+ this.active.next()
1827
+ .addClass( "ui-accordion-content-active" )
1828
+ .show();
1829
+
1830
+ this.headers
1831
+ .attr( "role", "tab" )
1832
+ .each(function() {
1833
+ var header = $( this ),
1834
+ headerId = header.uniqueId().attr( "id" ),
1835
+ panel = header.next(),
1836
+ panelId = panel.uniqueId().attr( "id" );
1837
+ header.attr( "aria-controls", panelId );
1838
+ panel.attr( "aria-labelledby", headerId );
1839
+ })
1840
+ .next()
1841
+ .attr( "role", "tabpanel" );
1842
+
1843
+ this.headers
1844
+ .not( this.active )
1845
+ .attr({
1846
+ "aria-selected": "false",
1847
+ "aria-expanded": "false",
1848
+ tabIndex: -1
1849
+ })
1850
+ .next()
1851
+ .attr({
1852
+ "aria-hidden": "true"
1853
+ })
1854
+ .hide();
1855
+
1856
+ // make sure at least one header is in the tab order
1857
+ if ( !this.active.length ) {
1858
+ this.headers.eq( 0 ).attr( "tabIndex", 0 );
1859
+ } else {
1860
+ this.active.attr({
1861
+ "aria-selected": "true",
1862
+ "aria-expanded": "true",
1863
+ tabIndex: 0
1864
+ })
1865
+ .next()
1866
+ .attr({
1867
+ "aria-hidden": "false"
1868
+ });
1869
+ }
1870
+
1871
+ this._createIcons();
1872
+
1873
+ this._setupEvents( options.event );
1874
+
1875
+ if ( heightStyle === "fill" ) {
1876
+ maxHeight = parent.height();
1877
+ this.element.siblings( ":visible" ).each(function() {
1878
+ var elem = $( this ),
1879
+ position = elem.css( "position" );
1880
+
1881
+ if ( position === "absolute" || position === "fixed" ) {
1882
+ return;
1883
+ }
1884
+ maxHeight -= elem.outerHeight( true );
1885
+ });
1886
+
1887
+ this.headers.each(function() {
1888
+ maxHeight -= $( this ).outerHeight( true );
1889
+ });
1890
+
1891
+ this.headers.next()
1892
+ .each(function() {
1893
+ $( this ).height( Math.max( 0, maxHeight -
1894
+ $( this ).innerHeight() + $( this ).height() ) );
1895
+ })
1896
+ .css( "overflow", "auto" );
1897
+ } else if ( heightStyle === "auto" ) {
1898
+ maxHeight = 0;
1899
+ this.headers.next()
1900
+ .each(function() {
1901
+ maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
1902
+ })
1903
+ .height( maxHeight );
1904
+ }
1905
+ },
1906
+
1907
+ _activate: function( index ) {
1908
+ var active = this._findActive( index )[ 0 ];
1909
+
1910
+ // trying to activate the already active panel
1911
+ if ( active === this.active[ 0 ] ) {
1912
+ return;
1913
+ }
1914
+
1915
+ // trying to collapse, simulate a click on the currently active header
1916
+ active = active || this.active[ 0 ];
1917
+
1918
+ this._eventHandler({
1919
+ target: active,
1920
+ currentTarget: active,
1921
+ preventDefault: $.noop
1922
+ });
1923
+ },
1924
+
1925
+ _findActive: function( selector ) {
1926
+ return typeof selector === "number" ? this.headers.eq( selector ) : $();
1927
+ },
1928
+
1929
+ _setupEvents: function( event ) {
1930
+ var events = {
1931
+ keydown: "_keydown"
1932
+ };
1933
+ if ( event ) {
1934
+ $.each( event.split( " " ), function( index, eventName ) {
1935
+ events[ eventName ] = "_eventHandler";
1936
+ });
1937
+ }
1938
+
1939
+ this._off( this.headers.add( this.headers.next() ) );
1940
+ this._on( this.headers, events );
1941
+ this._on( this.headers.next(), { keydown: "_panelKeyDown" });
1942
+ this._hoverable( this.headers );
1943
+ this._focusable( this.headers );
1944
+ },
1945
+
1946
+ _eventHandler: function( event ) {
1947
+ var options = this.options,
1948
+ active = this.active,
1949
+ clicked = $( event.currentTarget ),
1950
+ clickedIsActive = clicked[ 0 ] === active[ 0 ],
1951
+ collapsing = clickedIsActive && options.collapsible,
1952
+ toShow = collapsing ? $() : clicked.next(),
1953
+ toHide = active.next(),
1954
+ eventData = {
1955
+ oldHeader: active,
1956
+ oldPanel: toHide,
1957
+ newHeader: collapsing ? $() : clicked,
1958
+ newPanel: toShow
1959
+ };
1960
+
1961
+ event.preventDefault();
1962
+
1963
+ if (
1964
+ // click on active header, but not collapsible
1965
+ ( clickedIsActive && !options.collapsible ) ||
1966
+ // allow canceling activation
1967
+ ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
1968
+ return;
1969
+ }
1970
+
1971
+ options.active = collapsing ? false : this.headers.index( clicked );
1972
+
1973
+ // when the call to ._toggle() comes after the class changes
1974
+ // it causes a very odd bug in IE 8 (see #6720)
1975
+ this.active = clickedIsActive ? $() : clicked;
1976
+ this._toggle( eventData );
1977
+
1978
+ // switch classes
1979
+ // corner classes on the previously active header stay after the animation
1980
+ active.removeClass( "ui-accordion-header-active ui-state-active" );
1981
+ if ( options.icons ) {
1982
+ active.children( ".ui-accordion-header-icon" )
1983
+ .removeClass( options.icons.activeHeader )
1984
+ .addClass( options.icons.header );
1985
+ }
1986
+
1987
+ if ( !clickedIsActive ) {
1988
+ clicked
1989
+ .removeClass( "ui-corner-all" )
1990
+ .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
1991
+ if ( options.icons ) {
1992
+ clicked.children( ".ui-accordion-header-icon" )
1993
+ .removeClass( options.icons.header )
1994
+ .addClass( options.icons.activeHeader );
1995
+ }
1996
+
1997
+ clicked
1998
+ .next()
1999
+ .addClass( "ui-accordion-content-active" );
2000
+ }
2001
+ },
2002
+
2003
+ _toggle: function( data ) {
2004
+ var toShow = data.newPanel,
2005
+ toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
2006
+
2007
+ // handle activating a panel during the animation for another activation
2008
+ this.prevShow.add( this.prevHide ).stop( true, true );
2009
+ this.prevShow = toShow;
2010
+ this.prevHide = toHide;
2011
+
2012
+ if ( this.options.animate ) {
2013
+ this._animate( toShow, toHide, data );
2014
+ } else {
2015
+ toHide.hide();
2016
+ toShow.show();
2017
+ this._toggleComplete( data );
2018
+ }
2019
+
2020
+ toHide.attr({
2021
+ "aria-hidden": "true"
2022
+ });
2023
+ toHide.prev().attr({
2024
+ "aria-selected": "false",
2025
+ "aria-expanded": "false"
2026
+ });
2027
+ // if we're switching panels, remove the old header from the tab order
2028
+ // if we're opening from collapsed state, remove the previous header from the tab order
2029
+ // if we're collapsing, then keep the collapsing header in the tab order
2030
+ if ( toShow.length && toHide.length ) {
2031
+ toHide.prev().attr({
2032
+ "tabIndex": -1,
2033
+ "aria-expanded": "false"
2034
+ });
2035
+ } else if ( toShow.length ) {
2036
+ this.headers.filter(function() {
2037
+ return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
2038
+ })
2039
+ .attr( "tabIndex", -1 );
2040
+ }
2041
+
2042
+ toShow
2043
+ .attr( "aria-hidden", "false" )
2044
+ .prev()
2045
+ .attr({
2046
+ "aria-selected": "true",
2047
+ "aria-expanded": "true",
2048
+ tabIndex: 0
2049
+ });
2050
+ },
2051
+
2052
+ _animate: function( toShow, toHide, data ) {
2053
+ var total, easing, duration,
2054
+ that = this,
2055
+ adjust = 0,
2056
+ boxSizing = toShow.css( "box-sizing" ),
2057
+ down = toShow.length &&
2058
+ ( !toHide.length || ( toShow.index() < toHide.index() ) ),
2059
+ animate = this.options.animate || {},
2060
+ options = down && animate.down || animate,
2061
+ complete = function() {
2062
+ that._toggleComplete( data );
2063
+ };
2064
+
2065
+ if ( typeof options === "number" ) {
2066
+ duration = options;
2067
+ }
2068
+ if ( typeof options === "string" ) {
2069
+ easing = options;
2070
+ }
2071
+ // fall back from options to animation in case of partial down settings
2072
+ easing = easing || options.easing || animate.easing;
2073
+ duration = duration || options.duration || animate.duration;
2074
+
2075
+ if ( !toHide.length ) {
2076
+ return toShow.animate( this.showProps, duration, easing, complete );
2077
+ }
2078
+ if ( !toShow.length ) {
2079
+ return toHide.animate( this.hideProps, duration, easing, complete );
2080
+ }
2081
+
2082
+ total = toShow.show().outerHeight();
2083
+ toHide.animate( this.hideProps, {
2084
+ duration: duration,
2085
+ easing: easing,
2086
+ step: function( now, fx ) {
2087
+ fx.now = Math.round( now );
2088
+ }
2089
+ });
2090
+ toShow
2091
+ .hide()
2092
+ .animate( this.showProps, {
2093
+ duration: duration,
2094
+ easing: easing,
2095
+ complete: complete,
2096
+ step: function( now, fx ) {
2097
+ fx.now = Math.round( now );
2098
+ if ( fx.prop !== "height" ) {
2099
+ if ( boxSizing === "content-box" ) {
2100
+ adjust += fx.now;
2101
+ }
2102
+ } else if ( that.options.heightStyle !== "content" ) {
2103
+ fx.now = Math.round( total - toHide.outerHeight() - adjust );
2104
+ adjust = 0;
2105
+ }
2106
+ }
2107
+ });
2108
+ },
2109
+
2110
+ _toggleComplete: function( data ) {
2111
+ var toHide = data.oldPanel;
2112
+
2113
+ toHide
2114
+ .removeClass( "ui-accordion-content-active" )
2115
+ .prev()
2116
+ .removeClass( "ui-corner-top" )
2117
+ .addClass( "ui-corner-all" );
2118
+
2119
+ // Work around for rendering bug in IE (#5421)
2120
+ if ( toHide.length ) {
2121
+ toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
2122
+ }
2123
+ this._trigger( "activate", null, data );
2124
+ }
2125
+ });
2126
+
2127
+
2128
+ /*!
2129
+ * jQuery UI Menu 1.11.4
2130
+ * http://jqueryui.com
2131
+ *
2132
+ * Copyright jQuery Foundation and other contributors
2133
+ * Released under the MIT license.
2134
+ * http://jquery.org/license
2135
+ *
2136
+ * http://api.jqueryui.com/menu/
2137
+ */
2138
+
2139
+
2140
+ var menu = $.widget( "ui.menu", {
2141
+ version: "1.11.4",
2142
+ defaultElement: "<ul>",
2143
+ delay: 300,
2144
+ options: {
2145
+ icons: {
2146
+ submenu: "ui-icon-carat-1-e"
2147
+ },
2148
+ items: "> *",
2149
+ menus: "ul",
2150
+ position: {
2151
+ my: "left-1 top",
2152
+ at: "right top"
2153
+ },
2154
+ role: "menu",
2155
+
2156
+ // callbacks
2157
+ blur: null,
2158
+ focus: null,
2159
+ select: null
2160
+ },
2161
+
2162
+ _create: function() {
2163
+ this.activeMenu = this.element;
2164
+
2165
+ // Flag used to prevent firing of the click handler
2166
+ // as the event bubbles up through nested menus
2167
+ this.mouseHandled = false;
2168
+ this.element
2169
+ .uniqueId()
2170
+ .addClass( "ui-menu ui-widget ui-widget-content" )
2171
+ .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
2172
+ .attr({
2173
+ role: this.options.role,
2174
+ tabIndex: 0
2175
+ });
2176
+
2177
+ if ( this.options.disabled ) {
2178
+ this.element
2179
+ .addClass( "ui-state-disabled" )
2180
+ .attr( "aria-disabled", "true" );
2181
+ }
2182
+
2183
+ this._on({
2184
+ // Prevent focus from sticking to links inside menu after clicking
2185
+ // them (focus should always stay on UL during navigation).
2186
+ "mousedown .ui-menu-item": function( event ) {
2187
+ event.preventDefault();
2188
+ },
2189
+ "click .ui-menu-item": function( event ) {
2190
+ var target = $( event.target );
2191
+ if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
2192
+ this.select( event );
2193
+
2194
+ // Only set the mouseHandled flag if the event will bubble, see #9469.
2195
+ if ( !event.isPropagationStopped() ) {
2196
+ this.mouseHandled = true;
2197
+ }
2198
+
2199
+ // Open submenu on click
2200
+ if ( target.has( ".ui-menu" ).length ) {
2201
+ this.expand( event );
2202
+ } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) {
2203
+
2204
+ // Redirect focus to the menu
2205
+ this.element.trigger( "focus", [ true ] );
2206
+
2207
+ // If the active item is on the top level, let it stay active.
2208
+ // Otherwise, blur the active item since it is no longer visible.
2209
+ if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
2210
+ clearTimeout( this.timer );
2211
+ }
2212
+ }
2213
+ }
2214
+ },
2215
+ "mouseenter .ui-menu-item": function( event ) {
2216
+ // Ignore mouse events while typeahead is active, see #10458.
2217
+ // Prevents focusing the wrong item when typeahead causes a scroll while the mouse
2218
+ // is over an item in the menu
2219
+ if ( this.previousFilter ) {
2220
+ return;
2221
+ }
2222
+ var target = $( event.currentTarget );
2223
+ // Remove ui-state-active class from siblings of the newly focused menu item
2224
+ // to avoid a jump caused by adjacent elements both having a class with a border
2225
+ target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" );
2226
+ this.focus( event, target );
2227
+ },
2228
+ mouseleave: "collapseAll",
2229
+ "mouseleave .ui-menu": "collapseAll",
2230
+ focus: function( event, keepActiveItem ) {
2231
+ // If there's already an active item, keep it active
2232
+ // If not, activate the first item
2233
+ var item = this.active || this.element.find( this.options.items ).eq( 0 );
2234
+
2235
+ if ( !keepActiveItem ) {
2236
+ this.focus( event, item );
2237
+ }
2238
+ },
2239
+ blur: function( event ) {
2240
+ this._delay(function() {
2241
+ if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
2242
+ this.collapseAll( event );
2243
+ }
2244
+ });
2245
+ },
2246
+ keydown: "_keydown"
2247
+ });
2248
+
2249
+ this.refresh();
2250
+
2251
+ // Clicks outside of a menu collapse any open menus
2252
+ this._on( this.document, {
2253
+ click: function( event ) {
2254
+ if ( this._closeOnDocumentClick( event ) ) {
2255
+ this.collapseAll( event );
2256
+ }
2257
+
2258
+ // Reset the mouseHandled flag
2259
+ this.mouseHandled = false;
2260
+ }
2261
+ });
2262
+ },
2263
+
2264
+ _destroy: function() {
2265
+ // Destroy (sub)menus
2266
+ this.element
2267
+ .removeAttr( "aria-activedescendant" )
2268
+ .find( ".ui-menu" ).addBack()
2269
+ .removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" )
2270
+ .removeAttr( "role" )
2271
+ .removeAttr( "tabIndex" )
2272
+ .removeAttr( "aria-labelledby" )
2273
+ .removeAttr( "aria-expanded" )
2274
+ .removeAttr( "aria-hidden" )
2275
+ .removeAttr( "aria-disabled" )
2276
+ .removeUniqueId()
2277
+ .show();
2278
+
2279
+ // Destroy menu items
2280
+ this.element.find( ".ui-menu-item" )
2281
+ .removeClass( "ui-menu-item" )
2282
+ .removeAttr( "role" )
2283
+ .removeAttr( "aria-disabled" )
2284
+ .removeUniqueId()
2285
+ .removeClass( "ui-state-hover" )
2286
+ .removeAttr( "tabIndex" )
2287
+ .removeAttr( "role" )
2288
+ .removeAttr( "aria-haspopup" )
2289
+ .children().each( function() {
2290
+ var elem = $( this );
2291
+ if ( elem.data( "ui-menu-submenu-carat" ) ) {
2292
+ elem.remove();
2293
+ }
2294
+ });
2295
+
2296
+ // Destroy menu dividers
2297
+ this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
2298
+ },
2299
+
2300
+ _keydown: function( event ) {
2301
+ var match, prev, character, skip,
2302
+ preventDefault = true;
2303
+
2304
+ switch ( event.keyCode ) {
2305
+ case $.ui.keyCode.PAGE_UP:
2306
+ this.previousPage( event );
2307
+ break;
2308
+ case $.ui.keyCode.PAGE_DOWN:
2309
+ this.nextPage( event );
2310
+ break;
2311
+ case $.ui.keyCode.HOME:
2312
+ this._move( "first", "first", event );
2313
+ break;
2314
+ case $.ui.keyCode.END:
2315
+ this._move( "last", "last", event );
2316
+ break;
2317
+ case $.ui.keyCode.UP:
2318
+ this.previous( event );
2319
+ break;
2320
+ case $.ui.keyCode.DOWN:
2321
+ this.next( event );
2322
+ break;
2323
+ case $.ui.keyCode.LEFT:
2324
+ this.collapse( event );
2325
+ break;
2326
+ case $.ui.keyCode.RIGHT:
2327
+ if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
2328
+ this.expand( event );
2329
+ }
2330
+ break;
2331
+ case $.ui.keyCode.ENTER:
2332
+ case $.ui.keyCode.SPACE:
2333
+ this._activate( event );
2334
+ break;
2335
+ case $.ui.keyCode.ESCAPE:
2336
+ this.collapse( event );
2337
+ break;
2338
+ default:
2339
+ preventDefault = false;
2340
+ prev = this.previousFilter || "";
2341
+ character = String.fromCharCode( event.keyCode );
2342
+ skip = false;
2343
+
2344
+ clearTimeout( this.filterTimer );
2345
+
2346
+ if ( character === prev ) {
2347
+ skip = true;
2348
+ } else {
2349
+ character = prev + character;
2350
+ }
2351
+
2352
+ match = this._filterMenuItems( character );
2353
+ match = skip && match.index( this.active.next() ) !== -1 ?
2354
+ this.active.nextAll( ".ui-menu-item" ) :
2355
+ match;
2356
+
2357
+ // If no matches on the current filter, reset to the last character pressed
2358
+ // to move down the menu to the first item that starts with that character
2359
+ if ( !match.length ) {
2360
+ character = String.fromCharCode( event.keyCode );
2361
+ match = this._filterMenuItems( character );
2362
+ }
2363
+
2364
+ if ( match.length ) {
2365
+ this.focus( event, match );
2366
+ this.previousFilter = character;
2367
+ this.filterTimer = this._delay(function() {
2368
+ delete this.previousFilter;
2369
+ }, 1000 );
2370
+ } else {
2371
+ delete this.previousFilter;
2372
+ }
2373
+ }
2374
+
2375
+ if ( preventDefault ) {
2376
+ event.preventDefault();
2377
+ }
2378
+ },
2379
+
2380
+ _activate: function( event ) {
2381
+ if ( !this.active.is( ".ui-state-disabled" ) ) {
2382
+ if ( this.active.is( "[aria-haspopup='true']" ) ) {
2383
+ this.expand( event );
2384
+ } else {
2385
+ this.select( event );
2386
+ }
2387
+ }
2388
+ },
2389
+
2390
+ refresh: function() {
2391
+ var menus, items,
2392
+ that = this,
2393
+ icon = this.options.icons.submenu,
2394
+ submenus = this.element.find( this.options.menus );
2395
+
2396
+ this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length );
2397
+
2398
+ // Initialize nested menus
2399
+ submenus.filter( ":not(.ui-menu)" )
2400
+ .addClass( "ui-menu ui-widget ui-widget-content ui-front" )
2401
+ .hide()
2402
+ .attr({
2403
+ role: this.options.role,
2404
+ "aria-hidden": "true",
2405
+ "aria-expanded": "false"
2406
+ })
2407
+ .each(function() {
2408
+ var menu = $( this ),
2409
+ item = menu.parent(),
2410
+ submenuCarat = $( "<span>" )
2411
+ .addClass( "ui-menu-icon ui-icon " + icon )
2412
+ .data( "ui-menu-submenu-carat", true );
2413
+
2414
+ item
2415
+ .attr( "aria-haspopup", "true" )
2416
+ .prepend( submenuCarat );
2417
+ menu.attr( "aria-labelledby", item.attr( "id" ) );
2418
+ });
2419
+
2420
+ menus = submenus.add( this.element );
2421
+ items = menus.find( this.options.items );
2422
+
2423
+ // Initialize menu-items containing spaces and/or dashes only as dividers
2424
+ items.not( ".ui-menu-item" ).each(function() {
2425
+ var item = $( this );
2426
+ if ( that._isDivider( item ) ) {
2427
+ item.addClass( "ui-widget-content ui-menu-divider" );
2428
+ }
2429
+ });
2430
+
2431
+ // Don't refresh list items that are already adapted
2432
+ items.not( ".ui-menu-item, .ui-menu-divider" )
2433
+ .addClass( "ui-menu-item" )
2434
+ .uniqueId()
2435
+ .attr({
2436
+ tabIndex: -1,
2437
+ role: this._itemRole()
2438
+ });
2439
+
2440
+ // Add aria-disabled attribute to any disabled menu item
2441
+ items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
2442
+
2443
+ // If the active item has been removed, blur the menu
2444
+ if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
2445
+ this.blur();
2446
+ }
2447
+ },
2448
+
2449
+ _itemRole: function() {
2450
+ return {
2451
+ menu: "menuitem",
2452
+ listbox: "option"
2453
+ }[ this.options.role ];
2454
+ },
2455
+
2456
+ _setOption: function( key, value ) {
2457
+ if ( key === "icons" ) {
2458
+ this.element.find( ".ui-menu-icon" )
2459
+ .removeClass( this.options.icons.submenu )
2460
+ .addClass( value.submenu );
2461
+ }
2462
+ if ( key === "disabled" ) {
2463
+ this.element
2464
+ .toggleClass( "ui-state-disabled", !!value )
2465
+ .attr( "aria-disabled", value );
2466
+ }
2467
+ this._super( key, value );
2468
+ },
2469
+
2470
+ focus: function( event, item ) {
2471
+ var nested, focused;
2472
+ this.blur( event, event && event.type === "focus" );
2473
+
2474
+ this._scrollIntoView( item );
2475
+
2476
+ this.active = item.first();
2477
+ focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" );
2478
+ // Only update aria-activedescendant if there's a role
2479
+ // otherwise we assume focus is managed elsewhere
2480
+ if ( this.options.role ) {
2481
+ this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
2482
+ }
2483
+
2484
+ // Highlight active parent menu item, if any
2485
+ this.active
2486
+ .parent()
2487
+ .closest( ".ui-menu-item" )
2488
+ .addClass( "ui-state-active" );
2489
+
2490
+ if ( event && event.type === "keydown" ) {
2491
+ this._close();
2492
+ } else {
2493
+ this.timer = this._delay(function() {
2494
+ this._close();
2495
+ }, this.delay );
2496
+ }
2497
+
2498
+ nested = item.children( ".ui-menu" );
2499
+ if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
2500
+ this._startOpening(nested);
2501
+ }
2502
+ this.activeMenu = item.parent();
2503
+
2504
+ this._trigger( "focus", event, { item: item } );
2505
+ },
2506
+
2507
+ _scrollIntoView: function( item ) {
2508
+ var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
2509
+ if ( this._hasScroll() ) {
2510
+ borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
2511
+ paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
2512
+ offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
2513
+ scroll = this.activeMenu.scrollTop();
2514
+ elementHeight = this.activeMenu.height();
2515
+ itemHeight = item.outerHeight();
2516
+
2517
+ if ( offset < 0 ) {
2518
+ this.activeMenu.scrollTop( scroll + offset );
2519
+ } else if ( offset + itemHeight > elementHeight ) {
2520
+ this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
2521
+ }
2522
+ }
2523
+ },
2524
+
2525
+ blur: function( event, fromFocus ) {
2526
+ if ( !fromFocus ) {
2527
+ clearTimeout( this.timer );
2528
+ }
2529
+
2530
+ if ( !this.active ) {
2531
+ return;
2532
+ }
2533
+
2534
+ this.active.removeClass( "ui-state-focus" );
2535
+ this.active = null;
2536
+
2537
+ this._trigger( "blur", event, { item: this.active } );
2538
+ },
2539
+
2540
+ _startOpening: function( submenu ) {
2541
+ clearTimeout( this.timer );
2542
+
2543
+ // Don't open if already open fixes a Firefox bug that caused a .5 pixel
2544
+ // shift in the submenu position when mousing over the carat icon
2545
+ if ( submenu.attr( "aria-hidden" ) !== "true" ) {
2546
+ return;
2547
+ }
2548
+
2549
+ this.timer = this._delay(function() {
2550
+ this._close();
2551
+ this._open( submenu );
2552
+ }, this.delay );
2553
+ },
2554
+
2555
+ _open: function( submenu ) {
2556
+ var position = $.extend({
2557
+ of: this.active
2558
+ }, this.options.position );
2559
+
2560
+ clearTimeout( this.timer );
2561
+ this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
2562
+ .hide()
2563
+ .attr( "aria-hidden", "true" );
2564
+
2565
+ submenu
2566
+ .show()
2567
+ .removeAttr( "aria-hidden" )
2568
+ .attr( "aria-expanded", "true" )
2569
+ .position( position );
2570
+ },
2571
+
2572
+ collapseAll: function( event, all ) {
2573
+ clearTimeout( this.timer );
2574
+ this.timer = this._delay(function() {
2575
+ // If we were passed an event, look for the submenu that contains the event
2576
+ var currentMenu = all ? this.element :
2577
+ $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
2578
+
2579
+ // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
2580
+ if ( !currentMenu.length ) {
2581
+ currentMenu = this.element;
2582
+ }
2583
+
2584
+ this._close( currentMenu );
2585
+
2586
+ this.blur( event );
2587
+ this.activeMenu = currentMenu;
2588
+ }, this.delay );
2589
+ },
2590
+
2591
+ // With no arguments, closes the currently active menu - if nothing is active
2592
+ // it closes all menus. If passed an argument, it will search for menus BELOW
2593
+ _close: function( startMenu ) {
2594
+ if ( !startMenu ) {
2595
+ startMenu = this.active ? this.active.parent() : this.element;
2596
+ }
2597
+
2598
+ startMenu
2599
+ .find( ".ui-menu" )
2600
+ .hide()
2601
+ .attr( "aria-hidden", "true" )
2602
+ .attr( "aria-expanded", "false" )
2603
+ .end()
2604
+ .find( ".ui-state-active" ).not( ".ui-state-focus" )
2605
+ .removeClass( "ui-state-active" );
2606
+ },
2607
+
2608
+ _closeOnDocumentClick: function( event ) {
2609
+ return !$( event.target ).closest( ".ui-menu" ).length;
2610
+ },
2611
+
2612
+ _isDivider: function( item ) {
2613
+
2614
+ // Match hyphen, em dash, en dash
2615
+ return !/[^\-\u2014\u2013\s]/.test( item.text() );
2616
+ },
2617
+
2618
+ collapse: function( event ) {
2619
+ var newItem = this.active &&
2620
+ this.active.parent().closest( ".ui-menu-item", this.element );
2621
+ if ( newItem && newItem.length ) {
2622
+ this._close();
2623
+ this.focus( event, newItem );
2624
+ }
2625
+ },
2626
+
2627
+ expand: function( event ) {
2628
+ var newItem = this.active &&
2629
+ this.active
2630
+ .children( ".ui-menu " )
2631
+ .find( this.options.items )
2632
+ .first();
2633
+
2634
+ if ( newItem && newItem.length ) {
2635
+ this._open( newItem.parent() );
2636
+
2637
+ // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
2638
+ this._delay(function() {
2639
+ this.focus( event, newItem );
2640
+ });
2641
+ }
2642
+ },
2643
+
2644
+ next: function( event ) {
2645
+ this._move( "next", "first", event );
2646
+ },
2647
+
2648
+ previous: function( event ) {
2649
+ this._move( "prev", "last", event );
2650
+ },
2651
+
2652
+ isFirstItem: function() {
2653
+ return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
2654
+ },
2655
+
2656
+ isLastItem: function() {
2657
+ return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
2658
+ },
2659
+
2660
+ _move: function( direction, filter, event ) {
2661
+ var next;
2662
+ if ( this.active ) {
2663
+ if ( direction === "first" || direction === "last" ) {
2664
+ next = this.active
2665
+ [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
2666
+ .eq( -1 );
2667
+ } else {
2668
+ next = this.active
2669
+ [ direction + "All" ]( ".ui-menu-item" )
2670
+ .eq( 0 );
2671
+ }
2672
+ }
2673
+ if ( !next || !next.length || !this.active ) {
2674
+ next = this.activeMenu.find( this.options.items )[ filter ]();
2675
+ }
2676
+
2677
+ this.focus( event, next );
2678
+ },
2679
+
2680
+ nextPage: function( event ) {
2681
+ var item, base, height;
2682
+
2683
+ if ( !this.active ) {
2684
+ this.next( event );
2685
+ return;
2686
+ }
2687
+ if ( this.isLastItem() ) {
2688
+ return;
2689
+ }
2690
+ if ( this._hasScroll() ) {
2691
+ base = this.active.offset().top;
2692
+ height = this.element.height();
2693
+ this.active.nextAll( ".ui-menu-item" ).each(function() {
2694
+ item = $( this );
2695
+ return item.offset().top - base - height < 0;
2696
+ });
2697
+
2698
+ this.focus( event, item );
2699
+ } else {
2700
+ this.focus( event, this.activeMenu.find( this.options.items )
2701
+ [ !this.active ? "first" : "last" ]() );
2702
+ }
2703
+ },
2704
+
2705
+ previousPage: function( event ) {
2706
+ var item, base, height;
2707
+ if ( !this.active ) {
2708
+ this.next( event );
2709
+ return;
2710
+ }
2711
+ if ( this.isFirstItem() ) {
2712
+ return;
2713
+ }
2714
+ if ( this._hasScroll() ) {
2715
+ base = this.active.offset().top;
2716
+ height = this.element.height();
2717
+ this.active.prevAll( ".ui-menu-item" ).each(function() {
2718
+ item = $( this );
2719
+ return item.offset().top - base + height > 0;
2720
+ });
2721
+
2722
+ this.focus( event, item );
2723
+ } else {
2724
+ this.focus( event, this.activeMenu.find( this.options.items ).first() );
2725
+ }
2726
+ },
2727
+
2728
+ _hasScroll: function() {
2729
+ return this.element.outerHeight() < this.element.prop( "scrollHeight" );
2730
+ },
2731
+
2732
+ select: function( event ) {
2733
+ // TODO: It should never be possible to not have an active item at this
2734
+ // point, but the tests don't trigger mouseenter before click.
2735
+ this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
2736
+ var ui = { item: this.active };
2737
+ if ( !this.active.has( ".ui-menu" ).length ) {
2738
+ this.collapseAll( event, true );
2739
+ }
2740
+ this._trigger( "select", event, ui );
2741
+ },
2742
+
2743
+ _filterMenuItems: function(character) {
2744
+ var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
2745
+ regex = new RegExp( "^" + escapedCharacter, "i" );
2746
+
2747
+ return this.activeMenu
2748
+ .find( this.options.items )
2749
+
2750
+ // Only match on items, not dividers or other content (#10571)
2751
+ .filter( ".ui-menu-item" )
2752
+ .filter(function() {
2753
+ return regex.test( $.trim( $( this ).text() ) );
2754
+ });
2755
+ }
2756
+ });
2757
+
2758
+
2759
+ /*!
2760
+ * jQuery UI Autocomplete 1.11.4
2761
+ * http://jqueryui.com
2762
+ *
2763
+ * Copyright jQuery Foundation and other contributors
2764
+ * Released under the MIT license.
2765
+ * http://jquery.org/license
2766
+ *
2767
+ * http://api.jqueryui.com/autocomplete/
2768
+ */
2769
+
2770
+
2771
+ $.widget( "ui.autocomplete", {
2772
+ version: "1.11.4",
2773
+ defaultElement: "<input>",
2774
+ options: {
2775
+ appendTo: null,
2776
+ autoFocus: false,
2777
+ delay: 300,
2778
+ minLength: 1,
2779
+ position: {
2780
+ my: "left top",
2781
+ at: "left bottom",
2782
+ collision: "none"
2783
+ },
2784
+ source: null,
2785
+
2786
+ // callbacks
2787
+ change: null,
2788
+ close: null,
2789
+ focus: null,
2790
+ open: null,
2791
+ response: null,
2792
+ search: null,
2793
+ select: null
2794
+ },
2795
+
2796
+ requestIndex: 0,
2797
+ pending: 0,
2798
+
2799
+ _create: function() {
2800
+ // Some browsers only repeat keydown events, not keypress events,
2801
+ // so we use the suppressKeyPress flag to determine if we've already
2802
+ // handled the keydown event. #7269
2803
+ // Unfortunately the code for & in keypress is the same as the up arrow,
2804
+ // so we use the suppressKeyPressRepeat flag to avoid handling keypress
2805
+ // events when we know the keydown event was used to modify the
2806
+ // search term. #7799
2807
+ var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
2808
+ nodeName = this.element[ 0 ].nodeName.toLowerCase(),
2809
+ isTextarea = nodeName === "textarea",
2810
+ isInput = nodeName === "input";
2811
+
2812
+ this.isMultiLine =
2813
+ // Textareas are always multi-line
2814
+ isTextarea ? true :
2815
+ // Inputs are always single-line, even if inside a contentEditable element
2816
+ // IE also treats inputs as contentEditable
2817
+ isInput ? false :
2818
+ // All other element types are determined by whether or not they're contentEditable
2819
+ this.element.prop( "isContentEditable" );
2820
+
2821
+ this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
2822
+ this.isNewMenu = true;
2823
+
2824
+ this.element
2825
+ .addClass( "ui-autocomplete-input" )
2826
+ .attr( "autocomplete", "off" );
2827
+
2828
+ this._on( this.element, {
2829
+ keydown: function( event ) {
2830
+ if ( this.element.prop( "readOnly" ) ) {
2831
+ suppressKeyPress = true;
2832
+ suppressInput = true;
2833
+ suppressKeyPressRepeat = true;
2834
+ return;
2835
+ }
2836
+
2837
+ suppressKeyPress = false;
2838
+ suppressInput = false;
2839
+ suppressKeyPressRepeat = false;
2840
+ var keyCode = $.ui.keyCode;
2841
+ switch ( event.keyCode ) {
2842
+ case keyCode.PAGE_UP:
2843
+ suppressKeyPress = true;
2844
+ this._move( "previousPage", event );
2845
+ break;
2846
+ case keyCode.PAGE_DOWN:
2847
+ suppressKeyPress = true;
2848
+ this._move( "nextPage", event );
2849
+ break;
2850
+ case keyCode.UP:
2851
+ suppressKeyPress = true;
2852
+ this._keyEvent( "previous", event );
2853
+ break;
2854
+ case keyCode.DOWN:
2855
+ suppressKeyPress = true;
2856
+ this._keyEvent( "next", event );
2857
+ break;
2858
+ case keyCode.ENTER:
2859
+ // when menu is open and has focus
2860
+ if ( this.menu.active ) {
2861
+ // #6055 - Opera still allows the keypress to occur
2862
+ // which causes forms to submit
2863
+ suppressKeyPress = true;
2864
+ event.preventDefault();
2865
+ this.menu.select( event );
2866
+ }
2867
+ break;
2868
+ case keyCode.TAB:
2869
+ if ( this.menu.active ) {
2870
+ this.menu.select( event );
2871
+ }
2872
+ break;
2873
+ case keyCode.ESCAPE:
2874
+ if ( this.menu.element.is( ":visible" ) ) {
2875
+ if ( !this.isMultiLine ) {
2876
+ this._value( this.term );
2877
+ }
2878
+ this.close( event );
2879
+ // Different browsers have different default behavior for escape
2880
+ // Single press can mean undo or clear
2881
+ // Double press in IE means clear the whole form
2882
+ event.preventDefault();
2883
+ }
2884
+ break;
2885
+ default:
2886
+ suppressKeyPressRepeat = true;
2887
+ // search timeout should be triggered before the input value is changed
2888
+ this._searchTimeout( event );
2889
+ break;
2890
+ }
2891
+ },
2892
+ keypress: function( event ) {
2893
+ if ( suppressKeyPress ) {
2894
+ suppressKeyPress = false;
2895
+ if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
2896
+ event.preventDefault();
2897
+ }
2898
+ return;
2899
+ }
2900
+ if ( suppressKeyPressRepeat ) {
2901
+ return;
2902
+ }
2903
+
2904
+ // replicate some key handlers to allow them to repeat in Firefox and Opera
2905
+ var keyCode = $.ui.keyCode;
2906
+ switch ( event.keyCode ) {
2907
+ case keyCode.PAGE_UP:
2908
+ this._move( "previousPage", event );
2909
+ break;
2910
+ case keyCode.PAGE_DOWN:
2911
+ this._move( "nextPage", event );
2912
+ break;
2913
+ case keyCode.UP:
2914
+ this._keyEvent( "previous", event );
2915
+ break;
2916
+ case keyCode.DOWN:
2917
+ this._keyEvent( "next", event );
2918
+ break;
2919
+ }
2920
+ },
2921
+ input: function( event ) {
2922
+ if ( suppressInput ) {
2923
+ suppressInput = false;
2924
+ event.preventDefault();
2925
+ return;
2926
+ }
2927
+ this._searchTimeout( event );
2928
+ },
2929
+ focus: function() {
2930
+ this.selectedItem = null;
2931
+ this.previous = this._value();
2932
+ },
2933
+ blur: function( event ) {
2934
+ if ( this.cancelBlur ) {
2935
+ delete this.cancelBlur;
2936
+ return;
2937
+ }
2938
+
2939
+ clearTimeout( this.searching );
2940
+ this.close( event );
2941
+ this._change( event );
2942
+ }
2943
+ });
2944
+
2945
+ this._initSource();
2946
+ this.menu = $( "<ul>" )
2947
+ .addClass( "ui-autocomplete ui-front" )
2948
+ .appendTo( this._appendTo() )
2949
+ .menu({
2950
+ // disable ARIA support, the live region takes care of that
2951
+ role: null
2952
+ })
2953
+ .hide()
2954
+ .menu( "instance" );
2955
+
2956
+ this._on( this.menu.element, {
2957
+ mousedown: function( event ) {
2958
+ // prevent moving focus out of the text field
2959
+ event.preventDefault();
2960
+
2961
+ // IE doesn't prevent moving focus even with event.preventDefault()
2962
+ // so we set a flag to know when we should ignore the blur event
2963
+ this.cancelBlur = true;
2964
+ this._delay(function() {
2965
+ delete this.cancelBlur;
2966
+ });
2967
+
2968
+ // clicking on the scrollbar causes focus to shift to the body
2969
+ // but we can't detect a mouseup or a click immediately afterward
2970
+ // so we have to track the next mousedown and close the menu if
2971
+ // the user clicks somewhere outside of the autocomplete
2972
+ var menuElement = this.menu.element[ 0 ];
2973
+ if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
2974
+ this._delay(function() {
2975
+ var that = this;
2976
+ this.document.one( "mousedown", function( event ) {
2977
+ if ( event.target !== that.element[ 0 ] &&
2978
+ event.target !== menuElement &&
2979
+ !$.contains( menuElement, event.target ) ) {
2980
+ that.close();
2981
+ }
2982
+ });
2983
+ });
2984
+ }
2985
+ },
2986
+ menufocus: function( event, ui ) {
2987
+ var label, item;
2988
+ // support: Firefox
2989
+ // Prevent accidental activation of menu items in Firefox (#7024 #9118)
2990
+ if ( this.isNewMenu ) {
2991
+ this.isNewMenu = false;
2992
+ if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
2993
+ this.menu.blur();
2994
+
2995
+ this.document.one( "mousemove", function() {
2996
+ $( event.target ).trigger( event.originalEvent );
2997
+ });
2998
+
2999
+ return;
3000
+ }
3001
+ }
3002
+
3003
+ item = ui.item.data( "ui-autocomplete-item" );
3004
+ if ( false !== this._trigger( "focus", event, { item: item } ) ) {
3005
+ // use value to match what will end up in the input, if it was a key event
3006
+ if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
3007
+ this._value( item.value );
3008
+ }
3009
+ }
3010
+
3011
+ // Announce the value in the liveRegion
3012
+ label = ui.item.attr( "aria-label" ) || item.value;
3013
+ if ( label && $.trim( label ).length ) {
3014
+ this.liveRegion.children().hide();
3015
+ $( "<div>" ).text( label ).appendTo( this.liveRegion );
3016
+ }
3017
+ },
3018
+ menuselect: function( event, ui ) {
3019
+ var item = ui.item.data( "ui-autocomplete-item" ),
3020
+ previous = this.previous;
3021
+
3022
+ // only trigger when focus was lost (click on menu)
3023
+ if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
3024
+ this.element.focus();
3025
+ this.previous = previous;
3026
+ // #6109 - IE triggers two focus events and the second
3027
+ // is asynchronous, so we need to reset the previous
3028
+ // term synchronously and asynchronously :-(
3029
+ this._delay(function() {
3030
+ this.previous = previous;
3031
+ this.selectedItem = item;
3032
+ });
3033
+ }
3034
+
3035
+ if ( false !== this._trigger( "select", event, { item: item } ) ) {
3036
+ this._value( item.value );
3037
+ }
3038
+ // reset the term after the select event
3039
+ // this allows custom select handling to work properly
3040
+ this.term = this._value();
3041
+
3042
+ this.close( event );
3043
+ this.selectedItem = item;
3044
+ }
3045
+ });
3046
+
3047
+ this.liveRegion = $( "<span>", {
3048
+ role: "status",
3049
+ "aria-live": "assertive",
3050
+ "aria-relevant": "additions"
3051
+ })
3052
+ .addClass( "ui-helper-hidden-accessible" )
3053
+ .appendTo( this.document[ 0 ].body );
3054
+
3055
+ // turning off autocomplete prevents the browser from remembering the
3056
+ // value when navigating through history, so we re-enable autocomplete
3057
+ // if the page is unloaded before the widget is destroyed. #7790
3058
+ this._on( this.window, {
3059
+ beforeunload: function() {
3060
+ this.element.removeAttr( "autocomplete" );
3061
+ }
3062
+ });
3063
+ },
3064
+
3065
+ _destroy: function() {
3066
+ clearTimeout( this.searching );
3067
+ this.element
3068
+ .removeClass( "ui-autocomplete-input" )
3069
+ .removeAttr( "autocomplete" );
3070
+ this.menu.element.remove();
3071
+ this.liveRegion.remove();
3072
+ },
3073
+
3074
+ _setOption: function( key, value ) {
3075
+ this._super( key, value );
3076
+ if ( key === "source" ) {
3077
+ this._initSource();
3078
+ }
3079
+ if ( key === "appendTo" ) {
3080
+ this.menu.element.appendTo( this._appendTo() );
3081
+ }
3082
+ if ( key === "disabled" && value && this.xhr ) {
3083
+ this.xhr.abort();
3084
+ }
3085
+ },
3086
+
3087
+ _appendTo: function() {
3088
+ var element = this.options.appendTo;
3089
+
3090
+ if ( element ) {
3091
+ element = element.jquery || element.nodeType ?
3092
+ $( element ) :
3093
+ this.document.find( element ).eq( 0 );
3094
+ }
3095
+
3096
+ if ( !element || !element[ 0 ] ) {
3097
+ element = this.element.closest( ".ui-front" );
3098
+ }
3099
+
3100
+ if ( !element.length ) {
3101
+ element = this.document[ 0 ].body;
3102
+ }
3103
+
3104
+ return element;
3105
+ },
3106
+
3107
+ _initSource: function() {
3108
+ var array, url,
3109
+ that = this;
3110
+ if ( $.isArray( this.options.source ) ) {
3111
+ array = this.options.source;
3112
+ this.source = function( request, response ) {
3113
+ response( $.ui.autocomplete.filter( array, request.term ) );
3114
+ };
3115
+ } else if ( typeof this.options.source === "string" ) {
3116
+ url = this.options.source;
3117
+ this.source = function( request, response ) {
3118
+ if ( that.xhr ) {
3119
+ that.xhr.abort();
3120
+ }
3121
+ that.xhr = $.ajax({
3122
+ url: url,
3123
+ data: request,
3124
+ dataType: "json",
3125
+ success: function( data ) {
3126
+ response( data );
3127
+ },
3128
+ error: function() {
3129
+ response([]);
3130
+ }
3131
+ });
3132
+ };
3133
+ } else {
3134
+ this.source = this.options.source;
3135
+ }
3136
+ },
3137
+
3138
+ _searchTimeout: function( event ) {
3139
+ clearTimeout( this.searching );
3140
+ this.searching = this._delay(function() {
3141
+
3142
+ // Search if the value has changed, or if the user retypes the same value (see #7434)
3143
+ var equalValues = this.term === this._value(),
3144
+ menuVisible = this.menu.element.is( ":visible" ),
3145
+ modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
3146
+
3147
+ if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
3148
+ this.selectedItem = null;
3149
+ this.search( null, event );
3150
+ }
3151
+ }, this.options.delay );
3152
+ },
3153
+
3154
+ search: function( value, event ) {
3155
+ value = value != null ? value : this._value();
3156
+
3157
+ // always save the actual value, not the one passed as an argument
3158
+ this.term = this._value();
3159
+
3160
+ if ( value.length < this.options.minLength ) {
3161
+ return this.close( event );
3162
+ }
3163
+
3164
+ if ( this._trigger( "search", event ) === false ) {
3165
+ return;
3166
+ }
3167
+
3168
+ return this._search( value );
3169
+ },
3170
+
3171
+ _search: function( value ) {
3172
+ this.pending++;
3173
+ this.element.addClass( "ui-autocomplete-loading" );
3174
+ this.cancelSearch = false;
3175
+
3176
+ this.source( { term: value }, this._response() );
3177
+ },
3178
+
3179
+ _response: function() {
3180
+ var index = ++this.requestIndex;
3181
+
3182
+ return $.proxy(function( content ) {
3183
+ if ( index === this.requestIndex ) {
3184
+ this.__response( content );
3185
+ }
3186
+
3187
+ this.pending--;
3188
+ if ( !this.pending ) {
3189
+ this.element.removeClass( "ui-autocomplete-loading" );
3190
+ }
3191
+ }, this );
3192
+ },
3193
+
3194
+ __response: function( content ) {
3195
+ if ( content ) {
3196
+ content = this._normalize( content );
3197
+ }
3198
+ this._trigger( "response", null, { content: content } );
3199
+ if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
3200
+ this._suggest( content );
3201
+ this._trigger( "open" );
3202
+ } else {
3203
+ // use ._close() instead of .close() so we don't cancel future searches
3204
+ this._close();
3205
+ }
3206
+ },
3207
+
3208
+ close: function( event ) {
3209
+ this.cancelSearch = true;
3210
+ this._close( event );
3211
+ },
3212
+
3213
+ _close: function( event ) {
3214
+ if ( this.menu.element.is( ":visible" ) ) {
3215
+ this.menu.element.hide();
3216
+ this.menu.blur();
3217
+ this.isNewMenu = true;
3218
+ this._trigger( "close", event );
3219
+ }
3220
+ },
3221
+
3222
+ _change: function( event ) {
3223
+ if ( this.previous !== this._value() ) {
3224
+ this._trigger( "change", event, { item: this.selectedItem } );
3225
+ }
3226
+ },
3227
+
3228
+ _normalize: function( items ) {
3229
+ // assume all items have the right format when the first item is complete
3230
+ if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
3231
+ return items;
3232
+ }
3233
+ return $.map( items, function( item ) {
3234
+ if ( typeof item === "string" ) {
3235
+ return {
3236
+ label: item,
3237
+ value: item
3238
+ };
3239
+ }
3240
+ return $.extend( {}, item, {
3241
+ label: item.label || item.value,
3242
+ value: item.value || item.label
3243
+ });
3244
+ });
3245
+ },
3246
+
3247
+ _suggest: function( items ) {
3248
+ var ul = this.menu.element.empty();
3249
+ this._renderMenu( ul, items );
3250
+ this.isNewMenu = true;
3251
+ this.menu.refresh();
3252
+
3253
+ // size and position menu
3254
+ ul.show();
3255
+ this._resizeMenu();
3256
+ ul.position( $.extend({
3257
+ of: this.element
3258
+ }, this.options.position ) );
3259
+
3260
+ if ( this.options.autoFocus ) {
3261
+ this.menu.next();
3262
+ }
3263
+ },
3264
+
3265
+ _resizeMenu: function() {
3266
+ var ul = this.menu.element;
3267
+ ul.outerWidth( Math.max(
3268
+ // Firefox wraps long text (possibly a rounding bug)
3269
+ // so we add 1px to avoid the wrapping (#7513)
3270
+ ul.width( "" ).outerWidth() + 1,
3271
+ this.element.outerWidth()
3272
+ ) );
3273
+ },
3274
+
3275
+ _renderMenu: function( ul, items ) {
3276
+ var that = this;
3277
+ $.each( items, function( index, item ) {
3278
+ that._renderItemData( ul, item );
3279
+ });
3280
+ },
3281
+
3282
+ _renderItemData: function( ul, item ) {
3283
+ return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
3284
+ },
3285
+
3286
+ _renderItem: function( ul, item ) {
3287
+ return $( "<li>" ).text( item.label ).appendTo( ul );
3288
+ },
3289
+
3290
+ _move: function( direction, event ) {
3291
+ if ( !this.menu.element.is( ":visible" ) ) {
3292
+ this.search( null, event );
3293
+ return;
3294
+ }
3295
+ if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
3296
+ this.menu.isLastItem() && /^next/.test( direction ) ) {
3297
+
3298
+ if ( !this.isMultiLine ) {
3299
+ this._value( this.term );
3300
+ }
3301
+
3302
+ this.menu.blur();
3303
+ return;
3304
+ }
3305
+ this.menu[ direction ]( event );
3306
+ },
3307
+
3308
+ widget: function() {
3309
+ return this.menu.element;
3310
+ },
3311
+
3312
+ _value: function() {
3313
+ return this.valueMethod.apply( this.element, arguments );
3314
+ },
3315
+
3316
+ _keyEvent: function( keyEvent, event ) {
3317
+ if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
3318
+ this._move( keyEvent, event );
3319
+
3320
+ // prevents moving cursor to beginning/end of the text field in some browsers
3321
+ event.preventDefault();
3322
+ }
3323
+ }
3324
+ });
3325
+
3326
+ $.extend( $.ui.autocomplete, {
3327
+ escapeRegex: function( value ) {
3328
+ return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
3329
+ },
3330
+ filter: function( array, term ) {
3331
+ var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
3332
+ return $.grep( array, function( value ) {
3333
+ return matcher.test( value.label || value.value || value );
3334
+ });
3335
+ }
3336
+ });
3337
+
3338
+ // live region extension, adding a `messages` option
3339
+ // NOTE: This is an experimental API. We are still investigating
3340
+ // a full solution for string manipulation and internationalization.
3341
+ $.widget( "ui.autocomplete", $.ui.autocomplete, {
3342
+ options: {
3343
+ messages: {
3344
+ noResults: "No search results.",
3345
+ results: function( amount ) {
3346
+ return amount + ( amount > 1 ? " results are" : " result is" ) +
3347
+ " available, use up and down arrow keys to navigate.";
3348
+ }
3349
+ }
3350
+ },
3351
+
3352
+ __response: function( content ) {
3353
+ var message;
3354
+ this._superApply( arguments );
3355
+ if ( this.options.disabled || this.cancelSearch ) {
3356
+ return;
3357
+ }
3358
+ if ( content && content.length ) {
3359
+ message = this.options.messages.results( content.length );
3360
+ } else {
3361
+ message = this.options.messages.noResults;
3362
+ }
3363
+ this.liveRegion.children().hide();
3364
+ $( "<div>" ).text( message ).appendTo( this.liveRegion );
3365
+ }
3366
+ });
3367
+
3368
+ var autocomplete = $.ui.autocomplete;
3369
+
3370
+
3371
+ /*!
3372
+ * jQuery UI Button 1.11.4
3373
+ * http://jqueryui.com
3374
+ *
3375
+ * Copyright jQuery Foundation and other contributors
3376
+ * Released under the MIT license.
3377
+ * http://jquery.org/license
3378
+ *
3379
+ * http://api.jqueryui.com/button/
3380
+ */
3381
+
3382
+
3383
+ var lastActive,
3384
+ baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
3385
+ typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
3386
+ formResetHandler = function() {
3387
+ var form = $( this );
3388
+ setTimeout(function() {
3389
+ form.find( ":ui-button" ).button( "refresh" );
3390
+ }, 1 );
3391
+ },
3392
+ radioGroup = function( radio ) {
3393
+ var name = radio.name,
3394
+ form = radio.form,
3395
+ radios = $( [] );
3396
+ if ( name ) {
3397
+ name = name.replace( /'/g, "\\'" );
3398
+ if ( form ) {
3399
+ radios = $( form ).find( "[name='" + name + "'][type=radio]" );
3400
+ } else {
3401
+ radios = $( "[name='" + name + "'][type=radio]", radio.ownerDocument )
3402
+ .filter(function() {
3403
+ return !this.form;
3404
+ });
3405
+ }
3406
+ }
3407
+ return radios;
3408
+ };
3409
+
3410
+ $.widget( "ui.button", {
3411
+ version: "1.11.4",
3412
+ defaultElement: "<button>",
3413
+ options: {
3414
+ disabled: null,
3415
+ text: true,
3416
+ label: null,
3417
+ icons: {
3418
+ primary: null,
3419
+ secondary: null
3420
+ }
3421
+ },
3422
+ _create: function() {
3423
+ this.element.closest( "form" )
3424
+ .unbind( "reset" + this.eventNamespace )
3425
+ .bind( "reset" + this.eventNamespace, formResetHandler );
3426
+
3427
+ if ( typeof this.options.disabled !== "boolean" ) {
3428
+ this.options.disabled = !!this.element.prop( "disabled" );
3429
+ } else {
3430
+ this.element.prop( "disabled", this.options.disabled );
3431
+ }
3432
+
3433
+ this._determineButtonType();
3434
+ this.hasTitle = !!this.buttonElement.attr( "title" );
3435
+
3436
+ var that = this,
3437
+ options = this.options,
3438
+ toggleButton = this.type === "checkbox" || this.type === "radio",
3439
+ activeClass = !toggleButton ? "ui-state-active" : "";
3440
+
3441
+ if ( options.label === null ) {
3442
+ options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
3443
+ }
3444
+
3445
+ this._hoverable( this.buttonElement );
3446
+
3447
+ this.buttonElement
3448
+ .addClass( baseClasses )
3449
+ .attr( "role", "button" )
3450
+ .bind( "mouseenter" + this.eventNamespace, function() {
3451
+ if ( options.disabled ) {
3452
+ return;
3453
+ }
3454
+ if ( this === lastActive ) {
3455
+ $( this ).addClass( "ui-state-active" );
3456
+ }
3457
+ })
3458
+ .bind( "mouseleave" + this.eventNamespace, function() {
3459
+ if ( options.disabled ) {
3460
+ return;
3461
+ }
3462
+ $( this ).removeClass( activeClass );
3463
+ })
3464
+ .bind( "click" + this.eventNamespace, function( event ) {
3465
+ if ( options.disabled ) {
3466
+ event.preventDefault();
3467
+ event.stopImmediatePropagation();
3468
+ }
3469
+ });
3470
+
3471
+ // Can't use _focusable() because the element that receives focus
3472
+ // and the element that gets the ui-state-focus class are different
3473
+ this._on({
3474
+ focus: function() {
3475
+ this.buttonElement.addClass( "ui-state-focus" );
3476
+ },
3477
+ blur: function() {
3478
+ this.buttonElement.removeClass( "ui-state-focus" );
3479
+ }
3480
+ });
3481
+
3482
+ if ( toggleButton ) {
3483
+ this.element.bind( "change" + this.eventNamespace, function() {
3484
+ that.refresh();
3485
+ });
3486
+ }
3487
+
3488
+ if ( this.type === "checkbox" ) {
3489
+ this.buttonElement.bind( "click" + this.eventNamespace, function() {
3490
+ if ( options.disabled ) {
3491
+ return false;
3492
+ }
3493
+ });
3494
+ } else if ( this.type === "radio" ) {
3495
+ this.buttonElement.bind( "click" + this.eventNamespace, function() {
3496
+ if ( options.disabled ) {
3497
+ return false;
3498
+ }
3499
+ $( this ).addClass( "ui-state-active" );
3500
+ that.buttonElement.attr( "aria-pressed", "true" );
3501
+
3502
+ var radio = that.element[ 0 ];
3503
+ radioGroup( radio )
3504
+ .not( radio )
3505
+ .map(function() {
3506
+ return $( this ).button( "widget" )[ 0 ];
3507
+ })
3508
+ .removeClass( "ui-state-active" )
3509
+ .attr( "aria-pressed", "false" );
3510
+ });
3511
+ } else {
3512
+ this.buttonElement
3513
+ .bind( "mousedown" + this.eventNamespace, function() {
3514
+ if ( options.disabled ) {
3515
+ return false;
3516
+ }
3517
+ $( this ).addClass( "ui-state-active" );
3518
+ lastActive = this;
3519
+ that.document.one( "mouseup", function() {
3520
+ lastActive = null;
3521
+ });
3522
+ })
3523
+ .bind( "mouseup" + this.eventNamespace, function() {
3524
+ if ( options.disabled ) {
3525
+ return false;
3526
+ }
3527
+ $( this ).removeClass( "ui-state-active" );
3528
+ })
3529
+ .bind( "keydown" + this.eventNamespace, function(event) {
3530
+ if ( options.disabled ) {
3531
+ return false;
3532
+ }
3533
+ if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
3534
+ $( this ).addClass( "ui-state-active" );
3535
+ }
3536
+ })
3537
+ // see #8559, we bind to blur here in case the button element loses
3538
+ // focus between keydown and keyup, it would be left in an "active" state
3539
+ .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
3540
+ $( this ).removeClass( "ui-state-active" );
3541
+ });
3542
+
3543
+ if ( this.buttonElement.is("a") ) {
3544
+ this.buttonElement.keyup(function(event) {
3545
+ if ( event.keyCode === $.ui.keyCode.SPACE ) {
3546
+ // TODO pass through original event correctly (just as 2nd argument doesn't work)
3547
+ $( this ).click();
3548
+ }
3549
+ });
3550
+ }
3551
+ }
3552
+
3553
+ this._setOption( "disabled", options.disabled );
3554
+ this._resetButton();
3555
+ },
3556
+
3557
+ _determineButtonType: function() {
3558
+ var ancestor, labelSelector, checked;
3559
+
3560
+ if ( this.element.is("[type=checkbox]") ) {
3561
+ this.type = "checkbox";
3562
+ } else if ( this.element.is("[type=radio]") ) {
3563
+ this.type = "radio";
3564
+ } else if ( this.element.is("input") ) {
3565
+ this.type = "input";
3566
+ } else {
3567
+ this.type = "button";
3568
+ }
3569
+
3570
+ if ( this.type === "checkbox" || this.type === "radio" ) {
3571
+ // we don't search against the document in case the element
3572
+ // is disconnected from the DOM
3573
+ ancestor = this.element.parents().last();
3574
+ labelSelector = "label[for='" + this.element.attr("id") + "']";
3575
+ this.buttonElement = ancestor.find( labelSelector );
3576
+ if ( !this.buttonElement.length ) {
3577
+ ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
3578
+ this.buttonElement = ancestor.filter( labelSelector );
3579
+ if ( !this.buttonElement.length ) {
3580
+ this.buttonElement = ancestor.find( labelSelector );
3581
+ }
3582
+ }
3583
+ this.element.addClass( "ui-helper-hidden-accessible" );
3584
+
3585
+ checked = this.element.is( ":checked" );
3586
+ if ( checked ) {
3587
+ this.buttonElement.addClass( "ui-state-active" );
3588
+ }
3589
+ this.buttonElement.prop( "aria-pressed", checked );
3590
+ } else {
3591
+ this.buttonElement = this.element;
3592
+ }
3593
+ },
3594
+
3595
+ widget: function() {
3596
+ return this.buttonElement;
3597
+ },
3598
+
3599
+ _destroy: function() {
3600
+ this.element
3601
+ .removeClass( "ui-helper-hidden-accessible" );
3602
+ this.buttonElement
3603
+ .removeClass( baseClasses + " ui-state-active " + typeClasses )
3604
+ .removeAttr( "role" )
3605
+ .removeAttr( "aria-pressed" )
3606
+ .html( this.buttonElement.find(".ui-button-text").html() );
3607
+
3608
+ if ( !this.hasTitle ) {
3609
+ this.buttonElement.removeAttr( "title" );
3610
+ }
3611
+ },
3612
+
3613
+ _setOption: function( key, value ) {
3614
+ this._super( key, value );
3615
+ if ( key === "disabled" ) {
3616
+ this.widget().toggleClass( "ui-state-disabled", !!value );
3617
+ this.element.prop( "disabled", !!value );
3618
+ if ( value ) {
3619
+ if ( this.type === "checkbox" || this.type === "radio" ) {
3620
+ this.buttonElement.removeClass( "ui-state-focus" );
3621
+ } else {
3622
+ this.buttonElement.removeClass( "ui-state-focus ui-state-active" );
3623
+ }
3624
+ }
3625
+ return;
3626
+ }
3627
+ this._resetButton();
3628
+ },
3629
+
3630
+ refresh: function() {
3631
+ //See #8237 & #8828
3632
+ var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
3633
+
3634
+ if ( isDisabled !== this.options.disabled ) {
3635
+ this._setOption( "disabled", isDisabled );
3636
+ }
3637
+ if ( this.type === "radio" ) {
3638
+ radioGroup( this.element[0] ).each(function() {
3639
+ if ( $( this ).is( ":checked" ) ) {
3640
+ $( this ).button( "widget" )
3641
+ .addClass( "ui-state-active" )
3642
+ .attr( "aria-pressed", "true" );
3643
+ } else {
3644
+ $( this ).button( "widget" )
3645
+ .removeClass( "ui-state-active" )
3646
+ .attr( "aria-pressed", "false" );
3647
+ }
3648
+ });
3649
+ } else if ( this.type === "checkbox" ) {
3650
+ if ( this.element.is( ":checked" ) ) {
3651
+ this.buttonElement
3652
+ .addClass( "ui-state-active" )
3653
+ .attr( "aria-pressed", "true" );
3654
+ } else {
3655
+ this.buttonElement
3656
+ .removeClass( "ui-state-active" )
3657
+ .attr( "aria-pressed", "false" );
3658
+ }
3659
+ }
3660
+ },
3661
+
3662
+ _resetButton: function() {
3663
+ if ( this.type === "input" ) {
3664
+ if ( this.options.label ) {
3665
+ this.element.val( this.options.label );
3666
+ }
3667
+ return;
3668
+ }
3669
+ var buttonElement = this.buttonElement.removeClass( typeClasses ),
3670
+ buttonText = $( "<span></span>", this.document[0] )
3671
+ .addClass( "ui-button-text" )
3672
+ .html( this.options.label )
3673
+ .appendTo( buttonElement.empty() )
3674
+ .text(),
3675
+ icons = this.options.icons,
3676
+ multipleIcons = icons.primary && icons.secondary,
3677
+ buttonClasses = [];
3678
+
3679
+ if ( icons.primary || icons.secondary ) {
3680
+ if ( this.options.text ) {
3681
+ buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
3682
+ }
3683
+
3684
+ if ( icons.primary ) {
3685
+ buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
3686
+ }
3687
+
3688
+ if ( icons.secondary ) {
3689
+ buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
3690
+ }
3691
+
3692
+ if ( !this.options.text ) {
3693
+ buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
3694
+
3695
+ if ( !this.hasTitle ) {
3696
+ buttonElement.attr( "title", $.trim( buttonText ) );
3697
+ }
3698
+ }
3699
+ } else {
3700
+ buttonClasses.push( "ui-button-text-only" );
3701
+ }
3702
+ buttonElement.addClass( buttonClasses.join( " " ) );
3703
+ }
3704
+ });
3705
+
3706
+ $.widget( "ui.buttonset", {
3707
+ version: "1.11.4",
3708
+ options: {
3709
+ items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
3710
+ },
3711
+
3712
+ _create: function() {
3713
+ this.element.addClass( "ui-buttonset" );
3714
+ },
3715
+
3716
+ _init: function() {
3717
+ this.refresh();
3718
+ },
3719
+
3720
+ _setOption: function( key, value ) {
3721
+ if ( key === "disabled" ) {
3722
+ this.buttons.button( "option", key, value );
3723
+ }
3724
+
3725
+ this._super( key, value );
3726
+ },
3727
+
3728
+ refresh: function() {
3729
+ var rtl = this.element.css( "direction" ) === "rtl",
3730
+ allButtons = this.element.find( this.options.items ),
3731
+ existingButtons = allButtons.filter( ":ui-button" );
3732
+
3733
+ // Initialize new buttons
3734
+ allButtons.not( ":ui-button" ).button();
3735
+
3736
+ // Refresh existing buttons
3737
+ existingButtons.button( "refresh" );
3738
+
3739
+ this.buttons = allButtons
3740
+ .map(function() {
3741
+ return $( this ).button( "widget" )[ 0 ];
3742
+ })
3743
+ .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
3744
+ .filter( ":first" )
3745
+ .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
3746
+ .end()
3747
+ .filter( ":last" )
3748
+ .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
3749
+ .end()
3750
+ .end();
3751
+ },
3752
+
3753
+ _destroy: function() {
3754
+ this.element.removeClass( "ui-buttonset" );
3755
+ this.buttons
3756
+ .map(function() {
3757
+ return $( this ).button( "widget" )[ 0 ];
3758
+ })
3759
+ .removeClass( "ui-corner-left ui-corner-right" )
3760
+ .end()
3761
+ .button( "destroy" );
3762
+ }
3763
+ });
3764
+
3765
+ var button = $.ui.button;
3766
+
3767
+
3768
+ /*!
3769
+ * jQuery UI Datepicker 1.11.4
3770
+ * http://jqueryui.com
3771
+ *
3772
+ * Copyright jQuery Foundation and other contributors
3773
+ * Released under the MIT license.
3774
+ * http://jquery.org/license
3775
+ *
3776
+ * http://api.jqueryui.com/datepicker/
3777
+ */
3778
+
3779
+
3780
+ $.extend($.ui, { datepicker: { version: "1.11.4" } });
3781
+
3782
+ var datepicker_instActive;
3783
+
3784
+ function datepicker_getZindex( elem ) {
3785
+ var position, value;
3786
+ while ( elem.length && elem[ 0 ] !== document ) {
3787
+ // Ignore z-index if position is set to a value where z-index is ignored by the browser
3788
+ // This makes behavior of this function consistent across browsers
3789
+ // WebKit always returns auto if the element is positioned
3790
+ position = elem.css( "position" );
3791
+ if ( position === "absolute" || position === "relative" || position === "fixed" ) {
3792
+ // IE returns 0 when zIndex is not specified
3793
+ // other browsers return a string
3794
+ // we ignore the case of nested elements with an explicit value of 0
3795
+ // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
3796
+ value = parseInt( elem.css( "zIndex" ), 10 );
3797
+ if ( !isNaN( value ) && value !== 0 ) {
3798
+ return value;
3799
+ }
3800
+ }
3801
+ elem = elem.parent();
3802
+ }
3803
+
3804
+ return 0;
3805
+ }
3806
+ /* Date picker manager.
3807
+ Use the singleton instance of this class, $.datepicker, to interact with the date picker.
3808
+ Settings for (groups of) date pickers are maintained in an instance object,
3809
+ allowing multiple different settings on the same page. */
3810
+
3811
+ function Datepicker() {
3812
+ this._curInst = null; // The current instance in use
3813
+ this._keyEvent = false; // If the last event was a key event
3814
+ this._disabledInputs = []; // List of date picker inputs that have been disabled
3815
+ this._datepickerShowing = false; // True if the popup picker is showing , false if not
3816
+ this._inDialog = false; // True if showing within a "dialog", false if not
3817
+ this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
3818
+ this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
3819
+ this._appendClass = "ui-datepicker-append"; // The name of the append marker class
3820
+ this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
3821
+ this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
3822
+ this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
3823
+ this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
3824
+ this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
3825
+ this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
3826
+ this.regional = []; // Available regional settings, indexed by language code
3827
+ this.regional[""] = { // Default regional settings
3828
+ closeText: "Done", // Display text for close link
3829
+ prevText: "Prev", // Display text for previous month link
3830
+ nextText: "Next", // Display text for next month link
3831
+ currentText: "Today", // Display text for current month link
3832
+ monthNames: ["January","February","March","April","May","June",
3833
+ "July","August","September","October","November","December"], // Names of months for drop-down and formatting
3834
+ monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
3835
+ dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
3836
+ dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
3837
+ dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
3838
+ weekHeader: "Wk", // Column header for week of the year
3839
+ dateFormat: "mm/dd/yy", // See format options on parseDate
3840
+ firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
3841
+ isRTL: false, // True if right-to-left language, false if left-to-right
3842
+ showMonthAfterYear: false, // True if the year select precedes month, false for month then year
3843
+ yearSuffix: "" // Additional text to append to the year in the month headers
3844
+ };
3845
+ this._defaults = { // Global defaults for all the date picker instances
3846
+ showOn: "focus", // "focus" for popup on focus,
3847
+ // "button" for trigger button, or "both" for either
3848
+ showAnim: "fadeIn", // Name of jQuery animation for popup
3849
+ showOptions: {}, // Options for enhanced animations
3850
+ defaultDate: null, // Used when field is blank: actual date,
3851
+ // +/-number for offset from today, null for today
3852
+ appendText: "", // Display text following the input box, e.g. showing the format
3853
+ buttonText: "...", // Text for trigger button
3854
+ buttonImage: "", // URL for trigger button image
3855
+ buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
3856
+ hideIfNoPrevNext: false, // True to hide next/previous month links
3857
+ // if not applicable, false to just disable them
3858
+ navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
3859
+ gotoCurrent: false, // True if today link goes back to current selection instead
3860
+ changeMonth: false, // True if month can be selected directly, false if only prev/next
3861
+ changeYear: false, // True if year can be selected directly, false if only prev/next
3862
+ yearRange: "c-10:c+10", // Range of years to display in drop-down,
3863
+ // either relative to today's year (-nn:+nn), relative to currently displayed year
3864
+ // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
3865
+ showOtherMonths: false, // True to show dates in other months, false to leave blank
3866
+ selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
3867
+ showWeek: false, // True to show week of the year, false to not show it
3868
+ calculateWeek: this.iso8601Week, // How to calculate the week of the year,
3869
+ // takes a Date and returns the number of the week for it
3870
+ shortYearCutoff: "+10", // Short year values < this are in the current century,
3871
+ // > this are in the previous century,
3872
+ // string value starting with "+" for current year + value
3873
+ minDate: null, // The earliest selectable date, or null for no limit
3874
+ maxDate: null, // The latest selectable date, or null for no limit
3875
+ duration: "fast", // Duration of display/closure
3876
+ beforeShowDay: null, // Function that takes a date and returns an array with
3877
+ // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
3878
+ // [2] = cell title (optional), e.g. $.datepicker.noWeekends
3879
+ beforeShow: null, // Function that takes an input field and
3880
+ // returns a set of custom settings for the date picker
3881
+ onSelect: null, // Define a callback function when a date is selected
3882
+ onChangeMonthYear: null, // Define a callback function when the month or year is changed
3883
+ onClose: null, // Define a callback function when the datepicker is closed
3884
+ numberOfMonths: 1, // Number of months to show at a time
3885
+ showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
3886
+ stepMonths: 1, // Number of months to step back/forward
3887
+ stepBigMonths: 12, // Number of months to step back/forward for the big links
3888
+ altField: "", // Selector for an alternate field to store selected dates into
3889
+ altFormat: "", // The date format to use for the alternate field
3890
+ constrainInput: true, // The input is constrained by the current date format
3891
+ showButtonPanel: false, // True to show button panel, false to not show it
3892
+ autoSize: false, // True to size the input for the date format, false to leave as is
3893
+ disabled: false // The initial disabled state
3894
+ };
3895
+ $.extend(this._defaults, this.regional[""]);
3896
+ this.regional.en = $.extend( true, {}, this.regional[ "" ]);
3897
+ this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
3898
+ this.dpDiv = datepicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
3899
+ }
3900
+
3901
+ $.extend(Datepicker.prototype, {
3902
+ /* Class name added to elements to indicate already configured with a date picker. */
3903
+ markerClassName: "hasDatepicker",
3904
+
3905
+ //Keep track of the maximum number of rows displayed (see #7043)
3906
+ maxRows: 4,
3907
+
3908
+ // TODO rename to "widget" when switching to widget factory
3909
+ _widgetDatepicker: function() {
3910
+ return this.dpDiv;
3911
+ },
3912
+
3913
+ /* Override the default settings for all instances of the date picker.
3914
+ * @param settings object - the new settings to use as defaults (anonymous object)
3915
+ * @return the manager object
3916
+ */
3917
+ setDefaults: function(settings) {
3918
+ datepicker_extendRemove(this._defaults, settings || {});
3919
+ return this;
3920
+ },
3921
+
3922
+ /* Attach the date picker to a jQuery selection.
3923
+ * @param target element - the target input field or division or span
3924
+ * @param settings object - the new settings to use for this date picker instance (anonymous)
3925
+ */
3926
+ _attachDatepicker: function(target, settings) {
3927
+ var nodeName, inline, inst;
3928
+ nodeName = target.nodeName.toLowerCase();
3929
+ inline = (nodeName === "div" || nodeName === "span");
3930
+ if (!target.id) {
3931
+ this.uuid += 1;
3932
+ target.id = "dp" + this.uuid;
3933
+ }
3934
+ inst = this._newInst($(target), inline);
3935
+ inst.settings = $.extend({}, settings || {});
3936
+ if (nodeName === "input") {
3937
+ this._connectDatepicker(target, inst);
3938
+ } else if (inline) {
3939
+ this._inlineDatepicker(target, inst);
3940
+ }
3941
+ },
3942
+
3943
+ /* Create a new instance object. */
3944
+ _newInst: function(target, inline) {
3945
+ var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
3946
+ return {id: id, input: target, // associated target
3947
+ selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
3948
+ drawMonth: 0, drawYear: 0, // month being drawn
3949
+ inline: inline, // is datepicker inline or not
3950
+ dpDiv: (!inline ? this.dpDiv : // presentation div
3951
+ datepicker_bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
3952
+ },
3953
+
3954
+ /* Attach the date picker to an input field. */
3955
+ _connectDatepicker: function(target, inst) {
3956
+ var input = $(target);
3957
+ inst.append = $([]);
3958
+ inst.trigger = $([]);
3959
+ if (input.hasClass(this.markerClassName)) {
3960
+ return;
3961
+ }
3962
+ this._attachments(input, inst);
3963
+ input.addClass(this.markerClassName).keydown(this._doKeyDown).
3964
+ keypress(this._doKeyPress).keyup(this._doKeyUp);
3965
+ this._autoSize(inst);
3966
+ $.data(target, "datepicker", inst);
3967
+ //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
3968
+ if( inst.settings.disabled ) {
3969
+ this._disableDatepicker( target );
3970
+ }
3971
+ },
3972
+
3973
+ /* Make attachments based on settings. */
3974
+ _attachments: function(input, inst) {
3975
+ var showOn, buttonText, buttonImage,
3976
+ appendText = this._get(inst, "appendText"),
3977
+ isRTL = this._get(inst, "isRTL");
3978
+
3979
+ if (inst.append) {
3980
+ inst.append.remove();
3981
+ }
3982
+ if (appendText) {
3983
+ inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
3984
+ input[isRTL ? "before" : "after"](inst.append);
3985
+ }
3986
+
3987
+ input.unbind("focus", this._showDatepicker);
3988
+
3989
+ if (inst.trigger) {
3990
+ inst.trigger.remove();
3991
+ }
3992
+
3993
+ showOn = this._get(inst, "showOn");
3994
+ if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
3995
+ input.focus(this._showDatepicker);
3996
+ }
3997
+ if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
3998
+ buttonText = this._get(inst, "buttonText");
3999
+ buttonImage = this._get(inst, "buttonImage");
4000
+ inst.trigger = $(this._get(inst, "buttonImageOnly") ?
4001
+ $("<img/>").addClass(this._triggerClass).
4002
+ attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
4003
+ $("<button type='button'></button>").addClass(this._triggerClass).
4004
+ html(!buttonImage ? buttonText : $("<img/>").attr(
4005
+ { src:buttonImage, alt:buttonText, title:buttonText })));
4006
+ input[isRTL ? "before" : "after"](inst.trigger);
4007
+ inst.trigger.click(function() {
4008
+ if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
4009
+ $.datepicker._hideDatepicker();
4010
+ } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
4011
+ $.datepicker._hideDatepicker();
4012
+ $.datepicker._showDatepicker(input[0]);
4013
+ } else {
4014
+ $.datepicker._showDatepicker(input[0]);
4015
+ }
4016
+ return false;
4017
+ });
4018
+ }
4019
+ },
4020
+
4021
+ /* Apply the maximum length for the date format. */
4022
+ _autoSize: function(inst) {
4023
+ if (this._get(inst, "autoSize") && !inst.inline) {
4024
+ var findMax, max, maxI, i,
4025
+ date = new Date(2009, 12 - 1, 20), // Ensure double digits
4026
+ dateFormat = this._get(inst, "dateFormat");
4027
+
4028
+ if (dateFormat.match(/[DM]/)) {
4029
+ findMax = function(names) {
4030
+ max = 0;
4031
+ maxI = 0;
4032
+ for (i = 0; i < names.length; i++) {
4033
+ if (names[i].length > max) {
4034
+ max = names[i].length;
4035
+ maxI = i;
4036
+ }
4037
+ }
4038
+ return maxI;
4039
+ };
4040
+ date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
4041
+ "monthNames" : "monthNamesShort"))));
4042
+ date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
4043
+ "dayNames" : "dayNamesShort"))) + 20 - date.getDay());
4044
+ }
4045
+ inst.input.attr("size", this._formatDate(inst, date).length);
4046
+ }
4047
+ },
4048
+
4049
+ /* Attach an inline date picker to a div. */
4050
+ _inlineDatepicker: function(target, inst) {
4051
+ var divSpan = $(target);
4052
+ if (divSpan.hasClass(this.markerClassName)) {
4053
+ return;
4054
+ }
4055
+ divSpan.addClass(this.markerClassName).append(inst.dpDiv);
4056
+ $.data(target, "datepicker", inst);
4057
+ this._setDate(inst, this._getDefaultDate(inst), true);
4058
+ this._updateDatepicker(inst);
4059
+ this._updateAlternate(inst);
4060
+ //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
4061
+ if( inst.settings.disabled ) {
4062
+ this._disableDatepicker( target );
4063
+ }
4064
+ // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
4065
+ // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
4066
+ inst.dpDiv.css( "display", "block" );
4067
+ },
4068
+
4069
+ /* Pop-up the date picker in a "dialog" box.
4070
+ * @param input element - ignored
4071
+ * @param date string or Date - the initial date to display
4072
+ * @param onSelect function - the function to call when a date is selected
4073
+ * @param settings object - update the dialog date picker instance's settings (anonymous object)
4074
+ * @param pos int[2] - coordinates for the dialog's position within the screen or
4075
+ * event - with x/y coordinates or
4076
+ * leave empty for default (screen centre)
4077
+ * @return the manager object
4078
+ */
4079
+ _dialogDatepicker: function(input, date, onSelect, settings, pos) {
4080
+ var id, browserWidth, browserHeight, scrollX, scrollY,
4081
+ inst = this._dialogInst; // internal instance
4082
+
4083
+ if (!inst) {
4084
+ this.uuid += 1;
4085
+ id = "dp" + this.uuid;
4086
+ this._dialogInput = $("<input type='text' id='" + id +
4087
+ "' style='position: absolute; top: -100px; width: 0px;'/>");
4088
+ this._dialogInput.keydown(this._doKeyDown);
4089
+ $("body").append(this._dialogInput);
4090
+ inst = this._dialogInst = this._newInst(this._dialogInput, false);
4091
+ inst.settings = {};
4092
+ $.data(this._dialogInput[0], "datepicker", inst);
4093
+ }
4094
+ datepicker_extendRemove(inst.settings, settings || {});
4095
+ date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
4096
+ this._dialogInput.val(date);
4097
+
4098
+ this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
4099
+ if (!this._pos) {
4100
+ browserWidth = document.documentElement.clientWidth;
4101
+ browserHeight = document.documentElement.clientHeight;
4102
+ scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
4103
+ scrollY = document.documentElement.scrollTop || document.body.scrollTop;
4104
+ this._pos = // should use actual width/height below
4105
+ [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
4106
+ }
4107
+
4108
+ // move input on screen for focus, but hidden behind dialog
4109
+ this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
4110
+ inst.settings.onSelect = onSelect;
4111
+ this._inDialog = true;
4112
+ this.dpDiv.addClass(this._dialogClass);
4113
+ this._showDatepicker(this._dialogInput[0]);
4114
+ if ($.blockUI) {
4115
+ $.blockUI(this.dpDiv);
4116
+ }
4117
+ $.data(this._dialogInput[0], "datepicker", inst);
4118
+ return this;
4119
+ },
4120
+
4121
+ /* Detach a datepicker from its control.
4122
+ * @param target element - the target input field or division or span
4123
+ */
4124
+ _destroyDatepicker: function(target) {
4125
+ var nodeName,
4126
+ $target = $(target),
4127
+ inst = $.data(target, "datepicker");
4128
+
4129
+ if (!$target.hasClass(this.markerClassName)) {
4130
+ return;
4131
+ }
4132
+
4133
+ nodeName = target.nodeName.toLowerCase();
4134
+ $.removeData(target, "datepicker");
4135
+ if (nodeName === "input") {
4136
+ inst.append.remove();
4137
+ inst.trigger.remove();
4138
+ $target.removeClass(this.markerClassName).
4139
+ unbind("focus", this._showDatepicker).
4140
+ unbind("keydown", this._doKeyDown).
4141
+ unbind("keypress", this._doKeyPress).
4142
+ unbind("keyup", this._doKeyUp);
4143
+ } else if (nodeName === "div" || nodeName === "span") {
4144
+ $target.removeClass(this.markerClassName).empty();
4145
+ }
4146
+
4147
+ if ( datepicker_instActive === inst ) {
4148
+ datepicker_instActive = null;
4149
+ }
4150
+ },
4151
+
4152
+ /* Enable the date picker to a jQuery selection.
4153
+ * @param target element - the target input field or division or span
4154
+ */
4155
+ _enableDatepicker: function(target) {
4156
+ var nodeName, inline,
4157
+ $target = $(target),
4158
+ inst = $.data(target, "datepicker");
4159
+
4160
+ if (!$target.hasClass(this.markerClassName)) {
4161
+ return;
4162
+ }
4163
+
4164
+ nodeName = target.nodeName.toLowerCase();
4165
+ if (nodeName === "input") {
4166
+ target.disabled = false;
4167
+ inst.trigger.filter("button").
4168
+ each(function() { this.disabled = false; }).end().
4169
+ filter("img").css({opacity: "1.0", cursor: ""});
4170
+ } else if (nodeName === "div" || nodeName === "span") {
4171
+ inline = $target.children("." + this._inlineClass);
4172
+ inline.children().removeClass("ui-state-disabled");
4173
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
4174
+ prop("disabled", false);
4175
+ }
4176
+ this._disabledInputs = $.map(this._disabledInputs,
4177
+ function(value) { return (value === target ? null : value); }); // delete entry
4178
+ },
4179
+
4180
+ /* Disable the date picker to a jQuery selection.
4181
+ * @param target element - the target input field or division or span
4182
+ */
4183
+ _disableDatepicker: function(target) {
4184
+ var nodeName, inline,
4185
+ $target = $(target),
4186
+ inst = $.data(target, "datepicker");
4187
+
4188
+ if (!$target.hasClass(this.markerClassName)) {
4189
+ return;
4190
+ }
4191
+
4192
+ nodeName = target.nodeName.toLowerCase();
4193
+ if (nodeName === "input") {
4194
+ target.disabled = true;
4195
+ inst.trigger.filter("button").
4196
+ each(function() { this.disabled = true; }).end().
4197
+ filter("img").css({opacity: "0.5", cursor: "default"});
4198
+ } else if (nodeName === "div" || nodeName === "span") {
4199
+ inline = $target.children("." + this._inlineClass);
4200
+ inline.children().addClass("ui-state-disabled");
4201
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
4202
+ prop("disabled", true);
4203
+ }
4204
+ this._disabledInputs = $.map(this._disabledInputs,
4205
+ function(value) { return (value === target ? null : value); }); // delete entry
4206
+ this._disabledInputs[this._disabledInputs.length] = target;
4207
+ },
4208
+
4209
+ /* Is the first field in a jQuery collection disabled as a datepicker?
4210
+ * @param target element - the target input field or division or span
4211
+ * @return boolean - true if disabled, false if enabled
4212
+ */
4213
+ _isDisabledDatepicker: function(target) {
4214
+ if (!target) {
4215
+ return false;
4216
+ }
4217
+ for (var i = 0; i < this._disabledInputs.length; i++) {
4218
+ if (this._disabledInputs[i] === target) {
4219
+ return true;
4220
+ }
4221
+ }
4222
+ return false;
4223
+ },
4224
+
4225
+ /* Retrieve the instance data for the target control.
4226
+ * @param target element - the target input field or division or span
4227
+ * @return object - the associated instance data
4228
+ * @throws error if a jQuery problem getting data
4229
+ */
4230
+ _getInst: function(target) {
4231
+ try {
4232
+ return $.data(target, "datepicker");
4233
+ }
4234
+ catch (err) {
4235
+ throw "Missing instance data for this datepicker";
4236
+ }
4237
+ },
4238
+
4239
+ /* Update or retrieve the settings for a date picker attached to an input field or division.
4240
+ * @param target element - the target input field or division or span
4241
+ * @param name object - the new settings to update or
4242
+ * string - the name of the setting to change or retrieve,
4243
+ * when retrieving also "all" for all instance settings or
4244
+ * "defaults" for all global defaults
4245
+ * @param value any - the new value for the setting
4246
+ * (omit if above is an object or to retrieve a value)
4247
+ */
4248
+ _optionDatepicker: function(target, name, value) {
4249
+ var settings, date, minDate, maxDate,
4250
+ inst = this._getInst(target);
4251
+
4252
+ if (arguments.length === 2 && typeof name === "string") {
4253
+ return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
4254
+ (inst ? (name === "all" ? $.extend({}, inst.settings) :
4255
+ this._get(inst, name)) : null));
4256
+ }
4257
+
4258
+ settings = name || {};
4259
+ if (typeof name === "string") {
4260
+ settings = {};
4261
+ settings[name] = value;
4262
+ }
4263
+
4264
+ if (inst) {
4265
+ if (this._curInst === inst) {
4266
+ this._hideDatepicker();
4267
+ }
4268
+
4269
+ date = this._getDateDatepicker(target, true);
4270
+ minDate = this._getMinMaxDate(inst, "min");
4271
+ maxDate = this._getMinMaxDate(inst, "max");
4272
+ datepicker_extendRemove(inst.settings, settings);
4273
+ // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
4274
+ if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
4275
+ inst.settings.minDate = this._formatDate(inst, minDate);
4276
+ }
4277
+ if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
4278
+ inst.settings.maxDate = this._formatDate(inst, maxDate);
4279
+ }
4280
+ if ( "disabled" in settings ) {
4281
+ if ( settings.disabled ) {
4282
+ this._disableDatepicker(target);
4283
+ } else {
4284
+ this._enableDatepicker(target);
4285
+ }
4286
+ }
4287
+ this._attachments($(target), inst);
4288
+ this._autoSize(inst);
4289
+ this._setDate(inst, date);
4290
+ this._updateAlternate(inst);
4291
+ this._updateDatepicker(inst);
4292
+ }
4293
+ },
4294
+
4295
+ // change method deprecated
4296
+ _changeDatepicker: function(target, name, value) {
4297
+ this._optionDatepicker(target, name, value);
4298
+ },
4299
+
4300
+ /* Redraw the date picker attached to an input field or division.
4301
+ * @param target element - the target input field or division or span
4302
+ */
4303
+ _refreshDatepicker: function(target) {
4304
+ var inst = this._getInst(target);
4305
+ if (inst) {
4306
+ this._updateDatepicker(inst);
4307
+ }
4308
+ },
4309
+
4310
+ /* Set the dates for a jQuery selection.
4311
+ * @param target element - the target input field or division or span
4312
+ * @param date Date - the new date
4313
+ */
4314
+ _setDateDatepicker: function(target, date) {
4315
+ var inst = this._getInst(target);
4316
+ if (inst) {
4317
+ this._setDate(inst, date);
4318
+ this._updateDatepicker(inst);
4319
+ this._updateAlternate(inst);
4320
+ }
4321
+ },
4322
+
4323
+ /* Get the date(s) for the first entry in a jQuery selection.
4324
+ * @param target element - the target input field or division or span
4325
+ * @param noDefault boolean - true if no default date is to be used
4326
+ * @return Date - the current date
4327
+ */
4328
+ _getDateDatepicker: function(target, noDefault) {
4329
+ var inst = this._getInst(target);
4330
+ if (inst && !inst.inline) {
4331
+ this._setDateFromField(inst, noDefault);
4332
+ }
4333
+ return (inst ? this._getDate(inst) : null);
4334
+ },
4335
+
4336
+ /* Handle keystrokes. */
4337
+ _doKeyDown: function(event) {
4338
+ var onSelect, dateStr, sel,
4339
+ inst = $.datepicker._getInst(event.target),
4340
+ handled = true,
4341
+ isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
4342
+
4343
+ inst._keyEvent = true;
4344
+ if ($.datepicker._datepickerShowing) {
4345
+ switch (event.keyCode) {
4346
+ case 9: $.datepicker._hideDatepicker();
4347
+ handled = false;
4348
+ break; // hide on tab out
4349
+ case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
4350
+ $.datepicker._currentClass + ")", inst.dpDiv);
4351
+ if (sel[0]) {
4352
+ $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
4353
+ }
4354
+
4355
+ onSelect = $.datepicker._get(inst, "onSelect");
4356
+ if (onSelect) {
4357
+ dateStr = $.datepicker._formatDate(inst);
4358
+
4359
+ // trigger custom callback
4360
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
4361
+ } else {
4362
+ $.datepicker._hideDatepicker();
4363
+ }
4364
+
4365
+ return false; // don't submit the form
4366
+ case 27: $.datepicker._hideDatepicker();
4367
+ break; // hide on escape
4368
+ case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4369
+ -$.datepicker._get(inst, "stepBigMonths") :
4370
+ -$.datepicker._get(inst, "stepMonths")), "M");
4371
+ break; // previous month/year on page up/+ ctrl
4372
+ case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4373
+ +$.datepicker._get(inst, "stepBigMonths") :
4374
+ +$.datepicker._get(inst, "stepMonths")), "M");
4375
+ break; // next month/year on page down/+ ctrl
4376
+ case 35: if (event.ctrlKey || event.metaKey) {
4377
+ $.datepicker._clearDate(event.target);
4378
+ }
4379
+ handled = event.ctrlKey || event.metaKey;
4380
+ break; // clear on ctrl or command +end
4381
+ case 36: if (event.ctrlKey || event.metaKey) {
4382
+ $.datepicker._gotoToday(event.target);
4383
+ }
4384
+ handled = event.ctrlKey || event.metaKey;
4385
+ break; // current on ctrl or command +home
4386
+ case 37: if (event.ctrlKey || event.metaKey) {
4387
+ $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
4388
+ }
4389
+ handled = event.ctrlKey || event.metaKey;
4390
+ // -1 day on ctrl or command +left
4391
+ if (event.originalEvent.altKey) {
4392
+ $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4393
+ -$.datepicker._get(inst, "stepBigMonths") :
4394
+ -$.datepicker._get(inst, "stepMonths")), "M");
4395
+ }
4396
+ // next month/year on alt +left on Mac
4397
+ break;
4398
+ case 38: if (event.ctrlKey || event.metaKey) {
4399
+ $.datepicker._adjustDate(event.target, -7, "D");
4400
+ }
4401
+ handled = event.ctrlKey || event.metaKey;
4402
+ break; // -1 week on ctrl or command +up
4403
+ case 39: if (event.ctrlKey || event.metaKey) {
4404
+ $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
4405
+ }
4406
+ handled = event.ctrlKey || event.metaKey;
4407
+ // +1 day on ctrl or command +right
4408
+ if (event.originalEvent.altKey) {
4409
+ $.datepicker._adjustDate(event.target, (event.ctrlKey ?
4410
+ +$.datepicker._get(inst, "stepBigMonths") :
4411
+ +$.datepicker._get(inst, "stepMonths")), "M");
4412
+ }
4413
+ // next month/year on alt +right
4414
+ break;
4415
+ case 40: if (event.ctrlKey || event.metaKey) {
4416
+ $.datepicker._adjustDate(event.target, +7, "D");
4417
+ }
4418
+ handled = event.ctrlKey || event.metaKey;
4419
+ break; // +1 week on ctrl or command +down
4420
+ default: handled = false;
4421
+ }
4422
+ } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
4423
+ $.datepicker._showDatepicker(this);
4424
+ } else {
4425
+ handled = false;
4426
+ }
4427
+
4428
+ if (handled) {
4429
+ event.preventDefault();
4430
+ event.stopPropagation();
4431
+ }
4432
+ },
4433
+
4434
+ /* Filter entered characters - based on date format. */
4435
+ _doKeyPress: function(event) {
4436
+ var chars, chr,
4437
+ inst = $.datepicker._getInst(event.target);
4438
+
4439
+ if ($.datepicker._get(inst, "constrainInput")) {
4440
+ chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
4441
+ chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
4442
+ return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
4443
+ }
4444
+ },
4445
+
4446
+ /* Synchronise manual entry and field/alternate field. */
4447
+ _doKeyUp: function(event) {
4448
+ var date,
4449
+ inst = $.datepicker._getInst(event.target);
4450
+
4451
+ if (inst.input.val() !== inst.lastVal) {
4452
+ try {
4453
+ date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
4454
+ (inst.input ? inst.input.val() : null),
4455
+ $.datepicker._getFormatConfig(inst));
4456
+
4457
+ if (date) { // only if valid
4458
+ $.datepicker._setDateFromField(inst);
4459
+ $.datepicker._updateAlternate(inst);
4460
+ $.datepicker._updateDatepicker(inst);
4461
+ }
4462
+ }
4463
+ catch (err) {
4464
+ }
4465
+ }
4466
+ return true;
4467
+ },
4468
+
4469
+ /* Pop-up the date picker for a given input field.
4470
+ * If false returned from beforeShow event handler do not show.
4471
+ * @param input element - the input field attached to the date picker or
4472
+ * event - if triggered by focus
4473
+ */
4474
+ _showDatepicker: function(input) {
4475
+ input = input.target || input;
4476
+ if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
4477
+ input = $("input", input.parentNode)[0];
4478
+ }
4479
+
4480
+ if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
4481
+ return;
4482
+ }
4483
+
4484
+ var inst, beforeShow, beforeShowSettings, isFixed,
4485
+ offset, showAnim, duration;
4486
+
4487
+ inst = $.datepicker._getInst(input);
4488
+ if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
4489
+ $.datepicker._curInst.dpDiv.stop(true, true);
4490
+ if ( inst && $.datepicker._datepickerShowing ) {
4491
+ $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
4492
+ }
4493
+ }
4494
+
4495
+ beforeShow = $.datepicker._get(inst, "beforeShow");
4496
+ beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
4497
+ if(beforeShowSettings === false){
4498
+ return;
4499
+ }
4500
+ datepicker_extendRemove(inst.settings, beforeShowSettings);
4501
+
4502
+ inst.lastVal = null;
4503
+ $.datepicker._lastInput = input;
4504
+ $.datepicker._setDateFromField(inst);
4505
+
4506
+ if ($.datepicker._inDialog) { // hide cursor
4507
+ input.value = "";
4508
+ }
4509
+ if (!$.datepicker._pos) { // position below input
4510
+ $.datepicker._pos = $.datepicker._findPos(input);
4511
+ $.datepicker._pos[1] += input.offsetHeight; // add the height
4512
+ }
4513
+
4514
+ isFixed = false;
4515
+ $(input).parents().each(function() {
4516
+ isFixed |= $(this).css("position") === "fixed";
4517
+ return !isFixed;
4518
+ });
4519
+
4520
+ offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
4521
+ $.datepicker._pos = null;
4522
+ //to avoid flashes on Firefox
4523
+ inst.dpDiv.empty();
4524
+ // determine sizing offscreen
4525
+ inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
4526
+ $.datepicker._updateDatepicker(inst);
4527
+ // fix width for dynamic number of date pickers
4528
+ // and adjust position before showing
4529
+ offset = $.datepicker._checkOffset(inst, offset, isFixed);
4530
+ inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
4531
+ "static" : (isFixed ? "fixed" : "absolute")), display: "none",
4532
+ left: offset.left + "px", top: offset.top + "px"});
4533
+
4534
+ if (!inst.inline) {
4535
+ showAnim = $.datepicker._get(inst, "showAnim");
4536
+ duration = $.datepicker._get(inst, "duration");
4537
+ inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
4538
+ $.datepicker._datepickerShowing = true;
4539
+
4540
+ if ( $.effects && $.effects.effect[ showAnim ] ) {
4541
+ inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
4542
+ } else {
4543
+ inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
4544
+ }
4545
+
4546
+ if ( $.datepicker._shouldFocusInput( inst ) ) {
4547
+ inst.input.focus();
4548
+ }
4549
+
4550
+ $.datepicker._curInst = inst;
4551
+ }
4552
+ },
4553
+
4554
+ /* Generate the date picker content. */
4555
+ _updateDatepicker: function(inst) {
4556
+ this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
4557
+ datepicker_instActive = inst; // for delegate hover events
4558
+ inst.dpDiv.empty().append(this._generateHTML(inst));
4559
+ this._attachHandlers(inst);
4560
+
4561
+ var origyearshtml,
4562
+ numMonths = this._getNumberOfMonths(inst),
4563
+ cols = numMonths[1],
4564
+ width = 17,
4565
+ activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" );
4566
+
4567
+ if ( activeCell.length > 0 ) {
4568
+ datepicker_handleMouseover.apply( activeCell.get( 0 ) );
4569
+ }
4570
+
4571
+ inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
4572
+ if (cols > 1) {
4573
+ inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
4574
+ }
4575
+ inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
4576
+ "Class"]("ui-datepicker-multi");
4577
+ inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
4578
+ "Class"]("ui-datepicker-rtl");
4579
+
4580
+ if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
4581
+ inst.input.focus();
4582
+ }
4583
+
4584
+ // deffered render of the years select (to avoid flashes on Firefox)
4585
+ if( inst.yearshtml ){
4586
+ origyearshtml = inst.yearshtml;
4587
+ setTimeout(function(){
4588
+ //assure that inst.yearshtml didn't change.
4589
+ if( origyearshtml === inst.yearshtml && inst.yearshtml ){
4590
+ inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
4591
+ }
4592
+ origyearshtml = inst.yearshtml = null;
4593
+ }, 0);
4594
+ }
4595
+ },
4596
+
4597
+ // #6694 - don't focus the input if it's already focused
4598
+ // this breaks the change event in IE
4599
+ // Support: IE and jQuery <1.9
4600
+ _shouldFocusInput: function( inst ) {
4601
+ return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
4602
+ },
4603
+
4604
+ /* Check positioning to remain on screen. */
4605
+ _checkOffset: function(inst, offset, isFixed) {
4606
+ var dpWidth = inst.dpDiv.outerWidth(),
4607
+ dpHeight = inst.dpDiv.outerHeight(),
4608
+ inputWidth = inst.input ? inst.input.outerWidth() : 0,
4609
+ inputHeight = inst.input ? inst.input.outerHeight() : 0,
4610
+ viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
4611
+ viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
4612
+
4613
+ offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
4614
+ offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
4615
+ offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
4616
+
4617
+ // now check if datepicker is showing outside window viewport - move to a better place if so.
4618
+ offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
4619
+ Math.abs(offset.left + dpWidth - viewWidth) : 0);
4620
+ offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
4621
+ Math.abs(dpHeight + inputHeight) : 0);
4622
+
4623
+ return offset;
4624
+ },
4625
+
4626
+ /* Find an object's position on the screen. */
4627
+ _findPos: function(obj) {
4628
+ var position,
4629
+ inst = this._getInst(obj),
4630
+ isRTL = this._get(inst, "isRTL");
4631
+
4632
+ while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
4633
+ obj = obj[isRTL ? "previousSibling" : "nextSibling"];
4634
+ }
4635
+
4636
+ position = $(obj).offset();
4637
+ return [position.left, position.top];
4638
+ },
4639
+
4640
+ /* Hide the date picker from view.
4641
+ * @param input element - the input field attached to the date picker
4642
+ */
4643
+ _hideDatepicker: function(input) {
4644
+ var showAnim, duration, postProcess, onClose,
4645
+ inst = this._curInst;
4646
+
4647
+ if (!inst || (input && inst !== $.data(input, "datepicker"))) {
4648
+ return;
4649
+ }
4650
+
4651
+ if (this._datepickerShowing) {
4652
+ showAnim = this._get(inst, "showAnim");
4653
+ duration = this._get(inst, "duration");
4654
+ postProcess = function() {
4655
+ $.datepicker._tidyDialog(inst);
4656
+ };
4657
+
4658
+ // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
4659
+ if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
4660
+ inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
4661
+ } else {
4662
+ inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
4663
+ (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
4664
+ }
4665
+
4666
+ if (!showAnim) {
4667
+ postProcess();
4668
+ }
4669
+ this._datepickerShowing = false;
4670
+
4671
+ onClose = this._get(inst, "onClose");
4672
+ if (onClose) {
4673
+ onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
4674
+ }
4675
+
4676
+ this._lastInput = null;
4677
+ if (this._inDialog) {
4678
+ this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
4679
+ if ($.blockUI) {
4680
+ $.unblockUI();
4681
+ $("body").append(this.dpDiv);
4682
+ }
4683
+ }
4684
+ this._inDialog = false;
4685
+ }
4686
+ },
4687
+
4688
+ /* Tidy up after a dialog display. */
4689
+ _tidyDialog: function(inst) {
4690
+ inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
4691
+ },
4692
+
4693
+ /* Close date picker if clicked elsewhere. */
4694
+ _checkExternalClick: function(event) {
4695
+ if (!$.datepicker._curInst) {
4696
+ return;
4697
+ }
4698
+
4699
+ var $target = $(event.target),
4700
+ inst = $.datepicker._getInst($target[0]);
4701
+
4702
+ if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
4703
+ $target.parents("#" + $.datepicker._mainDivId).length === 0 &&
4704
+ !$target.hasClass($.datepicker.markerClassName) &&
4705
+ !$target.closest("." + $.datepicker._triggerClass).length &&
4706
+ $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
4707
+ ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
4708
+ $.datepicker._hideDatepicker();
4709
+ }
4710
+ },
4711
+
4712
+ /* Adjust one of the date sub-fields. */
4713
+ _adjustDate: function(id, offset, period) {
4714
+ var target = $(id),
4715
+ inst = this._getInst(target[0]);
4716
+
4717
+ if (this._isDisabledDatepicker(target[0])) {
4718
+ return;
4719
+ }
4720
+ this._adjustInstDate(inst, offset +
4721
+ (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
4722
+ period);
4723
+ this._updateDatepicker(inst);
4724
+ },
4725
+
4726
+ /* Action for current link. */
4727
+ _gotoToday: function(id) {
4728
+ var date,
4729
+ target = $(id),
4730
+ inst = this._getInst(target[0]);
4731
+
4732
+ if (this._get(inst, "gotoCurrent") && inst.currentDay) {
4733
+ inst.selectedDay = inst.currentDay;
4734
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth;
4735
+ inst.drawYear = inst.selectedYear = inst.currentYear;
4736
+ } else {
4737
+ date = new Date();
4738
+ inst.selectedDay = date.getDate();
4739
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
4740
+ inst.drawYear = inst.selectedYear = date.getFullYear();
4741
+ }
4742
+ this._notifyChange(inst);
4743
+ this._adjustDate(target);
4744
+ },
4745
+
4746
+ /* Action for selecting a new month/year. */
4747
+ _selectMonthYear: function(id, select, period) {
4748
+ var target = $(id),
4749
+ inst = this._getInst(target[0]);
4750
+
4751
+ inst["selected" + (period === "M" ? "Month" : "Year")] =
4752
+ inst["draw" + (period === "M" ? "Month" : "Year")] =
4753
+ parseInt(select.options[select.selectedIndex].value,10);
4754
+
4755
+ this._notifyChange(inst);
4756
+ this._adjustDate(target);
4757
+ },
4758
+
4759
+ /* Action for selecting a day. */
4760
+ _selectDay: function(id, month, year, td) {
4761
+ var inst,
4762
+ target = $(id);
4763
+
4764
+ if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
4765
+ return;
4766
+ }
4767
+
4768
+ inst = this._getInst(target[0]);
4769
+ inst.selectedDay = inst.currentDay = $("a", td).html();
4770
+ inst.selectedMonth = inst.currentMonth = month;
4771
+ inst.selectedYear = inst.currentYear = year;
4772
+ this._selectDate(id, this._formatDate(inst,
4773
+ inst.currentDay, inst.currentMonth, inst.currentYear));
4774
+ },
4775
+
4776
+ /* Erase the input field and hide the date picker. */
4777
+ _clearDate: function(id) {
4778
+ var target = $(id);
4779
+ this._selectDate(target, "");
4780
+ },
4781
+
4782
+ /* Update the input field with the selected date. */
4783
+ _selectDate: function(id, dateStr) {
4784
+ var onSelect,
4785
+ target = $(id),
4786
+ inst = this._getInst(target[0]);
4787
+
4788
+ dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
4789
+ if (inst.input) {
4790
+ inst.input.val(dateStr);
4791
+ }
4792
+ this._updateAlternate(inst);
4793
+
4794
+ onSelect = this._get(inst, "onSelect");
4795
+ if (onSelect) {
4796
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
4797
+ } else if (inst.input) {
4798
+ inst.input.trigger("change"); // fire the change event
4799
+ }
4800
+
4801
+ if (inst.inline){
4802
+ this._updateDatepicker(inst);
4803
+ } else {
4804
+ this._hideDatepicker();
4805
+ this._lastInput = inst.input[0];
4806
+ if (typeof(inst.input[0]) !== "object") {
4807
+ inst.input.focus(); // restore focus
4808
+ }
4809
+ this._lastInput = null;
4810
+ }
4811
+ },
4812
+
4813
+ /* Update any alternate field to synchronise with the main field. */
4814
+ _updateAlternate: function(inst) {
4815
+ var altFormat, date, dateStr,
4816
+ altField = this._get(inst, "altField");
4817
+
4818
+ if (altField) { // update alternate field too
4819
+ altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
4820
+ date = this._getDate(inst);
4821
+ dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
4822
+ $(altField).each(function() { $(this).val(dateStr); });
4823
+ }
4824
+ },
4825
+
4826
+ /* Set as beforeShowDay function to prevent selection of weekends.
4827
+ * @param date Date - the date to customise
4828
+ * @return [boolean, string] - is this date selectable?, what is its CSS class?
4829
+ */
4830
+ noWeekends: function(date) {
4831
+ var day = date.getDay();
4832
+ return [(day > 0 && day < 6), ""];
4833
+ },
4834
+
4835
+ /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
4836
+ * @param date Date - the date to get the week for
4837
+ * @return number - the number of the week within the year that contains this date
4838
+ */
4839
+ iso8601Week: function(date) {
4840
+ var time,
4841
+ checkDate = new Date(date.getTime());
4842
+
4843
+ // Find Thursday of this week starting on Monday
4844
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
4845
+
4846
+ time = checkDate.getTime();
4847
+ checkDate.setMonth(0); // Compare with Jan 1
4848
+ checkDate.setDate(1);
4849
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
4850
+ },
4851
+
4852
+ /* Parse a string value into a date object.
4853
+ * See formatDate below for the possible formats.
4854
+ *
4855
+ * @param format string - the expected format of the date
4856
+ * @param value string - the date in the above format
4857
+ * @param settings Object - attributes include:
4858
+ * shortYearCutoff number - the cutoff year for determining the century (optional)
4859
+ * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
4860
+ * dayNames string[7] - names of the days from Sunday (optional)
4861
+ * monthNamesShort string[12] - abbreviated names of the months (optional)
4862
+ * monthNames string[12] - names of the months (optional)
4863
+ * @return Date - the extracted date value or null if value is blank
4864
+ */
4865
+ parseDate: function (format, value, settings) {
4866
+ if (format == null || value == null) {
4867
+ throw "Invalid arguments";
4868
+ }
4869
+
4870
+ value = (typeof value === "object" ? value.toString() : value + "");
4871
+ if (value === "") {
4872
+ return null;
4873
+ }
4874
+
4875
+ var iFormat, dim, extra,
4876
+ iValue = 0,
4877
+ shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
4878
+ shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
4879
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
4880
+ dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
4881
+ dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
4882
+ monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
4883
+ monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
4884
+ year = -1,
4885
+ month = -1,
4886
+ day = -1,
4887
+ doy = -1,
4888
+ literal = false,
4889
+ date,
4890
+ // Check whether a format character is doubled
4891
+ lookAhead = function(match) {
4892
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
4893
+ if (matches) {
4894
+ iFormat++;
4895
+ }
4896
+ return matches;
4897
+ },
4898
+ // Extract a number from the string value
4899
+ getNumber = function(match) {
4900
+ var isDoubled = lookAhead(match),
4901
+ size = (match === "@" ? 14 : (match === "!" ? 20 :
4902
+ (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
4903
+ minSize = (match === "y" ? size : 1),
4904
+ digits = new RegExp("^\\d{" + minSize + "," + size + "}"),
4905
+ num = value.substring(iValue).match(digits);
4906
+ if (!num) {
4907
+ throw "Missing number at position " + iValue;
4908
+ }
4909
+ iValue += num[0].length;
4910
+ return parseInt(num[0], 10);
4911
+ },
4912
+ // Extract a name from the string value and convert to an index
4913
+ getName = function(match, shortNames, longNames) {
4914
+ var index = -1,
4915
+ names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
4916
+ return [ [k, v] ];
4917
+ }).sort(function (a, b) {
4918
+ return -(a[1].length - b[1].length);
4919
+ });
4920
+
4921
+ $.each(names, function (i, pair) {
4922
+ var name = pair[1];
4923
+ if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
4924
+ index = pair[0];
4925
+ iValue += name.length;
4926
+ return false;
4927
+ }
4928
+ });
4929
+ if (index !== -1) {
4930
+ return index + 1;
4931
+ } else {
4932
+ throw "Unknown name at position " + iValue;
4933
+ }
4934
+ },
4935
+ // Confirm that a literal character matches the string value
4936
+ checkLiteral = function() {
4937
+ if (value.charAt(iValue) !== format.charAt(iFormat)) {
4938
+ throw "Unexpected literal at position " + iValue;
4939
+ }
4940
+ iValue++;
4941
+ };
4942
+
4943
+ for (iFormat = 0; iFormat < format.length; iFormat++) {
4944
+ if (literal) {
4945
+ if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
4946
+ literal = false;
4947
+ } else {
4948
+ checkLiteral();
4949
+ }
4950
+ } else {
4951
+ switch (format.charAt(iFormat)) {
4952
+ case "d":
4953
+ day = getNumber("d");
4954
+ break;
4955
+ case "D":
4956
+ getName("D", dayNamesShort, dayNames);
4957
+ break;
4958
+ case "o":
4959
+ doy = getNumber("o");
4960
+ break;
4961
+ case "m":
4962
+ month = getNumber("m");
4963
+ break;
4964
+ case "M":
4965
+ month = getName("M", monthNamesShort, monthNames);
4966
+ break;
4967
+ case "y":
4968
+ year = getNumber("y");
4969
+ break;
4970
+ case "@":
4971
+ date = new Date(getNumber("@"));
4972
+ year = date.getFullYear();
4973
+ month = date.getMonth() + 1;
4974
+ day = date.getDate();
4975
+ break;
4976
+ case "!":
4977
+ date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
4978
+ year = date.getFullYear();
4979
+ month = date.getMonth() + 1;
4980
+ day = date.getDate();
4981
+ break;
4982
+ case "'":
4983
+ if (lookAhead("'")){
4984
+ checkLiteral();
4985
+ } else {
4986
+ literal = true;
4987
+ }
4988
+ break;
4989
+ default:
4990
+ checkLiteral();
4991
+ }
4992
+ }
4993
+ }
4994
+
4995
+ if (iValue < value.length){
4996
+ extra = value.substr(iValue);
4997
+ if (!/^\s+/.test(extra)) {
4998
+ throw "Extra/unparsed characters found in date: " + extra;
4999
+ }
5000
+ }
5001
+
5002
+ if (year === -1) {
5003
+ year = new Date().getFullYear();
5004
+ } else if (year < 100) {
5005
+ year += new Date().getFullYear() - new Date().getFullYear() % 100 +
5006
+ (year <= shortYearCutoff ? 0 : -100);
5007
+ }
5008
+
5009
+ if (doy > -1) {
5010
+ month = 1;
5011
+ day = doy;
5012
+ do {
5013
+ dim = this._getDaysInMonth(year, month - 1);
5014
+ if (day <= dim) {
5015
+ break;
5016
+ }
5017
+ month++;
5018
+ day -= dim;
5019
+ } while (true);
5020
+ }
5021
+
5022
+ date = this._daylightSavingAdjust(new Date(year, month - 1, day));
5023
+ if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
5024
+ throw "Invalid date"; // E.g. 31/02/00
5025
+ }
5026
+ return date;
5027
+ },
5028
+
5029
+ /* Standard date formats. */
5030
+ ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
5031
+ COOKIE: "D, dd M yy",
5032
+ ISO_8601: "yy-mm-dd",
5033
+ RFC_822: "D, d M y",
5034
+ RFC_850: "DD, dd-M-y",
5035
+ RFC_1036: "D, d M y",
5036
+ RFC_1123: "D, d M yy",
5037
+ RFC_2822: "D, d M yy",
5038
+ RSS: "D, d M y", // RFC 822
5039
+ TICKS: "!",
5040
+ TIMESTAMP: "@",
5041
+ W3C: "yy-mm-dd", // ISO 8601
5042
+
5043
+ _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
5044
+ Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
5045
+
5046
+ /* Format a date object into a string value.
5047
+ * The format can be combinations of the following:
5048
+ * d - day of month (no leading zero)
5049
+ * dd - day of month (two digit)
5050
+ * o - day of year (no leading zeros)
5051
+ * oo - day of year (three digit)
5052
+ * D - day name short
5053
+ * DD - day name long
5054
+ * m - month of year (no leading zero)
5055
+ * mm - month of year (two digit)
5056
+ * M - month name short
5057
+ * MM - month name long
5058
+ * y - year (two digit)
5059
+ * yy - year (four digit)
5060
+ * @ - Unix timestamp (ms since 01/01/1970)
5061
+ * ! - Windows ticks (100ns since 01/01/0001)
5062
+ * "..." - literal text
5063
+ * '' - single quote
5064
+ *
5065
+ * @param format string - the desired format of the date
5066
+ * @param date Date - the date value to format
5067
+ * @param settings Object - attributes include:
5068
+ * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
5069
+ * dayNames string[7] - names of the days from Sunday (optional)
5070
+ * monthNamesShort string[12] - abbreviated names of the months (optional)
5071
+ * monthNames string[12] - names of the months (optional)
5072
+ * @return string - the date in the above format
5073
+ */
5074
+ formatDate: function (format, date, settings) {
5075
+ if (!date) {
5076
+ return "";
5077
+ }
5078
+
5079
+ var iFormat,
5080
+ dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
5081
+ dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
5082
+ monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
5083
+ monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
5084
+ // Check whether a format character is doubled
5085
+ lookAhead = function(match) {
5086
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
5087
+ if (matches) {
5088
+ iFormat++;
5089
+ }
5090
+ return matches;
5091
+ },
5092
+ // Format a number, with leading zero if necessary
5093
+ formatNumber = function(match, value, len) {
5094
+ var num = "" + value;
5095
+ if (lookAhead(match)) {
5096
+ while (num.length < len) {
5097
+ num = "0" + num;
5098
+ }
5099
+ }
5100
+ return num;
5101
+ },
5102
+ // Format a name, short or long as requested
5103
+ formatName = function(match, value, shortNames, longNames) {
5104
+ return (lookAhead(match) ? longNames[value] : shortNames[value]);
5105
+ },
5106
+ output = "",
5107
+ literal = false;
5108
+
5109
+ if (date) {
5110
+ for (iFormat = 0; iFormat < format.length; iFormat++) {
5111
+ if (literal) {
5112
+ if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
5113
+ literal = false;
5114
+ } else {
5115
+ output += format.charAt(iFormat);
5116
+ }
5117
+ } else {
5118
+ switch (format.charAt(iFormat)) {
5119
+ case "d":
5120
+ output += formatNumber("d", date.getDate(), 2);
5121
+ break;
5122
+ case "D":
5123
+ output += formatName("D", date.getDay(), dayNamesShort, dayNames);
5124
+ break;
5125
+ case "o":
5126
+ output += formatNumber("o",
5127
+ Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
5128
+ break;
5129
+ case "m":
5130
+ output += formatNumber("m", date.getMonth() + 1, 2);
5131
+ break;
5132
+ case "M":
5133
+ output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
5134
+ break;
5135
+ case "y":
5136
+ output += (lookAhead("y") ? date.getFullYear() :
5137
+ (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
5138
+ break;
5139
+ case "@":
5140
+ output += date.getTime();
5141
+ break;
5142
+ case "!":
5143
+ output += date.getTime() * 10000 + this._ticksTo1970;
5144
+ break;
5145
+ case "'":
5146
+ if (lookAhead("'")) {
5147
+ output += "'";
5148
+ } else {
5149
+ literal = true;
5150
+ }
5151
+ break;
5152
+ default:
5153
+ output += format.charAt(iFormat);
5154
+ }
5155
+ }
5156
+ }
5157
+ }
5158
+ return output;
5159
+ },
5160
+
5161
+ /* Extract all possible characters from the date format. */
5162
+ _possibleChars: function (format) {
5163
+ var iFormat,
5164
+ chars = "",
5165
+ literal = false,
5166
+ // Check whether a format character is doubled
5167
+ lookAhead = function(match) {
5168
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
5169
+ if (matches) {
5170
+ iFormat++;
5171
+ }
5172
+ return matches;
5173
+ };
5174
+
5175
+ for (iFormat = 0; iFormat < format.length; iFormat++) {
5176
+ if (literal) {
5177
+ if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
5178
+ literal = false;
5179
+ } else {
5180
+ chars += format.charAt(iFormat);
5181
+ }
5182
+ } else {
5183
+ switch (format.charAt(iFormat)) {
5184
+ case "d": case "m": case "y": case "@":
5185
+ chars += "0123456789";
5186
+ break;
5187
+ case "D": case "M":
5188
+ return null; // Accept anything
5189
+ case "'":
5190
+ if (lookAhead("'")) {
5191
+ chars += "'";
5192
+ } else {
5193
+ literal = true;
5194
+ }
5195
+ break;
5196
+ default:
5197
+ chars += format.charAt(iFormat);
5198
+ }
5199
+ }
5200
+ }
5201
+ return chars;
5202
+ },
5203
+
5204
+ /* Get a setting value, defaulting if necessary. */
5205
+ _get: function(inst, name) {
5206
+ return inst.settings[name] !== undefined ?
5207
+ inst.settings[name] : this._defaults[name];
5208
+ },
5209
+
5210
+ /* Parse existing date and initialise date picker. */
5211
+ _setDateFromField: function(inst, noDefault) {
5212
+ if (inst.input.val() === inst.lastVal) {
5213
+ return;
5214
+ }
5215
+
5216
+ var dateFormat = this._get(inst, "dateFormat"),
5217
+ dates = inst.lastVal = inst.input ? inst.input.val() : null,
5218
+ defaultDate = this._getDefaultDate(inst),
5219
+ date = defaultDate,
5220
+ settings = this._getFormatConfig(inst);
5221
+
5222
+ try {
5223
+ date = this.parseDate(dateFormat, dates, settings) || defaultDate;
5224
+ } catch (event) {
5225
+ dates = (noDefault ? "" : dates);
5226
+ }
5227
+ inst.selectedDay = date.getDate();
5228
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
5229
+ inst.drawYear = inst.selectedYear = date.getFullYear();
5230
+ inst.currentDay = (dates ? date.getDate() : 0);
5231
+ inst.currentMonth = (dates ? date.getMonth() : 0);
5232
+ inst.currentYear = (dates ? date.getFullYear() : 0);
5233
+ this._adjustInstDate(inst);
5234
+ },
5235
+
5236
+ /* Retrieve the default date shown on opening. */
5237
+ _getDefaultDate: function(inst) {
5238
+ return this._restrictMinMax(inst,
5239
+ this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
5240
+ },
5241
+
5242
+ /* A date may be specified as an exact value or a relative one. */
5243
+ _determineDate: function(inst, date, defaultDate) {
5244
+ var offsetNumeric = function(offset) {
5245
+ var date = new Date();
5246
+ date.setDate(date.getDate() + offset);
5247
+ return date;
5248
+ },
5249
+ offsetString = function(offset) {
5250
+ try {
5251
+ return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
5252
+ offset, $.datepicker._getFormatConfig(inst));
5253
+ }
5254
+ catch (e) {
5255
+ // Ignore
5256
+ }
5257
+
5258
+ var date = (offset.toLowerCase().match(/^c/) ?
5259
+ $.datepicker._getDate(inst) : null) || new Date(),
5260
+ year = date.getFullYear(),
5261
+ month = date.getMonth(),
5262
+ day = date.getDate(),
5263
+ pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
5264
+ matches = pattern.exec(offset);
5265
+
5266
+ while (matches) {
5267
+ switch (matches[2] || "d") {
5268
+ case "d" : case "D" :
5269
+ day += parseInt(matches[1],10); break;
5270
+ case "w" : case "W" :
5271
+ day += parseInt(matches[1],10) * 7; break;
5272
+ case "m" : case "M" :
5273
+ month += parseInt(matches[1],10);
5274
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
5275
+ break;
5276
+ case "y": case "Y" :
5277
+ year += parseInt(matches[1],10);
5278
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
5279
+ break;
5280
+ }
5281
+ matches = pattern.exec(offset);
5282
+ }
5283
+ return new Date(year, month, day);
5284
+ },
5285
+ newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
5286
+ (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
5287
+
5288
+ newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
5289
+ if (newDate) {
5290
+ newDate.setHours(0);
5291
+ newDate.setMinutes(0);
5292
+ newDate.setSeconds(0);
5293
+ newDate.setMilliseconds(0);
5294
+ }
5295
+ return this._daylightSavingAdjust(newDate);
5296
+ },
5297
+
5298
+ /* Handle switch to/from daylight saving.
5299
+ * Hours may be non-zero on daylight saving cut-over:
5300
+ * > 12 when midnight changeover, but then cannot generate
5301
+ * midnight datetime, so jump to 1AM, otherwise reset.
5302
+ * @param date (Date) the date to check
5303
+ * @return (Date) the corrected date
5304
+ */
5305
+ _daylightSavingAdjust: function(date) {
5306
+ if (!date) {
5307
+ return null;
5308
+ }
5309
+ date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
5310
+ return date;
5311
+ },
5312
+
5313
+ /* Set the date(s) directly. */
5314
+ _setDate: function(inst, date, noChange) {
5315
+ var clear = !date,
5316
+ origMonth = inst.selectedMonth,
5317
+ origYear = inst.selectedYear,
5318
+ newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
5319
+
5320
+ inst.selectedDay = inst.currentDay = newDate.getDate();
5321
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
5322
+ inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
5323
+ if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
5324
+ this._notifyChange(inst);
5325
+ }
5326
+ this._adjustInstDate(inst);
5327
+ if (inst.input) {
5328
+ inst.input.val(clear ? "" : this._formatDate(inst));
5329
+ }
5330
+ },
5331
+
5332
+ /* Retrieve the date(s) directly. */
5333
+ _getDate: function(inst) {
5334
+ var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
5335
+ this._daylightSavingAdjust(new Date(
5336
+ inst.currentYear, inst.currentMonth, inst.currentDay)));
5337
+ return startDate;
5338
+ },
5339
+
5340
+ /* Attach the onxxx handlers. These are declared statically so
5341
+ * they work with static code transformers like Caja.
5342
+ */
5343
+ _attachHandlers: function(inst) {
5344
+ var stepMonths = this._get(inst, "stepMonths"),
5345
+ id = "#" + inst.id.replace( /\\\\/g, "\\" );
5346
+ inst.dpDiv.find("[data-handler]").map(function () {
5347
+ var handler = {
5348
+ prev: function () {
5349
+ $.datepicker._adjustDate(id, -stepMonths, "M");
5350
+ },
5351
+ next: function () {
5352
+ $.datepicker._adjustDate(id, +stepMonths, "M");
5353
+ },
5354
+ hide: function () {
5355
+ $.datepicker._hideDatepicker();
5356
+ },
5357
+ today: function () {
5358
+ $.datepicker._gotoToday(id);
5359
+ },
5360
+ selectDay: function () {
5361
+ $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
5362
+ return false;
5363
+ },
5364
+ selectMonth: function () {
5365
+ $.datepicker._selectMonthYear(id, this, "M");
5366
+ return false;
5367
+ },
5368
+ selectYear: function () {
5369
+ $.datepicker._selectMonthYear(id, this, "Y");
5370
+ return false;
5371
+ }
5372
+ };
5373
+ $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
5374
+ });
5375
+ },
5376
+
5377
+ /* Generate the HTML for the current state of the date picker. */
5378
+ _generateHTML: function(inst) {
5379
+ var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
5380
+ controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
5381
+ monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
5382
+ selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
5383
+ cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
5384
+ printDate, dRow, tbody, daySettings, otherMonth, unselectable,
5385
+ tempDate = new Date(),
5386
+ today = this._daylightSavingAdjust(
5387
+ new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
5388
+ isRTL = this._get(inst, "isRTL"),
5389
+ showButtonPanel = this._get(inst, "showButtonPanel"),
5390
+ hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
5391
+ navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
5392
+ numMonths = this._getNumberOfMonths(inst),
5393
+ showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
5394
+ stepMonths = this._get(inst, "stepMonths"),
5395
+ isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
5396
+ currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
5397
+ new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
5398
+ minDate = this._getMinMaxDate(inst, "min"),
5399
+ maxDate = this._getMinMaxDate(inst, "max"),
5400
+ drawMonth = inst.drawMonth - showCurrentAtPos,
5401
+ drawYear = inst.drawYear;
5402
+
5403
+ if (drawMonth < 0) {
5404
+ drawMonth += 12;
5405
+ drawYear--;
5406
+ }
5407
+ if (maxDate) {
5408
+ maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
5409
+ maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
5410
+ maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
5411
+ while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
5412
+ drawMonth--;
5413
+ if (drawMonth < 0) {
5414
+ drawMonth = 11;
5415
+ drawYear--;
5416
+ }
5417
+ }
5418
+ }
5419
+ inst.drawMonth = drawMonth;
5420
+ inst.drawYear = drawYear;
5421
+
5422
+ prevText = this._get(inst, "prevText");
5423
+ prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
5424
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
5425
+ this._getFormatConfig(inst)));
5426
+
5427
+ prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
5428
+ "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
5429
+ " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
5430
+ (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>"));
5431
+
5432
+ nextText = this._get(inst, "nextText");
5433
+ nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
5434
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
5435
+ this._getFormatConfig(inst)));
5436
+
5437
+ next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
5438
+ "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
5439
+ " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
5440
+ (hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>"));
5441
+
5442
+ currentText = this._get(inst, "currentText");
5443
+ gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
5444
+ currentText = (!navigationAsDateFormat ? currentText :
5445
+ this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
5446
+
5447
+ controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
5448
+ this._get(inst, "closeText") + "</button>" : "");
5449
+
5450
+ buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
5451
+ (this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
5452
+ ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
5453
+
5454
+ firstDay = parseInt(this._get(inst, "firstDay"),10);
5455
+ firstDay = (isNaN(firstDay) ? 0 : firstDay);
5456
+
5457
+ showWeek = this._get(inst, "showWeek");
5458
+ dayNames = this._get(inst, "dayNames");
5459
+ dayNamesMin = this._get(inst, "dayNamesMin");
5460
+ monthNames = this._get(inst, "monthNames");
5461
+ monthNamesShort = this._get(inst, "monthNamesShort");
5462
+ beforeShowDay = this._get(inst, "beforeShowDay");
5463
+ showOtherMonths = this._get(inst, "showOtherMonths");
5464
+ selectOtherMonths = this._get(inst, "selectOtherMonths");
5465
+ defaultDate = this._getDefaultDate(inst);
5466
+ html = "";
5467
+ dow;
5468
+ for (row = 0; row < numMonths[0]; row++) {
5469
+ group = "";
5470
+ this.maxRows = 4;
5471
+ for (col = 0; col < numMonths[1]; col++) {
5472
+ selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
5473
+ cornerClass = " ui-corner-all";
5474
+ calender = "";
5475
+ if (isMultiMonth) {
5476
+ calender += "<div class='ui-datepicker-group";
5477
+ if (numMonths[1] > 1) {
5478
+ switch (col) {
5479
+ case 0: calender += " ui-datepicker-group-first";
5480
+ cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
5481
+ case numMonths[1]-1: calender += " ui-datepicker-group-last";
5482
+ cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
5483
+ default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
5484
+ }
5485
+ }
5486
+ calender += "'>";
5487
+ }
5488
+ calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
5489
+ (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
5490
+ (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
5491
+ this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
5492
+ row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
5493
+ "</div><table class='ui-datepicker-calendar'><thead>" +
5494
+ "<tr>";
5495
+ thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
5496
+ for (dow = 0; dow < 7; dow++) { // days of the week
5497
+ day = (dow + firstDay) % 7;
5498
+ thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
5499
+ "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
5500
+ }
5501
+ calender += thead + "</tr></thead><tbody>";
5502
+ daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
5503
+ if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
5504
+ inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
5505
+ }
5506
+ leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
5507
+ curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
5508
+ numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
5509
+ this.maxRows = numRows;
5510
+ printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
5511
+ for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
5512
+ calender += "<tr>";
5513
+ tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
5514
+ this._get(inst, "calculateWeek")(printDate) + "</td>");
5515
+ for (dow = 0; dow < 7; dow++) { // create date picker days
5516
+ daySettings = (beforeShowDay ?
5517
+ beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
5518
+ otherMonth = (printDate.getMonth() !== drawMonth);
5519
+ unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
5520
+ (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
5521
+ tbody += "<td class='" +
5522
+ ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
5523
+ (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
5524
+ ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
5525
+ (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
5526
+ // or defaultDate is current printedDate and defaultDate is selectedDate
5527
+ " " + this._dayOverClass : "") + // highlight selected day
5528
+ (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days
5529
+ (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
5530
+ (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
5531
+ (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
5532
+ ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
5533
+ (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
5534
+ (otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
5535
+ (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
5536
+ (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
5537
+ (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
5538
+ (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
5539
+ "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
5540
+ printDate.setDate(printDate.getDate() + 1);
5541
+ printDate = this._daylightSavingAdjust(printDate);
5542
+ }
5543
+ calender += tbody + "</tr>";
5544
+ }
5545
+ drawMonth++;
5546
+ if (drawMonth > 11) {
5547
+ drawMonth = 0;
5548
+ drawYear++;
5549
+ }
5550
+ calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
5551
+ ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
5552
+ group += calender;
5553
+ }
5554
+ html += group;
5555
+ }
5556
+ html += buttonPanel;
5557
+ inst._keyEvent = false;
5558
+ return html;
5559
+ },
5560
+
5561
+ /* Generate the month and year header. */
5562
+ _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
5563
+ secondary, monthNames, monthNamesShort) {
5564
+
5565
+ var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
5566
+ changeMonth = this._get(inst, "changeMonth"),
5567
+ changeYear = this._get(inst, "changeYear"),
5568
+ showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
5569
+ html = "<div class='ui-datepicker-title'>",
5570
+ monthHtml = "";
5571
+
5572
+ // month selection
5573
+ if (secondary || !changeMonth) {
5574
+ monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
5575
+ } else {
5576
+ inMinYear = (minDate && minDate.getFullYear() === drawYear);
5577
+ inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
5578
+ monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
5579
+ for ( month = 0; month < 12; month++) {
5580
+ if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
5581
+ monthHtml += "<option value='" + month + "'" +
5582
+ (month === drawMonth ? " selected='selected'" : "") +
5583
+ ">" + monthNamesShort[month] + "</option>";
5584
+ }
5585
+ }
5586
+ monthHtml += "</select>";
5587
+ }
5588
+
5589
+ if (!showMonthAfterYear) {
5590
+ html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
5591
+ }
5592
+
5593
+ // year selection
5594
+ if ( !inst.yearshtml ) {
5595
+ inst.yearshtml = "";
5596
+ if (secondary || !changeYear) {
5597
+ html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
5598
+ } else {
5599
+ // determine range of years to display
5600
+ years = this._get(inst, "yearRange").split(":");
5601
+ thisYear = new Date().getFullYear();
5602
+ determineYear = function(value) {
5603
+ var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
5604
+ (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
5605
+ parseInt(value, 10)));
5606
+ return (isNaN(year) ? thisYear : year);
5607
+ };
5608
+ year = determineYear(years[0]);
5609
+ endYear = Math.max(year, determineYear(years[1] || ""));
5610
+ year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
5611
+ endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
5612
+ inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
5613
+ for (; year <= endYear; year++) {
5614
+ inst.yearshtml += "<option value='" + year + "'" +
5615
+ (year === drawYear ? " selected='selected'" : "") +
5616
+ ">" + year + "</option>";
5617
+ }
5618
+ inst.yearshtml += "</select>";
5619
+
5620
+ html += inst.yearshtml;
5621
+ inst.yearshtml = null;
5622
+ }
5623
+ }
5624
+
5625
+ html += this._get(inst, "yearSuffix");
5626
+ if (showMonthAfterYear) {
5627
+ html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
5628
+ }
5629
+ html += "</div>"; // Close datepicker_header
5630
+ return html;
5631
+ },
5632
+
5633
+ /* Adjust one of the date sub-fields. */
5634
+ _adjustInstDate: function(inst, offset, period) {
5635
+ var year = inst.drawYear + (period === "Y" ? offset : 0),
5636
+ month = inst.drawMonth + (period === "M" ? offset : 0),
5637
+ day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
5638
+ date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
5639
+
5640
+ inst.selectedDay = date.getDate();
5641
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
5642
+ inst.drawYear = inst.selectedYear = date.getFullYear();
5643
+ if (period === "M" || period === "Y") {
5644
+ this._notifyChange(inst);
5645
+ }
5646
+ },
5647
+
5648
+ /* Ensure a date is within any min/max bounds. */
5649
+ _restrictMinMax: function(inst, date) {
5650
+ var minDate = this._getMinMaxDate(inst, "min"),
5651
+ maxDate = this._getMinMaxDate(inst, "max"),
5652
+ newDate = (minDate && date < minDate ? minDate : date);
5653
+ return (maxDate && newDate > maxDate ? maxDate : newDate);
5654
+ },
5655
+
5656
+ /* Notify change of month/year. */
5657
+ _notifyChange: function(inst) {
5658
+ var onChange = this._get(inst, "onChangeMonthYear");
5659
+ if (onChange) {
5660
+ onChange.apply((inst.input ? inst.input[0] : null),
5661
+ [inst.selectedYear, inst.selectedMonth + 1, inst]);
5662
+ }
5663
+ },
5664
+
5665
+ /* Determine the number of months to show. */
5666
+ _getNumberOfMonths: function(inst) {
5667
+ var numMonths = this._get(inst, "numberOfMonths");
5668
+ return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
5669
+ },
5670
+
5671
+ /* Determine the current maximum date - ensure no time components are set. */
5672
+ _getMinMaxDate: function(inst, minMax) {
5673
+ return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
5674
+ },
5675
+
5676
+ /* Find the number of days in a given month. */
5677
+ _getDaysInMonth: function(year, month) {
5678
+ return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
5679
+ },
5680
+
5681
+ /* Find the day of the week of the first of a month. */
5682
+ _getFirstDayOfMonth: function(year, month) {
5683
+ return new Date(year, month, 1).getDay();
5684
+ },
5685
+
5686
+ /* Determines if we should allow a "next/prev" month display change. */
5687
+ _canAdjustMonth: function(inst, offset, curYear, curMonth) {
5688
+ var numMonths = this._getNumberOfMonths(inst),
5689
+ date = this._daylightSavingAdjust(new Date(curYear,
5690
+ curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
5691
+
5692
+ if (offset < 0) {
5693
+ date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
5694
+ }
5695
+ return this._isInRange(inst, date);
5696
+ },
5697
+
5698
+ /* Is the given date in the accepted range? */
5699
+ _isInRange: function(inst, date) {
5700
+ var yearSplit, currentYear,
5701
+ minDate = this._getMinMaxDate(inst, "min"),
5702
+ maxDate = this._getMinMaxDate(inst, "max"),
5703
+ minYear = null,
5704
+ maxYear = null,
5705
+ years = this._get(inst, "yearRange");
5706
+ if (years){
5707
+ yearSplit = years.split(":");
5708
+ currentYear = new Date().getFullYear();
5709
+ minYear = parseInt(yearSplit[0], 10);
5710
+ maxYear = parseInt(yearSplit[1], 10);
5711
+ if ( yearSplit[0].match(/[+\-].*/) ) {
5712
+ minYear += currentYear;
5713
+ }
5714
+ if ( yearSplit[1].match(/[+\-].*/) ) {
5715
+ maxYear += currentYear;
5716
+ }
5717
+ }
5718
+
5719
+ return ((!minDate || date.getTime() >= minDate.getTime()) &&
5720
+ (!maxDate || date.getTime() <= maxDate.getTime()) &&
5721
+ (!minYear || date.getFullYear() >= minYear) &&
5722
+ (!maxYear || date.getFullYear() <= maxYear));
5723
+ },
5724
+
5725
+ /* Provide the configuration settings for formatting/parsing. */
5726
+ _getFormatConfig: function(inst) {
5727
+ var shortYearCutoff = this._get(inst, "shortYearCutoff");
5728
+ shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
5729
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
5730
+ return {shortYearCutoff: shortYearCutoff,
5731
+ dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
5732
+ monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
5733
+ },
5734
+
5735
+ /* Format the given date for display. */
5736
+ _formatDate: function(inst, day, month, year) {
5737
+ if (!day) {
5738
+ inst.currentDay = inst.selectedDay;
5739
+ inst.currentMonth = inst.selectedMonth;
5740
+ inst.currentYear = inst.selectedYear;
5741
+ }
5742
+ var date = (day ? (typeof day === "object" ? day :
5743
+ this._daylightSavingAdjust(new Date(year, month, day))) :
5744
+ this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
5745
+ return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
5746
+ }
5747
+ });
5748
+
5749
+ /*
5750
+ * Bind hover events for datepicker elements.
5751
+ * Done via delegate so the binding only occurs once in the lifetime of the parent div.
5752
+ * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
5753
+ */
5754
+ function datepicker_bindHover(dpDiv) {
5755
+ var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
5756
+ return dpDiv.delegate(selector, "mouseout", function() {
5757
+ $(this).removeClass("ui-state-hover");
5758
+ if (this.className.indexOf("ui-datepicker-prev") !== -1) {
5759
+ $(this).removeClass("ui-datepicker-prev-hover");
5760
+ }
5761
+ if (this.className.indexOf("ui-datepicker-next") !== -1) {
5762
+ $(this).removeClass("ui-datepicker-next-hover");
5763
+ }
5764
+ })
5765
+ .delegate( selector, "mouseover", datepicker_handleMouseover );
5766
+ }
5767
+
5768
+ function datepicker_handleMouseover() {
5769
+ if (!$.datepicker._isDisabledDatepicker( datepicker_instActive.inline? datepicker_instActive.dpDiv.parent()[0] : datepicker_instActive.input[0])) {
5770
+ $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
5771
+ $(this).addClass("ui-state-hover");
5772
+ if (this.className.indexOf("ui-datepicker-prev") !== -1) {
5773
+ $(this).addClass("ui-datepicker-prev-hover");
5774
+ }
5775
+ if (this.className.indexOf("ui-datepicker-next") !== -1) {
5776
+ $(this).addClass("ui-datepicker-next-hover");
5777
+ }
5778
+ }
5779
+ }
5780
+
5781
+ /* jQuery extend now ignores nulls! */
5782
+ function datepicker_extendRemove(target, props) {
5783
+ $.extend(target, props);
5784
+ for (var name in props) {
5785
+ if (props[name] == null) {
5786
+ target[name] = props[name];
5787
+ }
5788
+ }
5789
+ return target;
5790
+ }
5791
+
5792
+ /* Invoke the datepicker functionality.
5793
+ @param options string - a command, optionally followed by additional parameters or
5794
+ Object - settings for attaching new datepicker functionality
5795
+ @return jQuery object */
5796
+ $.fn.datepicker = function(options){
5797
+
5798
+ /* Verify an empty collection wasn't passed - Fixes #6976 */
5799
+ if ( !this.length ) {
5800
+ return this;
5801
+ }
5802
+
5803
+ /* Initialise the date picker. */
5804
+ if (!$.datepicker.initialized) {
5805
+ $(document).mousedown($.datepicker._checkExternalClick);
5806
+ $.datepicker.initialized = true;
5807
+ }
5808
+
5809
+ /* Append datepicker main container to body if not exist. */
5810
+ if ($("#"+$.datepicker._mainDivId).length === 0) {
5811
+ $("body").append($.datepicker.dpDiv);
5812
+ }
5813
+
5814
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
5815
+ if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
5816
+ return $.datepicker["_" + options + "Datepicker"].
5817
+ apply($.datepicker, [this[0]].concat(otherArgs));
5818
+ }
5819
+ if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
5820
+ return $.datepicker["_" + options + "Datepicker"].
5821
+ apply($.datepicker, [this[0]].concat(otherArgs));
5822
+ }
5823
+ return this.each(function() {
5824
+ typeof options === "string" ?
5825
+ $.datepicker["_" + options + "Datepicker"].
5826
+ apply($.datepicker, [this].concat(otherArgs)) :
5827
+ $.datepicker._attachDatepicker(this, options);
5828
+ });
5829
+ };
5830
+
5831
+ $.datepicker = new Datepicker(); // singleton instance
5832
+ $.datepicker.initialized = false;
5833
+ $.datepicker.uuid = new Date().getTime();
5834
+ $.datepicker.version = "1.11.4";
5835
+
5836
+ var datepicker = $.datepicker;
5837
+
5838
+
5839
+ /*!
5840
+ * jQuery UI Draggable 1.11.4
5841
+ * http://jqueryui.com
5842
+ *
5843
+ * Copyright jQuery Foundation and other contributors
5844
+ * Released under the MIT license.
5845
+ * http://jquery.org/license
5846
+ *
5847
+ * http://api.jqueryui.com/draggable/
5848
+ */
5849
+
5850
+
5851
+ $.widget("ui.draggable", $.ui.mouse, {
5852
+ version: "1.11.4",
5853
+ widgetEventPrefix: "drag",
5854
+ options: {
5855
+ addClasses: true,
5856
+ appendTo: "parent",
5857
+ axis: false,
5858
+ connectToSortable: false,
5859
+ containment: false,
5860
+ cursor: "auto",
5861
+ cursorAt: false,
5862
+ grid: false,
5863
+ handle: false,
5864
+ helper: "original",
5865
+ iframeFix: false,
5866
+ opacity: false,
5867
+ refreshPositions: false,
5868
+ revert: false,
5869
+ revertDuration: 500,
5870
+ scope: "default",
5871
+ scroll: true,
5872
+ scrollSensitivity: 20,
5873
+ scrollSpeed: 20,
5874
+ snap: false,
5875
+ snapMode: "both",
5876
+ snapTolerance: 20,
5877
+ stack: false,
5878
+ zIndex: false,
5879
+
5880
+ // callbacks
5881
+ drag: null,
5882
+ start: null,
5883
+ stop: null
5884
+ },
5885
+ _create: function() {
5886
+
5887
+ if ( this.options.helper === "original" ) {
5888
+ this._setPositionRelative();
5889
+ }
5890
+ if (this.options.addClasses){
5891
+ this.element.addClass("ui-draggable");
5892
+ }
5893
+ if (this.options.disabled){
5894
+ this.element.addClass("ui-draggable-disabled");
5895
+ }
5896
+ this._setHandleClassName();
5897
+
5898
+ this._mouseInit();
5899
+ },
5900
+
5901
+ _setOption: function( key, value ) {
5902
+ this._super( key, value );
5903
+ if ( key === "handle" ) {
5904
+ this._removeHandleClassName();
5905
+ this._setHandleClassName();
5906
+ }
5907
+ },
5908
+
5909
+ _destroy: function() {
5910
+ if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
5911
+ this.destroyOnClear = true;
5912
+ return;
5913
+ }
5914
+ this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
5915
+ this._removeHandleClassName();
5916
+ this._mouseDestroy();
5917
+ },
5918
+
5919
+ _mouseCapture: function(event) {
5920
+ var o = this.options;
5921
+
5922
+ this._blurActiveElement( event );
5923
+
5924
+ // among others, prevent a drag on a resizable-handle
5925
+ if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
5926
+ return false;
5927
+ }
5928
+
5929
+ //Quit if we're not on a valid handle
5930
+ this.handle = this._getHandle(event);
5931
+ if (!this.handle) {
5932
+ return false;
5933
+ }
5934
+
5935
+ this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
5936
+
5937
+ return true;
5938
+
5939
+ },
5940
+
5941
+ _blockFrames: function( selector ) {
5942
+ this.iframeBlocks = this.document.find( selector ).map(function() {
5943
+ var iframe = $( this );
5944
+
5945
+ return $( "<div>" )
5946
+ .css( "position", "absolute" )
5947
+ .appendTo( iframe.parent() )
5948
+ .outerWidth( iframe.outerWidth() )
5949
+ .outerHeight( iframe.outerHeight() )
5950
+ .offset( iframe.offset() )[ 0 ];
5951
+ });
5952
+ },
5953
+
5954
+ _unblockFrames: function() {
5955
+ if ( this.iframeBlocks ) {
5956
+ this.iframeBlocks.remove();
5957
+ delete this.iframeBlocks;
5958
+ }
5959
+ },
5960
+
5961
+ _blurActiveElement: function( event ) {
5962
+ var document = this.document[ 0 ];
5963
+
5964
+ // Only need to blur if the event occurred on the draggable itself, see #10527
5965
+ if ( !this.handleElement.is( event.target ) ) {
5966
+ return;
5967
+ }
5968
+
5969
+ // support: IE9
5970
+ // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
5971
+ try {
5972
+
5973
+ // Support: IE9, IE10
5974
+ // If the <body> is blurred, IE will switch windows, see #9520
5975
+ if ( document.activeElement && document.activeElement.nodeName.toLowerCase() !== "body" ) {
5976
+
5977
+ // Blur any element that currently has focus, see #4261
5978
+ $( document.activeElement ).blur();
5979
+ }
5980
+ } catch ( error ) {}
5981
+ },
5982
+
5983
+ _mouseStart: function(event) {
5984
+
5985
+ var o = this.options;
5986
+
5987
+ //Create and append the visible helper
5988
+ this.helper = this._createHelper(event);
5989
+
5990
+ this.helper.addClass("ui-draggable-dragging");
5991
+
5992
+ //Cache the helper size
5993
+ this._cacheHelperProportions();
5994
+
5995
+ //If ddmanager is used for droppables, set the global draggable
5996
+ if ($.ui.ddmanager) {
5997
+ $.ui.ddmanager.current = this;
5998
+ }
5999
+
6000
+ /*
6001
+ * - Position generation -
6002
+ * This block generates everything position related - it's the core of draggables.
6003
+ */
6004
+
6005
+ //Cache the margins of the original element
6006
+ this._cacheMargins();
6007
+
6008
+ //Store the helper's css position
6009
+ this.cssPosition = this.helper.css( "position" );
6010
+ this.scrollParent = this.helper.scrollParent( true );
6011
+ this.offsetParent = this.helper.offsetParent();
6012
+ this.hasFixedAncestor = this.helper.parents().filter(function() {
6013
+ return $( this ).css( "position" ) === "fixed";
6014
+ }).length > 0;
6015
+
6016
+ //The element's absolute position on the page minus margins
6017
+ this.positionAbs = this.element.offset();
6018
+ this._refreshOffsets( event );
6019
+
6020
+ //Generate the original position
6021
+ this.originalPosition = this.position = this._generatePosition( event, false );
6022
+ this.originalPageX = event.pageX;
6023
+ this.originalPageY = event.pageY;
6024
+
6025
+ //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
6026
+ (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
6027
+
6028
+ //Set a containment if given in the options
6029
+ this._setContainment();
6030
+
6031
+ //Trigger event + callbacks
6032
+ if (this._trigger("start", event) === false) {
6033
+ this._clear();
6034
+ return false;
6035
+ }
6036
+
6037
+ //Recache the helper size
6038
+ this._cacheHelperProportions();
6039
+
6040
+ //Prepare the droppable offsets
6041
+ if ($.ui.ddmanager && !o.dropBehaviour) {
6042
+ $.ui.ddmanager.prepareOffsets(this, event);
6043
+ }
6044
+
6045
+ // Reset helper's right/bottom css if they're set and set explicit width/height instead
6046
+ // as this prevents resizing of elements with right/bottom set (see #7772)
6047
+ this._normalizeRightBottom();
6048
+
6049
+ this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
6050
+
6051
+ //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
6052
+ if ( $.ui.ddmanager ) {
6053
+ $.ui.ddmanager.dragStart(this, event);
6054
+ }
6055
+
6056
+ return true;
6057
+ },
6058
+
6059
+ _refreshOffsets: function( event ) {
6060
+ this.offset = {
6061
+ top: this.positionAbs.top - this.margins.top,
6062
+ left: this.positionAbs.left - this.margins.left,
6063
+ scroll: false,
6064
+ parent: this._getParentOffset(),
6065
+ relative: this._getRelativeOffset()
6066
+ };
6067
+
6068
+ this.offset.click = {
6069
+ left: event.pageX - this.offset.left,
6070
+ top: event.pageY - this.offset.top
6071
+ };
6072
+ },
6073
+
6074
+ _mouseDrag: function(event, noPropagation) {
6075
+ // reset any necessary cached properties (see #5009)
6076
+ if ( this.hasFixedAncestor ) {
6077
+ this.offset.parent = this._getParentOffset();
6078
+ }
6079
+
6080
+ //Compute the helpers position
6081
+ this.position = this._generatePosition( event, true );
6082
+ this.positionAbs = this._convertPositionTo("absolute");
6083
+
6084
+ //Call plugins and callbacks and use the resulting position if something is returned
6085
+ if (!noPropagation) {
6086
+ var ui = this._uiHash();
6087
+ if (this._trigger("drag", event, ui) === false) {
6088
+ this._mouseUp({});
6089
+ return false;
6090
+ }
6091
+ this.position = ui.position;
6092
+ }
6093
+
6094
+ this.helper[ 0 ].style.left = this.position.left + "px";
6095
+ this.helper[ 0 ].style.top = this.position.top + "px";
6096
+
6097
+ if ($.ui.ddmanager) {
6098
+ $.ui.ddmanager.drag(this, event);
6099
+ }
6100
+
6101
+ return false;
6102
+ },
6103
+
6104
+ _mouseStop: function(event) {
6105
+
6106
+ //If we are using droppables, inform the manager about the drop
6107
+ var that = this,
6108
+ dropped = false;
6109
+ if ($.ui.ddmanager && !this.options.dropBehaviour) {
6110
+ dropped = $.ui.ddmanager.drop(this, event);
6111
+ }
6112
+
6113
+ //if a drop comes from outside (a sortable)
6114
+ if (this.dropped) {
6115
+ dropped = this.dropped;
6116
+ this.dropped = false;
6117
+ }
6118
+
6119
+ if ((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
6120
+ $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
6121
+ if (that._trigger("stop", event) !== false) {
6122
+ that._clear();
6123
+ }
6124
+ });
6125
+ } else {
6126
+ if (this._trigger("stop", event) !== false) {
6127
+ this._clear();
6128
+ }
6129
+ }
6130
+
6131
+ return false;
6132
+ },
6133
+
6134
+ _mouseUp: function( event ) {
6135
+ this._unblockFrames();
6136
+
6137
+ //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
6138
+ if ( $.ui.ddmanager ) {
6139
+ $.ui.ddmanager.dragStop(this, event);
6140
+ }
6141
+
6142
+ // Only need to focus if the event occurred on the draggable itself, see #10527
6143
+ if ( this.handleElement.is( event.target ) ) {
6144
+ // The interaction is over; whether or not the click resulted in a drag, focus the element
6145
+ this.element.focus();
6146
+ }
6147
+
6148
+ return $.ui.mouse.prototype._mouseUp.call(this, event);
6149
+ },
6150
+
6151
+ cancel: function() {
6152
+
6153
+ if (this.helper.is(".ui-draggable-dragging")) {
6154
+ this._mouseUp({});
6155
+ } else {
6156
+ this._clear();
6157
+ }
6158
+
6159
+ return this;
6160
+
6161
+ },
6162
+
6163
+ _getHandle: function(event) {
6164
+ return this.options.handle ?
6165
+ !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
6166
+ true;
6167
+ },
6168
+
6169
+ _setHandleClassName: function() {
6170
+ this.handleElement = this.options.handle ?
6171
+ this.element.find( this.options.handle ) : this.element;
6172
+ this.handleElement.addClass( "ui-draggable-handle" );
6173
+ },
6174
+
6175
+ _removeHandleClassName: function() {
6176
+ this.handleElement.removeClass( "ui-draggable-handle" );
6177
+ },
6178
+
6179
+ _createHelper: function(event) {
6180
+
6181
+ var o = this.options,
6182
+ helperIsFunction = $.isFunction( o.helper ),
6183
+ helper = helperIsFunction ?
6184
+ $( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
6185
+ ( o.helper === "clone" ?
6186
+ this.element.clone().removeAttr( "id" ) :
6187
+ this.element );
6188
+
6189
+ if (!helper.parents("body").length) {
6190
+ helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
6191
+ }
6192
+
6193
+ // http://bugs.jqueryui.com/ticket/9446
6194
+ // a helper function can return the original element
6195
+ // which wouldn't have been set to relative in _create
6196
+ if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
6197
+ this._setPositionRelative();
6198
+ }
6199
+
6200
+ if (helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
6201
+ helper.css("position", "absolute");
6202
+ }
6203
+
6204
+ return helper;
6205
+
6206
+ },
6207
+
6208
+ _setPositionRelative: function() {
6209
+ if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
6210
+ this.element[ 0 ].style.position = "relative";
6211
+ }
6212
+ },
6213
+
6214
+ _adjustOffsetFromHelper: function(obj) {
6215
+ if (typeof obj === "string") {
6216
+ obj = obj.split(" ");
6217
+ }
6218
+ if ($.isArray(obj)) {
6219
+ obj = { left: +obj[0], top: +obj[1] || 0 };
6220
+ }
6221
+ if ("left" in obj) {
6222
+ this.offset.click.left = obj.left + this.margins.left;
6223
+ }
6224
+ if ("right" in obj) {
6225
+ this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
6226
+ }
6227
+ if ("top" in obj) {
6228
+ this.offset.click.top = obj.top + this.margins.top;
6229
+ }
6230
+ if ("bottom" in obj) {
6231
+ this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
6232
+ }
6233
+ },
6234
+
6235
+ _isRootNode: function( element ) {
6236
+ return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
6237
+ },
6238
+
6239
+ _getParentOffset: function() {
6240
+
6241
+ //Get the offsetParent and cache its position
6242
+ var po = this.offsetParent.offset(),
6243
+ document = this.document[ 0 ];
6244
+
6245
+ // This is a special case where we need to modify a offset calculated on start, since the following happened:
6246
+ // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
6247
+ // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
6248
+ // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
6249
+ if (this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
6250
+ po.left += this.scrollParent.scrollLeft();
6251
+ po.top += this.scrollParent.scrollTop();
6252
+ }
6253
+
6254
+ if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
6255
+ po = { top: 0, left: 0 };
6256
+ }
6257
+
6258
+ return {
6259
+ top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
6260
+ left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
6261
+ };
6262
+
6263
+ },
6264
+
6265
+ _getRelativeOffset: function() {
6266
+ if ( this.cssPosition !== "relative" ) {
6267
+ return { top: 0, left: 0 };
6268
+ }
6269
+
6270
+ var p = this.element.position(),
6271
+ scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
6272
+
6273
+ return {
6274
+ top: p.top - ( parseInt(this.helper.css( "top" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
6275
+ left: p.left - ( parseInt(this.helper.css( "left" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
6276
+ };
6277
+
6278
+ },
6279
+
6280
+ _cacheMargins: function() {
6281
+ this.margins = {
6282
+ left: (parseInt(this.element.css("marginLeft"), 10) || 0),
6283
+ top: (parseInt(this.element.css("marginTop"), 10) || 0),
6284
+ right: (parseInt(this.element.css("marginRight"), 10) || 0),
6285
+ bottom: (parseInt(this.element.css("marginBottom"), 10) || 0)
6286
+ };
6287
+ },
6288
+
6289
+ _cacheHelperProportions: function() {
6290
+ this.helperProportions = {
6291
+ width: this.helper.outerWidth(),
6292
+ height: this.helper.outerHeight()
6293
+ };
6294
+ },
6295
+
6296
+ _setContainment: function() {
6297
+
6298
+ var isUserScrollable, c, ce,
6299
+ o = this.options,
6300
+ document = this.document[ 0 ];
6301
+
6302
+ this.relativeContainer = null;
6303
+
6304
+ if ( !o.containment ) {
6305
+ this.containment = null;
6306
+ return;
6307
+ }
6308
+
6309
+ if ( o.containment === "window" ) {
6310
+ this.containment = [
6311
+ $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
6312
+ $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
6313
+ $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
6314
+ $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
6315
+ ];
6316
+ return;
6317
+ }
6318
+
6319
+ if ( o.containment === "document") {
6320
+ this.containment = [
6321
+ 0,
6322
+ 0,
6323
+ $( document ).width() - this.helperProportions.width - this.margins.left,
6324
+ ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
6325
+ ];
6326
+ return;
6327
+ }
6328
+
6329
+ if ( o.containment.constructor === Array ) {
6330
+ this.containment = o.containment;
6331
+ return;
6332
+ }
6333
+
6334
+ if ( o.containment === "parent" ) {
6335
+ o.containment = this.helper[ 0 ].parentNode;
6336
+ }
6337
+
6338
+ c = $( o.containment );
6339
+ ce = c[ 0 ];
6340
+
6341
+ if ( !ce ) {
6342
+ return;
6343
+ }
6344
+
6345
+ isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
6346
+
6347
+ this.containment = [
6348
+ ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
6349
+ ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
6350
+ ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
6351
+ ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
6352
+ ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
6353
+ this.helperProportions.width -
6354
+ this.margins.left -
6355
+ this.margins.right,
6356
+ ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
6357
+ ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
6358
+ ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
6359
+ this.helperProportions.height -
6360
+ this.margins.top -
6361
+ this.margins.bottom
6362
+ ];
6363
+ this.relativeContainer = c;
6364
+ },
6365
+
6366
+ _convertPositionTo: function(d, pos) {
6367
+
6368
+ if (!pos) {
6369
+ pos = this.position;
6370
+ }
6371
+
6372
+ var mod = d === "absolute" ? 1 : -1,
6373
+ scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
6374
+
6375
+ return {
6376
+ top: (
6377
+ pos.top + // The absolute mouse position
6378
+ this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
6379
+ this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
6380
+ ( ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod)
6381
+ ),
6382
+ left: (
6383
+ pos.left + // The absolute mouse position
6384
+ this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
6385
+ this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
6386
+ ( ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod)
6387
+ )
6388
+ };
6389
+
6390
+ },
6391
+
6392
+ _generatePosition: function( event, constrainPosition ) {
6393
+
6394
+ var containment, co, top, left,
6395
+ o = this.options,
6396
+ scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
6397
+ pageX = event.pageX,
6398
+ pageY = event.pageY;
6399
+
6400
+ // Cache the scroll
6401
+ if ( !scrollIsRootNode || !this.offset.scroll ) {
6402
+ this.offset.scroll = {
6403
+ top: this.scrollParent.scrollTop(),
6404
+ left: this.scrollParent.scrollLeft()
6405
+ };
6406
+ }
6407
+
6408
+ /*
6409
+ * - Position constraining -
6410
+ * Constrain the position to a mix of grid, containment.
6411
+ */
6412
+
6413
+ // If we are not dragging yet, we won't check for options
6414
+ if ( constrainPosition ) {
6415
+ if ( this.containment ) {
6416
+ if ( this.relativeContainer ){
6417
+ co = this.relativeContainer.offset();
6418
+ containment = [
6419
+ this.containment[ 0 ] + co.left,
6420
+ this.containment[ 1 ] + co.top,
6421
+ this.containment[ 2 ] + co.left,
6422
+ this.containment[ 3 ] + co.top
6423
+ ];
6424
+ } else {
6425
+ containment = this.containment;
6426
+ }
6427
+
6428
+ if (event.pageX - this.offset.click.left < containment[0]) {
6429
+ pageX = containment[0] + this.offset.click.left;
6430
+ }
6431
+ if (event.pageY - this.offset.click.top < containment[1]) {
6432
+ pageY = containment[1] + this.offset.click.top;
6433
+ }
6434
+ if (event.pageX - this.offset.click.left > containment[2]) {
6435
+ pageX = containment[2] + this.offset.click.left;
6436
+ }
6437
+ if (event.pageY - this.offset.click.top > containment[3]) {
6438
+ pageY = containment[3] + this.offset.click.top;
6439
+ }
6440
+ }
6441
+
6442
+ if (o.grid) {
6443
+ //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
6444
+ top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
6445
+ pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
6446
+
6447
+ left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
6448
+ pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
6449
+ }
6450
+
6451
+ if ( o.axis === "y" ) {
6452
+ pageX = this.originalPageX;
6453
+ }
6454
+
6455
+ if ( o.axis === "x" ) {
6456
+ pageY = this.originalPageY;
6457
+ }
6458
+ }
6459
+
6460
+ return {
6461
+ top: (
6462
+ pageY - // The absolute mouse position
6463
+ this.offset.click.top - // Click offset (relative to the element)
6464
+ this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
6465
+ this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
6466
+ ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
6467
+ ),
6468
+ left: (
6469
+ pageX - // The absolute mouse position
6470
+ this.offset.click.left - // Click offset (relative to the element)
6471
+ this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
6472
+ this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
6473
+ ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
6474
+ )
6475
+ };
6476
+
6477
+ },
6478
+
6479
+ _clear: function() {
6480
+ this.helper.removeClass("ui-draggable-dragging");
6481
+ if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
6482
+ this.helper.remove();
6483
+ }
6484
+ this.helper = null;
6485
+ this.cancelHelperRemoval = false;
6486
+ if ( this.destroyOnClear ) {
6487
+ this.destroy();
6488
+ }
6489
+ },
6490
+
6491
+ _normalizeRightBottom: function() {
6492
+ if ( this.options.axis !== "y" && this.helper.css( "right" ) !== "auto" ) {
6493
+ this.helper.width( this.helper.width() );
6494
+ this.helper.css( "right", "auto" );
6495
+ }
6496
+ if ( this.options.axis !== "x" && this.helper.css( "bottom" ) !== "auto" ) {
6497
+ this.helper.height( this.helper.height() );
6498
+ this.helper.css( "bottom", "auto" );
6499
+ }
6500
+ },
6501
+
6502
+ // From now on bulk stuff - mainly helpers
6503
+
6504
+ _trigger: function( type, event, ui ) {
6505
+ ui = ui || this._uiHash();
6506
+ $.ui.plugin.call( this, type, [ event, ui, this ], true );
6507
+
6508
+ // Absolute position and offset (see #6884 ) have to be recalculated after plugins
6509
+ if ( /^(drag|start|stop)/.test( type ) ) {
6510
+ this.positionAbs = this._convertPositionTo( "absolute" );
6511
+ ui.offset = this.positionAbs;
6512
+ }
6513
+ return $.Widget.prototype._trigger.call( this, type, event, ui );
6514
+ },
6515
+
6516
+ plugins: {},
6517
+
6518
+ _uiHash: function() {
6519
+ return {
6520
+ helper: this.helper,
6521
+ position: this.position,
6522
+ originalPosition: this.originalPosition,
6523
+ offset: this.positionAbs
6524
+ };
6525
+ }
6526
+
6527
+ });
6528
+
6529
+ $.ui.plugin.add( "draggable", "connectToSortable", {
6530
+ start: function( event, ui, draggable ) {
6531
+ var uiSortable = $.extend( {}, ui, {
6532
+ item: draggable.element
6533
+ });
6534
+
6535
+ draggable.sortables = [];
6536
+ $( draggable.options.connectToSortable ).each(function() {
6537
+ var sortable = $( this ).sortable( "instance" );
6538
+
6539
+ if ( sortable && !sortable.options.disabled ) {
6540
+ draggable.sortables.push( sortable );
6541
+
6542
+ // refreshPositions is called at drag start to refresh the containerCache
6543
+ // which is used in drag. This ensures it's initialized and synchronized
6544
+ // with any changes that might have happened on the page since initialization.
6545
+ sortable.refreshPositions();
6546
+ sortable._trigger("activate", event, uiSortable);
6547
+ }
6548
+ });
6549
+ },
6550
+ stop: function( event, ui, draggable ) {
6551
+ var uiSortable = $.extend( {}, ui, {
6552
+ item: draggable.element
6553
+ });
6554
+
6555
+ draggable.cancelHelperRemoval = false;
6556
+
6557
+ $.each( draggable.sortables, function() {
6558
+ var sortable = this;
6559
+
6560
+ if ( sortable.isOver ) {
6561
+ sortable.isOver = 0;
6562
+
6563
+ // Allow this sortable to handle removing the helper
6564
+ draggable.cancelHelperRemoval = true;
6565
+ sortable.cancelHelperRemoval = false;
6566
+
6567
+ // Use _storedCSS To restore properties in the sortable,
6568
+ // as this also handles revert (#9675) since the draggable
6569
+ // may have modified them in unexpected ways (#8809)
6570
+ sortable._storedCSS = {
6571
+ position: sortable.placeholder.css( "position" ),
6572
+ top: sortable.placeholder.css( "top" ),
6573
+ left: sortable.placeholder.css( "left" )
6574
+ };
6575
+
6576
+ sortable._mouseStop(event);
6577
+
6578
+ // Once drag has ended, the sortable should return to using
6579
+ // its original helper, not the shared helper from draggable
6580
+ sortable.options.helper = sortable.options._helper;
6581
+ } else {
6582
+ // Prevent this Sortable from removing the helper.
6583
+ // However, don't set the draggable to remove the helper
6584
+ // either as another connected Sortable may yet handle the removal.
6585
+ sortable.cancelHelperRemoval = true;
6586
+
6587
+ sortable._trigger( "deactivate", event, uiSortable );
6588
+ }
6589
+ });
6590
+ },
6591
+ drag: function( event, ui, draggable ) {
6592
+ $.each( draggable.sortables, function() {
6593
+ var innermostIntersecting = false,
6594
+ sortable = this;
6595
+
6596
+ // Copy over variables that sortable's _intersectsWith uses
6597
+ sortable.positionAbs = draggable.positionAbs;
6598
+ sortable.helperProportions = draggable.helperProportions;
6599
+ sortable.offset.click = draggable.offset.click;
6600
+
6601
+ if ( sortable._intersectsWith( sortable.containerCache ) ) {
6602
+ innermostIntersecting = true;
6603
+
6604
+ $.each( draggable.sortables, function() {
6605
+ // Copy over variables that sortable's _intersectsWith uses
6606
+ this.positionAbs = draggable.positionAbs;
6607
+ this.helperProportions = draggable.helperProportions;
6608
+ this.offset.click = draggable.offset.click;
6609
+
6610
+ if ( this !== sortable &&
6611
+ this._intersectsWith( this.containerCache ) &&
6612
+ $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
6613
+ innermostIntersecting = false;
6614
+ }
6615
+
6616
+ return innermostIntersecting;
6617
+ });
6618
+ }
6619
+
6620
+ if ( innermostIntersecting ) {
6621
+ // If it intersects, we use a little isOver variable and set it once,
6622
+ // so that the move-in stuff gets fired only once.
6623
+ if ( !sortable.isOver ) {
6624
+ sortable.isOver = 1;
6625
+
6626
+ // Store draggable's parent in case we need to reappend to it later.
6627
+ draggable._parent = ui.helper.parent();
6628
+
6629
+ sortable.currentItem = ui.helper
6630
+ .appendTo( sortable.element )
6631
+ .data( "ui-sortable-item", true );
6632
+
6633
+ // Store helper option to later restore it
6634
+ sortable.options._helper = sortable.options.helper;
6635
+
6636
+ sortable.options.helper = function() {
6637
+ return ui.helper[ 0 ];
6638
+ };
6639
+
6640
+ // Fire the start events of the sortable with our passed browser event,
6641
+ // and our own helper (so it doesn't create a new one)
6642
+ event.target = sortable.currentItem[ 0 ];
6643
+ sortable._mouseCapture( event, true );
6644
+ sortable._mouseStart( event, true, true );
6645
+
6646
+ // Because the browser event is way off the new appended portlet,
6647
+ // modify necessary variables to reflect the changes
6648
+ sortable.offset.click.top = draggable.offset.click.top;
6649
+ sortable.offset.click.left = draggable.offset.click.left;
6650
+ sortable.offset.parent.left -= draggable.offset.parent.left -
6651
+ sortable.offset.parent.left;
6652
+ sortable.offset.parent.top -= draggable.offset.parent.top -
6653
+ sortable.offset.parent.top;
6654
+
6655
+ draggable._trigger( "toSortable", event );
6656
+
6657
+ // Inform draggable that the helper is in a valid drop zone,
6658
+ // used solely in the revert option to handle "valid/invalid".
6659
+ draggable.dropped = sortable.element;
6660
+
6661
+ // Need to refreshPositions of all sortables in the case that
6662
+ // adding to one sortable changes the location of the other sortables (#9675)
6663
+ $.each( draggable.sortables, function() {
6664
+ this.refreshPositions();
6665
+ });
6666
+
6667
+ // hack so receive/update callbacks work (mostly)
6668
+ draggable.currentItem = draggable.element;
6669
+ sortable.fromOutside = draggable;
6670
+ }
6671
+
6672
+ if ( sortable.currentItem ) {
6673
+ sortable._mouseDrag( event );
6674
+ // Copy the sortable's position because the draggable's can potentially reflect
6675
+ // a relative position, while sortable is always absolute, which the dragged
6676
+ // element has now become. (#8809)
6677
+ ui.position = sortable.position;
6678
+ }
6679
+ } else {
6680
+ // If it doesn't intersect with the sortable, and it intersected before,
6681
+ // we fake the drag stop of the sortable, but make sure it doesn't remove
6682
+ // the helper by using cancelHelperRemoval.
6683
+ if ( sortable.isOver ) {
6684
+
6685
+ sortable.isOver = 0;
6686
+ sortable.cancelHelperRemoval = true;
6687
+
6688
+ // Calling sortable's mouseStop would trigger a revert,
6689
+ // so revert must be temporarily false until after mouseStop is called.
6690
+ sortable.options._revert = sortable.options.revert;
6691
+ sortable.options.revert = false;
6692
+
6693
+ sortable._trigger( "out", event, sortable._uiHash( sortable ) );
6694
+ sortable._mouseStop( event, true );
6695
+
6696
+ // restore sortable behaviors that were modfied
6697
+ // when the draggable entered the sortable area (#9481)
6698
+ sortable.options.revert = sortable.options._revert;
6699
+ sortable.options.helper = sortable.options._helper;
6700
+
6701
+ if ( sortable.placeholder ) {
6702
+ sortable.placeholder.remove();
6703
+ }
6704
+
6705
+ // Restore and recalculate the draggable's offset considering the sortable
6706
+ // may have modified them in unexpected ways. (#8809, #10669)
6707
+ ui.helper.appendTo( draggable._parent );
6708
+ draggable._refreshOffsets( event );
6709
+ ui.position = draggable._generatePosition( event, true );
6710
+
6711
+ draggable._trigger( "fromSortable", event );
6712
+
6713
+ // Inform draggable that the helper is no longer in a valid drop zone
6714
+ draggable.dropped = false;
6715
+
6716
+ // Need to refreshPositions of all sortables just in case removing
6717
+ // from one sortable changes the location of other sortables (#9675)
6718
+ $.each( draggable.sortables, function() {
6719
+ this.refreshPositions();
6720
+ });
6721
+ }
6722
+ }
6723
+ });
6724
+ }
6725
+ });
6726
+
6727
+ $.ui.plugin.add("draggable", "cursor", {
6728
+ start: function( event, ui, instance ) {
6729
+ var t = $( "body" ),
6730
+ o = instance.options;
6731
+
6732
+ if (t.css("cursor")) {
6733
+ o._cursor = t.css("cursor");
6734
+ }
6735
+ t.css("cursor", o.cursor);
6736
+ },
6737
+ stop: function( event, ui, instance ) {
6738
+ var o = instance.options;
6739
+ if (o._cursor) {
6740
+ $("body").css("cursor", o._cursor);
6741
+ }
6742
+ }
6743
+ });
6744
+
6745
+ $.ui.plugin.add("draggable", "opacity", {
6746
+ start: function( event, ui, instance ) {
6747
+ var t = $( ui.helper ),
6748
+ o = instance.options;
6749
+ if (t.css("opacity")) {
6750
+ o._opacity = t.css("opacity");
6751
+ }
6752
+ t.css("opacity", o.opacity);
6753
+ },
6754
+ stop: function( event, ui, instance ) {
6755
+ var o = instance.options;
6756
+ if (o._opacity) {
6757
+ $(ui.helper).css("opacity", o._opacity);
6758
+ }
6759
+ }
6760
+ });
6761
+
6762
+ $.ui.plugin.add("draggable", "scroll", {
6763
+ start: function( event, ui, i ) {
6764
+ if ( !i.scrollParentNotHidden ) {
6765
+ i.scrollParentNotHidden = i.helper.scrollParent( false );
6766
+ }
6767
+
6768
+ if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
6769
+ i.overflowOffset = i.scrollParentNotHidden.offset();
6770
+ }
6771
+ },
6772
+ drag: function( event, ui, i ) {
6773
+
6774
+ var o = i.options,
6775
+ scrolled = false,
6776
+ scrollParent = i.scrollParentNotHidden[ 0 ],
6777
+ document = i.document[ 0 ];
6778
+
6779
+ if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
6780
+ if ( !o.axis || o.axis !== "x" ) {
6781
+ if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < o.scrollSensitivity ) {
6782
+ scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
6783
+ } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
6784
+ scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
6785
+ }
6786
+ }
6787
+
6788
+ if ( !o.axis || o.axis !== "y" ) {
6789
+ if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < o.scrollSensitivity ) {
6790
+ scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
6791
+ } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
6792
+ scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
6793
+ }
6794
+ }
6795
+
6796
+ } else {
6797
+
6798
+ if (!o.axis || o.axis !== "x") {
6799
+ if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
6800
+ scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
6801
+ } else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
6802
+ scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
6803
+ }
6804
+ }
6805
+
6806
+ if (!o.axis || o.axis !== "y") {
6807
+ if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
6808
+ scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
6809
+ } else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
6810
+ scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
6811
+ }
6812
+ }
6813
+
6814
+ }
6815
+
6816
+ if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
6817
+ $.ui.ddmanager.prepareOffsets(i, event);
6818
+ }
6819
+
6820
+ }
6821
+ });
6822
+
6823
+ $.ui.plugin.add("draggable", "snap", {
6824
+ start: function( event, ui, i ) {
6825
+
6826
+ var o = i.options;
6827
+
6828
+ i.snapElements = [];
6829
+
6830
+ $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
6831
+ var $t = $(this),
6832
+ $o = $t.offset();
6833
+ if (this !== i.element[0]) {
6834
+ i.snapElements.push({
6835
+ item: this,
6836
+ width: $t.outerWidth(), height: $t.outerHeight(),
6837
+ top: $o.top, left: $o.left
6838
+ });
6839
+ }
6840
+ });
6841
+
6842
+ },
6843
+ drag: function( event, ui, inst ) {
6844
+
6845
+ var ts, bs, ls, rs, l, r, t, b, i, first,
6846
+ o = inst.options,
6847
+ d = o.snapTolerance,
6848
+ x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
6849
+ y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
6850
+
6851
+ for (i = inst.snapElements.length - 1; i >= 0; i--){
6852
+
6853
+ l = inst.snapElements[i].left - inst.margins.left;
6854
+ r = l + inst.snapElements[i].width;
6855
+ t = inst.snapElements[i].top - inst.margins.top;
6856
+ b = t + inst.snapElements[i].height;
6857
+
6858
+ if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
6859
+ if (inst.snapElements[i].snapping) {
6860
+ (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
6861
+ }
6862
+ inst.snapElements[i].snapping = false;
6863
+ continue;
6864
+ }
6865
+
6866
+ if (o.snapMode !== "inner") {
6867
+ ts = Math.abs(t - y2) <= d;
6868
+ bs = Math.abs(b - y1) <= d;
6869
+ ls = Math.abs(l - x2) <= d;
6870
+ rs = Math.abs(r - x1) <= d;
6871
+ if (ts) {
6872
+ ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top;
6873
+ }
6874
+ if (bs) {
6875
+ ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top;
6876
+ }
6877
+ if (ls) {
6878
+ ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left;
6879
+ }
6880
+ if (rs) {
6881
+ ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left;
6882
+ }
6883
+ }
6884
+
6885
+ first = (ts || bs || ls || rs);
6886
+
6887
+ if (o.snapMode !== "outer") {
6888
+ ts = Math.abs(t - y1) <= d;
6889
+ bs = Math.abs(b - y2) <= d;
6890
+ ls = Math.abs(l - x1) <= d;
6891
+ rs = Math.abs(r - x2) <= d;
6892
+ if (ts) {
6893
+ ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top;
6894
+ }
6895
+ if (bs) {
6896
+ ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top;
6897
+ }
6898
+ if (ls) {
6899
+ ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left;
6900
+ }
6901
+ if (rs) {
6902
+ ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left;
6903
+ }
6904
+ }
6905
+
6906
+ if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
6907
+ (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
6908
+ }
6909
+ inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
6910
+
6911
+ }
6912
+
6913
+ }
6914
+ });
6915
+
6916
+ $.ui.plugin.add("draggable", "stack", {
6917
+ start: function( event, ui, instance ) {
6918
+ var min,
6919
+ o = instance.options,
6920
+ group = $.makeArray($(o.stack)).sort(function(a, b) {
6921
+ return (parseInt($(a).css("zIndex"), 10) || 0) - (parseInt($(b).css("zIndex"), 10) || 0);
6922
+ });
6923
+
6924
+ if (!group.length) { return; }
6925
+
6926
+ min = parseInt($(group[0]).css("zIndex"), 10) || 0;
6927
+ $(group).each(function(i) {
6928
+ $(this).css("zIndex", min + i);
6929
+ });
6930
+ this.css("zIndex", (min + group.length));
6931
+ }
6932
+ });
6933
+
6934
+ $.ui.plugin.add("draggable", "zIndex", {
6935
+ start: function( event, ui, instance ) {
6936
+ var t = $( ui.helper ),
6937
+ o = instance.options;
6938
+
6939
+ if (t.css("zIndex")) {
6940
+ o._zIndex = t.css("zIndex");
6941
+ }
6942
+ t.css("zIndex", o.zIndex);
6943
+ },
6944
+ stop: function( event, ui, instance ) {
6945
+ var o = instance.options;
6946
+
6947
+ if (o._zIndex) {
6948
+ $(ui.helper).css("zIndex", o._zIndex);
6949
+ }
6950
+ }
6951
+ });
6952
+
6953
+ var draggable = $.ui.draggable;
6954
+
6955
+
6956
+ /*!
6957
+ * jQuery UI Resizable 1.11.4
6958
+ * http://jqueryui.com
6959
+ *
6960
+ * Copyright jQuery Foundation and other contributors
6961
+ * Released under the MIT license.
6962
+ * http://jquery.org/license
6963
+ *
6964
+ * http://api.jqueryui.com/resizable/
6965
+ */
6966
+
6967
+
6968
+ $.widget("ui.resizable", $.ui.mouse, {
6969
+ version: "1.11.4",
6970
+ widgetEventPrefix: "resize",
6971
+ options: {
6972
+ alsoResize: false,
6973
+ animate: false,
6974
+ animateDuration: "slow",
6975
+ animateEasing: "swing",
6976
+ aspectRatio: false,
6977
+ autoHide: false,
6978
+ containment: false,
6979
+ ghost: false,
6980
+ grid: false,
6981
+ handles: "e,s,se",
6982
+ helper: false,
6983
+ maxHeight: null,
6984
+ maxWidth: null,
6985
+ minHeight: 10,
6986
+ minWidth: 10,
6987
+ // See #7960
6988
+ zIndex: 90,
6989
+
6990
+ // callbacks
6991
+ resize: null,
6992
+ start: null,
6993
+ stop: null
6994
+ },
6995
+
6996
+ _num: function( value ) {
6997
+ return parseInt( value, 10 ) || 0;
6998
+ },
6999
+
7000
+ _isNumber: function( value ) {
7001
+ return !isNaN( parseInt( value, 10 ) );
7002
+ },
7003
+
7004
+ _hasScroll: function( el, a ) {
7005
+
7006
+ if ( $( el ).css( "overflow" ) === "hidden") {
7007
+ return false;
7008
+ }
7009
+
7010
+ var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
7011
+ has = false;
7012
+
7013
+ if ( el[ scroll ] > 0 ) {
7014
+ return true;
7015
+ }
7016
+
7017
+ // TODO: determine which cases actually cause this to happen
7018
+ // if the element doesn't have the scroll set, see if it's possible to
7019
+ // set the scroll
7020
+ el[ scroll ] = 1;
7021
+ has = ( el[ scroll ] > 0 );
7022
+ el[ scroll ] = 0;
7023
+ return has;
7024
+ },
7025
+
7026
+ _create: function() {
7027
+
7028
+ var n, i, handle, axis, hname,
7029
+ that = this,
7030
+ o = this.options;
7031
+ this.element.addClass("ui-resizable");
7032
+
7033
+ $.extend(this, {
7034
+ _aspectRatio: !!(o.aspectRatio),
7035
+ aspectRatio: o.aspectRatio,
7036
+ originalElement: this.element,
7037
+ _proportionallyResizeElements: [],
7038
+ _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
7039
+ });
7040
+
7041
+ // Wrap the element if it cannot hold child nodes
7042
+ if (this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)) {
7043
+
7044
+ this.element.wrap(
7045
+ $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
7046
+ position: this.element.css("position"),
7047
+ width: this.element.outerWidth(),
7048
+ height: this.element.outerHeight(),
7049
+ top: this.element.css("top"),
7050
+ left: this.element.css("left")
7051
+ })
7052
+ );
7053
+
7054
+ this.element = this.element.parent().data(
7055
+ "ui-resizable", this.element.resizable( "instance" )
7056
+ );
7057
+
7058
+ this.elementIsWrapper = true;
7059
+
7060
+ this.element.css({
7061
+ marginLeft: this.originalElement.css("marginLeft"),
7062
+ marginTop: this.originalElement.css("marginTop"),
7063
+ marginRight: this.originalElement.css("marginRight"),
7064
+ marginBottom: this.originalElement.css("marginBottom")
7065
+ });
7066
+ this.originalElement.css({
7067
+ marginLeft: 0,
7068
+ marginTop: 0,
7069
+ marginRight: 0,
7070
+ marginBottom: 0
7071
+ });
7072
+ // support: Safari
7073
+ // Prevent Safari textarea resize
7074
+ this.originalResizeStyle = this.originalElement.css("resize");
7075
+ this.originalElement.css("resize", "none");
7076
+
7077
+ this._proportionallyResizeElements.push( this.originalElement.css({
7078
+ position: "static",
7079
+ zoom: 1,
7080
+ display: "block"
7081
+ }) );
7082
+
7083
+ // support: IE9
7084
+ // avoid IE jump (hard set the margin)
7085
+ this.originalElement.css({ margin: this.originalElement.css("margin") });
7086
+
7087
+ this._proportionallyResize();
7088
+ }
7089
+
7090
+ this.handles = o.handles ||
7091
+ ( !$(".ui-resizable-handle", this.element).length ?
7092
+ "e,s,se" : {
7093
+ n: ".ui-resizable-n",
7094
+ e: ".ui-resizable-e",
7095
+ s: ".ui-resizable-s",
7096
+ w: ".ui-resizable-w",
7097
+ se: ".ui-resizable-se",
7098
+ sw: ".ui-resizable-sw",
7099
+ ne: ".ui-resizable-ne",
7100
+ nw: ".ui-resizable-nw"
7101
+ } );
7102
+
7103
+ this._handles = $();
7104
+ if ( this.handles.constructor === String ) {
7105
+
7106
+ if ( this.handles === "all") {
7107
+ this.handles = "n,e,s,w,se,sw,ne,nw";
7108
+ }
7109
+
7110
+ n = this.handles.split(",");
7111
+ this.handles = {};
7112
+
7113
+ for (i = 0; i < n.length; i++) {
7114
+
7115
+ handle = $.trim(n[i]);
7116
+ hname = "ui-resizable-" + handle;
7117
+ axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
7118
+
7119
+ axis.css({ zIndex: o.zIndex });
7120
+
7121
+ // TODO : What's going on here?
7122
+ if ("se" === handle) {
7123
+ axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
7124
+ }
7125
+
7126
+ this.handles[handle] = ".ui-resizable-" + handle;
7127
+ this.element.append(axis);
7128
+ }
7129
+
7130
+ }
7131
+
7132
+ this._renderAxis = function(target) {
7133
+
7134
+ var i, axis, padPos, padWrapper;
7135
+
7136
+ target = target || this.element;
7137
+
7138
+ for (i in this.handles) {
7139
+
7140
+ if (this.handles[i].constructor === String) {
7141
+ this.handles[i] = this.element.children( this.handles[ i ] ).first().show();
7142
+ } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
7143
+ this.handles[ i ] = $( this.handles[ i ] );
7144
+ this._on( this.handles[ i ], { "mousedown": that._mouseDown });
7145
+ }
7146
+
7147
+ if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)) {
7148
+
7149
+ axis = $(this.handles[i], this.element);
7150
+
7151
+ padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
7152
+
7153
+ padPos = [ "padding",
7154
+ /ne|nw|n/.test(i) ? "Top" :
7155
+ /se|sw|s/.test(i) ? "Bottom" :
7156
+ /^e$/.test(i) ? "Right" : "Left" ].join("");
7157
+
7158
+ target.css(padPos, padWrapper);
7159
+
7160
+ this._proportionallyResize();
7161
+ }
7162
+
7163
+ this._handles = this._handles.add( this.handles[ i ] );
7164
+ }
7165
+ };
7166
+
7167
+ // TODO: make renderAxis a prototype function
7168
+ this._renderAxis(this.element);
7169
+
7170
+ this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
7171
+ this._handles.disableSelection();
7172
+
7173
+ this._handles.mouseover(function() {
7174
+ if (!that.resizing) {
7175
+ if (this.className) {
7176
+ axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
7177
+ }
7178
+ that.axis = axis && axis[1] ? axis[1] : "se";
7179
+ }
7180
+ });
7181
+
7182
+ if (o.autoHide) {
7183
+ this._handles.hide();
7184
+ $(this.element)
7185
+ .addClass("ui-resizable-autohide")
7186
+ .mouseenter(function() {
7187
+ if (o.disabled) {
7188
+ return;
7189
+ }
7190
+ $(this).removeClass("ui-resizable-autohide");
7191
+ that._handles.show();
7192
+ })
7193
+ .mouseleave(function() {
7194
+ if (o.disabled) {
7195
+ return;
7196
+ }
7197
+ if (!that.resizing) {
7198
+ $(this).addClass("ui-resizable-autohide");
7199
+ that._handles.hide();
7200
+ }
7201
+ });
7202
+ }
7203
+
7204
+ this._mouseInit();
7205
+ },
7206
+
7207
+ _destroy: function() {
7208
+
7209
+ this._mouseDestroy();
7210
+
7211
+ var wrapper,
7212
+ _destroy = function(exp) {
7213
+ $(exp)
7214
+ .removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
7215
+ .removeData("resizable")
7216
+ .removeData("ui-resizable")
7217
+ .unbind(".resizable")
7218
+ .find(".ui-resizable-handle")
7219
+ .remove();
7220
+ };
7221
+
7222
+ // TODO: Unwrap at same DOM position
7223
+ if (this.elementIsWrapper) {
7224
+ _destroy(this.element);
7225
+ wrapper = this.element;
7226
+ this.originalElement.css({
7227
+ position: wrapper.css("position"),
7228
+ width: wrapper.outerWidth(),
7229
+ height: wrapper.outerHeight(),
7230
+ top: wrapper.css("top"),
7231
+ left: wrapper.css("left")
7232
+ }).insertAfter( wrapper );
7233
+ wrapper.remove();
7234
+ }
7235
+
7236
+ this.originalElement.css("resize", this.originalResizeStyle);
7237
+ _destroy(this.originalElement);
7238
+
7239
+ return this;
7240
+ },
7241
+
7242
+ _mouseCapture: function(event) {
7243
+ var i, handle,
7244
+ capture = false;
7245
+
7246
+ for (i in this.handles) {
7247
+ handle = $(this.handles[i])[0];
7248
+ if (handle === event.target || $.contains(handle, event.target)) {
7249
+ capture = true;
7250
+ }
7251
+ }
7252
+
7253
+ return !this.options.disabled && capture;
7254
+ },
7255
+
7256
+ _mouseStart: function(event) {
7257
+
7258
+ var curleft, curtop, cursor,
7259
+ o = this.options,
7260
+ el = this.element;
7261
+
7262
+ this.resizing = true;
7263
+
7264
+ this._renderProxy();
7265
+
7266
+ curleft = this._num(this.helper.css("left"));
7267
+ curtop = this._num(this.helper.css("top"));
7268
+
7269
+ if (o.containment) {
7270
+ curleft += $(o.containment).scrollLeft() || 0;
7271
+ curtop += $(o.containment).scrollTop() || 0;
7272
+ }
7273
+
7274
+ this.offset = this.helper.offset();
7275
+ this.position = { left: curleft, top: curtop };
7276
+
7277
+ this.size = this._helper ? {
7278
+ width: this.helper.width(),
7279
+ height: this.helper.height()
7280
+ } : {
7281
+ width: el.width(),
7282
+ height: el.height()
7283
+ };
7284
+
7285
+ this.originalSize = this._helper ? {
7286
+ width: el.outerWidth(),
7287
+ height: el.outerHeight()
7288
+ } : {
7289
+ width: el.width(),
7290
+ height: el.height()
7291
+ };
7292
+
7293
+ this.sizeDiff = {
7294
+ width: el.outerWidth() - el.width(),
7295
+ height: el.outerHeight() - el.height()
7296
+ };
7297
+
7298
+ this.originalPosition = { left: curleft, top: curtop };
7299
+ this.originalMousePosition = { left: event.pageX, top: event.pageY };
7300
+
7301
+ this.aspectRatio = (typeof o.aspectRatio === "number") ?
7302
+ o.aspectRatio :
7303
+ ((this.originalSize.width / this.originalSize.height) || 1);
7304
+
7305
+ cursor = $(".ui-resizable-" + this.axis).css("cursor");
7306
+ $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
7307
+
7308
+ el.addClass("ui-resizable-resizing");
7309
+ this._propagate("start", event);
7310
+ return true;
7311
+ },
7312
+
7313
+ _mouseDrag: function(event) {
7314
+
7315
+ var data, props,
7316
+ smp = this.originalMousePosition,
7317
+ a = this.axis,
7318
+ dx = (event.pageX - smp.left) || 0,
7319
+ dy = (event.pageY - smp.top) || 0,
7320
+ trigger = this._change[a];
7321
+
7322
+ this._updatePrevProperties();
7323
+
7324
+ if (!trigger) {
7325
+ return false;
7326
+ }
7327
+
7328
+ data = trigger.apply(this, [ event, dx, dy ]);
7329
+
7330
+ this._updateVirtualBoundaries(event.shiftKey);
7331
+ if (this._aspectRatio || event.shiftKey) {
7332
+ data = this._updateRatio(data, event);
7333
+ }
7334
+
7335
+ data = this._respectSize(data, event);
7336
+
7337
+ this._updateCache(data);
7338
+
7339
+ this._propagate("resize", event);
7340
+
7341
+ props = this._applyChanges();
7342
+
7343
+ if ( !this._helper && this._proportionallyResizeElements.length ) {
7344
+ this._proportionallyResize();
7345
+ }
7346
+
7347
+ if ( !$.isEmptyObject( props ) ) {
7348
+ this._updatePrevProperties();
7349
+ this._trigger( "resize", event, this.ui() );
7350
+ this._applyChanges();
7351
+ }
7352
+
7353
+ return false;
7354
+ },
7355
+
7356
+ _mouseStop: function(event) {
7357
+
7358
+ this.resizing = false;
7359
+ var pr, ista, soffseth, soffsetw, s, left, top,
7360
+ o = this.options, that = this;
7361
+
7362
+ if (this._helper) {
7363
+
7364
+ pr = this._proportionallyResizeElements;
7365
+ ista = pr.length && (/textarea/i).test(pr[0].nodeName);
7366
+ soffseth = ista && this._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height;
7367
+ soffsetw = ista ? 0 : that.sizeDiff.width;
7368
+
7369
+ s = {
7370
+ width: (that.helper.width() - soffsetw),
7371
+ height: (that.helper.height() - soffseth)
7372
+ };
7373
+ left = (parseInt(that.element.css("left"), 10) +
7374
+ (that.position.left - that.originalPosition.left)) || null;
7375
+ top = (parseInt(that.element.css("top"), 10) +
7376
+ (that.position.top - that.originalPosition.top)) || null;
7377
+
7378
+ if (!o.animate) {
7379
+ this.element.css($.extend(s, { top: top, left: left }));
7380
+ }
7381
+
7382
+ that.helper.height(that.size.height);
7383
+ that.helper.width(that.size.width);
7384
+
7385
+ if (this._helper && !o.animate) {
7386
+ this._proportionallyResize();
7387
+ }
7388
+ }
7389
+
7390
+ $("body").css("cursor", "auto");
7391
+
7392
+ this.element.removeClass("ui-resizable-resizing");
7393
+
7394
+ this._propagate("stop", event);
7395
+
7396
+ if (this._helper) {
7397
+ this.helper.remove();
7398
+ }
7399
+
7400
+ return false;
7401
+
7402
+ },
7403
+
7404
+ _updatePrevProperties: function() {
7405
+ this.prevPosition = {
7406
+ top: this.position.top,
7407
+ left: this.position.left
7408
+ };
7409
+ this.prevSize = {
7410
+ width: this.size.width,
7411
+ height: this.size.height
7412
+ };
7413
+ },
7414
+
7415
+ _applyChanges: function() {
7416
+ var props = {};
7417
+
7418
+ if ( this.position.top !== this.prevPosition.top ) {
7419
+ props.top = this.position.top + "px";
7420
+ }
7421
+ if ( this.position.left !== this.prevPosition.left ) {
7422
+ props.left = this.position.left + "px";
7423
+ }
7424
+ if ( this.size.width !== this.prevSize.width ) {
7425
+ props.width = this.size.width + "px";
7426
+ }
7427
+ if ( this.size.height !== this.prevSize.height ) {
7428
+ props.height = this.size.height + "px";
7429
+ }
7430
+
7431
+ this.helper.css( props );
7432
+
7433
+ return props;
7434
+ },
7435
+
7436
+ _updateVirtualBoundaries: function(forceAspectRatio) {
7437
+ var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
7438
+ o = this.options;
7439
+
7440
+ b = {
7441
+ minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0,
7442
+ maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity,
7443
+ minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0,
7444
+ maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity
7445
+ };
7446
+
7447
+ if (this._aspectRatio || forceAspectRatio) {
7448
+ pMinWidth = b.minHeight * this.aspectRatio;
7449
+ pMinHeight = b.minWidth / this.aspectRatio;
7450
+ pMaxWidth = b.maxHeight * this.aspectRatio;
7451
+ pMaxHeight = b.maxWidth / this.aspectRatio;
7452
+
7453
+ if (pMinWidth > b.minWidth) {
7454
+ b.minWidth = pMinWidth;
7455
+ }
7456
+ if (pMinHeight > b.minHeight) {
7457
+ b.minHeight = pMinHeight;
7458
+ }
7459
+ if (pMaxWidth < b.maxWidth) {
7460
+ b.maxWidth = pMaxWidth;
7461
+ }
7462
+ if (pMaxHeight < b.maxHeight) {
7463
+ b.maxHeight = pMaxHeight;
7464
+ }
7465
+ }
7466
+ this._vBoundaries = b;
7467
+ },
7468
+
7469
+ _updateCache: function(data) {
7470
+ this.offset = this.helper.offset();
7471
+ if (this._isNumber(data.left)) {
7472
+ this.position.left = data.left;
7473
+ }
7474
+ if (this._isNumber(data.top)) {
7475
+ this.position.top = data.top;
7476
+ }
7477
+ if (this._isNumber(data.height)) {
7478
+ this.size.height = data.height;
7479
+ }
7480
+ if (this._isNumber(data.width)) {
7481
+ this.size.width = data.width;
7482
+ }
7483
+ },
7484
+
7485
+ _updateRatio: function( data ) {
7486
+
7487
+ var cpos = this.position,
7488
+ csize = this.size,
7489
+ a = this.axis;
7490
+
7491
+ if (this._isNumber(data.height)) {
7492
+ data.width = (data.height * this.aspectRatio);
7493
+ } else if (this._isNumber(data.width)) {
7494
+ data.height = (data.width / this.aspectRatio);
7495
+ }
7496
+
7497
+ if (a === "sw") {
7498
+ data.left = cpos.left + (csize.width - data.width);
7499
+ data.top = null;
7500
+ }
7501
+ if (a === "nw") {
7502
+ data.top = cpos.top + (csize.height - data.height);
7503
+ data.left = cpos.left + (csize.width - data.width);
7504
+ }
7505
+
7506
+ return data;
7507
+ },
7508
+
7509
+ _respectSize: function( data ) {
7510
+
7511
+ var o = this._vBoundaries,
7512
+ a = this.axis,
7513
+ ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width),
7514
+ ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
7515
+ isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width),
7516
+ isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
7517
+ dw = this.originalPosition.left + this.originalSize.width,
7518
+ dh = this.position.top + this.size.height,
7519
+ cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
7520
+ if (isminw) {
7521
+ data.width = o.minWidth;
7522
+ }
7523
+ if (isminh) {
7524
+ data.height = o.minHeight;
7525
+ }
7526
+ if (ismaxw) {
7527
+ data.width = o.maxWidth;
7528
+ }
7529
+ if (ismaxh) {
7530
+ data.height = o.maxHeight;
7531
+ }
7532
+
7533
+ if (isminw && cw) {
7534
+ data.left = dw - o.minWidth;
7535
+ }
7536
+ if (ismaxw && cw) {
7537
+ data.left = dw - o.maxWidth;
7538
+ }
7539
+ if (isminh && ch) {
7540
+ data.top = dh - o.minHeight;
7541
+ }
7542
+ if (ismaxh && ch) {
7543
+ data.top = dh - o.maxHeight;
7544
+ }
7545
+
7546
+ // Fixing jump error on top/left - bug #2330
7547
+ if (!data.width && !data.height && !data.left && data.top) {
7548
+ data.top = null;
7549
+ } else if (!data.width && !data.height && !data.top && data.left) {
7550
+ data.left = null;
7551
+ }
7552
+
7553
+ return data;
7554
+ },
7555
+
7556
+ _getPaddingPlusBorderDimensions: function( element ) {
7557
+ var i = 0,
7558
+ widths = [],
7559
+ borders = [
7560
+ element.css( "borderTopWidth" ),
7561
+ element.css( "borderRightWidth" ),
7562
+ element.css( "borderBottomWidth" ),
7563
+ element.css( "borderLeftWidth" )
7564
+ ],
7565
+ paddings = [
7566
+ element.css( "paddingTop" ),
7567
+ element.css( "paddingRight" ),
7568
+ element.css( "paddingBottom" ),
7569
+ element.css( "paddingLeft" )
7570
+ ];
7571
+
7572
+ for ( ; i < 4; i++ ) {
7573
+ widths[ i ] = ( parseInt( borders[ i ], 10 ) || 0 );
7574
+ widths[ i ] += ( parseInt( paddings[ i ], 10 ) || 0 );
7575
+ }
7576
+
7577
+ return {
7578
+ height: widths[ 0 ] + widths[ 2 ],
7579
+ width: widths[ 1 ] + widths[ 3 ]
7580
+ };
7581
+ },
7582
+
7583
+ _proportionallyResize: function() {
7584
+
7585
+ if (!this._proportionallyResizeElements.length) {
7586
+ return;
7587
+ }
7588
+
7589
+ var prel,
7590
+ i = 0,
7591
+ element = this.helper || this.element;
7592
+
7593
+ for ( ; i < this._proportionallyResizeElements.length; i++) {
7594
+
7595
+ prel = this._proportionallyResizeElements[i];
7596
+
7597
+ // TODO: Seems like a bug to cache this.outerDimensions
7598
+ // considering that we are in a loop.
7599
+ if (!this.outerDimensions) {
7600
+ this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
7601
+ }
7602
+
7603
+ prel.css({
7604
+ height: (element.height() - this.outerDimensions.height) || 0,
7605
+ width: (element.width() - this.outerDimensions.width) || 0
7606
+ });
7607
+
7608
+ }
7609
+
7610
+ },
7611
+
7612
+ _renderProxy: function() {
7613
+
7614
+ var el = this.element, o = this.options;
7615
+ this.elementOffset = el.offset();
7616
+
7617
+ if (this._helper) {
7618
+
7619
+ this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
7620
+
7621
+ this.helper.addClass(this._helper).css({
7622
+ width: this.element.outerWidth() - 1,
7623
+ height: this.element.outerHeight() - 1,
7624
+ position: "absolute",
7625
+ left: this.elementOffset.left + "px",
7626
+ top: this.elementOffset.top + "px",
7627
+ zIndex: ++o.zIndex //TODO: Don't modify option
7628
+ });
7629
+
7630
+ this.helper
7631
+ .appendTo("body")
7632
+ .disableSelection();
7633
+
7634
+ } else {
7635
+ this.helper = this.element;
7636
+ }
7637
+
7638
+ },
7639
+
7640
+ _change: {
7641
+ e: function(event, dx) {
7642
+ return { width: this.originalSize.width + dx };
7643
+ },
7644
+ w: function(event, dx) {
7645
+ var cs = this.originalSize, sp = this.originalPosition;
7646
+ return { left: sp.left + dx, width: cs.width - dx };
7647
+ },
7648
+ n: function(event, dx, dy) {
7649
+ var cs = this.originalSize, sp = this.originalPosition;
7650
+ return { top: sp.top + dy, height: cs.height - dy };
7651
+ },
7652
+ s: function(event, dx, dy) {
7653
+ return { height: this.originalSize.height + dy };
7654
+ },
7655
+ se: function(event, dx, dy) {
7656
+ return $.extend(this._change.s.apply(this, arguments),
7657
+ this._change.e.apply(this, [ event, dx, dy ]));
7658
+ },
7659
+ sw: function(event, dx, dy) {
7660
+ return $.extend(this._change.s.apply(this, arguments),
7661
+ this._change.w.apply(this, [ event, dx, dy ]));
7662
+ },
7663
+ ne: function(event, dx, dy) {
7664
+ return $.extend(this._change.n.apply(this, arguments),
7665
+ this._change.e.apply(this, [ event, dx, dy ]));
7666
+ },
7667
+ nw: function(event, dx, dy) {
7668
+ return $.extend(this._change.n.apply(this, arguments),
7669
+ this._change.w.apply(this, [ event, dx, dy ]));
7670
+ }
7671
+ },
7672
+
7673
+ _propagate: function(n, event) {
7674
+ $.ui.plugin.call(this, n, [ event, this.ui() ]);
7675
+ (n !== "resize" && this._trigger(n, event, this.ui()));
7676
+ },
7677
+
7678
+ plugins: {},
7679
+
7680
+ ui: function() {
7681
+ return {
7682
+ originalElement: this.originalElement,
7683
+ element: this.element,
7684
+ helper: this.helper,
7685
+ position: this.position,
7686
+ size: this.size,
7687
+ originalSize: this.originalSize,
7688
+ originalPosition: this.originalPosition
7689
+ };
7690
+ }
7691
+
7692
+ });
7693
+
7694
+ /*
7695
+ * Resizable Extensions
7696
+ */
7697
+
7698
+ $.ui.plugin.add("resizable", "animate", {
7699
+
7700
+ stop: function( event ) {
7701
+ var that = $(this).resizable( "instance" ),
7702
+ o = that.options,
7703
+ pr = that._proportionallyResizeElements,
7704
+ ista = pr.length && (/textarea/i).test(pr[0].nodeName),
7705
+ soffseth = ista && that._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height,
7706
+ soffsetw = ista ? 0 : that.sizeDiff.width,
7707
+ style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
7708
+ left = (parseInt(that.element.css("left"), 10) +
7709
+ (that.position.left - that.originalPosition.left)) || null,
7710
+ top = (parseInt(that.element.css("top"), 10) +
7711
+ (that.position.top - that.originalPosition.top)) || null;
7712
+
7713
+ that.element.animate(
7714
+ $.extend(style, top && left ? { top: top, left: left } : {}), {
7715
+ duration: o.animateDuration,
7716
+ easing: o.animateEasing,
7717
+ step: function() {
7718
+
7719
+ var data = {
7720
+ width: parseInt(that.element.css("width"), 10),
7721
+ height: parseInt(that.element.css("height"), 10),
7722
+ top: parseInt(that.element.css("top"), 10),
7723
+ left: parseInt(that.element.css("left"), 10)
7724
+ };
7725
+
7726
+ if (pr && pr.length) {
7727
+ $(pr[0]).css({ width: data.width, height: data.height });
7728
+ }
7729
+
7730
+ // propagating resize, and updating values for each animation step
7731
+ that._updateCache(data);
7732
+ that._propagate("resize", event);
7733
+
7734
+ }
7735
+ }
7736
+ );
7737
+ }
7738
+
7739
+ });
7740
+
7741
+ $.ui.plugin.add( "resizable", "containment", {
7742
+
7743
+ start: function() {
7744
+ var element, p, co, ch, cw, width, height,
7745
+ that = $( this ).resizable( "instance" ),
7746
+ o = that.options,
7747
+ el = that.element,
7748
+ oc = o.containment,
7749
+ ce = ( oc instanceof $ ) ? oc.get( 0 ) : ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
7750
+
7751
+ if ( !ce ) {
7752
+ return;
7753
+ }
7754
+
7755
+ that.containerElement = $( ce );
7756
+
7757
+ if ( /document/.test( oc ) || oc === document ) {
7758
+ that.containerOffset = {
7759
+ left: 0,
7760
+ top: 0
7761
+ };
7762
+ that.containerPosition = {
7763
+ left: 0,
7764
+ top: 0
7765
+ };
7766
+
7767
+ that.parentData = {
7768
+ element: $( document ),
7769
+ left: 0,
7770
+ top: 0,
7771
+ width: $( document ).width(),
7772
+ height: $( document ).height() || document.body.parentNode.scrollHeight
7773
+ };
7774
+ } else {
7775
+ element = $( ce );
7776
+ p = [];
7777
+ $([ "Top", "Right", "Left", "Bottom" ]).each(function( i, name ) {
7778
+ p[ i ] = that._num( element.css( "padding" + name ) );
7779
+ });
7780
+
7781
+ that.containerOffset = element.offset();
7782
+ that.containerPosition = element.position();
7783
+ that.containerSize = {
7784
+ height: ( element.innerHeight() - p[ 3 ] ),
7785
+ width: ( element.innerWidth() - p[ 1 ] )
7786
+ };
7787
+
7788
+ co = that.containerOffset;
7789
+ ch = that.containerSize.height;
7790
+ cw = that.containerSize.width;
7791
+ width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
7792
+ height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
7793
+
7794
+ that.parentData = {
7795
+ element: ce,
7796
+ left: co.left,
7797
+ top: co.top,
7798
+ width: width,
7799
+ height: height
7800
+ };
7801
+ }
7802
+ },
7803
+
7804
+ resize: function( event ) {
7805
+ var woset, hoset, isParent, isOffsetRelative,
7806
+ that = $( this ).resizable( "instance" ),
7807
+ o = that.options,
7808
+ co = that.containerOffset,
7809
+ cp = that.position,
7810
+ pRatio = that._aspectRatio || event.shiftKey,
7811
+ cop = {
7812
+ top: 0,
7813
+ left: 0
7814
+ },
7815
+ ce = that.containerElement,
7816
+ continueResize = true;
7817
+
7818
+ if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
7819
+ cop = co;
7820
+ }
7821
+
7822
+ if ( cp.left < ( that._helper ? co.left : 0 ) ) {
7823
+ that.size.width = that.size.width +
7824
+ ( that._helper ?
7825
+ ( that.position.left - co.left ) :
7826
+ ( that.position.left - cop.left ) );
7827
+
7828
+ if ( pRatio ) {
7829
+ that.size.height = that.size.width / that.aspectRatio;
7830
+ continueResize = false;
7831
+ }
7832
+ that.position.left = o.helper ? co.left : 0;
7833
+ }
7834
+
7835
+ if ( cp.top < ( that._helper ? co.top : 0 ) ) {
7836
+ that.size.height = that.size.height +
7837
+ ( that._helper ?
7838
+ ( that.position.top - co.top ) :
7839
+ that.position.top );
7840
+
7841
+ if ( pRatio ) {
7842
+ that.size.width = that.size.height * that.aspectRatio;
7843
+ continueResize = false;
7844
+ }
7845
+ that.position.top = that._helper ? co.top : 0;
7846
+ }
7847
+
7848
+ isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
7849
+ isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
7850
+
7851
+ if ( isParent && isOffsetRelative ) {
7852
+ that.offset.left = that.parentData.left + that.position.left;
7853
+ that.offset.top = that.parentData.top + that.position.top;
7854
+ } else {
7855
+ that.offset.left = that.element.offset().left;
7856
+ that.offset.top = that.element.offset().top;
7857
+ }
7858
+
7859
+ woset = Math.abs( that.sizeDiff.width +
7860
+ (that._helper ?
7861
+ that.offset.left - cop.left :
7862
+ (that.offset.left - co.left)) );
7863
+
7864
+ hoset = Math.abs( that.sizeDiff.height +
7865
+ (that._helper ?
7866
+ that.offset.top - cop.top :
7867
+ (that.offset.top - co.top)) );
7868
+
7869
+ if ( woset + that.size.width >= that.parentData.width ) {
7870
+ that.size.width = that.parentData.width - woset;
7871
+ if ( pRatio ) {
7872
+ that.size.height = that.size.width / that.aspectRatio;
7873
+ continueResize = false;
7874
+ }
7875
+ }
7876
+
7877
+ if ( hoset + that.size.height >= that.parentData.height ) {
7878
+ that.size.height = that.parentData.height - hoset;
7879
+ if ( pRatio ) {
7880
+ that.size.width = that.size.height * that.aspectRatio;
7881
+ continueResize = false;
7882
+ }
7883
+ }
7884
+
7885
+ if ( !continueResize ) {
7886
+ that.position.left = that.prevPosition.left;
7887
+ that.position.top = that.prevPosition.top;
7888
+ that.size.width = that.prevSize.width;
7889
+ that.size.height = that.prevSize.height;
7890
+ }
7891
+ },
7892
+
7893
+ stop: function() {
7894
+ var that = $( this ).resizable( "instance" ),
7895
+ o = that.options,
7896
+ co = that.containerOffset,
7897
+ cop = that.containerPosition,
7898
+ ce = that.containerElement,
7899
+ helper = $( that.helper ),
7900
+ ho = helper.offset(),
7901
+ w = helper.outerWidth() - that.sizeDiff.width,
7902
+ h = helper.outerHeight() - that.sizeDiff.height;
7903
+
7904
+ if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
7905
+ $( this ).css({
7906
+ left: ho.left - cop.left - co.left,
7907
+ width: w,
7908
+ height: h
7909
+ });
7910
+ }
7911
+
7912
+ if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
7913
+ $( this ).css({
7914
+ left: ho.left - cop.left - co.left,
7915
+ width: w,
7916
+ height: h
7917
+ });
7918
+ }
7919
+ }
7920
+ });
7921
+
7922
+ $.ui.plugin.add("resizable", "alsoResize", {
7923
+
7924
+ start: function() {
7925
+ var that = $(this).resizable( "instance" ),
7926
+ o = that.options;
7927
+
7928
+ $(o.alsoResize).each(function() {
7929
+ var el = $(this);
7930
+ el.data("ui-resizable-alsoresize", {
7931
+ width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
7932
+ left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
7933
+ });
7934
+ });
7935
+ },
7936
+
7937
+ resize: function(event, ui) {
7938
+ var that = $(this).resizable( "instance" ),
7939
+ o = that.options,
7940
+ os = that.originalSize,
7941
+ op = that.originalPosition,
7942
+ delta = {
7943
+ height: (that.size.height - os.height) || 0,
7944
+ width: (that.size.width - os.width) || 0,
7945
+ top: (that.position.top - op.top) || 0,
7946
+ left: (that.position.left - op.left) || 0
7947
+ };
7948
+
7949
+ $(o.alsoResize).each(function() {
7950
+ var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
7951
+ css = el.parents(ui.originalElement[0]).length ?
7952
+ [ "width", "height" ] :
7953
+ [ "width", "height", "top", "left" ];
7954
+
7955
+ $.each(css, function(i, prop) {
7956
+ var sum = (start[prop] || 0) + (delta[prop] || 0);
7957
+ if (sum && sum >= 0) {
7958
+ style[prop] = sum || null;
7959
+ }
7960
+ });
7961
+
7962
+ el.css(style);
7963
+ });
7964
+ },
7965
+
7966
+ stop: function() {
7967
+ $(this).removeData("resizable-alsoresize");
7968
+ }
7969
+ });
7970
+
7971
+ $.ui.plugin.add("resizable", "ghost", {
7972
+
7973
+ start: function() {
7974
+
7975
+ var that = $(this).resizable( "instance" ), o = that.options, cs = that.size;
7976
+
7977
+ that.ghost = that.originalElement.clone();
7978
+ that.ghost
7979
+ .css({
7980
+ opacity: 0.25,
7981
+ display: "block",
7982
+ position: "relative",
7983
+ height: cs.height,
7984
+ width: cs.width,
7985
+ margin: 0,
7986
+ left: 0,
7987
+ top: 0
7988
+ })
7989
+ .addClass("ui-resizable-ghost")
7990
+ .addClass(typeof o.ghost === "string" ? o.ghost : "");
7991
+
7992
+ that.ghost.appendTo(that.helper);
7993
+
7994
+ },
7995
+
7996
+ resize: function() {
7997
+ var that = $(this).resizable( "instance" );
7998
+ if (that.ghost) {
7999
+ that.ghost.css({
8000
+ position: "relative",
8001
+ height: that.size.height,
8002
+ width: that.size.width
8003
+ });
8004
+ }
8005
+ },
8006
+
8007
+ stop: function() {
8008
+ var that = $(this).resizable( "instance" );
8009
+ if (that.ghost && that.helper) {
8010
+ that.helper.get(0).removeChild(that.ghost.get(0));
8011
+ }
8012
+ }
8013
+
8014
+ });
8015
+
8016
+ $.ui.plugin.add("resizable", "grid", {
8017
+
8018
+ resize: function() {
8019
+ var outerDimensions,
8020
+ that = $(this).resizable( "instance" ),
8021
+ o = that.options,
8022
+ cs = that.size,
8023
+ os = that.originalSize,
8024
+ op = that.originalPosition,
8025
+ a = that.axis,
8026
+ grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
8027
+ gridX = (grid[0] || 1),
8028
+ gridY = (grid[1] || 1),
8029
+ ox = Math.round((cs.width - os.width) / gridX) * gridX,
8030
+ oy = Math.round((cs.height - os.height) / gridY) * gridY,
8031
+ newWidth = os.width + ox,
8032
+ newHeight = os.height + oy,
8033
+ isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
8034
+ isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
8035
+ isMinWidth = o.minWidth && (o.minWidth > newWidth),
8036
+ isMinHeight = o.minHeight && (o.minHeight > newHeight);
8037
+
8038
+ o.grid = grid;
8039
+
8040
+ if (isMinWidth) {
8041
+ newWidth += gridX;
8042
+ }
8043
+ if (isMinHeight) {
8044
+ newHeight += gridY;
8045
+ }
8046
+ if (isMaxWidth) {
8047
+ newWidth -= gridX;
8048
+ }
8049
+ if (isMaxHeight) {
8050
+ newHeight -= gridY;
8051
+ }
8052
+
8053
+ if (/^(se|s|e)$/.test(a)) {
8054
+ that.size.width = newWidth;
8055
+ that.size.height = newHeight;
8056
+ } else if (/^(ne)$/.test(a)) {
8057
+ that.size.width = newWidth;
8058
+ that.size.height = newHeight;
8059
+ that.position.top = op.top - oy;
8060
+ } else if (/^(sw)$/.test(a)) {
8061
+ that.size.width = newWidth;
8062
+ that.size.height = newHeight;
8063
+ that.position.left = op.left - ox;
8064
+ } else {
8065
+ if ( newHeight - gridY <= 0 || newWidth - gridX <= 0) {
8066
+ outerDimensions = that._getPaddingPlusBorderDimensions( this );
8067
+ }
8068
+
8069
+ if ( newHeight - gridY > 0 ) {
8070
+ that.size.height = newHeight;
8071
+ that.position.top = op.top - oy;
8072
+ } else {
8073
+ newHeight = gridY - outerDimensions.height;
8074
+ that.size.height = newHeight;
8075
+ that.position.top = op.top + os.height - newHeight;
8076
+ }
8077
+ if ( newWidth - gridX > 0 ) {
8078
+ that.size.width = newWidth;
8079
+ that.position.left = op.left - ox;
8080
+ } else {
8081
+ newWidth = gridX - outerDimensions.width;
8082
+ that.size.width = newWidth;
8083
+ that.position.left = op.left + os.width - newWidth;
8084
+ }
8085
+ }
8086
+ }
8087
+
8088
+ });
8089
+
8090
+ var resizable = $.ui.resizable;
8091
+
8092
+
8093
+ /*!
8094
+ * jQuery UI Dialog 1.11.4
8095
+ * http://jqueryui.com
8096
+ *
8097
+ * Copyright jQuery Foundation and other contributors
8098
+ * Released under the MIT license.
8099
+ * http://jquery.org/license
8100
+ *
8101
+ * http://api.jqueryui.com/dialog/
8102
+ */
8103
+
8104
+
8105
+ var dialog = $.widget( "ui.dialog", {
8106
+ version: "1.11.4",
8107
+ options: {
8108
+ appendTo: "body",
8109
+ autoOpen: true,
8110
+ buttons: [],
8111
+ closeOnEscape: true,
8112
+ closeText: "Close",
8113
+ dialogClass: "",
8114
+ draggable: true,
8115
+ hide: null,
8116
+ height: "auto",
8117
+ maxHeight: null,
8118
+ maxWidth: null,
8119
+ minHeight: 150,
8120
+ minWidth: 150,
8121
+ modal: false,
8122
+ position: {
8123
+ my: "center",
8124
+ at: "center",
8125
+ of: window,
8126
+ collision: "fit",
8127
+ // Ensure the titlebar is always visible
8128
+ using: function( pos ) {
8129
+ var topOffset = $( this ).css( pos ).offset().top;
8130
+ if ( topOffset < 0 ) {
8131
+ $( this ).css( "top", pos.top - topOffset );
8132
+ }
8133
+ }
8134
+ },
8135
+ resizable: true,
8136
+ show: null,
8137
+ title: null,
8138
+ width: 300,
8139
+
8140
+ // callbacks
8141
+ beforeClose: null,
8142
+ close: null,
8143
+ drag: null,
8144
+ dragStart: null,
8145
+ dragStop: null,
8146
+ focus: null,
8147
+ open: null,
8148
+ resize: null,
8149
+ resizeStart: null,
8150
+ resizeStop: null
8151
+ },
8152
+
8153
+ sizeRelatedOptions: {
8154
+ buttons: true,
8155
+ height: true,
8156
+ maxHeight: true,
8157
+ maxWidth: true,
8158
+ minHeight: true,
8159
+ minWidth: true,
8160
+ width: true
8161
+ },
8162
+
8163
+ resizableRelatedOptions: {
8164
+ maxHeight: true,
8165
+ maxWidth: true,
8166
+ minHeight: true,
8167
+ minWidth: true
8168
+ },
8169
+
8170
+ _create: function() {
8171
+ this.originalCss = {
8172
+ display: this.element[ 0 ].style.display,
8173
+ width: this.element[ 0 ].style.width,
8174
+ minHeight: this.element[ 0 ].style.minHeight,
8175
+ maxHeight: this.element[ 0 ].style.maxHeight,
8176
+ height: this.element[ 0 ].style.height
8177
+ };
8178
+ this.originalPosition = {
8179
+ parent: this.element.parent(),
8180
+ index: this.element.parent().children().index( this.element )
8181
+ };
8182
+ this.originalTitle = this.element.attr( "title" );
8183
+ this.options.title = this.options.title || this.originalTitle;
8184
+
8185
+ this._createWrapper();
8186
+
8187
+ this.element
8188
+ .show()
8189
+ .removeAttr( "title" )
8190
+ .addClass( "ui-dialog-content ui-widget-content" )
8191
+ .appendTo( this.uiDialog );
8192
+
8193
+ this._createTitlebar();
8194
+ this._createButtonPane();
8195
+
8196
+ if ( this.options.draggable && $.fn.draggable ) {
8197
+ this._makeDraggable();
8198
+ }
8199
+ if ( this.options.resizable && $.fn.resizable ) {
8200
+ this._makeResizable();
8201
+ }
8202
+
8203
+ this._isOpen = false;
8204
+
8205
+ this._trackFocus();
8206
+ },
8207
+
8208
+ _init: function() {
8209
+ if ( this.options.autoOpen ) {
8210
+ this.open();
8211
+ }
8212
+ },
8213
+
8214
+ _appendTo: function() {
8215
+ var element = this.options.appendTo;
8216
+ if ( element && (element.jquery || element.nodeType) ) {
8217
+ return $( element );
8218
+ }
8219
+ return this.document.find( element || "body" ).eq( 0 );
8220
+ },
8221
+
8222
+ _destroy: function() {
8223
+ var next,
8224
+ originalPosition = this.originalPosition;
8225
+
8226
+ this._untrackInstance();
8227
+ this._destroyOverlay();
8228
+
8229
+ this.element
8230
+ .removeUniqueId()
8231
+ .removeClass( "ui-dialog-content ui-widget-content" )
8232
+ .css( this.originalCss )
8233
+ // Without detaching first, the following becomes really slow
8234
+ .detach();
8235
+
8236
+ this.uiDialog.stop( true, true ).remove();
8237
+
8238
+ if ( this.originalTitle ) {
8239
+ this.element.attr( "title", this.originalTitle );
8240
+ }
8241
+
8242
+ next = originalPosition.parent.children().eq( originalPosition.index );
8243
+ // Don't try to place the dialog next to itself (#8613)
8244
+ if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
8245
+ next.before( this.element );
8246
+ } else {
8247
+ originalPosition.parent.append( this.element );
8248
+ }
8249
+ },
8250
+
8251
+ widget: function() {
8252
+ return this.uiDialog;
8253
+ },
8254
+
8255
+ disable: $.noop,
8256
+ enable: $.noop,
8257
+
8258
+ close: function( event ) {
8259
+ var activeElement,
8260
+ that = this;
8261
+
8262
+ if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
8263
+ return;
8264
+ }
8265
+
8266
+ this._isOpen = false;
8267
+ this._focusedElement = null;
8268
+ this._destroyOverlay();
8269
+ this._untrackInstance();
8270
+
8271
+ if ( !this.opener.filter( ":focusable" ).focus().length ) {
8272
+
8273
+ // support: IE9
8274
+ // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
8275
+ try {
8276
+ activeElement = this.document[ 0 ].activeElement;
8277
+
8278
+ // Support: IE9, IE10
8279
+ // If the <body> is blurred, IE will switch windows, see #4520
8280
+ if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) {
8281
+
8282
+ // Hiding a focused element doesn't trigger blur in WebKit
8283
+ // so in case we have nothing to focus on, explicitly blur the active element
8284
+ // https://bugs.webkit.org/show_bug.cgi?id=47182
8285
+ $( activeElement ).blur();
8286
+ }
8287
+ } catch ( error ) {}
8288
+ }
8289
+
8290
+ this._hide( this.uiDialog, this.options.hide, function() {
8291
+ that._trigger( "close", event );
8292
+ });
8293
+ },
8294
+
8295
+ isOpen: function() {
8296
+ return this._isOpen;
8297
+ },
8298
+
8299
+ moveToTop: function() {
8300
+ this._moveToTop();
8301
+ },
8302
+
8303
+ _moveToTop: function( event, silent ) {
8304
+ var moved = false,
8305
+ zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map(function() {
8306
+ return +$( this ).css( "z-index" );
8307
+ }).get(),
8308
+ zIndexMax = Math.max.apply( null, zIndices );
8309
+
8310
+ if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
8311
+ this.uiDialog.css( "z-index", zIndexMax + 1 );
8312
+ moved = true;
8313
+ }
8314
+
8315
+ if ( moved && !silent ) {
8316
+ this._trigger( "focus", event );
8317
+ }
8318
+ return moved;
8319
+ },
8320
+
8321
+ open: function() {
8322
+ var that = this;
8323
+ if ( this._isOpen ) {
8324
+ if ( this._moveToTop() ) {
8325
+ this._focusTabbable();
8326
+ }
8327
+ return;
8328
+ }
8329
+
8330
+ this._isOpen = true;
8331
+ this.opener = $( this.document[ 0 ].activeElement );
8332
+
8333
+ this._size();
8334
+ this._position();
8335
+ this._createOverlay();
8336
+ this._moveToTop( null, true );
8337
+
8338
+ // Ensure the overlay is moved to the top with the dialog, but only when
8339
+ // opening. The overlay shouldn't move after the dialog is open so that
8340
+ // modeless dialogs opened after the modal dialog stack properly.
8341
+ if ( this.overlay ) {
8342
+ this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
8343
+ }
8344
+
8345
+ this._show( this.uiDialog, this.options.show, function() {
8346
+ that._focusTabbable();
8347
+ that._trigger( "focus" );
8348
+ });
8349
+
8350
+ // Track the dialog immediately upon openening in case a focus event
8351
+ // somehow occurs outside of the dialog before an element inside the
8352
+ // dialog is focused (#10152)
8353
+ this._makeFocusTarget();
8354
+
8355
+ this._trigger( "open" );
8356
+ },
8357
+
8358
+ _focusTabbable: function() {
8359
+ // Set focus to the first match:
8360
+ // 1. An element that was focused previously
8361
+ // 2. First element inside the dialog matching [autofocus]
8362
+ // 3. Tabbable element inside the content element
8363
+ // 4. Tabbable element inside the buttonpane
8364
+ // 5. The close button
8365
+ // 6. The dialog itself
8366
+ var hasFocus = this._focusedElement;
8367
+ if ( !hasFocus ) {
8368
+ hasFocus = this.element.find( "[autofocus]" );
8369
+ }
8370
+ if ( !hasFocus.length ) {
8371
+ hasFocus = this.element.find( ":tabbable" );
8372
+ }
8373
+ if ( !hasFocus.length ) {
8374
+ hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
8375
+ }
8376
+ if ( !hasFocus.length ) {
8377
+ hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
8378
+ }
8379
+ if ( !hasFocus.length ) {
8380
+ hasFocus = this.uiDialog;
8381
+ }
8382
+ hasFocus.eq( 0 ).focus();
8383
+ },
8384
+
8385
+ _keepFocus: function( event ) {
8386
+ function checkFocus() {
8387
+ var activeElement = this.document[0].activeElement,
8388
+ isActive = this.uiDialog[0] === activeElement ||
8389
+ $.contains( this.uiDialog[0], activeElement );
8390
+ if ( !isActive ) {
8391
+ this._focusTabbable();
8392
+ }
8393
+ }
8394
+ event.preventDefault();
8395
+ checkFocus.call( this );
8396
+ // support: IE
8397
+ // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
8398
+ // so we check again later
8399
+ this._delay( checkFocus );
8400
+ },
8401
+
8402
+ _createWrapper: function() {
8403
+ this.uiDialog = $("<div>")
8404
+ .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
8405
+ this.options.dialogClass )
8406
+ .hide()
8407
+ .attr({
8408
+ // Setting tabIndex makes the div focusable
8409
+ tabIndex: -1,
8410
+ role: "dialog"
8411
+ })
8412
+ .appendTo( this._appendTo() );
8413
+
8414
+ this._on( this.uiDialog, {
8415
+ keydown: function( event ) {
8416
+ if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
8417
+ event.keyCode === $.ui.keyCode.ESCAPE ) {
8418
+ event.preventDefault();
8419
+ this.close( event );
8420
+ return;
8421
+ }
8422
+
8423
+ // prevent tabbing out of dialogs
8424
+ if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
8425
+ return;
8426
+ }
8427
+ var tabbables = this.uiDialog.find( ":tabbable" ),
8428
+ first = tabbables.filter( ":first" ),
8429
+ last = tabbables.filter( ":last" );
8430
+
8431
+ if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
8432
+ this._delay(function() {
8433
+ first.focus();
8434
+ });
8435
+ event.preventDefault();
8436
+ } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
8437
+ this._delay(function() {
8438
+ last.focus();
8439
+ });
8440
+ event.preventDefault();
8441
+ }
8442
+ },
8443
+ mousedown: function( event ) {
8444
+ if ( this._moveToTop( event ) ) {
8445
+ this._focusTabbable();
8446
+ }
8447
+ }
8448
+ });
8449
+
8450
+ // We assume that any existing aria-describedby attribute means
8451
+ // that the dialog content is marked up properly
8452
+ // otherwise we brute force the content as the description
8453
+ if ( !this.element.find( "[aria-describedby]" ).length ) {
8454
+ this.uiDialog.attr({
8455
+ "aria-describedby": this.element.uniqueId().attr( "id" )
8456
+ });
8457
+ }
8458
+ },
8459
+
8460
+ _createTitlebar: function() {
8461
+ var uiDialogTitle;
8462
+
8463
+ this.uiDialogTitlebar = $( "<div>" )
8464
+ .addClass( "ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" )
8465
+ .prependTo( this.uiDialog );
8466
+ this._on( this.uiDialogTitlebar, {
8467
+ mousedown: function( event ) {
8468
+ // Don't prevent click on close button (#8838)
8469
+ // Focusing a dialog that is partially scrolled out of view
8470
+ // causes the browser to scroll it into view, preventing the click event
8471
+ if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
8472
+ // Dialog isn't getting focus when dragging (#8063)
8473
+ this.uiDialog.focus();
8474
+ }
8475
+ }
8476
+ });
8477
+
8478
+ // support: IE
8479
+ // Use type="button" to prevent enter keypresses in textboxes from closing the
8480
+ // dialog in IE (#9312)
8481
+ this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
8482
+ .button({
8483
+ label: this.options.closeText,
8484
+ icons: {
8485
+ primary: "ui-icon-closethick"
8486
+ },
8487
+ text: false
8488
+ })
8489
+ .addClass( "ui-dialog-titlebar-close" )
8490
+ .appendTo( this.uiDialogTitlebar );
8491
+ this._on( this.uiDialogTitlebarClose, {
8492
+ click: function( event ) {
8493
+ event.preventDefault();
8494
+ this.close( event );
8495
+ }
8496
+ });
8497
+
8498
+ uiDialogTitle = $( "<span>" )
8499
+ .uniqueId()
8500
+ .addClass( "ui-dialog-title" )
8501
+ .prependTo( this.uiDialogTitlebar );
8502
+ this._title( uiDialogTitle );
8503
+
8504
+ this.uiDialog.attr({
8505
+ "aria-labelledby": uiDialogTitle.attr( "id" )
8506
+ });
8507
+ },
8508
+
8509
+ _title: function( title ) {
8510
+ if ( !this.options.title ) {
8511
+ title.html( "&#160;" );
8512
+ }
8513
+ title.text( this.options.title );
8514
+ },
8515
+
8516
+ _createButtonPane: function() {
8517
+ this.uiDialogButtonPane = $( "<div>" )
8518
+ .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" );
8519
+
8520
+ this.uiButtonSet = $( "<div>" )
8521
+ .addClass( "ui-dialog-buttonset" )
8522
+ .appendTo( this.uiDialogButtonPane );
8523
+
8524
+ this._createButtons();
8525
+ },
8526
+
8527
+ _createButtons: function() {
8528
+ var that = this,
8529
+ buttons = this.options.buttons;
8530
+
8531
+ // if we already have a button pane, remove it
8532
+ this.uiDialogButtonPane.remove();
8533
+ this.uiButtonSet.empty();
8534
+
8535
+ if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
8536
+ this.uiDialog.removeClass( "ui-dialog-buttons" );
8537
+ return;
8538
+ }
8539
+
8540
+ $.each( buttons, function( name, props ) {
8541
+ var click, buttonOptions;
8542
+ props = $.isFunction( props ) ?
8543
+ { click: props, text: name } :
8544
+ props;
8545
+ // Default to a non-submitting button
8546
+ props = $.extend( { type: "button" }, props );
8547
+ // Change the context for the click callback to be the main element
8548
+ click = props.click;
8549
+ props.click = function() {
8550
+ click.apply( that.element[ 0 ], arguments );
8551
+ };
8552
+ buttonOptions = {
8553
+ icons: props.icons,
8554
+ text: props.showText
8555
+ };
8556
+ delete props.icons;
8557
+ delete props.showText;
8558
+ $( "<button></button>", props )
8559
+ .button( buttonOptions )
8560
+ .appendTo( that.uiButtonSet );
8561
+ });
8562
+ this.uiDialog.addClass( "ui-dialog-buttons" );
8563
+ this.uiDialogButtonPane.appendTo( this.uiDialog );
8564
+ },
8565
+
8566
+ _makeDraggable: function() {
8567
+ var that = this,
8568
+ options = this.options;
8569
+
8570
+ function filteredUi( ui ) {
8571
+ return {
8572
+ position: ui.position,
8573
+ offset: ui.offset
8574
+ };
8575
+ }
8576
+
8577
+ this.uiDialog.draggable({
8578
+ cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
8579
+ handle: ".ui-dialog-titlebar",
8580
+ containment: "document",
8581
+ start: function( event, ui ) {
8582
+ $( this ).addClass( "ui-dialog-dragging" );
8583
+ that._blockFrames();
8584
+ that._trigger( "dragStart", event, filteredUi( ui ) );
8585
+ },
8586
+ drag: function( event, ui ) {
8587
+ that._trigger( "drag", event, filteredUi( ui ) );
8588
+ },
8589
+ stop: function( event, ui ) {
8590
+ var left = ui.offset.left - that.document.scrollLeft(),
8591
+ top = ui.offset.top - that.document.scrollTop();
8592
+
8593
+ options.position = {
8594
+ my: "left top",
8595
+ at: "left" + (left >= 0 ? "+" : "") + left + " " +
8596
+ "top" + (top >= 0 ? "+" : "") + top,
8597
+ of: that.window
8598
+ };
8599
+ $( this ).removeClass( "ui-dialog-dragging" );
8600
+ that._unblockFrames();
8601
+ that._trigger( "dragStop", event, filteredUi( ui ) );
8602
+ }
8603
+ });
8604
+ },
8605
+
8606
+ _makeResizable: function() {
8607
+ var that = this,
8608
+ options = this.options,
8609
+ handles = options.resizable,
8610
+ // .ui-resizable has position: relative defined in the stylesheet
8611
+ // but dialogs have to use absolute or fixed positioning
8612
+ position = this.uiDialog.css("position"),
8613
+ resizeHandles = typeof handles === "string" ?
8614
+ handles :
8615
+ "n,e,s,w,se,sw,ne,nw";
8616
+
8617
+ function filteredUi( ui ) {
8618
+ return {
8619
+ originalPosition: ui.originalPosition,
8620
+ originalSize: ui.originalSize,
8621
+ position: ui.position,
8622
+ size: ui.size
8623
+ };
8624
+ }
8625
+
8626
+ this.uiDialog.resizable({
8627
+ cancel: ".ui-dialog-content",
8628
+ containment: "document",
8629
+ alsoResize: this.element,
8630
+ maxWidth: options.maxWidth,
8631
+ maxHeight: options.maxHeight,
8632
+ minWidth: options.minWidth,
8633
+ minHeight: this._minHeight(),
8634
+ handles: resizeHandles,
8635
+ start: function( event, ui ) {
8636
+ $( this ).addClass( "ui-dialog-resizing" );
8637
+ that._blockFrames();
8638
+ that._trigger( "resizeStart", event, filteredUi( ui ) );
8639
+ },
8640
+ resize: function( event, ui ) {
8641
+ that._trigger( "resize", event, filteredUi( ui ) );
8642
+ },
8643
+ stop: function( event, ui ) {
8644
+ var offset = that.uiDialog.offset(),
8645
+ left = offset.left - that.document.scrollLeft(),
8646
+ top = offset.top - that.document.scrollTop();
8647
+
8648
+ options.height = that.uiDialog.height();
8649
+ options.width = that.uiDialog.width();
8650
+ options.position = {
8651
+ my: "left top",
8652
+ at: "left" + (left >= 0 ? "+" : "") + left + " " +
8653
+ "top" + (top >= 0 ? "+" : "") + top,
8654
+ of: that.window
8655
+ };
8656
+ $( this ).removeClass( "ui-dialog-resizing" );
8657
+ that._unblockFrames();
8658
+ that._trigger( "resizeStop", event, filteredUi( ui ) );
8659
+ }
8660
+ })
8661
+ .css( "position", position );
8662
+ },
8663
+
8664
+ _trackFocus: function() {
8665
+ this._on( this.widget(), {
8666
+ focusin: function( event ) {
8667
+ this._makeFocusTarget();
8668
+ this._focusedElement = $( event.target );
8669
+ }
8670
+ });
8671
+ },
8672
+
8673
+ _makeFocusTarget: function() {
8674
+ this._untrackInstance();
8675
+ this._trackingInstances().unshift( this );
8676
+ },
8677
+
8678
+ _untrackInstance: function() {
8679
+ var instances = this._trackingInstances(),
8680
+ exists = $.inArray( this, instances );
8681
+ if ( exists !== -1 ) {
8682
+ instances.splice( exists, 1 );
8683
+ }
8684
+ },
8685
+
8686
+ _trackingInstances: function() {
8687
+ var instances = this.document.data( "ui-dialog-instances" );
8688
+ if ( !instances ) {
8689
+ instances = [];
8690
+ this.document.data( "ui-dialog-instances", instances );
8691
+ }
8692
+ return instances;
8693
+ },
8694
+
8695
+ _minHeight: function() {
8696
+ var options = this.options;
8697
+
8698
+ return options.height === "auto" ?
8699
+ options.minHeight :
8700
+ Math.min( options.minHeight, options.height );
8701
+ },
8702
+
8703
+ _position: function() {
8704
+ // Need to show the dialog to get the actual offset in the position plugin
8705
+ var isVisible = this.uiDialog.is( ":visible" );
8706
+ if ( !isVisible ) {
8707
+ this.uiDialog.show();
8708
+ }
8709
+ this.uiDialog.position( this.options.position );
8710
+ if ( !isVisible ) {
8711
+ this.uiDialog.hide();
8712
+ }
8713
+ },
8714
+
8715
+ _setOptions: function( options ) {
8716
+ var that = this,
8717
+ resize = false,
8718
+ resizableOptions = {};
8719
+
8720
+ $.each( options, function( key, value ) {
8721
+ that._setOption( key, value );
8722
+
8723
+ if ( key in that.sizeRelatedOptions ) {
8724
+ resize = true;
8725
+ }
8726
+ if ( key in that.resizableRelatedOptions ) {
8727
+ resizableOptions[ key ] = value;
8728
+ }
8729
+ });
8730
+
8731
+ if ( resize ) {
8732
+ this._size();
8733
+ this._position();
8734
+ }
8735
+ if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
8736
+ this.uiDialog.resizable( "option", resizableOptions );
8737
+ }
8738
+ },
8739
+
8740
+ _setOption: function( key, value ) {
8741
+ var isDraggable, isResizable,
8742
+ uiDialog = this.uiDialog;
8743
+
8744
+ if ( key === "dialogClass" ) {
8745
+ uiDialog
8746
+ .removeClass( this.options.dialogClass )
8747
+ .addClass( value );
8748
+ }
8749
+
8750
+ if ( key === "disabled" ) {
8751
+ return;
8752
+ }
8753
+
8754
+ this._super( key, value );
8755
+
8756
+ if ( key === "appendTo" ) {
8757
+ this.uiDialog.appendTo( this._appendTo() );
8758
+ }
8759
+
8760
+ if ( key === "buttons" ) {
8761
+ this._createButtons();
8762
+ }
8763
+
8764
+ if ( key === "closeText" ) {
8765
+ this.uiDialogTitlebarClose.button({
8766
+ // Ensure that we always pass a string
8767
+ label: "" + value
8768
+ });
8769
+ }
8770
+
8771
+ if ( key === "draggable" ) {
8772
+ isDraggable = uiDialog.is( ":data(ui-draggable)" );
8773
+ if ( isDraggable && !value ) {
8774
+ uiDialog.draggable( "destroy" );
8775
+ }
8776
+
8777
+ if ( !isDraggable && value ) {
8778
+ this._makeDraggable();
8779
+ }
8780
+ }
8781
+
8782
+ if ( key === "position" ) {
8783
+ this._position();
8784
+ }
8785
+
8786
+ if ( key === "resizable" ) {
8787
+ // currently resizable, becoming non-resizable
8788
+ isResizable = uiDialog.is( ":data(ui-resizable)" );
8789
+ if ( isResizable && !value ) {
8790
+ uiDialog.resizable( "destroy" );
8791
+ }
8792
+
8793
+ // currently resizable, changing handles
8794
+ if ( isResizable && typeof value === "string" ) {
8795
+ uiDialog.resizable( "option", "handles", value );
8796
+ }
8797
+
8798
+ // currently non-resizable, becoming resizable
8799
+ if ( !isResizable && value !== false ) {
8800
+ this._makeResizable();
8801
+ }
8802
+ }
8803
+
8804
+ if ( key === "title" ) {
8805
+ this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
8806
+ }
8807
+ },
8808
+
8809
+ _size: function() {
8810
+ // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
8811
+ // divs will both have width and height set, so we need to reset them
8812
+ var nonContentHeight, minContentHeight, maxContentHeight,
8813
+ options = this.options;
8814
+
8815
+ // Reset content sizing
8816
+ this.element.show().css({
8817
+ width: "auto",
8818
+ minHeight: 0,
8819
+ maxHeight: "none",
8820
+ height: 0
8821
+ });
8822
+
8823
+ if ( options.minWidth > options.width ) {
8824
+ options.width = options.minWidth;
8825
+ }
8826
+
8827
+ // reset wrapper sizing
8828
+ // determine the height of all the non-content elements
8829
+ nonContentHeight = this.uiDialog.css({
8830
+ height: "auto",
8831
+ width: options.width
8832
+ })
8833
+ .outerHeight();
8834
+ minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
8835
+ maxContentHeight = typeof options.maxHeight === "number" ?
8836
+ Math.max( 0, options.maxHeight - nonContentHeight ) :
8837
+ "none";
8838
+
8839
+ if ( options.height === "auto" ) {
8840
+ this.element.css({
8841
+ minHeight: minContentHeight,
8842
+ maxHeight: maxContentHeight,
8843
+ height: "auto"
8844
+ });
8845
+ } else {
8846
+ this.element.height( Math.max( 0, options.height - nonContentHeight ) );
8847
+ }
8848
+
8849
+ if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
8850
+ this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
8851
+ }
8852
+ },
8853
+
8854
+ _blockFrames: function() {
8855
+ this.iframeBlocks = this.document.find( "iframe" ).map(function() {
8856
+ var iframe = $( this );
8857
+
8858
+ return $( "<div>" )
8859
+ .css({
8860
+ position: "absolute",
8861
+ width: iframe.outerWidth(),
8862
+ height: iframe.outerHeight()
8863
+ })
8864
+ .appendTo( iframe.parent() )
8865
+ .offset( iframe.offset() )[0];
8866
+ });
8867
+ },
8868
+
8869
+ _unblockFrames: function() {
8870
+ if ( this.iframeBlocks ) {
8871
+ this.iframeBlocks.remove();
8872
+ delete this.iframeBlocks;
8873
+ }
8874
+ },
8875
+
8876
+ _allowInteraction: function( event ) {
8877
+ if ( $( event.target ).closest( ".ui-dialog" ).length ) {
8878
+ return true;
8879
+ }
8880
+
8881
+ // TODO: Remove hack when datepicker implements
8882
+ // the .ui-front logic (#8989)
8883
+ return !!$( event.target ).closest( ".ui-datepicker" ).length;
8884
+ },
8885
+
8886
+ _createOverlay: function() {
8887
+ if ( !this.options.modal ) {
8888
+ return;
8889
+ }
8890
+
8891
+ // We use a delay in case the overlay is created from an
8892
+ // event that we're going to be cancelling (#2804)
8893
+ var isOpening = true;
8894
+ this._delay(function() {
8895
+ isOpening = false;
8896
+ });
8897
+
8898
+ if ( !this.document.data( "ui-dialog-overlays" ) ) {
8899
+
8900
+ // Prevent use of anchors and inputs
8901
+ // Using _on() for an event handler shared across many instances is
8902
+ // safe because the dialogs stack and must be closed in reverse order
8903
+ this._on( this.document, {
8904
+ focusin: function( event ) {
8905
+ if ( isOpening ) {
8906
+ return;
8907
+ }
8908
+
8909
+ if ( !this._allowInteraction( event ) ) {
8910
+ event.preventDefault();
8911
+ this._trackingInstances()[ 0 ]._focusTabbable();
8912
+ }
8913
+ }
8914
+ });
8915
+ }
8916
+
8917
+ this.overlay = $( "<div>" )
8918
+ .addClass( "ui-widget-overlay ui-front" )
8919
+ .appendTo( this._appendTo() );
8920
+ this._on( this.overlay, {
8921
+ mousedown: "_keepFocus"
8922
+ });
8923
+ this.document.data( "ui-dialog-overlays",
8924
+ (this.document.data( "ui-dialog-overlays" ) || 0) + 1 );
8925
+ },
8926
+
8927
+ _destroyOverlay: function() {
8928
+ if ( !this.options.modal ) {
8929
+ return;
8930
+ }
8931
+
8932
+ if ( this.overlay ) {
8933
+ var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
8934
+
8935
+ if ( !overlays ) {
8936
+ this.document
8937
+ .unbind( "focusin" )
8938
+ .removeData( "ui-dialog-overlays" );
8939
+ } else {
8940
+ this.document.data( "ui-dialog-overlays", overlays );
8941
+ }
8942
+
8943
+ this.overlay.remove();
8944
+ this.overlay = null;
8945
+ }
8946
+ }
8947
+ });
8948
+
8949
+
8950
+ /*!
8951
+ * jQuery UI Droppable 1.11.4
8952
+ * http://jqueryui.com
8953
+ *
8954
+ * Copyright jQuery Foundation and other contributors
8955
+ * Released under the MIT license.
8956
+ * http://jquery.org/license
8957
+ *
8958
+ * http://api.jqueryui.com/droppable/
8959
+ */
8960
+
8961
+
8962
+ $.widget( "ui.droppable", {
8963
+ version: "1.11.4",
8964
+ widgetEventPrefix: "drop",
8965
+ options: {
8966
+ accept: "*",
8967
+ activeClass: false,
8968
+ addClasses: true,
8969
+ greedy: false,
8970
+ hoverClass: false,
8971
+ scope: "default",
8972
+ tolerance: "intersect",
8973
+
8974
+ // callbacks
8975
+ activate: null,
8976
+ deactivate: null,
8977
+ drop: null,
8978
+ out: null,
8979
+ over: null
8980
+ },
8981
+ _create: function() {
8982
+
8983
+ var proportions,
8984
+ o = this.options,
8985
+ accept = o.accept;
8986
+
8987
+ this.isover = false;
8988
+ this.isout = true;
8989
+
8990
+ this.accept = $.isFunction( accept ) ? accept : function( d ) {
8991
+ return d.is( accept );
8992
+ };
8993
+
8994
+ this.proportions = function( /* valueToWrite */ ) {
8995
+ if ( arguments.length ) {
8996
+ // Store the droppable's proportions
8997
+ proportions = arguments[ 0 ];
8998
+ } else {
8999
+ // Retrieve or derive the droppable's proportions
9000
+ return proportions ?
9001
+ proportions :
9002
+ proportions = {
9003
+ width: this.element[ 0 ].offsetWidth,
9004
+ height: this.element[ 0 ].offsetHeight
9005
+ };
9006
+ }
9007
+ };
9008
+
9009
+ this._addToManager( o.scope );
9010
+
9011
+ o.addClasses && this.element.addClass( "ui-droppable" );
9012
+
9013
+ },
9014
+
9015
+ _addToManager: function( scope ) {
9016
+ // Add the reference and positions to the manager
9017
+ $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
9018
+ $.ui.ddmanager.droppables[ scope ].push( this );
9019
+ },
9020
+
9021
+ _splice: function( drop ) {
9022
+ var i = 0;
9023
+ for ( ; i < drop.length; i++ ) {
9024
+ if ( drop[ i ] === this ) {
9025
+ drop.splice( i, 1 );
9026
+ }
9027
+ }
9028
+ },
9029
+
9030
+ _destroy: function() {
9031
+ var drop = $.ui.ddmanager.droppables[ this.options.scope ];
9032
+
9033
+ this._splice( drop );
9034
+
9035
+ this.element.removeClass( "ui-droppable ui-droppable-disabled" );
9036
+ },
9037
+
9038
+ _setOption: function( key, value ) {
9039
+
9040
+ if ( key === "accept" ) {
9041
+ this.accept = $.isFunction( value ) ? value : function( d ) {
9042
+ return d.is( value );
9043
+ };
9044
+ } else if ( key === "scope" ) {
9045
+ var drop = $.ui.ddmanager.droppables[ this.options.scope ];
9046
+
9047
+ this._splice( drop );
9048
+ this._addToManager( value );
9049
+ }
9050
+
9051
+ this._super( key, value );
9052
+ },
9053
+
9054
+ _activate: function( event ) {
9055
+ var draggable = $.ui.ddmanager.current;
9056
+ if ( this.options.activeClass ) {
9057
+ this.element.addClass( this.options.activeClass );
9058
+ }
9059
+ if ( draggable ){
9060
+ this._trigger( "activate", event, this.ui( draggable ) );
9061
+ }
9062
+ },
9063
+
9064
+ _deactivate: function( event ) {
9065
+ var draggable = $.ui.ddmanager.current;
9066
+ if ( this.options.activeClass ) {
9067
+ this.element.removeClass( this.options.activeClass );
9068
+ }
9069
+ if ( draggable ){
9070
+ this._trigger( "deactivate", event, this.ui( draggable ) );
9071
+ }
9072
+ },
9073
+
9074
+ _over: function( event ) {
9075
+
9076
+ var draggable = $.ui.ddmanager.current;
9077
+
9078
+ // Bail if draggable and droppable are same element
9079
+ if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
9080
+ return;
9081
+ }
9082
+
9083
+ if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9084
+ if ( this.options.hoverClass ) {
9085
+ this.element.addClass( this.options.hoverClass );
9086
+ }
9087
+ this._trigger( "over", event, this.ui( draggable ) );
9088
+ }
9089
+
9090
+ },
9091
+
9092
+ _out: function( event ) {
9093
+
9094
+ var draggable = $.ui.ddmanager.current;
9095
+
9096
+ // Bail if draggable and droppable are same element
9097
+ if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
9098
+ return;
9099
+ }
9100
+
9101
+ if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9102
+ if ( this.options.hoverClass ) {
9103
+ this.element.removeClass( this.options.hoverClass );
9104
+ }
9105
+ this._trigger( "out", event, this.ui( draggable ) );
9106
+ }
9107
+
9108
+ },
9109
+
9110
+ _drop: function( event, custom ) {
9111
+
9112
+ var draggable = custom || $.ui.ddmanager.current,
9113
+ childrenIntersection = false;
9114
+
9115
+ // Bail if draggable and droppable are same element
9116
+ if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) {
9117
+ return false;
9118
+ }
9119
+
9120
+ this.element.find( ":data(ui-droppable)" ).not( ".ui-draggable-dragging" ).each(function() {
9121
+ var inst = $( this ).droppable( "instance" );
9122
+ if (
9123
+ inst.options.greedy &&
9124
+ !inst.options.disabled &&
9125
+ inst.options.scope === draggable.options.scope &&
9126
+ inst.accept.call( inst.element[ 0 ], ( draggable.currentItem || draggable.element ) ) &&
9127
+ $.ui.intersect( draggable, $.extend( inst, { offset: inst.element.offset() } ), inst.options.tolerance, event )
9128
+ ) { childrenIntersection = true; return false; }
9129
+ });
9130
+ if ( childrenIntersection ) {
9131
+ return false;
9132
+ }
9133
+
9134
+ if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9135
+ if ( this.options.activeClass ) {
9136
+ this.element.removeClass( this.options.activeClass );
9137
+ }
9138
+ if ( this.options.hoverClass ) {
9139
+ this.element.removeClass( this.options.hoverClass );
9140
+ }
9141
+ this._trigger( "drop", event, this.ui( draggable ) );
9142
+ return this.element;
9143
+ }
9144
+
9145
+ return false;
9146
+
9147
+ },
9148
+
9149
+ ui: function( c ) {
9150
+ return {
9151
+ draggable: ( c.currentItem || c.element ),
9152
+ helper: c.helper,
9153
+ position: c.position,
9154
+ offset: c.positionAbs
9155
+ };
9156
+ }
9157
+
9158
+ });
9159
+
9160
+ $.ui.intersect = (function() {
9161
+ function isOverAxis( x, reference, size ) {
9162
+ return ( x >= reference ) && ( x < ( reference + size ) );
9163
+ }
9164
+
9165
+ return function( draggable, droppable, toleranceMode, event ) {
9166
+
9167
+ if ( !droppable.offset ) {
9168
+ return false;
9169
+ }
9170
+
9171
+ var x1 = ( draggable.positionAbs || draggable.position.absolute ).left + draggable.margins.left,
9172
+ y1 = ( draggable.positionAbs || draggable.position.absolute ).top + draggable.margins.top,
9173
+ x2 = x1 + draggable.helperProportions.width,
9174
+ y2 = y1 + draggable.helperProportions.height,
9175
+ l = droppable.offset.left,
9176
+ t = droppable.offset.top,
9177
+ r = l + droppable.proportions().width,
9178
+ b = t + droppable.proportions().height;
9179
+
9180
+ switch ( toleranceMode ) {
9181
+ case "fit":
9182
+ return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
9183
+ case "intersect":
9184
+ return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
9185
+ x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
9186
+ t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
9187
+ y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
9188
+ case "pointer":
9189
+ return isOverAxis( event.pageY, t, droppable.proportions().height ) && isOverAxis( event.pageX, l, droppable.proportions().width );
9190
+ case "touch":
9191
+ return (
9192
+ ( y1 >= t && y1 <= b ) || // Top edge touching
9193
+ ( y2 >= t && y2 <= b ) || // Bottom edge touching
9194
+ ( y1 < t && y2 > b ) // Surrounded vertically
9195
+ ) && (
9196
+ ( x1 >= l && x1 <= r ) || // Left edge touching
9197
+ ( x2 >= l && x2 <= r ) || // Right edge touching
9198
+ ( x1 < l && x2 > r ) // Surrounded horizontally
9199
+ );
9200
+ default:
9201
+ return false;
9202
+ }
9203
+ };
9204
+ })();
9205
+
9206
+ /*
9207
+ This manager tracks offsets of draggables and droppables
9208
+ */
9209
+ $.ui.ddmanager = {
9210
+ current: null,
9211
+ droppables: { "default": [] },
9212
+ prepareOffsets: function( t, event ) {
9213
+
9214
+ var i, j,
9215
+ m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
9216
+ type = event ? event.type : null, // workaround for #2317
9217
+ list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
9218
+
9219
+ droppablesLoop: for ( i = 0; i < m.length; i++ ) {
9220
+
9221
+ // No disabled and non-accepted
9222
+ if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], ( t.currentItem || t.element ) ) ) ) {
9223
+ continue;
9224
+ }
9225
+
9226
+ // Filter out elements in the current dragged item
9227
+ for ( j = 0; j < list.length; j++ ) {
9228
+ if ( list[ j ] === m[ i ].element[ 0 ] ) {
9229
+ m[ i ].proportions().height = 0;
9230
+ continue droppablesLoop;
9231
+ }
9232
+ }
9233
+
9234
+ m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
9235
+ if ( !m[ i ].visible ) {
9236
+ continue;
9237
+ }
9238
+
9239
+ // Activate the droppable if used directly from draggables
9240
+ if ( type === "mousedown" ) {
9241
+ m[ i ]._activate.call( m[ i ], event );
9242
+ }
9243
+
9244
+ m[ i ].offset = m[ i ].element.offset();
9245
+ m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight });
9246
+
9247
+ }
9248
+
9249
+ },
9250
+ drop: function( draggable, event ) {
9251
+
9252
+ var dropped = false;
9253
+ // Create a copy of the droppables in case the list changes during the drop (#9116)
9254
+ $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
9255
+
9256
+ if ( !this.options ) {
9257
+ return;
9258
+ }
9259
+ if ( !this.options.disabled && this.visible && $.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
9260
+ dropped = this._drop.call( this, event ) || dropped;
9261
+ }
9262
+
9263
+ if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) {
9264
+ this.isout = true;
9265
+ this.isover = false;
9266
+ this._deactivate.call( this, event );
9267
+ }
9268
+
9269
+ });
9270
+ return dropped;
9271
+
9272
+ },
9273
+ dragStart: function( draggable, event ) {
9274
+ // Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
9275
+ draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
9276
+ if ( !draggable.options.refreshPositions ) {
9277
+ $.ui.ddmanager.prepareOffsets( draggable, event );
9278
+ }
9279
+ });
9280
+ },
9281
+ drag: function( draggable, event ) {
9282
+
9283
+ // If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
9284
+ if ( draggable.options.refreshPositions ) {
9285
+ $.ui.ddmanager.prepareOffsets( draggable, event );
9286
+ }
9287
+
9288
+ // Run through all droppables and check their positions based on specific tolerance options
9289
+ $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
9290
+
9291
+ if ( this.options.disabled || this.greedyChild || !this.visible ) {
9292
+ return;
9293
+ }
9294
+
9295
+ var parentInstance, scope, parent,
9296
+ intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
9297
+ c = !intersects && this.isover ? "isout" : ( intersects && !this.isover ? "isover" : null );
9298
+ if ( !c ) {
9299
+ return;
9300
+ }
9301
+
9302
+ if ( this.options.greedy ) {
9303
+ // find droppable parents with same scope
9304
+ scope = this.options.scope;
9305
+ parent = this.element.parents( ":data(ui-droppable)" ).filter(function() {
9306
+ return $( this ).droppable( "instance" ).options.scope === scope;
9307
+ });
9308
+
9309
+ if ( parent.length ) {
9310
+ parentInstance = $( parent[ 0 ] ).droppable( "instance" );
9311
+ parentInstance.greedyChild = ( c === "isover" );
9312
+ }
9313
+ }
9314
+
9315
+ // we just moved into a greedy child
9316
+ if ( parentInstance && c === "isover" ) {
9317
+ parentInstance.isover = false;
9318
+ parentInstance.isout = true;
9319
+ parentInstance._out.call( parentInstance, event );
9320
+ }
9321
+
9322
+ this[ c ] = true;
9323
+ this[c === "isout" ? "isover" : "isout"] = false;
9324
+ this[c === "isover" ? "_over" : "_out"].call( this, event );
9325
+
9326
+ // we just moved out of a greedy child
9327
+ if ( parentInstance && c === "isout" ) {
9328
+ parentInstance.isout = false;
9329
+ parentInstance.isover = true;
9330
+ parentInstance._over.call( parentInstance, event );
9331
+ }
9332
+ });
9333
+
9334
+ },
9335
+ dragStop: function( draggable, event ) {
9336
+ draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
9337
+ // Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
9338
+ if ( !draggable.options.refreshPositions ) {
9339
+ $.ui.ddmanager.prepareOffsets( draggable, event );
9340
+ }
9341
+ }
9342
+ };
9343
+
9344
+ var droppable = $.ui.droppable;
9345
+
9346
+
9347
+ /*!
9348
+ * jQuery UI Effects 1.11.4
9349
+ * http://jqueryui.com
9350
+ *
9351
+ * Copyright jQuery Foundation and other contributors
9352
+ * Released under the MIT license.
9353
+ * http://jquery.org/license
9354
+ *
9355
+ * http://api.jqueryui.com/category/effects-core/
9356
+ */
9357
+
9358
+
9359
+ var dataSpace = "ui-effects-",
9360
+
9361
+ // Create a local jQuery because jQuery Color relies on it and the
9362
+ // global may not exist with AMD and a custom build (#10199)
9363
+ jQuery = $;
9364
+
9365
+ $.effects = {
9366
+ effect: {}
9367
+ };
9368
+
9369
+ /*!
9370
+ * jQuery Color Animations v2.1.2
9371
+ * https://github.com/jquery/jquery-color
9372
+ *
9373
+ * Copyright 2014 jQuery Foundation and other contributors
9374
+ * Released under the MIT license.
9375
+ * http://jquery.org/license
9376
+ *
9377
+ * Date: Wed Jan 16 08:47:09 2013 -0600
9378
+ */
9379
+ (function( jQuery, undefined ) {
9380
+
9381
+ var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
9382
+
9383
+ // plusequals test for += 100 -= 100
9384
+ rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
9385
+ // a set of RE's that can match strings and generate color tuples.
9386
+ stringParsers = [ {
9387
+ re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9388
+ parse: function( execResult ) {
9389
+ return [
9390
+ execResult[ 1 ],
9391
+ execResult[ 2 ],
9392
+ execResult[ 3 ],
9393
+ execResult[ 4 ]
9394
+ ];
9395
+ }
9396
+ }, {
9397
+ re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9398
+ parse: function( execResult ) {
9399
+ return [
9400
+ execResult[ 1 ] * 2.55,
9401
+ execResult[ 2 ] * 2.55,
9402
+ execResult[ 3 ] * 2.55,
9403
+ execResult[ 4 ]
9404
+ ];
9405
+ }
9406
+ }, {
9407
+ // this regex ignores A-F because it's compared against an already lowercased string
9408
+ re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
9409
+ parse: function( execResult ) {
9410
+ return [
9411
+ parseInt( execResult[ 1 ], 16 ),
9412
+ parseInt( execResult[ 2 ], 16 ),
9413
+ parseInt( execResult[ 3 ], 16 )
9414
+ ];
9415
+ }
9416
+ }, {
9417
+ // this regex ignores A-F because it's compared against an already lowercased string
9418
+ re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
9419
+ parse: function( execResult ) {
9420
+ return [
9421
+ parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
9422
+ parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
9423
+ parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
9424
+ ];
9425
+ }
9426
+ }, {
9427
+ re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
9428
+ space: "hsla",
9429
+ parse: function( execResult ) {
9430
+ return [
9431
+ execResult[ 1 ],
9432
+ execResult[ 2 ] / 100,
9433
+ execResult[ 3 ] / 100,
9434
+ execResult[ 4 ]
9435
+ ];
9436
+ }
9437
+ } ],
9438
+
9439
+ // jQuery.Color( )
9440
+ color = jQuery.Color = function( color, green, blue, alpha ) {
9441
+ return new jQuery.Color.fn.parse( color, green, blue, alpha );
9442
+ },
9443
+ spaces = {
9444
+ rgba: {
9445
+ props: {
9446
+ red: {
9447
+ idx: 0,
9448
+ type: "byte"
9449
+ },
9450
+ green: {
9451
+ idx: 1,
9452
+ type: "byte"
9453
+ },
9454
+ blue: {
9455
+ idx: 2,
9456
+ type: "byte"
9457
+ }
9458
+ }
9459
+ },
9460
+
9461
+ hsla: {
9462
+ props: {
9463
+ hue: {
9464
+ idx: 0,
9465
+ type: "degrees"
9466
+ },
9467
+ saturation: {
9468
+ idx: 1,
9469
+ type: "percent"
9470
+ },
9471
+ lightness: {
9472
+ idx: 2,
9473
+ type: "percent"
9474
+ }
9475
+ }
9476
+ }
9477
+ },
9478
+ propTypes = {
9479
+ "byte": {
9480
+ floor: true,
9481
+ max: 255
9482
+ },
9483
+ "percent": {
9484
+ max: 1
9485
+ },
9486
+ "degrees": {
9487
+ mod: 360,
9488
+ floor: true
9489
+ }
9490
+ },
9491
+ support = color.support = {},
9492
+
9493
+ // element for support tests
9494
+ supportElem = jQuery( "<p>" )[ 0 ],
9495
+
9496
+ // colors = jQuery.Color.names
9497
+ colors,
9498
+
9499
+ // local aliases of functions called often
9500
+ each = jQuery.each;
9501
+
9502
+ // determine rgba support immediately
9503
+ supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
9504
+ support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
9505
+
9506
+ // define cache name and alpha properties
9507
+ // for rgba and hsla spaces
9508
+ each( spaces, function( spaceName, space ) {
9509
+ space.cache = "_" + spaceName;
9510
+ space.props.alpha = {
9511
+ idx: 3,
9512
+ type: "percent",
9513
+ def: 1
9514
+ };
9515
+ });
9516
+
9517
+ function clamp( value, prop, allowEmpty ) {
9518
+ var type = propTypes[ prop.type ] || {};
9519
+
9520
+ if ( value == null ) {
9521
+ return (allowEmpty || !prop.def) ? null : prop.def;
9522
+ }
9523
+
9524
+ // ~~ is an short way of doing floor for positive numbers
9525
+ value = type.floor ? ~~value : parseFloat( value );
9526
+
9527
+ // IE will pass in empty strings as value for alpha,
9528
+ // which will hit this case
9529
+ if ( isNaN( value ) ) {
9530
+ return prop.def;
9531
+ }
9532
+
9533
+ if ( type.mod ) {
9534
+ // we add mod before modding to make sure that negatives values
9535
+ // get converted properly: -10 -> 350
9536
+ return (value + type.mod) % type.mod;
9537
+ }
9538
+
9539
+ // for now all property types without mod have min and max
9540
+ return 0 > value ? 0 : type.max < value ? type.max : value;
9541
+ }
9542
+
9543
+ function stringParse( string ) {
9544
+ var inst = color(),
9545
+ rgba = inst._rgba = [];
9546
+
9547
+ string = string.toLowerCase();
9548
+
9549
+ each( stringParsers, function( i, parser ) {
9550
+ var parsed,
9551
+ match = parser.re.exec( string ),
9552
+ values = match && parser.parse( match ),
9553
+ spaceName = parser.space || "rgba";
9554
+
9555
+ if ( values ) {
9556
+ parsed = inst[ spaceName ]( values );
9557
+
9558
+ // if this was an rgba parse the assignment might happen twice
9559
+ // oh well....
9560
+ inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
9561
+ rgba = inst._rgba = parsed._rgba;
9562
+
9563
+ // exit each( stringParsers ) here because we matched
9564
+ return false;
9565
+ }
9566
+ });
9567
+
9568
+ // Found a stringParser that handled it
9569
+ if ( rgba.length ) {
9570
+
9571
+ // if this came from a parsed string, force "transparent" when alpha is 0
9572
+ // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
9573
+ if ( rgba.join() === "0,0,0,0" ) {
9574
+ jQuery.extend( rgba, colors.transparent );
9575
+ }
9576
+ return inst;
9577
+ }
9578
+
9579
+ // named colors
9580
+ return colors[ string ];
9581
+ }
9582
+
9583
+ color.fn = jQuery.extend( color.prototype, {
9584
+ parse: function( red, green, blue, alpha ) {
9585
+ if ( red === undefined ) {
9586
+ this._rgba = [ null, null, null, null ];
9587
+ return this;
9588
+ }
9589
+ if ( red.jquery || red.nodeType ) {
9590
+ red = jQuery( red ).css( green );
9591
+ green = undefined;
9592
+ }
9593
+
9594
+ var inst = this,
9595
+ type = jQuery.type( red ),
9596
+ rgba = this._rgba = [];
9597
+
9598
+ // more than 1 argument specified - assume ( red, green, blue, alpha )
9599
+ if ( green !== undefined ) {
9600
+ red = [ red, green, blue, alpha ];
9601
+ type = "array";
9602
+ }
9603
+
9604
+ if ( type === "string" ) {
9605
+ return this.parse( stringParse( red ) || colors._default );
9606
+ }
9607
+
9608
+ if ( type === "array" ) {
9609
+ each( spaces.rgba.props, function( key, prop ) {
9610
+ rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
9611
+ });
9612
+ return this;
9613
+ }
9614
+
9615
+ if ( type === "object" ) {
9616
+ if ( red instanceof color ) {
9617
+ each( spaces, function( spaceName, space ) {
9618
+ if ( red[ space.cache ] ) {
9619
+ inst[ space.cache ] = red[ space.cache ].slice();
9620
+ }
9621
+ });
9622
+ } else {
9623
+ each( spaces, function( spaceName, space ) {
9624
+ var cache = space.cache;
9625
+ each( space.props, function( key, prop ) {
9626
+
9627
+ // if the cache doesn't exist, and we know how to convert
9628
+ if ( !inst[ cache ] && space.to ) {
9629
+
9630
+ // if the value was null, we don't need to copy it
9631
+ // if the key was alpha, we don't need to copy it either
9632
+ if ( key === "alpha" || red[ key ] == null ) {
9633
+ return;
9634
+ }
9635
+ inst[ cache ] = space.to( inst._rgba );
9636
+ }
9637
+
9638
+ // this is the only case where we allow nulls for ALL properties.
9639
+ // call clamp with alwaysAllowEmpty
9640
+ inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
9641
+ });
9642
+
9643
+ // everything defined but alpha?
9644
+ if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
9645
+ // use the default of 1
9646
+ inst[ cache ][ 3 ] = 1;
9647
+ if ( space.from ) {
9648
+ inst._rgba = space.from( inst[ cache ] );
9649
+ }
9650
+ }
9651
+ });
9652
+ }
9653
+ return this;
9654
+ }
9655
+ },
9656
+ is: function( compare ) {
9657
+ var is = color( compare ),
9658
+ same = true,
9659
+ inst = this;
9660
+
9661
+ each( spaces, function( _, space ) {
9662
+ var localCache,
9663
+ isCache = is[ space.cache ];
9664
+ if (isCache) {
9665
+ localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
9666
+ each( space.props, function( _, prop ) {
9667
+ if ( isCache[ prop.idx ] != null ) {
9668
+ same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
9669
+ return same;
9670
+ }
9671
+ });
9672
+ }
9673
+ return same;
9674
+ });
9675
+ return same;
9676
+ },
9677
+ _space: function() {
9678
+ var used = [],
9679
+ inst = this;
9680
+ each( spaces, function( spaceName, space ) {
9681
+ if ( inst[ space.cache ] ) {
9682
+ used.push( spaceName );
9683
+ }
9684
+ });
9685
+ return used.pop();
9686
+ },
9687
+ transition: function( other, distance ) {
9688
+ var end = color( other ),
9689
+ spaceName = end._space(),
9690
+ space = spaces[ spaceName ],
9691
+ startColor = this.alpha() === 0 ? color( "transparent" ) : this,
9692
+ start = startColor[ space.cache ] || space.to( startColor._rgba ),
9693
+ result = start.slice();
9694
+
9695
+ end = end[ space.cache ];
9696
+ each( space.props, function( key, prop ) {
9697
+ var index = prop.idx,
9698
+ startValue = start[ index ],
9699
+ endValue = end[ index ],
9700
+ type = propTypes[ prop.type ] || {};
9701
+
9702
+ // if null, don't override start value
9703
+ if ( endValue === null ) {
9704
+ return;
9705
+ }
9706
+ // if null - use end
9707
+ if ( startValue === null ) {
9708
+ result[ index ] = endValue;
9709
+ } else {
9710
+ if ( type.mod ) {
9711
+ if ( endValue - startValue > type.mod / 2 ) {
9712
+ startValue += type.mod;
9713
+ } else if ( startValue - endValue > type.mod / 2 ) {
9714
+ startValue -= type.mod;
9715
+ }
9716
+ }
9717
+ result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
9718
+ }
9719
+ });
9720
+ return this[ spaceName ]( result );
9721
+ },
9722
+ blend: function( opaque ) {
9723
+ // if we are already opaque - return ourself
9724
+ if ( this._rgba[ 3 ] === 1 ) {
9725
+ return this;
9726
+ }
9727
+
9728
+ var rgb = this._rgba.slice(),
9729
+ a = rgb.pop(),
9730
+ blend = color( opaque )._rgba;
9731
+
9732
+ return color( jQuery.map( rgb, function( v, i ) {
9733
+ return ( 1 - a ) * blend[ i ] + a * v;
9734
+ }));
9735
+ },
9736
+ toRgbaString: function() {
9737
+ var prefix = "rgba(",
9738
+ rgba = jQuery.map( this._rgba, function( v, i ) {
9739
+ return v == null ? ( i > 2 ? 1 : 0 ) : v;
9740
+ });
9741
+
9742
+ if ( rgba[ 3 ] === 1 ) {
9743
+ rgba.pop();
9744
+ prefix = "rgb(";
9745
+ }
9746
+
9747
+ return prefix + rgba.join() + ")";
9748
+ },
9749
+ toHslaString: function() {
9750
+ var prefix = "hsla(",
9751
+ hsla = jQuery.map( this.hsla(), function( v, i ) {
9752
+ if ( v == null ) {
9753
+ v = i > 2 ? 1 : 0;
9754
+ }
9755
+
9756
+ // catch 1 and 2
9757
+ if ( i && i < 3 ) {
9758
+ v = Math.round( v * 100 ) + "%";
9759
+ }
9760
+ return v;
9761
+ });
9762
+
9763
+ if ( hsla[ 3 ] === 1 ) {
9764
+ hsla.pop();
9765
+ prefix = "hsl(";
9766
+ }
9767
+ return prefix + hsla.join() + ")";
9768
+ },
9769
+ toHexString: function( includeAlpha ) {
9770
+ var rgba = this._rgba.slice(),
9771
+ alpha = rgba.pop();
9772
+
9773
+ if ( includeAlpha ) {
9774
+ rgba.push( ~~( alpha * 255 ) );
9775
+ }
9776
+
9777
+ return "#" + jQuery.map( rgba, function( v ) {
9778
+
9779
+ // default to 0 when nulls exist
9780
+ v = ( v || 0 ).toString( 16 );
9781
+ return v.length === 1 ? "0" + v : v;
9782
+ }).join("");
9783
+ },
9784
+ toString: function() {
9785
+ return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
9786
+ }
9787
+ });
9788
+ color.fn.parse.prototype = color.fn;
9789
+
9790
+ // hsla conversions adapted from:
9791
+ // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
9792
+
9793
+ function hue2rgb( p, q, h ) {
9794
+ h = ( h + 1 ) % 1;
9795
+ if ( h * 6 < 1 ) {
9796
+ return p + ( q - p ) * h * 6;
9797
+ }
9798
+ if ( h * 2 < 1) {
9799
+ return q;
9800
+ }
9801
+ if ( h * 3 < 2 ) {
9802
+ return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
9803
+ }
9804
+ return p;
9805
+ }
9806
+
9807
+ spaces.hsla.to = function( rgba ) {
9808
+ if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
9809
+ return [ null, null, null, rgba[ 3 ] ];
9810
+ }
9811
+ var r = rgba[ 0 ] / 255,
9812
+ g = rgba[ 1 ] / 255,
9813
+ b = rgba[ 2 ] / 255,
9814
+ a = rgba[ 3 ],
9815
+ max = Math.max( r, g, b ),
9816
+ min = Math.min( r, g, b ),
9817
+ diff = max - min,
9818
+ add = max + min,
9819
+ l = add * 0.5,
9820
+ h, s;
9821
+
9822
+ if ( min === max ) {
9823
+ h = 0;
9824
+ } else if ( r === max ) {
9825
+ h = ( 60 * ( g - b ) / diff ) + 360;
9826
+ } else if ( g === max ) {
9827
+ h = ( 60 * ( b - r ) / diff ) + 120;
9828
+ } else {
9829
+ h = ( 60 * ( r - g ) / diff ) + 240;
9830
+ }
9831
+
9832
+ // chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
9833
+ // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
9834
+ if ( diff === 0 ) {
9835
+ s = 0;
9836
+ } else if ( l <= 0.5 ) {
9837
+ s = diff / add;
9838
+ } else {
9839
+ s = diff / ( 2 - add );
9840
+ }
9841
+ return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
9842
+ };
9843
+
9844
+ spaces.hsla.from = function( hsla ) {
9845
+ if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
9846
+ return [ null, null, null, hsla[ 3 ] ];
9847
+ }
9848
+ var h = hsla[ 0 ] / 360,
9849
+ s = hsla[ 1 ],
9850
+ l = hsla[ 2 ],
9851
+ a = hsla[ 3 ],
9852
+ q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
9853
+ p = 2 * l - q;
9854
+
9855
+ return [
9856
+ Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
9857
+ Math.round( hue2rgb( p, q, h ) * 255 ),
9858
+ Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
9859
+ a
9860
+ ];
9861
+ };
9862
+
9863
+ each( spaces, function( spaceName, space ) {
9864
+ var props = space.props,
9865
+ cache = space.cache,
9866
+ to = space.to,
9867
+ from = space.from;
9868
+
9869
+ // makes rgba() and hsla()
9870
+ color.fn[ spaceName ] = function( value ) {
9871
+
9872
+ // generate a cache for this space if it doesn't exist
9873
+ if ( to && !this[ cache ] ) {
9874
+ this[ cache ] = to( this._rgba );
9875
+ }
9876
+ if ( value === undefined ) {
9877
+ return this[ cache ].slice();
9878
+ }
9879
+
9880
+ var ret,
9881
+ type = jQuery.type( value ),
9882
+ arr = ( type === "array" || type === "object" ) ? value : arguments,
9883
+ local = this[ cache ].slice();
9884
+
9885
+ each( props, function( key, prop ) {
9886
+ var val = arr[ type === "object" ? key : prop.idx ];
9887
+ if ( val == null ) {
9888
+ val = local[ prop.idx ];
9889
+ }
9890
+ local[ prop.idx ] = clamp( val, prop );
9891
+ });
9892
+
9893
+ if ( from ) {
9894
+ ret = color( from( local ) );
9895
+ ret[ cache ] = local;
9896
+ return ret;
9897
+ } else {
9898
+ return color( local );
9899
+ }
9900
+ };
9901
+
9902
+ // makes red() green() blue() alpha() hue() saturation() lightness()
9903
+ each( props, function( key, prop ) {
9904
+ // alpha is included in more than one space
9905
+ if ( color.fn[ key ] ) {
9906
+ return;
9907
+ }
9908
+ color.fn[ key ] = function( value ) {
9909
+ var vtype = jQuery.type( value ),
9910
+ fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
9911
+ local = this[ fn ](),
9912
+ cur = local[ prop.idx ],
9913
+ match;
9914
+
9915
+ if ( vtype === "undefined" ) {
9916
+ return cur;
9917
+ }
9918
+
9919
+ if ( vtype === "function" ) {
9920
+ value = value.call( this, cur );
9921
+ vtype = jQuery.type( value );
9922
+ }
9923
+ if ( value == null && prop.empty ) {
9924
+ return this;
9925
+ }
9926
+ if ( vtype === "string" ) {
9927
+ match = rplusequals.exec( value );
9928
+ if ( match ) {
9929
+ value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
9930
+ }
9931
+ }
9932
+ local[ prop.idx ] = value;
9933
+ return this[ fn ]( local );
9934
+ };
9935
+ });
9936
+ });
9937
+
9938
+ // add cssHook and .fx.step function for each named hook.
9939
+ // accept a space separated string of properties
9940
+ color.hook = function( hook ) {
9941
+ var hooks = hook.split( " " );
9942
+ each( hooks, function( i, hook ) {
9943
+ jQuery.cssHooks[ hook ] = {
9944
+ set: function( elem, value ) {
9945
+ var parsed, curElem,
9946
+ backgroundColor = "";
9947
+
9948
+ if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
9949
+ value = color( parsed || value );
9950
+ if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
9951
+ curElem = hook === "backgroundColor" ? elem.parentNode : elem;
9952
+ while (
9953
+ (backgroundColor === "" || backgroundColor === "transparent") &&
9954
+ curElem && curElem.style
9955
+ ) {
9956
+ try {
9957
+ backgroundColor = jQuery.css( curElem, "backgroundColor" );
9958
+ curElem = curElem.parentNode;
9959
+ } catch ( e ) {
9960
+ }
9961
+ }
9962
+
9963
+ value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
9964
+ backgroundColor :
9965
+ "_default" );
9966
+ }
9967
+
9968
+ value = value.toRgbaString();
9969
+ }
9970
+ try {
9971
+ elem.style[ hook ] = value;
9972
+ } catch ( e ) {
9973
+ // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
9974
+ }
9975
+ }
9976
+ };
9977
+ jQuery.fx.step[ hook ] = function( fx ) {
9978
+ if ( !fx.colorInit ) {
9979
+ fx.start = color( fx.elem, hook );
9980
+ fx.end = color( fx.end );
9981
+ fx.colorInit = true;
9982
+ }
9983
+ jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
9984
+ };
9985
+ });
9986
+
9987
+ };
9988
+
9989
+ color.hook( stepHooks );
9990
+
9991
+ jQuery.cssHooks.borderColor = {
9992
+ expand: function( value ) {
9993
+ var expanded = {};
9994
+
9995
+ each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
9996
+ expanded[ "border" + part + "Color" ] = value;
9997
+ });
9998
+ return expanded;
9999
+ }
10000
+ };
10001
+
10002
+ // Basic color names only.
10003
+ // Usage of any of the other color names requires adding yourself or including
10004
+ // jquery.color.svg-names.js.
10005
+ colors = jQuery.Color.names = {
10006
+ // 4.1. Basic color keywords
10007
+ aqua: "#00ffff",
10008
+ black: "#000000",
10009
+ blue: "#0000ff",
10010
+ fuchsia: "#ff00ff",
10011
+ gray: "#808080",
10012
+ green: "#008000",
10013
+ lime: "#00ff00",
10014
+ maroon: "#800000",
10015
+ navy: "#000080",
10016
+ olive: "#808000",
10017
+ purple: "#800080",
10018
+ red: "#ff0000",
10019
+ silver: "#c0c0c0",
10020
+ teal: "#008080",
10021
+ white: "#ffffff",
10022
+ yellow: "#ffff00",
10023
+
10024
+ // 4.2.3. "transparent" color keyword
10025
+ transparent: [ null, null, null, 0 ],
10026
+
10027
+ _default: "#ffffff"
10028
+ };
10029
+
10030
+ })( jQuery );
10031
+
10032
+ /******************************************************************************/
10033
+ /****************************** CLASS ANIMATIONS ******************************/
10034
+ /******************************************************************************/
10035
+ (function() {
10036
+
10037
+ var classAnimationActions = [ "add", "remove", "toggle" ],
10038
+ shorthandStyles = {
10039
+ border: 1,
10040
+ borderBottom: 1,
10041
+ borderColor: 1,
10042
+ borderLeft: 1,
10043
+ borderRight: 1,
10044
+ borderTop: 1,
10045
+ borderWidth: 1,
10046
+ margin: 1,
10047
+ padding: 1
10048
+ };
10049
+
10050
+ $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
10051
+ $.fx.step[ prop ] = function( fx ) {
10052
+ if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
10053
+ jQuery.style( fx.elem, prop, fx.end );
10054
+ fx.setAttr = true;
10055
+ }
10056
+ };
10057
+ });
10058
+
10059
+ function getElementStyles( elem ) {
10060
+ var key, len,
10061
+ style = elem.ownerDocument.defaultView ?
10062
+ elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
10063
+ elem.currentStyle,
10064
+ styles = {};
10065
+
10066
+ if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
10067
+ len = style.length;
10068
+ while ( len-- ) {
10069
+ key = style[ len ];
10070
+ if ( typeof style[ key ] === "string" ) {
10071
+ styles[ $.camelCase( key ) ] = style[ key ];
10072
+ }
10073
+ }
10074
+ // support: Opera, IE <9
10075
+ } else {
10076
+ for ( key in style ) {
10077
+ if ( typeof style[ key ] === "string" ) {
10078
+ styles[ key ] = style[ key ];
10079
+ }
10080
+ }
10081
+ }
10082
+
10083
+ return styles;
10084
+ }
10085
+
10086
+ function styleDifference( oldStyle, newStyle ) {
10087
+ var diff = {},
10088
+ name, value;
10089
+
10090
+ for ( name in newStyle ) {
10091
+ value = newStyle[ name ];
10092
+ if ( oldStyle[ name ] !== value ) {
10093
+ if ( !shorthandStyles[ name ] ) {
10094
+ if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
10095
+ diff[ name ] = value;
10096
+ }
10097
+ }
10098
+ }
10099
+ }
10100
+
10101
+ return diff;
10102
+ }
10103
+
10104
+ // support: jQuery <1.8
10105
+ if ( !$.fn.addBack ) {
10106
+ $.fn.addBack = function( selector ) {
10107
+ return this.add( selector == null ?
10108
+ this.prevObject : this.prevObject.filter( selector )
10109
+ );
10110
+ };
10111
+ }
10112
+
10113
+ $.effects.animateClass = function( value, duration, easing, callback ) {
10114
+ var o = $.speed( duration, easing, callback );
10115
+
10116
+ return this.queue( function() {
10117
+ var animated = $( this ),
10118
+ baseClass = animated.attr( "class" ) || "",
10119
+ applyClassChange,
10120
+ allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
10121
+
10122
+ // map the animated objects to store the original styles.
10123
+ allAnimations = allAnimations.map(function() {
10124
+ var el = $( this );
10125
+ return {
10126
+ el: el,
10127
+ start: getElementStyles( this )
10128
+ };
10129
+ });
10130
+
10131
+ // apply class change
10132
+ applyClassChange = function() {
10133
+ $.each( classAnimationActions, function(i, action) {
10134
+ if ( value[ action ] ) {
10135
+ animated[ action + "Class" ]( value[ action ] );
10136
+ }
10137
+ });
10138
+ };
10139
+ applyClassChange();
10140
+
10141
+ // map all animated objects again - calculate new styles and diff
10142
+ allAnimations = allAnimations.map(function() {
10143
+ this.end = getElementStyles( this.el[ 0 ] );
10144
+ this.diff = styleDifference( this.start, this.end );
10145
+ return this;
10146
+ });
10147
+
10148
+ // apply original class
10149
+ animated.attr( "class", baseClass );
10150
+
10151
+ // map all animated objects again - this time collecting a promise
10152
+ allAnimations = allAnimations.map(function() {
10153
+ var styleInfo = this,
10154
+ dfd = $.Deferred(),
10155
+ opts = $.extend({}, o, {
10156
+ queue: false,
10157
+ complete: function() {
10158
+ dfd.resolve( styleInfo );
10159
+ }
10160
+ });
10161
+
10162
+ this.el.animate( this.diff, opts );
10163
+ return dfd.promise();
10164
+ });
10165
+
10166
+ // once all animations have completed:
10167
+ $.when.apply( $, allAnimations.get() ).done(function() {
10168
+
10169
+ // set the final class
10170
+ applyClassChange();
10171
+
10172
+ // for each animated element,
10173
+ // clear all css properties that were animated
10174
+ $.each( arguments, function() {
10175
+ var el = this.el;
10176
+ $.each( this.diff, function(key) {
10177
+ el.css( key, "" );
10178
+ });
10179
+ });
10180
+
10181
+ // this is guarnteed to be there if you use jQuery.speed()
10182
+ // it also handles dequeuing the next anim...
10183
+ o.complete.call( animated[ 0 ] );
10184
+ });
10185
+ });
10186
+ };
10187
+
10188
+ $.fn.extend({
10189
+ addClass: (function( orig ) {
10190
+ return function( classNames, speed, easing, callback ) {
10191
+ return speed ?
10192
+ $.effects.animateClass.call( this,
10193
+ { add: classNames }, speed, easing, callback ) :
10194
+ orig.apply( this, arguments );
10195
+ };
10196
+ })( $.fn.addClass ),
10197
+
10198
+ removeClass: (function( orig ) {
10199
+ return function( classNames, speed, easing, callback ) {
10200
+ return arguments.length > 1 ?
10201
+ $.effects.animateClass.call( this,
10202
+ { remove: classNames }, speed, easing, callback ) :
10203
+ orig.apply( this, arguments );
10204
+ };
10205
+ })( $.fn.removeClass ),
10206
+
10207
+ toggleClass: (function( orig ) {
10208
+ return function( classNames, force, speed, easing, callback ) {
10209
+ if ( typeof force === "boolean" || force === undefined ) {
10210
+ if ( !speed ) {
10211
+ // without speed parameter
10212
+ return orig.apply( this, arguments );
10213
+ } else {
10214
+ return $.effects.animateClass.call( this,
10215
+ (force ? { add: classNames } : { remove: classNames }),
10216
+ speed, easing, callback );
10217
+ }
10218
+ } else {
10219
+ // without force parameter
10220
+ return $.effects.animateClass.call( this,
10221
+ { toggle: classNames }, force, speed, easing );
10222
+ }
10223
+ };
10224
+ })( $.fn.toggleClass ),
10225
+
10226
+ switchClass: function( remove, add, speed, easing, callback) {
10227
+ return $.effects.animateClass.call( this, {
10228
+ add: add,
10229
+ remove: remove
10230
+ }, speed, easing, callback );
10231
+ }
10232
+ });
10233
+
10234
+ })();
10235
+
10236
+ /******************************************************************************/
10237
+ /*********************************** EFFECTS **********************************/
10238
+ /******************************************************************************/
10239
+
10240
+ (function() {
10241
+
10242
+ $.extend( $.effects, {
10243
+ version: "1.11.4",
10244
+
10245
+ // Saves a set of properties in a data storage
10246
+ save: function( element, set ) {
10247
+ for ( var i = 0; i < set.length; i++ ) {
10248
+ if ( set[ i ] !== null ) {
10249
+ element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
10250
+ }
10251
+ }
10252
+ },
10253
+
10254
+ // Restores a set of previously saved properties from a data storage
10255
+ restore: function( element, set ) {
10256
+ var val, i;
10257
+ for ( i = 0; i < set.length; i++ ) {
10258
+ if ( set[ i ] !== null ) {
10259
+ val = element.data( dataSpace + set[ i ] );
10260
+ // support: jQuery 1.6.2
10261
+ // http://bugs.jquery.com/ticket/9917
10262
+ // jQuery 1.6.2 incorrectly returns undefined for any falsy value.
10263
+ // We can't differentiate between "" and 0 here, so we just assume
10264
+ // empty string since it's likely to be a more common value...
10265
+ if ( val === undefined ) {
10266
+ val = "";
10267
+ }
10268
+ element.css( set[ i ], val );
10269
+ }
10270
+ }
10271
+ },
10272
+
10273
+ setMode: function( el, mode ) {
10274
+ if (mode === "toggle") {
10275
+ mode = el.is( ":hidden" ) ? "show" : "hide";
10276
+ }
10277
+ return mode;
10278
+ },
10279
+
10280
+ // Translates a [top,left] array into a baseline value
10281
+ // this should be a little more flexible in the future to handle a string & hash
10282
+ getBaseline: function( origin, original ) {
10283
+ var y, x;
10284
+ switch ( origin[ 0 ] ) {
10285
+ case "top": y = 0; break;
10286
+ case "middle": y = 0.5; break;
10287
+ case "bottom": y = 1; break;
10288
+ default: y = origin[ 0 ] / original.height;
10289
+ }
10290
+ switch ( origin[ 1 ] ) {
10291
+ case "left": x = 0; break;
10292
+ case "center": x = 0.5; break;
10293
+ case "right": x = 1; break;
10294
+ default: x = origin[ 1 ] / original.width;
10295
+ }
10296
+ return {
10297
+ x: x,
10298
+ y: y
10299
+ };
10300
+ },
10301
+
10302
+ // Wraps the element around a wrapper that copies position properties
10303
+ createWrapper: function( element ) {
10304
+
10305
+ // if the element is already wrapped, return it
10306
+ if ( element.parent().is( ".ui-effects-wrapper" )) {
10307
+ return element.parent();
10308
+ }
10309
+
10310
+ // wrap the element
10311
+ var props = {
10312
+ width: element.outerWidth(true),
10313
+ height: element.outerHeight(true),
10314
+ "float": element.css( "float" )
10315
+ },
10316
+ wrapper = $( "<div></div>" )
10317
+ .addClass( "ui-effects-wrapper" )
10318
+ .css({
10319
+ fontSize: "100%",
10320
+ background: "transparent",
10321
+ border: "none",
10322
+ margin: 0,
10323
+ padding: 0
10324
+ }),
10325
+ // Store the size in case width/height are defined in % - Fixes #5245
10326
+ size = {
10327
+ width: element.width(),
10328
+ height: element.height()
10329
+ },
10330
+ active = document.activeElement;
10331
+
10332
+ // support: Firefox
10333
+ // Firefox incorrectly exposes anonymous content
10334
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
10335
+ try {
10336
+ active.id;
10337
+ } catch ( e ) {
10338
+ active = document.body;
10339
+ }
10340
+
10341
+ element.wrap( wrapper );
10342
+
10343
+ // Fixes #7595 - Elements lose focus when wrapped.
10344
+ if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
10345
+ $( active ).focus();
10346
+ }
10347
+
10348
+ wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
10349
+
10350
+ // transfer positioning properties to the wrapper
10351
+ if ( element.css( "position" ) === "static" ) {
10352
+ wrapper.css({ position: "relative" });
10353
+ element.css({ position: "relative" });
10354
+ } else {
10355
+ $.extend( props, {
10356
+ position: element.css( "position" ),
10357
+ zIndex: element.css( "z-index" )
10358
+ });
10359
+ $.each([ "top", "left", "bottom", "right" ], function(i, pos) {
10360
+ props[ pos ] = element.css( pos );
10361
+ if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
10362
+ props[ pos ] = "auto";
10363
+ }
10364
+ });
10365
+ element.css({
10366
+ position: "relative",
10367
+ top: 0,
10368
+ left: 0,
10369
+ right: "auto",
10370
+ bottom: "auto"
10371
+ });
10372
+ }
10373
+ element.css(size);
10374
+
10375
+ return wrapper.css( props ).show();
10376
+ },
10377
+
10378
+ removeWrapper: function( element ) {
10379
+ var active = document.activeElement;
10380
+
10381
+ if ( element.parent().is( ".ui-effects-wrapper" ) ) {
10382
+ element.parent().replaceWith( element );
10383
+
10384
+ // Fixes #7595 - Elements lose focus when wrapped.
10385
+ if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
10386
+ $( active ).focus();
10387
+ }
10388
+ }
10389
+
10390
+ return element;
10391
+ },
10392
+
10393
+ setTransition: function( element, list, factor, value ) {
10394
+ value = value || {};
10395
+ $.each( list, function( i, x ) {
10396
+ var unit = element.cssUnit( x );
10397
+ if ( unit[ 0 ] > 0 ) {
10398
+ value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
10399
+ }
10400
+ });
10401
+ return value;
10402
+ }
10403
+ });
10404
+
10405
+ // return an effect options object for the given parameters:
10406
+ function _normalizeArguments( effect, options, speed, callback ) {
10407
+
10408
+ // allow passing all options as the first parameter
10409
+ if ( $.isPlainObject( effect ) ) {
10410
+ options = effect;
10411
+ effect = effect.effect;
10412
+ }
10413
+
10414
+ // convert to an object
10415
+ effect = { effect: effect };
10416
+
10417
+ // catch (effect, null, ...)
10418
+ if ( options == null ) {
10419
+ options = {};
10420
+ }
10421
+
10422
+ // catch (effect, callback)
10423
+ if ( $.isFunction( options ) ) {
10424
+ callback = options;
10425
+ speed = null;
10426
+ options = {};
10427
+ }
10428
+
10429
+ // catch (effect, speed, ?)
10430
+ if ( typeof options === "number" || $.fx.speeds[ options ] ) {
10431
+ callback = speed;
10432
+ speed = options;
10433
+ options = {};
10434
+ }
10435
+
10436
+ // catch (effect, options, callback)
10437
+ if ( $.isFunction( speed ) ) {
10438
+ callback = speed;
10439
+ speed = null;
10440
+ }
10441
+
10442
+ // add options to effect
10443
+ if ( options ) {
10444
+ $.extend( effect, options );
10445
+ }
10446
+
10447
+ speed = speed || options.duration;
10448
+ effect.duration = $.fx.off ? 0 :
10449
+ typeof speed === "number" ? speed :
10450
+ speed in $.fx.speeds ? $.fx.speeds[ speed ] :
10451
+ $.fx.speeds._default;
10452
+
10453
+ effect.complete = callback || options.complete;
10454
+
10455
+ return effect;
10456
+ }
10457
+
10458
+ function standardAnimationOption( option ) {
10459
+ // Valid standard speeds (nothing, number, named speed)
10460
+ if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
10461
+ return true;
10462
+ }
10463
+
10464
+ // Invalid strings - treat as "normal" speed
10465
+ if ( typeof option === "string" && !$.effects.effect[ option ] ) {
10466
+ return true;
10467
+ }
10468
+
10469
+ // Complete callback
10470
+ if ( $.isFunction( option ) ) {
10471
+ return true;
10472
+ }
10473
+
10474
+ // Options hash (but not naming an effect)
10475
+ if ( typeof option === "object" && !option.effect ) {
10476
+ return true;
10477
+ }
10478
+
10479
+ // Didn't match any standard API
10480
+ return false;
10481
+ }
10482
+
10483
+ $.fn.extend({
10484
+ effect: function( /* effect, options, speed, callback */ ) {
10485
+ var args = _normalizeArguments.apply( this, arguments ),
10486
+ mode = args.mode,
10487
+ queue = args.queue,
10488
+ effectMethod = $.effects.effect[ args.effect ];
10489
+
10490
+ if ( $.fx.off || !effectMethod ) {
10491
+ // delegate to the original method (e.g., .show()) if possible
10492
+ if ( mode ) {
10493
+ return this[ mode ]( args.duration, args.complete );
10494
+ } else {
10495
+ return this.each( function() {
10496
+ if ( args.complete ) {
10497
+ args.complete.call( this );
10498
+ }
10499
+ });
10500
+ }
10501
+ }
10502
+
10503
+ function run( next ) {
10504
+ var elem = $( this ),
10505
+ complete = args.complete,
10506
+ mode = args.mode;
10507
+
10508
+ function done() {
10509
+ if ( $.isFunction( complete ) ) {
10510
+ complete.call( elem[0] );
10511
+ }
10512
+ if ( $.isFunction( next ) ) {
10513
+ next();
10514
+ }
10515
+ }
10516
+
10517
+ // If the element already has the correct final state, delegate to
10518
+ // the core methods so the internal tracking of "olddisplay" works.
10519
+ if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
10520
+ elem[ mode ]();
10521
+ done();
10522
+ } else {
10523
+ effectMethod.call( elem[0], args, done );
10524
+ }
10525
+ }
10526
+
10527
+ return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
10528
+ },
10529
+
10530
+ show: (function( orig ) {
10531
+ return function( option ) {
10532
+ if ( standardAnimationOption( option ) ) {
10533
+ return orig.apply( this, arguments );
10534
+ } else {
10535
+ var args = _normalizeArguments.apply( this, arguments );
10536
+ args.mode = "show";
10537
+ return this.effect.call( this, args );
10538
+ }
10539
+ };
10540
+ })( $.fn.show ),
10541
+
10542
+ hide: (function( orig ) {
10543
+ return function( option ) {
10544
+ if ( standardAnimationOption( option ) ) {
10545
+ return orig.apply( this, arguments );
10546
+ } else {
10547
+ var args = _normalizeArguments.apply( this, arguments );
10548
+ args.mode = "hide";
10549
+ return this.effect.call( this, args );
10550
+ }
10551
+ };
10552
+ })( $.fn.hide ),
10553
+
10554
+ toggle: (function( orig ) {
10555
+ return function( option ) {
10556
+ if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
10557
+ return orig.apply( this, arguments );
10558
+ } else {
10559
+ var args = _normalizeArguments.apply( this, arguments );
10560
+ args.mode = "toggle";
10561
+ return this.effect.call( this, args );
10562
+ }
10563
+ };
10564
+ })( $.fn.toggle ),
10565
+
10566
+ // helper functions
10567
+ cssUnit: function(key) {
10568
+ var style = this.css( key ),
10569
+ val = [];
10570
+
10571
+ $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
10572
+ if ( style.indexOf( unit ) > 0 ) {
10573
+ val = [ parseFloat( style ), unit ];
10574
+ }
10575
+ });
10576
+ return val;
10577
+ }
10578
+ });
10579
+
10580
+ })();
10581
+
10582
+ /******************************************************************************/
10583
+ /*********************************** EASING ***********************************/
10584
+ /******************************************************************************/
10585
+
10586
+ (function() {
10587
+
10588
+ // based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
10589
+
10590
+ var baseEasings = {};
10591
+
10592
+ $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
10593
+ baseEasings[ name ] = function( p ) {
10594
+ return Math.pow( p, i + 2 );
10595
+ };
10596
+ });
10597
+
10598
+ $.extend( baseEasings, {
10599
+ Sine: function( p ) {
10600
+ return 1 - Math.cos( p * Math.PI / 2 );
10601
+ },
10602
+ Circ: function( p ) {
10603
+ return 1 - Math.sqrt( 1 - p * p );
10604
+ },
10605
+ Elastic: function( p ) {
10606
+ return p === 0 || p === 1 ? p :
10607
+ -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
10608
+ },
10609
+ Back: function( p ) {
10610
+ return p * p * ( 3 * p - 2 );
10611
+ },
10612
+ Bounce: function( p ) {
10613
+ var pow2,
10614
+ bounce = 4;
10615
+
10616
+ while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
10617
+ return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
10618
+ }
10619
+ });
10620
+
10621
+ $.each( baseEasings, function( name, easeIn ) {
10622
+ $.easing[ "easeIn" + name ] = easeIn;
10623
+ $.easing[ "easeOut" + name ] = function( p ) {
10624
+ return 1 - easeIn( 1 - p );
10625
+ };
10626
+ $.easing[ "easeInOut" + name ] = function( p ) {
10627
+ return p < 0.5 ?
10628
+ easeIn( p * 2 ) / 2 :
10629
+ 1 - easeIn( p * -2 + 2 ) / 2;
10630
+ };
10631
+ });
10632
+
10633
+ })();
10634
+
10635
+ var effect = $.effects;
10636
+
10637
+
10638
+ /*!
10639
+ * jQuery UI Effects Blind 1.11.4
10640
+ * http://jqueryui.com
10641
+ *
10642
+ * Copyright jQuery Foundation and other contributors
10643
+ * Released under the MIT license.
10644
+ * http://jquery.org/license
10645
+ *
10646
+ * http://api.jqueryui.com/blind-effect/
10647
+ */
10648
+
10649
+
10650
+ var effectBlind = $.effects.effect.blind = function( o, done ) {
10651
+ // Create element
10652
+ var el = $( this ),
10653
+ rvertical = /up|down|vertical/,
10654
+ rpositivemotion = /up|left|vertical|horizontal/,
10655
+ props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10656
+ mode = $.effects.setMode( el, o.mode || "hide" ),
10657
+ direction = o.direction || "up",
10658
+ vertical = rvertical.test( direction ),
10659
+ ref = vertical ? "height" : "width",
10660
+ ref2 = vertical ? "top" : "left",
10661
+ motion = rpositivemotion.test( direction ),
10662
+ animation = {},
10663
+ show = mode === "show",
10664
+ wrapper, distance, margin;
10665
+
10666
+ // if already wrapped, the wrapper's properties are my property. #6245
10667
+ if ( el.parent().is( ".ui-effects-wrapper" ) ) {
10668
+ $.effects.save( el.parent(), props );
10669
+ } else {
10670
+ $.effects.save( el, props );
10671
+ }
10672
+ el.show();
10673
+ wrapper = $.effects.createWrapper( el ).css({
10674
+ overflow: "hidden"
10675
+ });
10676
+
10677
+ distance = wrapper[ ref ]();
10678
+ margin = parseFloat( wrapper.css( ref2 ) ) || 0;
10679
+
10680
+ animation[ ref ] = show ? distance : 0;
10681
+ if ( !motion ) {
10682
+ el
10683
+ .css( vertical ? "bottom" : "right", 0 )
10684
+ .css( vertical ? "top" : "left", "auto" )
10685
+ .css({ position: "absolute" });
10686
+
10687
+ animation[ ref2 ] = show ? margin : distance + margin;
10688
+ }
10689
+
10690
+ // start at 0 if we are showing
10691
+ if ( show ) {
10692
+ wrapper.css( ref, 0 );
10693
+ if ( !motion ) {
10694
+ wrapper.css( ref2, margin + distance );
10695
+ }
10696
+ }
10697
+
10698
+ // Animate
10699
+ wrapper.animate( animation, {
10700
+ duration: o.duration,
10701
+ easing: o.easing,
10702
+ queue: false,
10703
+ complete: function() {
10704
+ if ( mode === "hide" ) {
10705
+ el.hide();
10706
+ }
10707
+ $.effects.restore( el, props );
10708
+ $.effects.removeWrapper( el );
10709
+ done();
10710
+ }
10711
+ });
10712
+ };
10713
+
10714
+
10715
+ /*!
10716
+ * jQuery UI Effects Bounce 1.11.4
10717
+ * http://jqueryui.com
10718
+ *
10719
+ * Copyright jQuery Foundation and other contributors
10720
+ * Released under the MIT license.
10721
+ * http://jquery.org/license
10722
+ *
10723
+ * http://api.jqueryui.com/bounce-effect/
10724
+ */
10725
+
10726
+
10727
+ var effectBounce = $.effects.effect.bounce = function( o, done ) {
10728
+ var el = $( this ),
10729
+ props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10730
+
10731
+ // defaults:
10732
+ mode = $.effects.setMode( el, o.mode || "effect" ),
10733
+ hide = mode === "hide",
10734
+ show = mode === "show",
10735
+ direction = o.direction || "up",
10736
+ distance = o.distance,
10737
+ times = o.times || 5,
10738
+
10739
+ // number of internal animations
10740
+ anims = times * 2 + ( show || hide ? 1 : 0 ),
10741
+ speed = o.duration / anims,
10742
+ easing = o.easing,
10743
+
10744
+ // utility:
10745
+ ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10746
+ motion = ( direction === "up" || direction === "left" ),
10747
+ i,
10748
+ upAnim,
10749
+ downAnim,
10750
+
10751
+ // we will need to re-assemble the queue to stack our animations in place
10752
+ queue = el.queue(),
10753
+ queuelen = queue.length;
10754
+
10755
+ // Avoid touching opacity to prevent clearType and PNG issues in IE
10756
+ if ( show || hide ) {
10757
+ props.push( "opacity" );
10758
+ }
10759
+
10760
+ $.effects.save( el, props );
10761
+ el.show();
10762
+ $.effects.createWrapper( el ); // Create Wrapper
10763
+
10764
+ // default distance for the BIGGEST bounce is the outer Distance / 3
10765
+ if ( !distance ) {
10766
+ distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
10767
+ }
10768
+
10769
+ if ( show ) {
10770
+ downAnim = { opacity: 1 };
10771
+ downAnim[ ref ] = 0;
10772
+
10773
+ // if we are showing, force opacity 0 and set the initial position
10774
+ // then do the "first" animation
10775
+ el.css( "opacity", 0 )
10776
+ .css( ref, motion ? -distance * 2 : distance * 2 )
10777
+ .animate( downAnim, speed, easing );
10778
+ }
10779
+
10780
+ // start at the smallest distance if we are hiding
10781
+ if ( hide ) {
10782
+ distance = distance / Math.pow( 2, times - 1 );
10783
+ }
10784
+
10785
+ downAnim = {};
10786
+ downAnim[ ref ] = 0;
10787
+ // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
10788
+ for ( i = 0; i < times; i++ ) {
10789
+ upAnim = {};
10790
+ upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10791
+
10792
+ el.animate( upAnim, speed, easing )
10793
+ .animate( downAnim, speed, easing );
10794
+
10795
+ distance = hide ? distance * 2 : distance / 2;
10796
+ }
10797
+
10798
+ // Last Bounce when Hiding
10799
+ if ( hide ) {
10800
+ upAnim = { opacity: 0 };
10801
+ upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
10802
+
10803
+ el.animate( upAnim, speed, easing );
10804
+ }
10805
+
10806
+ el.queue(function() {
10807
+ if ( hide ) {
10808
+ el.hide();
10809
+ }
10810
+ $.effects.restore( el, props );
10811
+ $.effects.removeWrapper( el );
10812
+ done();
10813
+ });
10814
+
10815
+ // inject all the animations we just queued to be first in line (after "inprogress")
10816
+ if ( queuelen > 1) {
10817
+ queue.splice.apply( queue,
10818
+ [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
10819
+ }
10820
+ el.dequeue();
10821
+
10822
+ };
10823
+
10824
+
10825
+ /*!
10826
+ * jQuery UI Effects Clip 1.11.4
10827
+ * http://jqueryui.com
10828
+ *
10829
+ * Copyright jQuery Foundation and other contributors
10830
+ * Released under the MIT license.
10831
+ * http://jquery.org/license
10832
+ *
10833
+ * http://api.jqueryui.com/clip-effect/
10834
+ */
10835
+
10836
+
10837
+ var effectClip = $.effects.effect.clip = function( o, done ) {
10838
+ // Create element
10839
+ var el = $( this ),
10840
+ props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
10841
+ mode = $.effects.setMode( el, o.mode || "hide" ),
10842
+ show = mode === "show",
10843
+ direction = o.direction || "vertical",
10844
+ vert = direction === "vertical",
10845
+ size = vert ? "height" : "width",
10846
+ position = vert ? "top" : "left",
10847
+ animation = {},
10848
+ wrapper, animate, distance;
10849
+
10850
+ // Save & Show
10851
+ $.effects.save( el, props );
10852
+ el.show();
10853
+
10854
+ // Create Wrapper
10855
+ wrapper = $.effects.createWrapper( el ).css({
10856
+ overflow: "hidden"
10857
+ });
10858
+ animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
10859
+ distance = animate[ size ]();
10860
+
10861
+ // Shift
10862
+ if ( show ) {
10863
+ animate.css( size, 0 );
10864
+ animate.css( position, distance / 2 );
10865
+ }
10866
+
10867
+ // Create Animation Object:
10868
+ animation[ size ] = show ? distance : 0;
10869
+ animation[ position ] = show ? 0 : distance / 2;
10870
+
10871
+ // Animate
10872
+ animate.animate( animation, {
10873
+ queue: false,
10874
+ duration: o.duration,
10875
+ easing: o.easing,
10876
+ complete: function() {
10877
+ if ( !show ) {
10878
+ el.hide();
10879
+ }
10880
+ $.effects.restore( el, props );
10881
+ $.effects.removeWrapper( el );
10882
+ done();
10883
+ }
10884
+ });
10885
+
10886
+ };
10887
+
10888
+
10889
+ /*!
10890
+ * jQuery UI Effects Drop 1.11.4
10891
+ * http://jqueryui.com
10892
+ *
10893
+ * Copyright jQuery Foundation and other contributors
10894
+ * Released under the MIT license.
10895
+ * http://jquery.org/license
10896
+ *
10897
+ * http://api.jqueryui.com/drop-effect/
10898
+ */
10899
+
10900
+
10901
+ var effectDrop = $.effects.effect.drop = function( o, done ) {
10902
+
10903
+ var el = $( this ),
10904
+ props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
10905
+ mode = $.effects.setMode( el, o.mode || "hide" ),
10906
+ show = mode === "show",
10907
+ direction = o.direction || "left",
10908
+ ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
10909
+ motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
10910
+ animation = {
10911
+ opacity: show ? 1 : 0
10912
+ },
10913
+ distance;
10914
+
10915
+ // Adjust
10916
+ $.effects.save( el, props );
10917
+ el.show();
10918
+ $.effects.createWrapper( el );
10919
+
10920
+ distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
10921
+
10922
+ if ( show ) {
10923
+ el
10924
+ .css( "opacity", 0 )
10925
+ .css( ref, motion === "pos" ? -distance : distance );
10926
+ }
10927
+
10928
+ // Animation
10929
+ animation[ ref ] = ( show ?
10930
+ ( motion === "pos" ? "+=" : "-=" ) :
10931
+ ( motion === "pos" ? "-=" : "+=" ) ) +
10932
+ distance;
10933
+
10934
+ // Animate
10935
+ el.animate( animation, {
10936
+ queue: false,
10937
+ duration: o.duration,
10938
+ easing: o.easing,
10939
+ complete: function() {
10940
+ if ( mode === "hide" ) {
10941
+ el.hide();
10942
+ }
10943
+ $.effects.restore( el, props );
10944
+ $.effects.removeWrapper( el );
10945
+ done();
10946
+ }
10947
+ });
10948
+ };
10949
+
10950
+
10951
+ /*!
10952
+ * jQuery UI Effects Explode 1.11.4
10953
+ * http://jqueryui.com
10954
+ *
10955
+ * Copyright jQuery Foundation and other contributors
10956
+ * Released under the MIT license.
10957
+ * http://jquery.org/license
10958
+ *
10959
+ * http://api.jqueryui.com/explode-effect/
10960
+ */
10961
+
10962
+
10963
+ var effectExplode = $.effects.effect.explode = function( o, done ) {
10964
+
10965
+ var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
10966
+ cells = rows,
10967
+ el = $( this ),
10968
+ mode = $.effects.setMode( el, o.mode || "hide" ),
10969
+ show = mode === "show",
10970
+
10971
+ // show and then visibility:hidden the element before calculating offset
10972
+ offset = el.show().css( "visibility", "hidden" ).offset(),
10973
+
10974
+ // width and height of a piece
10975
+ width = Math.ceil( el.outerWidth() / cells ),
10976
+ height = Math.ceil( el.outerHeight() / rows ),
10977
+ pieces = [],
10978
+
10979
+ // loop
10980
+ i, j, left, top, mx, my;
10981
+
10982
+ // children animate complete:
10983
+ function childComplete() {
10984
+ pieces.push( this );
10985
+ if ( pieces.length === rows * cells ) {
10986
+ animComplete();
10987
+ }
10988
+ }
10989
+
10990
+ // clone the element for each row and cell.
10991
+ for ( i = 0; i < rows ; i++ ) { // ===>
10992
+ top = offset.top + i * height;
10993
+ my = i - ( rows - 1 ) / 2 ;
10994
+
10995
+ for ( j = 0; j < cells ; j++ ) { // |||
10996
+ left = offset.left + j * width;
10997
+ mx = j - ( cells - 1 ) / 2 ;
10998
+
10999
+ // Create a clone of the now hidden main element that will be absolute positioned
11000
+ // within a wrapper div off the -left and -top equal to size of our pieces
11001
+ el
11002
+ .clone()
11003
+ .appendTo( "body" )
11004
+ .wrap( "<div></div>" )
11005
+ .css({
11006
+ position: "absolute",
11007
+ visibility: "visible",
11008
+ left: -j * width,
11009
+ top: -i * height
11010
+ })
11011
+
11012
+ // select the wrapper - make it overflow: hidden and absolute positioned based on
11013
+ // where the original was located +left and +top equal to the size of pieces
11014
+ .parent()
11015
+ .addClass( "ui-effects-explode" )
11016
+ .css({
11017
+ position: "absolute",
11018
+ overflow: "hidden",
11019
+ width: width,
11020
+ height: height,
11021
+ left: left + ( show ? mx * width : 0 ),
11022
+ top: top + ( show ? my * height : 0 ),
11023
+ opacity: show ? 0 : 1
11024
+ }).animate({
11025
+ left: left + ( show ? 0 : mx * width ),
11026
+ top: top + ( show ? 0 : my * height ),
11027
+ opacity: show ? 1 : 0
11028
+ }, o.duration || 500, o.easing, childComplete );
11029
+ }
11030
+ }
11031
+
11032
+ function animComplete() {
11033
+ el.css({
11034
+ visibility: "visible"
11035
+ });
11036
+ $( pieces ).remove();
11037
+ if ( !show ) {
11038
+ el.hide();
11039
+ }
11040
+ done();
11041
+ }
11042
+ };
11043
+
11044
+
11045
+ /*!
11046
+ * jQuery UI Effects Fade 1.11.4
11047
+ * http://jqueryui.com
11048
+ *
11049
+ * Copyright jQuery Foundation and other contributors
11050
+ * Released under the MIT license.
11051
+ * http://jquery.org/license
11052
+ *
11053
+ * http://api.jqueryui.com/fade-effect/
11054
+ */
11055
+
11056
+
11057
+ var effectFade = $.effects.effect.fade = function( o, done ) {
11058
+ var el = $( this ),
11059
+ mode = $.effects.setMode( el, o.mode || "toggle" );
11060
+
11061
+ el.animate({
11062
+ opacity: mode
11063
+ }, {
11064
+ queue: false,
11065
+ duration: o.duration,
11066
+ easing: o.easing,
11067
+ complete: done
11068
+ });
11069
+ };
11070
+
11071
+
11072
+ /*!
11073
+ * jQuery UI Effects Fold 1.11.4
11074
+ * http://jqueryui.com
11075
+ *
11076
+ * Copyright jQuery Foundation and other contributors
11077
+ * Released under the MIT license.
11078
+ * http://jquery.org/license
11079
+ *
11080
+ * http://api.jqueryui.com/fold-effect/
11081
+ */
11082
+
11083
+
11084
+ var effectFold = $.effects.effect.fold = function( o, done ) {
11085
+
11086
+ // Create element
11087
+ var el = $( this ),
11088
+ props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
11089
+ mode = $.effects.setMode( el, o.mode || "hide" ),
11090
+ show = mode === "show",
11091
+ hide = mode === "hide",
11092
+ size = o.size || 15,
11093
+ percent = /([0-9]+)%/.exec( size ),
11094
+ horizFirst = !!o.horizFirst,
11095
+ widthFirst = show !== horizFirst,
11096
+ ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
11097
+ duration = o.duration / 2,
11098
+ wrapper, distance,
11099
+ animation1 = {},
11100
+ animation2 = {};
11101
+
11102
+ $.effects.save( el, props );
11103
+ el.show();
11104
+
11105
+ // Create Wrapper
11106
+ wrapper = $.effects.createWrapper( el ).css({
11107
+ overflow: "hidden"
11108
+ });
11109
+ distance = widthFirst ?
11110
+ [ wrapper.width(), wrapper.height() ] :
11111
+ [ wrapper.height(), wrapper.width() ];
11112
+
11113
+ if ( percent ) {
11114
+ size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
11115
+ }
11116
+ if ( show ) {
11117
+ wrapper.css( horizFirst ? {
11118
+ height: 0,
11119
+ width: size
11120
+ } : {
11121
+ height: size,
11122
+ width: 0
11123
+ });
11124
+ }
11125
+
11126
+ // Animation
11127
+ animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
11128
+ animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
11129
+
11130
+ // Animate
11131
+ wrapper
11132
+ .animate( animation1, duration, o.easing )
11133
+ .animate( animation2, duration, o.easing, function() {
11134
+ if ( hide ) {
11135
+ el.hide();
11136
+ }
11137
+ $.effects.restore( el, props );
11138
+ $.effects.removeWrapper( el );
11139
+ done();
11140
+ });
11141
+
11142
+ };
11143
+
11144
+
11145
+ /*!
11146
+ * jQuery UI Effects Highlight 1.11.4
11147
+ * http://jqueryui.com
11148
+ *
11149
+ * Copyright jQuery Foundation and other contributors
11150
+ * Released under the MIT license.
11151
+ * http://jquery.org/license
11152
+ *
11153
+ * http://api.jqueryui.com/highlight-effect/
11154
+ */
11155
+
11156
+
11157
+ var effectHighlight = $.effects.effect.highlight = function( o, done ) {
11158
+ var elem = $( this ),
11159
+ props = [ "backgroundImage", "backgroundColor", "opacity" ],
11160
+ mode = $.effects.setMode( elem, o.mode || "show" ),
11161
+ animation = {
11162
+ backgroundColor: elem.css( "backgroundColor" )
11163
+ };
11164
+
11165
+ if (mode === "hide") {
11166
+ animation.opacity = 0;
11167
+ }
11168
+
11169
+ $.effects.save( elem, props );
11170
+
11171
+ elem
11172
+ .show()
11173
+ .css({
11174
+ backgroundImage: "none",
11175
+ backgroundColor: o.color || "#ffff99"
11176
+ })
11177
+ .animate( animation, {
11178
+ queue: false,
11179
+ duration: o.duration,
11180
+ easing: o.easing,
11181
+ complete: function() {
11182
+ if ( mode === "hide" ) {
11183
+ elem.hide();
11184
+ }
11185
+ $.effects.restore( elem, props );
11186
+ done();
11187
+ }
11188
+ });
11189
+ };
11190
+
11191
+
11192
+ /*!
11193
+ * jQuery UI Effects Size 1.11.4
11194
+ * http://jqueryui.com
11195
+ *
11196
+ * Copyright jQuery Foundation and other contributors
11197
+ * Released under the MIT license.
11198
+ * http://jquery.org/license
11199
+ *
11200
+ * http://api.jqueryui.com/size-effect/
11201
+ */
11202
+
11203
+
11204
+ var effectSize = $.effects.effect.size = function( o, done ) {
11205
+
11206
+ // Create element
11207
+ var original, baseline, factor,
11208
+ el = $( this ),
11209
+ props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
11210
+
11211
+ // Always restore
11212
+ props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
11213
+
11214
+ // Copy for children
11215
+ props2 = [ "width", "height", "overflow" ],
11216
+ cProps = [ "fontSize" ],
11217
+ vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
11218
+ hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
11219
+
11220
+ // Set options
11221
+ mode = $.effects.setMode( el, o.mode || "effect" ),
11222
+ restore = o.restore || mode !== "effect",
11223
+ scale = o.scale || "both",
11224
+ origin = o.origin || [ "middle", "center" ],
11225
+ position = el.css( "position" ),
11226
+ props = restore ? props0 : props1,
11227
+ zero = {
11228
+ height: 0,
11229
+ width: 0,
11230
+ outerHeight: 0,
11231
+ outerWidth: 0
11232
+ };
11233
+
11234
+ if ( mode === "show" ) {
11235
+ el.show();
11236
+ }
11237
+ original = {
11238
+ height: el.height(),
11239
+ width: el.width(),
11240
+ outerHeight: el.outerHeight(),
11241
+ outerWidth: el.outerWidth()
11242
+ };
11243
+
11244
+ if ( o.mode === "toggle" && mode === "show" ) {
11245
+ el.from = o.to || zero;
11246
+ el.to = o.from || original;
11247
+ } else {
11248
+ el.from = o.from || ( mode === "show" ? zero : original );
11249
+ el.to = o.to || ( mode === "hide" ? zero : original );
11250
+ }
11251
+
11252
+ // Set scaling factor
11253
+ factor = {
11254
+ from: {
11255
+ y: el.from.height / original.height,
11256
+ x: el.from.width / original.width
11257
+ },
11258
+ to: {
11259
+ y: el.to.height / original.height,
11260
+ x: el.to.width / original.width
11261
+ }
11262
+ };
11263
+
11264
+ // Scale the css box
11265
+ if ( scale === "box" || scale === "both" ) {
11266
+
11267
+ // Vertical props scaling
11268
+ if ( factor.from.y !== factor.to.y ) {
11269
+ props = props.concat( vProps );
11270
+ el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
11271
+ el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
11272
+ }
11273
+
11274
+ // Horizontal props scaling
11275
+ if ( factor.from.x !== factor.to.x ) {
11276
+ props = props.concat( hProps );
11277
+ el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
11278
+ el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
11279
+ }
11280
+ }
11281
+
11282
+ // Scale the content
11283
+ if ( scale === "content" || scale === "both" ) {
11284
+
11285
+ // Vertical props scaling
11286
+ if ( factor.from.y !== factor.to.y ) {
11287
+ props = props.concat( cProps ).concat( props2 );
11288
+ el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
11289
+ el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
11290
+ }
11291
+ }
11292
+
11293
+ $.effects.save( el, props );
11294
+ el.show();
11295
+ $.effects.createWrapper( el );
11296
+ el.css( "overflow", "hidden" ).css( el.from );
11297
+
11298
+ // Adjust
11299
+ if (origin) { // Calculate baseline shifts
11300
+ baseline = $.effects.getBaseline( origin, original );
11301
+ el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
11302
+ el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
11303
+ el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
11304
+ el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
11305
+ }
11306
+ el.css( el.from ); // set top & left
11307
+
11308
+ // Animate
11309
+ if ( scale === "content" || scale === "both" ) { // Scale the children
11310
+
11311
+ // Add margins/font-size
11312
+ vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
11313
+ hProps = hProps.concat([ "marginLeft", "marginRight" ]);
11314
+ props2 = props0.concat(vProps).concat(hProps);
11315
+
11316
+ el.find( "*[width]" ).each( function() {
11317
+ var child = $( this ),
11318
+ c_original = {
11319
+ height: child.height(),
11320
+ width: child.width(),
11321
+ outerHeight: child.outerHeight(),
11322
+ outerWidth: child.outerWidth()
11323
+ };
11324
+ if (restore) {
11325
+ $.effects.save(child, props2);
11326
+ }
11327
+
11328
+ child.from = {
11329
+ height: c_original.height * factor.from.y,
11330
+ width: c_original.width * factor.from.x,
11331
+ outerHeight: c_original.outerHeight * factor.from.y,
11332
+ outerWidth: c_original.outerWidth * factor.from.x
11333
+ };
11334
+ child.to = {
11335
+ height: c_original.height * factor.to.y,
11336
+ width: c_original.width * factor.to.x,
11337
+ outerHeight: c_original.height * factor.to.y,
11338
+ outerWidth: c_original.width * factor.to.x
11339
+ };
11340
+
11341
+ // Vertical props scaling
11342
+ if ( factor.from.y !== factor.to.y ) {
11343
+ child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
11344
+ child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
11345
+ }
11346
+
11347
+ // Horizontal props scaling
11348
+ if ( factor.from.x !== factor.to.x ) {
11349
+ child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
11350
+ child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
11351
+ }
11352
+
11353
+ // Animate children
11354
+ child.css( child.from );
11355
+ child.animate( child.to, o.duration, o.easing, function() {
11356
+
11357
+ // Restore children
11358
+ if ( restore ) {
11359
+ $.effects.restore( child, props2 );
11360
+ }
11361
+ });
11362
+ });
11363
+ }
11364
+
11365
+ // Animate
11366
+ el.animate( el.to, {
11367
+ queue: false,
11368
+ duration: o.duration,
11369
+ easing: o.easing,
11370
+ complete: function() {
11371
+ if ( el.to.opacity === 0 ) {
11372
+ el.css( "opacity", el.from.opacity );
11373
+ }
11374
+ if ( mode === "hide" ) {
11375
+ el.hide();
11376
+ }
11377
+ $.effects.restore( el, props );
11378
+ if ( !restore ) {
11379
+
11380
+ // we need to calculate our new positioning based on the scaling
11381
+ if ( position === "static" ) {
11382
+ el.css({
11383
+ position: "relative",
11384
+ top: el.to.top,
11385
+ left: el.to.left
11386
+ });
11387
+ } else {
11388
+ $.each([ "top", "left" ], function( idx, pos ) {
11389
+ el.css( pos, function( _, str ) {
11390
+ var val = parseInt( str, 10 ),
11391
+ toRef = idx ? el.to.left : el.to.top;
11392
+
11393
+ // if original was "auto", recalculate the new value from wrapper
11394
+ if ( str === "auto" ) {
11395
+ return toRef + "px";
11396
+ }
11397
+
11398
+ return val + toRef + "px";
11399
+ });
11400
+ });
11401
+ }
11402
+ }
11403
+
11404
+ $.effects.removeWrapper( el );
11405
+ done();
11406
+ }
11407
+ });
11408
+
11409
+ };
11410
+
11411
+
11412
+ /*!
11413
+ * jQuery UI Effects Scale 1.11.4
11414
+ * http://jqueryui.com
11415
+ *
11416
+ * Copyright jQuery Foundation and other contributors
11417
+ * Released under the MIT license.
11418
+ * http://jquery.org/license
11419
+ *
11420
+ * http://api.jqueryui.com/scale-effect/
11421
+ */
11422
+
11423
+
11424
+ var effectScale = $.effects.effect.scale = function( o, done ) {
11425
+
11426
+ // Create element
11427
+ var el = $( this ),
11428
+ options = $.extend( true, {}, o ),
11429
+ mode = $.effects.setMode( el, o.mode || "effect" ),
11430
+ percent = parseInt( o.percent, 10 ) ||
11431
+ ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
11432
+ direction = o.direction || "both",
11433
+ origin = o.origin,
11434
+ original = {
11435
+ height: el.height(),
11436
+ width: el.width(),
11437
+ outerHeight: el.outerHeight(),
11438
+ outerWidth: el.outerWidth()
11439
+ },
11440
+ factor = {
11441
+ y: direction !== "horizontal" ? (percent / 100) : 1,
11442
+ x: direction !== "vertical" ? (percent / 100) : 1
11443
+ };
11444
+
11445
+ // We are going to pass this effect to the size effect:
11446
+ options.effect = "size";
11447
+ options.queue = false;
11448
+ options.complete = done;
11449
+
11450
+ // Set default origin and restore for show/hide
11451
+ if ( mode !== "effect" ) {
11452
+ options.origin = origin || [ "middle", "center" ];
11453
+ options.restore = true;
11454
+ }
11455
+
11456
+ options.from = o.from || ( mode === "show" ? {
11457
+ height: 0,
11458
+ width: 0,
11459
+ outerHeight: 0,
11460
+ outerWidth: 0
11461
+ } : original );
11462
+ options.to = {
11463
+ height: original.height * factor.y,
11464
+ width: original.width * factor.x,
11465
+ outerHeight: original.outerHeight * factor.y,
11466
+ outerWidth: original.outerWidth * factor.x
11467
+ };
11468
+
11469
+ // Fade option to support puff
11470
+ if ( options.fade ) {
11471
+ if ( mode === "show" ) {
11472
+ options.from.opacity = 0;
11473
+ options.to.opacity = 1;
11474
+ }
11475
+ if ( mode === "hide" ) {
11476
+ options.from.opacity = 1;
11477
+ options.to.opacity = 0;
11478
+ }
11479
+ }
11480
+
11481
+ // Animate
11482
+ el.effect( options );
11483
+
11484
+ };
11485
+
11486
+
11487
+ /*!
11488
+ * jQuery UI Effects Puff 1.11.4
11489
+ * http://jqueryui.com
11490
+ *
11491
+ * Copyright jQuery Foundation and other contributors
11492
+ * Released under the MIT license.
11493
+ * http://jquery.org/license
11494
+ *
11495
+ * http://api.jqueryui.com/puff-effect/
11496
+ */
11497
+
11498
+
11499
+ var effectPuff = $.effects.effect.puff = function( o, done ) {
11500
+ var elem = $( this ),
11501
+ mode = $.effects.setMode( elem, o.mode || "hide" ),
11502
+ hide = mode === "hide",
11503
+ percent = parseInt( o.percent, 10 ) || 150,
11504
+ factor = percent / 100,
11505
+ original = {
11506
+ height: elem.height(),
11507
+ width: elem.width(),
11508
+ outerHeight: elem.outerHeight(),
11509
+ outerWidth: elem.outerWidth()
11510
+ };
11511
+
11512
+ $.extend( o, {
11513
+ effect: "scale",
11514
+ queue: false,
11515
+ fade: true,
11516
+ mode: mode,
11517
+ complete: done,
11518
+ percent: hide ? percent : 100,
11519
+ from: hide ?
11520
+ original :
11521
+ {
11522
+ height: original.height * factor,
11523
+ width: original.width * factor,
11524
+ outerHeight: original.outerHeight * factor,
11525
+ outerWidth: original.outerWidth * factor
11526
+ }
11527
+ });
11528
+
11529
+ elem.effect( o );
11530
+ };
11531
+
11532
+
11533
+ /*!
11534
+ * jQuery UI Effects Pulsate 1.11.4
11535
+ * http://jqueryui.com
11536
+ *
11537
+ * Copyright jQuery Foundation and other contributors
11538
+ * Released under the MIT license.
11539
+ * http://jquery.org/license
11540
+ *
11541
+ * http://api.jqueryui.com/pulsate-effect/
11542
+ */
11543
+
11544
+
11545
+ var effectPulsate = $.effects.effect.pulsate = function( o, done ) {
11546
+ var elem = $( this ),
11547
+ mode = $.effects.setMode( elem, o.mode || "show" ),
11548
+ show = mode === "show",
11549
+ hide = mode === "hide",
11550
+ showhide = ( show || mode === "hide" ),
11551
+
11552
+ // showing or hiding leaves of the "last" animation
11553
+ anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
11554
+ duration = o.duration / anims,
11555
+ animateTo = 0,
11556
+ queue = elem.queue(),
11557
+ queuelen = queue.length,
11558
+ i;
11559
+
11560
+ if ( show || !elem.is(":visible")) {
11561
+ elem.css( "opacity", 0 ).show();
11562
+ animateTo = 1;
11563
+ }
11564
+
11565
+ // anims - 1 opacity "toggles"
11566
+ for ( i = 1; i < anims; i++ ) {
11567
+ elem.animate({
11568
+ opacity: animateTo
11569
+ }, duration, o.easing );
11570
+ animateTo = 1 - animateTo;
11571
+ }
11572
+
11573
+ elem.animate({
11574
+ opacity: animateTo
11575
+ }, duration, o.easing);
11576
+
11577
+ elem.queue(function() {
11578
+ if ( hide ) {
11579
+ elem.hide();
11580
+ }
11581
+ done();
11582
+ });
11583
+
11584
+ // We just queued up "anims" animations, we need to put them next in the queue
11585
+ if ( queuelen > 1 ) {
11586
+ queue.splice.apply( queue,
11587
+ [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
11588
+ }
11589
+ elem.dequeue();
11590
+ };
11591
+
11592
+
11593
+ /*!
11594
+ * jQuery UI Effects Shake 1.11.4
11595
+ * http://jqueryui.com
11596
+ *
11597
+ * Copyright jQuery Foundation and other contributors
11598
+ * Released under the MIT license.
11599
+ * http://jquery.org/license
11600
+ *
11601
+ * http://api.jqueryui.com/shake-effect/
11602
+ */
11603
+
11604
+
11605
+ var effectShake = $.effects.effect.shake = function( o, done ) {
11606
+
11607
+ var el = $( this ),
11608
+ props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
11609
+ mode = $.effects.setMode( el, o.mode || "effect" ),
11610
+ direction = o.direction || "left",
11611
+ distance = o.distance || 20,
11612
+ times = o.times || 3,
11613
+ anims = times * 2 + 1,
11614
+ speed = Math.round( o.duration / anims ),
11615
+ ref = (direction === "up" || direction === "down") ? "top" : "left",
11616
+ positiveMotion = (direction === "up" || direction === "left"),
11617
+ animation = {},
11618
+ animation1 = {},
11619
+ animation2 = {},
11620
+ i,
11621
+
11622
+ // we will need to re-assemble the queue to stack our animations in place
11623
+ queue = el.queue(),
11624
+ queuelen = queue.length;
11625
+
11626
+ $.effects.save( el, props );
11627
+ el.show();
11628
+ $.effects.createWrapper( el );
11629
+
11630
+ // Animation
11631
+ animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
11632
+ animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
11633
+ animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
11634
+
11635
+ // Animate
11636
+ el.animate( animation, speed, o.easing );
11637
+
11638
+ // Shakes
11639
+ for ( i = 1; i < times; i++ ) {
11640
+ el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
11641
+ }
11642
+ el
11643
+ .animate( animation1, speed, o.easing )
11644
+ .animate( animation, speed / 2, o.easing )
11645
+ .queue(function() {
11646
+ if ( mode === "hide" ) {
11647
+ el.hide();
11648
+ }
11649
+ $.effects.restore( el, props );
11650
+ $.effects.removeWrapper( el );
11651
+ done();
11652
+ });
11653
+
11654
+ // inject all the animations we just queued to be first in line (after "inprogress")
11655
+ if ( queuelen > 1) {
11656
+ queue.splice.apply( queue,
11657
+ [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
11658
+ }
11659
+ el.dequeue();
11660
+
11661
+ };
11662
+
11663
+
11664
+ /*!
11665
+ * jQuery UI Effects Slide 1.11.4
11666
+ * http://jqueryui.com
11667
+ *
11668
+ * Copyright jQuery Foundation and other contributors
11669
+ * Released under the MIT license.
11670
+ * http://jquery.org/license
11671
+ *
11672
+ * http://api.jqueryui.com/slide-effect/
11673
+ */
11674
+
11675
+
11676
+ var effectSlide = $.effects.effect.slide = function( o, done ) {
11677
+
11678
+ // Create element
11679
+ var el = $( this ),
11680
+ props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
11681
+ mode = $.effects.setMode( el, o.mode || "show" ),
11682
+ show = mode === "show",
11683
+ direction = o.direction || "left",
11684
+ ref = (direction === "up" || direction === "down") ? "top" : "left",
11685
+ positiveMotion = (direction === "up" || direction === "left"),
11686
+ distance,
11687
+ animation = {};
11688
+
11689
+ // Adjust
11690
+ $.effects.save( el, props );
11691
+ el.show();
11692
+ distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
11693
+
11694
+ $.effects.createWrapper( el ).css({
11695
+ overflow: "hidden"
11696
+ });
11697
+
11698
+ if ( show ) {
11699
+ el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
11700
+ }
11701
+
11702
+ // Animation
11703
+ animation[ ref ] = ( show ?
11704
+ ( positiveMotion ? "+=" : "-=") :
11705
+ ( positiveMotion ? "-=" : "+=")) +
11706
+ distance;
11707
+
11708
+ // Animate
11709
+ el.animate( animation, {
11710
+ queue: false,
11711
+ duration: o.duration,
11712
+ easing: o.easing,
11713
+ complete: function() {
11714
+ if ( mode === "hide" ) {
11715
+ el.hide();
11716
+ }
11717
+ $.effects.restore( el, props );
11718
+ $.effects.removeWrapper( el );
11719
+ done();
11720
+ }
11721
+ });
11722
+ };
11723
+
11724
+
11725
+ /*!
11726
+ * jQuery UI Effects Transfer 1.11.4
11727
+ * http://jqueryui.com
11728
+ *
11729
+ * Copyright jQuery Foundation and other contributors
11730
+ * Released under the MIT license.
11731
+ * http://jquery.org/license
11732
+ *
11733
+ * http://api.jqueryui.com/transfer-effect/
11734
+ */
11735
+
11736
+
11737
+ var effectTransfer = $.effects.effect.transfer = function( o, done ) {
11738
+ var elem = $( this ),
11739
+ target = $( o.to ),
11740
+ targetFixed = target.css( "position" ) === "fixed",
11741
+ body = $("body"),
11742
+ fixTop = targetFixed ? body.scrollTop() : 0,
11743
+ fixLeft = targetFixed ? body.scrollLeft() : 0,
11744
+ endPosition = target.offset(),
11745
+ animation = {
11746
+ top: endPosition.top - fixTop,
11747
+ left: endPosition.left - fixLeft,
11748
+ height: target.innerHeight(),
11749
+ width: target.innerWidth()
11750
+ },
11751
+ startPosition = elem.offset(),
11752
+ transfer = $( "<div class='ui-effects-transfer'></div>" )
11753
+ .appendTo( document.body )
11754
+ .addClass( o.className )
11755
+ .css({
11756
+ top: startPosition.top - fixTop,
11757
+ left: startPosition.left - fixLeft,
11758
+ height: elem.innerHeight(),
11759
+ width: elem.innerWidth(),
11760
+ position: targetFixed ? "fixed" : "absolute"
11761
+ })
11762
+ .animate( animation, o.duration, o.easing, function() {
11763
+ transfer.remove();
11764
+ done();
11765
+ });
11766
+ };
11767
+
11768
+
11769
+ /*!
11770
+ * jQuery UI Progressbar 1.11.4
11771
+ * http://jqueryui.com
11772
+ *
11773
+ * Copyright jQuery Foundation and other contributors
11774
+ * Released under the MIT license.
11775
+ * http://jquery.org/license
11776
+ *
11777
+ * http://api.jqueryui.com/progressbar/
11778
+ */
11779
+
11780
+
11781
+ var progressbar = $.widget( "ui.progressbar", {
11782
+ version: "1.11.4",
11783
+ options: {
11784
+ max: 100,
11785
+ value: 0,
11786
+
11787
+ change: null,
11788
+ complete: null
11789
+ },
11790
+
11791
+ min: 0,
11792
+
11793
+ _create: function() {
11794
+ // Constrain initial value
11795
+ this.oldValue = this.options.value = this._constrainedValue();
11796
+
11797
+ this.element
11798
+ .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
11799
+ .attr({
11800
+ // Only set static values, aria-valuenow and aria-valuemax are
11801
+ // set inside _refreshValue()
11802
+ role: "progressbar",
11803
+ "aria-valuemin": this.min
11804
+ });
11805
+
11806
+ this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
11807
+ .appendTo( this.element );
11808
+
11809
+ this._refreshValue();
11810
+ },
11811
+
11812
+ _destroy: function() {
11813
+ this.element
11814
+ .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
11815
+ .removeAttr( "role" )
11816
+ .removeAttr( "aria-valuemin" )
11817
+ .removeAttr( "aria-valuemax" )
11818
+ .removeAttr( "aria-valuenow" );
11819
+
11820
+ this.valueDiv.remove();
11821
+ },
11822
+
11823
+ value: function( newValue ) {
11824
+ if ( newValue === undefined ) {
11825
+ return this.options.value;
11826
+ }
11827
+
11828
+ this.options.value = this._constrainedValue( newValue );
11829
+ this._refreshValue();
11830
+ },
11831
+
11832
+ _constrainedValue: function( newValue ) {
11833
+ if ( newValue === undefined ) {
11834
+ newValue = this.options.value;
11835
+ }
11836
+
11837
+ this.indeterminate = newValue === false;
11838
+
11839
+ // sanitize value
11840
+ if ( typeof newValue !== "number" ) {
11841
+ newValue = 0;
11842
+ }
11843
+
11844
+ return this.indeterminate ? false :
11845
+ Math.min( this.options.max, Math.max( this.min, newValue ) );
11846
+ },
11847
+
11848
+ _setOptions: function( options ) {
11849
+ // Ensure "value" option is set after other values (like max)
11850
+ var value = options.value;
11851
+ delete options.value;
11852
+
11853
+ this._super( options );
11854
+
11855
+ this.options.value = this._constrainedValue( value );
11856
+ this._refreshValue();
11857
+ },
11858
+
11859
+ _setOption: function( key, value ) {
11860
+ if ( key === "max" ) {
11861
+ // Don't allow a max less than min
11862
+ value = Math.max( this.min, value );
11863
+ }
11864
+ if ( key === "disabled" ) {
11865
+ this.element
11866
+ .toggleClass( "ui-state-disabled", !!value )
11867
+ .attr( "aria-disabled", value );
11868
+ }
11869
+ this._super( key, value );
11870
+ },
11871
+
11872
+ _percentage: function() {
11873
+ return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
11874
+ },
11875
+
11876
+ _refreshValue: function() {
11877
+ var value = this.options.value,
11878
+ percentage = this._percentage();
11879
+
11880
+ this.valueDiv
11881
+ .toggle( this.indeterminate || value > this.min )
11882
+ .toggleClass( "ui-corner-right", value === this.options.max )
11883
+ .width( percentage.toFixed(0) + "%" );
11884
+
11885
+ this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );
11886
+
11887
+ if ( this.indeterminate ) {
11888
+ this.element.removeAttr( "aria-valuenow" );
11889
+ if ( !this.overlayDiv ) {
11890
+ this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
11891
+ }
11892
+ } else {
11893
+ this.element.attr({
11894
+ "aria-valuemax": this.options.max,
11895
+ "aria-valuenow": value
11896
+ });
11897
+ if ( this.overlayDiv ) {
11898
+ this.overlayDiv.remove();
11899
+ this.overlayDiv = null;
11900
+ }
11901
+ }
11902
+
11903
+ if ( this.oldValue !== value ) {
11904
+ this.oldValue = value;
11905
+ this._trigger( "change" );
11906
+ }
11907
+ if ( value === this.options.max ) {
11908
+ this._trigger( "complete" );
11909
+ }
11910
+ }
11911
+ });
11912
+
11913
+
11914
+ /*!
11915
+ * jQuery UI Selectable 1.11.4
11916
+ * http://jqueryui.com
11917
+ *
11918
+ * Copyright jQuery Foundation and other contributors
11919
+ * Released under the MIT license.
11920
+ * http://jquery.org/license
11921
+ *
11922
+ * http://api.jqueryui.com/selectable/
11923
+ */
11924
+
11925
+
11926
+ var selectable = $.widget("ui.selectable", $.ui.mouse, {
11927
+ version: "1.11.4",
11928
+ options: {
11929
+ appendTo: "body",
11930
+ autoRefresh: true,
11931
+ distance: 0,
11932
+ filter: "*",
11933
+ tolerance: "touch",
11934
+
11935
+ // callbacks
11936
+ selected: null,
11937
+ selecting: null,
11938
+ start: null,
11939
+ stop: null,
11940
+ unselected: null,
11941
+ unselecting: null
11942
+ },
11943
+ _create: function() {
11944
+ var selectees,
11945
+ that = this;
11946
+
11947
+ this.element.addClass("ui-selectable");
11948
+
11949
+ this.dragged = false;
11950
+
11951
+ // cache selectee children based on filter
11952
+ this.refresh = function() {
11953
+ selectees = $(that.options.filter, that.element[0]);
11954
+ selectees.addClass("ui-selectee");
11955
+ selectees.each(function() {
11956
+ var $this = $(this),
11957
+ pos = $this.offset();
11958
+ $.data(this, "selectable-item", {
11959
+ element: this,
11960
+ $element: $this,
11961
+ left: pos.left,
11962
+ top: pos.top,
11963
+ right: pos.left + $this.outerWidth(),
11964
+ bottom: pos.top + $this.outerHeight(),
11965
+ startselected: false,
11966
+ selected: $this.hasClass("ui-selected"),
11967
+ selecting: $this.hasClass("ui-selecting"),
11968
+ unselecting: $this.hasClass("ui-unselecting")
11969
+ });
11970
+ });
11971
+ };
11972
+ this.refresh();
11973
+
11974
+ this.selectees = selectees.addClass("ui-selectee");
11975
+
11976
+ this._mouseInit();
11977
+
11978
+ this.helper = $("<div class='ui-selectable-helper'></div>");
11979
+ },
11980
+
11981
+ _destroy: function() {
11982
+ this.selectees
11983
+ .removeClass("ui-selectee")
11984
+ .removeData("selectable-item");
11985
+ this.element
11986
+ .removeClass("ui-selectable ui-selectable-disabled");
11987
+ this._mouseDestroy();
11988
+ },
11989
+
11990
+ _mouseStart: function(event) {
11991
+ var that = this,
11992
+ options = this.options;
11993
+
11994
+ this.opos = [ event.pageX, event.pageY ];
11995
+
11996
+ if (this.options.disabled) {
11997
+ return;
11998
+ }
11999
+
12000
+ this.selectees = $(options.filter, this.element[0]);
12001
+
12002
+ this._trigger("start", event);
12003
+
12004
+ $(options.appendTo).append(this.helper);
12005
+ // position helper (lasso)
12006
+ this.helper.css({
12007
+ "left": event.pageX,
12008
+ "top": event.pageY,
12009
+ "width": 0,
12010
+ "height": 0
12011
+ });
12012
+
12013
+ if (options.autoRefresh) {
12014
+ this.refresh();
12015
+ }
12016
+
12017
+ this.selectees.filter(".ui-selected").each(function() {
12018
+ var selectee = $.data(this, "selectable-item");
12019
+ selectee.startselected = true;
12020
+ if (!event.metaKey && !event.ctrlKey) {
12021
+ selectee.$element.removeClass("ui-selected");
12022
+ selectee.selected = false;
12023
+ selectee.$element.addClass("ui-unselecting");
12024
+ selectee.unselecting = true;
12025
+ // selectable UNSELECTING callback
12026
+ that._trigger("unselecting", event, {
12027
+ unselecting: selectee.element
12028
+ });
12029
+ }
12030
+ });
12031
+
12032
+ $(event.target).parents().addBack().each(function() {
12033
+ var doSelect,
12034
+ selectee = $.data(this, "selectable-item");
12035
+ if (selectee) {
12036
+ doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
12037
+ selectee.$element
12038
+ .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
12039
+ .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
12040
+ selectee.unselecting = !doSelect;
12041
+ selectee.selecting = doSelect;
12042
+ selectee.selected = doSelect;
12043
+ // selectable (UN)SELECTING callback
12044
+ if (doSelect) {
12045
+ that._trigger("selecting", event, {
12046
+ selecting: selectee.element
12047
+ });
12048
+ } else {
12049
+ that._trigger("unselecting", event, {
12050
+ unselecting: selectee.element
12051
+ });
12052
+ }
12053
+ return false;
12054
+ }
12055
+ });
12056
+
12057
+ },
12058
+
12059
+ _mouseDrag: function(event) {
12060
+
12061
+ this.dragged = true;
12062
+
12063
+ if (this.options.disabled) {
12064
+ return;
12065
+ }
12066
+
12067
+ var tmp,
12068
+ that = this,
12069
+ options = this.options,
12070
+ x1 = this.opos[0],
12071
+ y1 = this.opos[1],
12072
+ x2 = event.pageX,
12073
+ y2 = event.pageY;
12074
+
12075
+ if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
12076
+ if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
12077
+ this.helper.css({ left: x1, top: y1, width: x2 - x1, height: y2 - y1 });
12078
+
12079
+ this.selectees.each(function() {
12080
+ var selectee = $.data(this, "selectable-item"),
12081
+ hit = false;
12082
+
12083
+ //prevent helper from being selected if appendTo: selectable
12084
+ if (!selectee || selectee.element === that.element[0]) {
12085
+ return;
12086
+ }
12087
+
12088
+ if (options.tolerance === "touch") {
12089
+ hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
12090
+ } else if (options.tolerance === "fit") {
12091
+ hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
12092
+ }
12093
+
12094
+ if (hit) {
12095
+ // SELECT
12096
+ if (selectee.selected) {
12097
+ selectee.$element.removeClass("ui-selected");
12098
+ selectee.selected = false;
12099
+ }
12100
+ if (selectee.unselecting) {
12101
+ selectee.$element.removeClass("ui-unselecting");
12102
+ selectee.unselecting = false;
12103
+ }
12104
+ if (!selectee.selecting) {
12105
+ selectee.$element.addClass("ui-selecting");
12106
+ selectee.selecting = true;
12107
+ // selectable SELECTING callback
12108
+ that._trigger("selecting", event, {
12109
+ selecting: selectee.element
12110
+ });
12111
+ }
12112
+ } else {
12113
+ // UNSELECT
12114
+ if (selectee.selecting) {
12115
+ if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
12116
+ selectee.$element.removeClass("ui-selecting");
12117
+ selectee.selecting = false;
12118
+ selectee.$element.addClass("ui-selected");
12119
+ selectee.selected = true;
12120
+ } else {
12121
+ selectee.$element.removeClass("ui-selecting");
12122
+ selectee.selecting = false;
12123
+ if (selectee.startselected) {
12124
+ selectee.$element.addClass("ui-unselecting");
12125
+ selectee.unselecting = true;
12126
+ }
12127
+ // selectable UNSELECTING callback
12128
+ that._trigger("unselecting", event, {
12129
+ unselecting: selectee.element
12130
+ });
12131
+ }
12132
+ }
12133
+ if (selectee.selected) {
12134
+ if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
12135
+ selectee.$element.removeClass("ui-selected");
12136
+ selectee.selected = false;
12137
+
12138
+ selectee.$element.addClass("ui-unselecting");
12139
+ selectee.unselecting = true;
12140
+ // selectable UNSELECTING callback
12141
+ that._trigger("unselecting", event, {
12142
+ unselecting: selectee.element
12143
+ });
12144
+ }
12145
+ }
12146
+ }
12147
+ });
12148
+
12149
+ return false;
12150
+ },
12151
+
12152
+ _mouseStop: function(event) {
12153
+ var that = this;
12154
+
12155
+ this.dragged = false;
12156
+
12157
+ $(".ui-unselecting", this.element[0]).each(function() {
12158
+ var selectee = $.data(this, "selectable-item");
12159
+ selectee.$element.removeClass("ui-unselecting");
12160
+ selectee.unselecting = false;
12161
+ selectee.startselected = false;
12162
+ that._trigger("unselected", event, {
12163
+ unselected: selectee.element
12164
+ });
12165
+ });
12166
+ $(".ui-selecting", this.element[0]).each(function() {
12167
+ var selectee = $.data(this, "selectable-item");
12168
+ selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
12169
+ selectee.selecting = false;
12170
+ selectee.selected = true;
12171
+ selectee.startselected = true;
12172
+ that._trigger("selected", event, {
12173
+ selected: selectee.element
12174
+ });
12175
+ });
12176
+ this._trigger("stop", event);
12177
+
12178
+ this.helper.remove();
12179
+
12180
+ return false;
12181
+ }
12182
+
12183
+ });
12184
+
12185
+
12186
+ /*!
12187
+ * jQuery UI Selectmenu 1.11.4
12188
+ * http://jqueryui.com
12189
+ *
12190
+ * Copyright jQuery Foundation and other contributors
12191
+ * Released under the MIT license.
12192
+ * http://jquery.org/license
12193
+ *
12194
+ * http://api.jqueryui.com/selectmenu
12195
+ */
12196
+
12197
+
12198
+ var selectmenu = $.widget( "ui.selectmenu", {
12199
+ version: "1.11.4",
12200
+ defaultElement: "<select>",
12201
+ options: {
12202
+ appendTo: null,
12203
+ disabled: null,
12204
+ icons: {
12205
+ button: "ui-icon-triangle-1-s"
12206
+ },
12207
+ position: {
12208
+ my: "left top",
12209
+ at: "left bottom",
12210
+ collision: "none"
12211
+ },
12212
+ width: null,
12213
+
12214
+ // callbacks
12215
+ change: null,
12216
+ close: null,
12217
+ focus: null,
12218
+ open: null,
12219
+ select: null
12220
+ },
12221
+
12222
+ _create: function() {
12223
+ var selectmenuId = this.element.uniqueId().attr( "id" );
12224
+ this.ids = {
12225
+ element: selectmenuId,
12226
+ button: selectmenuId + "-button",
12227
+ menu: selectmenuId + "-menu"
12228
+ };
12229
+
12230
+ this._drawButton();
12231
+ this._drawMenu();
12232
+
12233
+ if ( this.options.disabled ) {
12234
+ this.disable();
12235
+ }
12236
+ },
12237
+
12238
+ _drawButton: function() {
12239
+ var that = this;
12240
+
12241
+ // Associate existing label with the new button
12242
+ this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button );
12243
+ this._on( this.label, {
12244
+ click: function( event ) {
12245
+ this.button.focus();
12246
+ event.preventDefault();
12247
+ }
12248
+ });
12249
+
12250
+ // Hide original select element
12251
+ this.element.hide();
12252
+
12253
+ // Create button
12254
+ this.button = $( "<span>", {
12255
+ "class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all",
12256
+ tabindex: this.options.disabled ? -1 : 0,
12257
+ id: this.ids.button,
12258
+ role: "combobox",
12259
+ "aria-expanded": "false",
12260
+ "aria-autocomplete": "list",
12261
+ "aria-owns": this.ids.menu,
12262
+ "aria-haspopup": "true"
12263
+ })
12264
+ .insertAfter( this.element );
12265
+
12266
+ $( "<span>", {
12267
+ "class": "ui-icon " + this.options.icons.button
12268
+ })
12269
+ .prependTo( this.button );
12270
+
12271
+ this.buttonText = $( "<span>", {
12272
+ "class": "ui-selectmenu-text"
12273
+ })
12274
+ .appendTo( this.button );
12275
+
12276
+ this._setText( this.buttonText, this.element.find( "option:selected" ).text() );
12277
+ this._resizeButton();
12278
+
12279
+ this._on( this.button, this._buttonEvents );
12280
+ this.button.one( "focusin", function() {
12281
+
12282
+ // Delay rendering the menu items until the button receives focus.
12283
+ // The menu may have already been rendered via a programmatic open.
12284
+ if ( !that.menuItems ) {
12285
+ that._refreshMenu();
12286
+ }
12287
+ });
12288
+ this._hoverable( this.button );
12289
+ this._focusable( this.button );
12290
+ },
12291
+
12292
+ _drawMenu: function() {
12293
+ var that = this;
12294
+
12295
+ // Create menu
12296
+ this.menu = $( "<ul>", {
12297
+ "aria-hidden": "true",
12298
+ "aria-labelledby": this.ids.button,
12299
+ id: this.ids.menu
12300
+ });
12301
+
12302
+ // Wrap menu
12303
+ this.menuWrap = $( "<div>", {
12304
+ "class": "ui-selectmenu-menu ui-front"
12305
+ })
12306
+ .append( this.menu )
12307
+ .appendTo( this._appendTo() );
12308
+
12309
+ // Initialize menu widget
12310
+ this.menuInstance = this.menu
12311
+ .menu({
12312
+ role: "listbox",
12313
+ select: function( event, ui ) {
12314
+ event.preventDefault();
12315
+
12316
+ // support: IE8
12317
+ // If the item was selected via a click, the text selection
12318
+ // will be destroyed in IE
12319
+ that._setSelection();
12320
+
12321
+ that._select( ui.item.data( "ui-selectmenu-item" ), event );
12322
+ },
12323
+ focus: function( event, ui ) {
12324
+ var item = ui.item.data( "ui-selectmenu-item" );
12325
+
12326
+ // Prevent inital focus from firing and check if its a newly focused item
12327
+ if ( that.focusIndex != null && item.index !== that.focusIndex ) {
12328
+ that._trigger( "focus", event, { item: item } );
12329
+ if ( !that.isOpen ) {
12330
+ that._select( item, event );
12331
+ }
12332
+ }
12333
+ that.focusIndex = item.index;
12334
+
12335
+ that.button.attr( "aria-activedescendant",
12336
+ that.menuItems.eq( item.index ).attr( "id" ) );
12337
+ }
12338
+ })
12339
+ .menu( "instance" );
12340
+
12341
+ // Adjust menu styles to dropdown
12342
+ this.menu
12343
+ .addClass( "ui-corner-bottom" )
12344
+ .removeClass( "ui-corner-all" );
12345
+
12346
+ // Don't close the menu on mouseleave
12347
+ this.menuInstance._off( this.menu, "mouseleave" );
12348
+
12349
+ // Cancel the menu's collapseAll on document click
12350
+ this.menuInstance._closeOnDocumentClick = function() {
12351
+ return false;
12352
+ };
12353
+
12354
+ // Selects often contain empty items, but never contain dividers
12355
+ this.menuInstance._isDivider = function() {
12356
+ return false;
12357
+ };
12358
+ },
12359
+
12360
+ refresh: function() {
12361
+ this._refreshMenu();
12362
+ this._setText( this.buttonText, this._getSelectedItem().text() );
12363
+ if ( !this.options.width ) {
12364
+ this._resizeButton();
12365
+ }
12366
+ },
12367
+
12368
+ _refreshMenu: function() {
12369
+ this.menu.empty();
12370
+
12371
+ var item,
12372
+ options = this.element.find( "option" );
12373
+
12374
+ if ( !options.length ) {
12375
+ return;
12376
+ }
12377
+
12378
+ this._parseOptions( options );
12379
+ this._renderMenu( this.menu, this.items );
12380
+
12381
+ this.menuInstance.refresh();
12382
+ this.menuItems = this.menu.find( "li" ).not( ".ui-selectmenu-optgroup" );
12383
+
12384
+ item = this._getSelectedItem();
12385
+
12386
+ // Update the menu to have the correct item focused
12387
+ this.menuInstance.focus( null, item );
12388
+ this._setAria( item.data( "ui-selectmenu-item" ) );
12389
+
12390
+ // Set disabled state
12391
+ this._setOption( "disabled", this.element.prop( "disabled" ) );
12392
+ },
12393
+
12394
+ open: function( event ) {
12395
+ if ( this.options.disabled ) {
12396
+ return;
12397
+ }
12398
+
12399
+ // If this is the first time the menu is being opened, render the items
12400
+ if ( !this.menuItems ) {
12401
+ this._refreshMenu();
12402
+ } else {
12403
+
12404
+ // Menu clears focus on close, reset focus to selected item
12405
+ this.menu.find( ".ui-state-focus" ).removeClass( "ui-state-focus" );
12406
+ this.menuInstance.focus( null, this._getSelectedItem() );
12407
+ }
12408
+
12409
+ this.isOpen = true;
12410
+ this._toggleAttr();
12411
+ this._resizeMenu();
12412
+ this._position();
12413
+
12414
+ this._on( this.document, this._documentClick );
12415
+
12416
+ this._trigger( "open", event );
12417
+ },
12418
+
12419
+ _position: function() {
12420
+ this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
12421
+ },
12422
+
12423
+ close: function( event ) {
12424
+ if ( !this.isOpen ) {
12425
+ return;
12426
+ }
12427
+
12428
+ this.isOpen = false;
12429
+ this._toggleAttr();
12430
+
12431
+ this.range = null;
12432
+ this._off( this.document );
12433
+
12434
+ this._trigger( "close", event );
12435
+ },
12436
+
12437
+ widget: function() {
12438
+ return this.button;
12439
+ },
12440
+
12441
+ menuWidget: function() {
12442
+ return this.menu;
12443
+ },
12444
+
12445
+ _renderMenu: function( ul, items ) {
12446
+ var that = this,
12447
+ currentOptgroup = "";
12448
+
12449
+ $.each( items, function( index, item ) {
12450
+ if ( item.optgroup !== currentOptgroup ) {
12451
+ $( "<li>", {
12452
+ "class": "ui-selectmenu-optgroup ui-menu-divider" +
12453
+ ( item.element.parent( "optgroup" ).prop( "disabled" ) ?
12454
+ " ui-state-disabled" :
12455
+ "" ),
12456
+ text: item.optgroup
12457
+ })
12458
+ .appendTo( ul );
12459
+
12460
+ currentOptgroup = item.optgroup;
12461
+ }
12462
+
12463
+ that._renderItemData( ul, item );
12464
+ });
12465
+ },
12466
+
12467
+ _renderItemData: function( ul, item ) {
12468
+ return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
12469
+ },
12470
+
12471
+ _renderItem: function( ul, item ) {
12472
+ var li = $( "<li>" );
12473
+
12474
+ if ( item.disabled ) {
12475
+ li.addClass( "ui-state-disabled" );
12476
+ }
12477
+ this._setText( li, item.label );
12478
+
12479
+ return li.appendTo( ul );
12480
+ },
12481
+
12482
+ _setText: function( element, value ) {
12483
+ if ( value ) {
12484
+ element.text( value );
12485
+ } else {
12486
+ element.html( "&#160;" );
12487
+ }
12488
+ },
12489
+
12490
+ _move: function( direction, event ) {
12491
+ var item, next,
12492
+ filter = ".ui-menu-item";
12493
+
12494
+ if ( this.isOpen ) {
12495
+ item = this.menuItems.eq( this.focusIndex );
12496
+ } else {
12497
+ item = this.menuItems.eq( this.element[ 0 ].selectedIndex );
12498
+ filter += ":not(.ui-state-disabled)";
12499
+ }
12500
+
12501
+ if ( direction === "first" || direction === "last" ) {
12502
+ next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
12503
+ } else {
12504
+ next = item[ direction + "All" ]( filter ).eq( 0 );
12505
+ }
12506
+
12507
+ if ( next.length ) {
12508
+ this.menuInstance.focus( event, next );
12509
+ }
12510
+ },
12511
+
12512
+ _getSelectedItem: function() {
12513
+ return this.menuItems.eq( this.element[ 0 ].selectedIndex );
12514
+ },
12515
+
12516
+ _toggle: function( event ) {
12517
+ this[ this.isOpen ? "close" : "open" ]( event );
12518
+ },
12519
+
12520
+ _setSelection: function() {
12521
+ var selection;
12522
+
12523
+ if ( !this.range ) {
12524
+ return;
12525
+ }
12526
+
12527
+ if ( window.getSelection ) {
12528
+ selection = window.getSelection();
12529
+ selection.removeAllRanges();
12530
+ selection.addRange( this.range );
12531
+
12532
+ // support: IE8
12533
+ } else {
12534
+ this.range.select();
12535
+ }
12536
+
12537
+ // support: IE
12538
+ // Setting the text selection kills the button focus in IE, but
12539
+ // restoring the focus doesn't kill the selection.
12540
+ this.button.focus();
12541
+ },
12542
+
12543
+ _documentClick: {
12544
+ mousedown: function( event ) {
12545
+ if ( !this.isOpen ) {
12546
+ return;
12547
+ }
12548
+
12549
+ if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + this.ids.button ).length ) {
12550
+ this.close( event );
12551
+ }
12552
+ }
12553
+ },
12554
+
12555
+ _buttonEvents: {
12556
+
12557
+ // Prevent text selection from being reset when interacting with the selectmenu (#10144)
12558
+ mousedown: function() {
12559
+ var selection;
12560
+
12561
+ if ( window.getSelection ) {
12562
+ selection = window.getSelection();
12563
+ if ( selection.rangeCount ) {
12564
+ this.range = selection.getRangeAt( 0 );
12565
+ }
12566
+
12567
+ // support: IE8
12568
+ } else {
12569
+ this.range = document.selection.createRange();
12570
+ }
12571
+ },
12572
+
12573
+ click: function( event ) {
12574
+ this._setSelection();
12575
+ this._toggle( event );
12576
+ },
12577
+
12578
+ keydown: function( event ) {
12579
+ var preventDefault = true;
12580
+ switch ( event.keyCode ) {
12581
+ case $.ui.keyCode.TAB:
12582
+ case $.ui.keyCode.ESCAPE:
12583
+ this.close( event );
12584
+ preventDefault = false;
12585
+ break;
12586
+ case $.ui.keyCode.ENTER:
12587
+ if ( this.isOpen ) {
12588
+ this._selectFocusedItem( event );
12589
+ }
12590
+ break;
12591
+ case $.ui.keyCode.UP:
12592
+ if ( event.altKey ) {
12593
+ this._toggle( event );
12594
+ } else {
12595
+ this._move( "prev", event );
12596
+ }
12597
+ break;
12598
+ case $.ui.keyCode.DOWN:
12599
+ if ( event.altKey ) {
12600
+ this._toggle( event );
12601
+ } else {
12602
+ this._move( "next", event );
12603
+ }
12604
+ break;
12605
+ case $.ui.keyCode.SPACE:
12606
+ if ( this.isOpen ) {
12607
+ this._selectFocusedItem( event );
12608
+ } else {
12609
+ this._toggle( event );
12610
+ }
12611
+ break;
12612
+ case $.ui.keyCode.LEFT:
12613
+ this._move( "prev", event );
12614
+ break;
12615
+ case $.ui.keyCode.RIGHT:
12616
+ this._move( "next", event );
12617
+ break;
12618
+ case $.ui.keyCode.HOME:
12619
+ case $.ui.keyCode.PAGE_UP:
12620
+ this._move( "first", event );
12621
+ break;
12622
+ case $.ui.keyCode.END:
12623
+ case $.ui.keyCode.PAGE_DOWN:
12624
+ this._move( "last", event );
12625
+ break;
12626
+ default:
12627
+ this.menu.trigger( event );
12628
+ preventDefault = false;
12629
+ }
12630
+
12631
+ if ( preventDefault ) {
12632
+ event.preventDefault();
12633
+ }
12634
+ }
12635
+ },
12636
+
12637
+ _selectFocusedItem: function( event ) {
12638
+ var item = this.menuItems.eq( this.focusIndex );
12639
+ if ( !item.hasClass( "ui-state-disabled" ) ) {
12640
+ this._select( item.data( "ui-selectmenu-item" ), event );
12641
+ }
12642
+ },
12643
+
12644
+ _select: function( item, event ) {
12645
+ var oldIndex = this.element[ 0 ].selectedIndex;
12646
+
12647
+ // Change native select element
12648
+ this.element[ 0 ].selectedIndex = item.index;
12649
+ this._setText( this.buttonText, item.label );
12650
+ this._setAria( item );
12651
+ this._trigger( "select", event, { item: item } );
12652
+
12653
+ if ( item.index !== oldIndex ) {
12654
+ this._trigger( "change", event, { item: item } );
12655
+ }
12656
+
12657
+ this.close( event );
12658
+ },
12659
+
12660
+ _setAria: function( item ) {
12661
+ var id = this.menuItems.eq( item.index ).attr( "id" );
12662
+
12663
+ this.button.attr({
12664
+ "aria-labelledby": id,
12665
+ "aria-activedescendant": id
12666
+ });
12667
+ this.menu.attr( "aria-activedescendant", id );
12668
+ },
12669
+
12670
+ _setOption: function( key, value ) {
12671
+ if ( key === "icons" ) {
12672
+ this.button.find( "span.ui-icon" )
12673
+ .removeClass( this.options.icons.button )
12674
+ .addClass( value.button );
12675
+ }
12676
+
12677
+ this._super( key, value );
12678
+
12679
+ if ( key === "appendTo" ) {
12680
+ this.menuWrap.appendTo( this._appendTo() );
12681
+ }
12682
+
12683
+ if ( key === "disabled" ) {
12684
+ this.menuInstance.option( "disabled", value );
12685
+ this.button
12686
+ .toggleClass( "ui-state-disabled", value )
12687
+ .attr( "aria-disabled", value );
12688
+
12689
+ this.element.prop( "disabled", value );
12690
+ if ( value ) {
12691
+ this.button.attr( "tabindex", -1 );
12692
+ this.close();
12693
+ } else {
12694
+ this.button.attr( "tabindex", 0 );
12695
+ }
12696
+ }
12697
+
12698
+ if ( key === "width" ) {
12699
+ this._resizeButton();
12700
+ }
12701
+ },
12702
+
12703
+ _appendTo: function() {
12704
+ var element = this.options.appendTo;
12705
+
12706
+ if ( element ) {
12707
+ element = element.jquery || element.nodeType ?
12708
+ $( element ) :
12709
+ this.document.find( element ).eq( 0 );
12710
+ }
12711
+
12712
+ if ( !element || !element[ 0 ] ) {
12713
+ element = this.element.closest( ".ui-front" );
12714
+ }
12715
+
12716
+ if ( !element.length ) {
12717
+ element = this.document[ 0 ].body;
12718
+ }
12719
+
12720
+ return element;
12721
+ },
12722
+
12723
+ _toggleAttr: function() {
12724
+ this.button
12725
+ .toggleClass( "ui-corner-top", this.isOpen )
12726
+ .toggleClass( "ui-corner-all", !this.isOpen )
12727
+ .attr( "aria-expanded", this.isOpen );
12728
+ this.menuWrap.toggleClass( "ui-selectmenu-open", this.isOpen );
12729
+ this.menu.attr( "aria-hidden", !this.isOpen );
12730
+ },
12731
+
12732
+ _resizeButton: function() {
12733
+ var width = this.options.width;
12734
+
12735
+ if ( !width ) {
12736
+ width = this.element.show().outerWidth();
12737
+ this.element.hide();
12738
+ }
12739
+
12740
+ this.button.outerWidth( width );
12741
+ },
12742
+
12743
+ _resizeMenu: function() {
12744
+ this.menu.outerWidth( Math.max(
12745
+ this.button.outerWidth(),
12746
+
12747
+ // support: IE10
12748
+ // IE10 wraps long text (possibly a rounding bug)
12749
+ // so we add 1px to avoid the wrapping
12750
+ this.menu.width( "" ).outerWidth() + 1
12751
+ ) );
12752
+ },
12753
+
12754
+ _getCreateOptions: function() {
12755
+ return { disabled: this.element.prop( "disabled" ) };
12756
+ },
12757
+
12758
+ _parseOptions: function( options ) {
12759
+ var data = [];
12760
+ options.each(function( index, item ) {
12761
+ var option = $( item ),
12762
+ optgroup = option.parent( "optgroup" );
12763
+ data.push({
12764
+ element: option,
12765
+ index: index,
12766
+ value: option.val(),
12767
+ label: option.text(),
12768
+ optgroup: optgroup.attr( "label" ) || "",
12769
+ disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
12770
+ });
12771
+ });
12772
+ this.items = data;
12773
+ },
12774
+
12775
+ _destroy: function() {
12776
+ this.menuWrap.remove();
12777
+ this.button.remove();
12778
+ this.element.show();
12779
+ this.element.removeUniqueId();
12780
+ this.label.attr( "for", this.ids.element );
12781
+ }
12782
+ });
12783
+
12784
+
12785
+ /*!
12786
+ * jQuery UI Slider 1.11.4
12787
+ * http://jqueryui.com
12788
+ *
12789
+ * Copyright jQuery Foundation and other contributors
12790
+ * Released under the MIT license.
12791
+ * http://jquery.org/license
12792
+ *
12793
+ * http://api.jqueryui.com/slider/
12794
+ */
12795
+
12796
+
12797
+ var slider = $.widget( "ui.slider", $.ui.mouse, {
12798
+ version: "1.11.4",
12799
+ widgetEventPrefix: "slide",
12800
+
12801
+ options: {
12802
+ animate: false,
12803
+ distance: 0,
12804
+ max: 100,
12805
+ min: 0,
12806
+ orientation: "horizontal",
12807
+ range: false,
12808
+ step: 1,
12809
+ value: 0,
12810
+ values: null,
12811
+
12812
+ // callbacks
12813
+ change: null,
12814
+ slide: null,
12815
+ start: null,
12816
+ stop: null
12817
+ },
12818
+
12819
+ // number of pages in a slider
12820
+ // (how many times can you page up/down to go through the whole range)
12821
+ numPages: 5,
12822
+
12823
+ _create: function() {
12824
+ this._keySliding = false;
12825
+ this._mouseSliding = false;
12826
+ this._animateOff = true;
12827
+ this._handleIndex = null;
12828
+ this._detectOrientation();
12829
+ this._mouseInit();
12830
+ this._calculateNewMax();
12831
+
12832
+ this.element
12833
+ .addClass( "ui-slider" +
12834
+ " ui-slider-" + this.orientation +
12835
+ " ui-widget" +
12836
+ " ui-widget-content" +
12837
+ " ui-corner-all");
12838
+
12839
+ this._refresh();
12840
+ this._setOption( "disabled", this.options.disabled );
12841
+
12842
+ this._animateOff = false;
12843
+ },
12844
+
12845
+ _refresh: function() {
12846
+ this._createRange();
12847
+ this._createHandles();
12848
+ this._setupEvents();
12849
+ this._refreshValue();
12850
+ },
12851
+
12852
+ _createHandles: function() {
12853
+ var i, handleCount,
12854
+ options = this.options,
12855
+ existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
12856
+ handle = "<span class='ui-slider-handle mullnav_rng ui-state-default ui-corner-all' onmouseup='mullnav_rng();' tabindex='0'></span>",
12857
+ handles = [];
12858
+
12859
+ handleCount = ( options.values && options.values.length ) || 1;
12860
+
12861
+ if ( existingHandles.length > handleCount ) {
12862
+ existingHandles.slice( handleCount ).remove();
12863
+ existingHandles = existingHandles.slice( 0, handleCount );
12864
+ }
12865
+
12866
+ for ( i = existingHandles.length; i < handleCount; i++ ) {
12867
+ handles.push( handle );
12868
+ }
12869
+
12870
+ this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
12871
+
12872
+ this.handle = this.handles.eq( 0 );
12873
+
12874
+ this.handles.each(function( i ) {
12875
+ $( this ).data( "ui-slider-handle-index", i );
12876
+ });
12877
+ },
12878
+
12879
+ _createRange: function() {
12880
+ var options = this.options,
12881
+ classes = "";
12882
+
12883
+ if ( options.range ) {
12884
+ if ( options.range === true ) {
12885
+ if ( !options.values ) {
12886
+ options.values = [ this._valueMin(), this._valueMin() ];
12887
+ } else if ( options.values.length && options.values.length !== 2 ) {
12888
+ options.values = [ options.values[0], options.values[0] ];
12889
+ } else if ( $.isArray( options.values ) ) {
12890
+ options.values = options.values.slice(0);
12891
+ }
12892
+ }
12893
+
12894
+ if ( !this.range || !this.range.length ) {
12895
+ this.range = $( "<div></div>" )
12896
+ .appendTo( this.element );
12897
+
12898
+ classes = "ui-slider-range" +
12899
+ // note: this isn't the most fittingly semantic framework class for this element,
12900
+ // but worked best visually with a variety of themes
12901
+ " ui-widget-header ui-corner-all";
12902
+ } else {
12903
+ this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
12904
+ // Handle range switching from true to min/max
12905
+ .css({
12906
+ "left": "",
12907
+ "bottom": ""
12908
+ });
12909
+ }
12910
+
12911
+ this.range.addClass( classes +
12912
+ ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
12913
+ } else {
12914
+ if ( this.range ) {
12915
+ this.range.remove();
12916
+ }
12917
+ this.range = null;
12918
+ }
12919
+ },
12920
+
12921
+ _setupEvents: function() {
12922
+ this._off( this.handles );
12923
+ this._on( this.handles, this._handleEvents );
12924
+ this._hoverable( this.handles );
12925
+ this._focusable( this.handles );
12926
+ },
12927
+
12928
+ _destroy: function() {
12929
+ this.handles.remove();
12930
+ if ( this.range ) {
12931
+ this.range.remove();
12932
+ }
12933
+
12934
+ this.element
12935
+ .removeClass( "ui-slider" +
12936
+ " ui-slider-horizontal" +
12937
+ " ui-slider-vertical" +
12938
+ " ui-widget" +
12939
+ " ui-widget-content" +
12940
+ " ui-corner-all" );
12941
+
12942
+ this._mouseDestroy();
12943
+ },
12944
+
12945
+ _mouseCapture: function( event ) {
12946
+ var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
12947
+ that = this,
12948
+ o = this.options;
12949
+
12950
+ if ( o.disabled ) {
12951
+ return false;
12952
+ }
12953
+
12954
+ this.elementSize = {
12955
+ width: this.element.outerWidth(),
12956
+ height: this.element.outerHeight()
12957
+ };
12958
+ this.elementOffset = this.element.offset();
12959
+
12960
+ position = { x: event.pageX, y: event.pageY };
12961
+ normValue = this._normValueFromMouse( position );
12962
+ distance = this._valueMax() - this._valueMin() + 1;
12963
+ this.handles.each(function( i ) {
12964
+ var thisDistance = Math.abs( normValue - that.values(i) );
12965
+ if (( distance > thisDistance ) ||
12966
+ ( distance === thisDistance &&
12967
+ (i === that._lastChangedValue || that.values(i) === o.min ))) {
12968
+ distance = thisDistance;
12969
+ closestHandle = $( this );
12970
+ index = i;
12971
+ }
12972
+ });
12973
+
12974
+ allowed = this._start( event, index );
12975
+ if ( allowed === false ) {
12976
+ return false;
12977
+ }
12978
+ this._mouseSliding = true;
12979
+
12980
+ this._handleIndex = index;
12981
+
12982
+ closestHandle
12983
+ .addClass( "ui-state-active" )
12984
+ .focus();
12985
+
12986
+ offset = closestHandle.offset();
12987
+ mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
12988
+ this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
12989
+ left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
12990
+ top: event.pageY - offset.top -
12991
+ ( closestHandle.height() / 2 ) -
12992
+ ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
12993
+ ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
12994
+ ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
12995
+ };
12996
+
12997
+ if ( !this.handles.hasClass( "ui-state-hover" ) ) {
12998
+ this._slide( event, index, normValue );
12999
+ }
13000
+ this._animateOff = true;
13001
+ return true;
13002
+ },
13003
+
13004
+ _mouseStart: function() {
13005
+ return true;
13006
+ },
13007
+
13008
+ _mouseDrag: function( event ) {
13009
+ var position = { x: event.pageX, y: event.pageY },
13010
+ normValue = this._normValueFromMouse( position );
13011
+
13012
+ this._slide( event, this._handleIndex, normValue );
13013
+
13014
+ return false;
13015
+ },
13016
+
13017
+ _mouseStop: function( event ) {
13018
+ this.handles.removeClass( "ui-state-active" );
13019
+ this._mouseSliding = false;
13020
+
13021
+ this._stop( event, this._handleIndex );
13022
+ this._change( event, this._handleIndex );
13023
+
13024
+ this._handleIndex = null;
13025
+ this._clickOffset = null;
13026
+ this._animateOff = false;
13027
+
13028
+ return false;
13029
+ },
13030
+
13031
+ _detectOrientation: function() {
13032
+ this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
13033
+ },
13034
+
13035
+ _normValueFromMouse: function( position ) {
13036
+ var pixelTotal,
13037
+ pixelMouse,
13038
+ percentMouse,
13039
+ valueTotal,
13040
+ valueMouse;
13041
+
13042
+ if ( this.orientation === "horizontal" ) {
13043
+ pixelTotal = this.elementSize.width;
13044
+ pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
13045
+ } else {
13046
+ pixelTotal = this.elementSize.height;
13047
+ pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
13048
+ }
13049
+
13050
+ percentMouse = ( pixelMouse / pixelTotal );
13051
+ if ( percentMouse > 1 ) {
13052
+ percentMouse = 1;
13053
+ }
13054
+ if ( percentMouse < 0 ) {
13055
+ percentMouse = 0;
13056
+ }
13057
+ if ( this.orientation === "vertical" ) {
13058
+ percentMouse = 1 - percentMouse;
13059
+ }
13060
+
13061
+ valueTotal = this._valueMax() - this._valueMin();
13062
+ valueMouse = this._valueMin() + percentMouse * valueTotal;
13063
+
13064
+ return this._trimAlignValue( valueMouse );
13065
+ },
13066
+
13067
+ _start: function( event, index ) {
13068
+ var uiHash = {
13069
+ handle: this.handles[ index ],
13070
+ value: this.value()
13071
+ };
13072
+ if ( this.options.values && this.options.values.length ) {
13073
+ uiHash.value = this.values( index );
13074
+ uiHash.values = this.values();
13075
+ }
13076
+ return this._trigger( "start", event, uiHash );
13077
+ },
13078
+
13079
+ _slide: function( event, index, newVal ) {
13080
+ var otherVal,
13081
+ newValues,
13082
+ allowed;
13083
+
13084
+ if ( this.options.values && this.options.values.length ) {
13085
+ otherVal = this.values( index ? 0 : 1 );
13086
+
13087
+ if ( ( this.options.values.length === 2 && this.options.range === true ) &&
13088
+ ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
13089
+ ) {
13090
+ newVal = otherVal;
13091
+ }
13092
+
13093
+ if ( newVal !== this.values( index ) ) {
13094
+ newValues = this.values();
13095
+ newValues[ index ] = newVal;
13096
+ // A slide can be canceled by returning false from the slide callback
13097
+ allowed = this._trigger( "slide", event, {
13098
+ handle: this.handles[ index ],
13099
+ value: newVal,
13100
+ values: newValues
13101
+ } );
13102
+ otherVal = this.values( index ? 0 : 1 );
13103
+ if ( allowed !== false ) {
13104
+ this.values( index, newVal );
13105
+ }
13106
+ }
13107
+ } else {
13108
+ if ( newVal !== this.value() ) {
13109
+ // A slide can be canceled by returning false from the slide callback
13110
+ allowed = this._trigger( "slide", event, {
13111
+ handle: this.handles[ index ],
13112
+ value: newVal
13113
+ } );
13114
+ if ( allowed !== false ) {
13115
+ this.value( newVal );
13116
+ }
13117
+ }
13118
+ }
13119
+ },
13120
+
13121
+ _stop: function( event, index ) {
13122
+ var uiHash = {
13123
+ handle: this.handles[ index ],
13124
+ value: this.value()
13125
+ };
13126
+ if ( this.options.values && this.options.values.length ) {
13127
+ uiHash.value = this.values( index );
13128
+ uiHash.values = this.values();
13129
+ }
13130
+
13131
+ this._trigger( "stop", event, uiHash );
13132
+ },
13133
+
13134
+ _change: function( event, index ) {
13135
+ if ( !this._keySliding && !this._mouseSliding ) {
13136
+ var uiHash = {
13137
+ handle: this.handles[ index ],
13138
+ value: this.value()
13139
+ };
13140
+ if ( this.options.values && this.options.values.length ) {
13141
+ uiHash.value = this.values( index );
13142
+ uiHash.values = this.values();
13143
+ }
13144
+
13145
+ //store the last changed value index for reference when handles overlap
13146
+ this._lastChangedValue = index;
13147
+
13148
+ this._trigger( "change", event, uiHash );
13149
+ }
13150
+ },
13151
+
13152
+ value: function( newValue ) {
13153
+ if ( arguments.length ) {
13154
+ this.options.value = this._trimAlignValue( newValue );
13155
+ this._refreshValue();
13156
+ this._change( null, 0 );
13157
+ return;
13158
+ }
13159
+
13160
+ return this._value();
13161
+ },
13162
+
13163
+ values: function( index, newValue ) {
13164
+ var vals,
13165
+ newValues,
13166
+ i;
13167
+
13168
+ if ( arguments.length > 1 ) {
13169
+ this.options.values[ index ] = this._trimAlignValue( newValue );
13170
+ this._refreshValue();
13171
+ this._change( null, index );
13172
+ return;
13173
+ }
13174
+
13175
+ if ( arguments.length ) {
13176
+ if ( $.isArray( arguments[ 0 ] ) ) {
13177
+ vals = this.options.values;
13178
+ newValues = arguments[ 0 ];
13179
+ for ( i = 0; i < vals.length; i += 1 ) {
13180
+ vals[ i ] = this._trimAlignValue( newValues[ i ] );
13181
+ this._change( null, i );
13182
+ }
13183
+ this._refreshValue();
13184
+ } else {
13185
+ if ( this.options.values && this.options.values.length ) {
13186
+ return this._values( index );
13187
+ } else {
13188
+ return this.value();
13189
+ }
13190
+ }
13191
+ } else {
13192
+ return this._values();
13193
+ }
13194
+ },
13195
+
13196
+ _setOption: function( key, value ) {
13197
+ var i,
13198
+ valsLength = 0;
13199
+
13200
+ if ( key === "range" && this.options.range === true ) {
13201
+ if ( value === "min" ) {
13202
+ this.options.value = this._values( 0 );
13203
+ this.options.values = null;
13204
+ } else if ( value === "max" ) {
13205
+ this.options.value = this._values( this.options.values.length - 1 );
13206
+ this.options.values = null;
13207
+ }
13208
+ }
13209
+
13210
+ if ( $.isArray( this.options.values ) ) {
13211
+ valsLength = this.options.values.length;
13212
+ }
13213
+
13214
+ if ( key === "disabled" ) {
13215
+ this.element.toggleClass( "ui-state-disabled", !!value );
13216
+ }
13217
+
13218
+ this._super( key, value );
13219
+
13220
+ switch ( key ) {
13221
+ case "orientation":
13222
+ this._detectOrientation();
13223
+ this.element
13224
+ .removeClass( "ui-slider-horizontal ui-slider-vertical" )
13225
+ .addClass( "ui-slider-" + this.orientation );
13226
+ this._refreshValue();
13227
+
13228
+ // Reset positioning from previous orientation
13229
+ this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
13230
+ break;
13231
+ case "value":
13232
+ this._animateOff = true;
13233
+ this._refreshValue();
13234
+ this._change( null, 0 );
13235
+ this._animateOff = false;
13236
+ break;
13237
+ case "values":
13238
+ this._animateOff = true;
13239
+ this._refreshValue();
13240
+ for ( i = 0; i < valsLength; i += 1 ) {
13241
+ this._change( null, i );
13242
+ }
13243
+ this._animateOff = false;
13244
+ break;
13245
+ case "step":
13246
+ case "min":
13247
+ case "max":
13248
+ this._animateOff = true;
13249
+ this._calculateNewMax();
13250
+ this._refreshValue();
13251
+ this._animateOff = false;
13252
+ break;
13253
+ case "range":
13254
+ this._animateOff = true;
13255
+ this._refresh();
13256
+ this._animateOff = false;
13257
+ break;
13258
+ }
13259
+ },
13260
+
13261
+ //internal value getter
13262
+ // _value() returns value trimmed by min and max, aligned by step
13263
+ _value: function() {
13264
+ var val = this.options.value;
13265
+ val = this._trimAlignValue( val );
13266
+
13267
+ return val;
13268
+ },
13269
+
13270
+ //internal values getter
13271
+ // _values() returns array of values trimmed by min and max, aligned by step
13272
+ // _values( index ) returns single value trimmed by min and max, aligned by step
13273
+ _values: function( index ) {
13274
+ var val,
13275
+ vals,
13276
+ i;
13277
+
13278
+ if ( arguments.length ) {
13279
+ val = this.options.values[ index ];
13280
+ val = this._trimAlignValue( val );
13281
+
13282
+ return val;
13283
+ } else if ( this.options.values && this.options.values.length ) {
13284
+ // .slice() creates a copy of the array
13285
+ // this copy gets trimmed by min and max and then returned
13286
+ vals = this.options.values.slice();
13287
+ for ( i = 0; i < vals.length; i += 1) {
13288
+ vals[ i ] = this._trimAlignValue( vals[ i ] );
13289
+ }
13290
+
13291
+ return vals;
13292
+ } else {
13293
+ return [];
13294
+ }
13295
+ },
13296
+
13297
+ // returns the step-aligned value that val is closest to, between (inclusive) min and max
13298
+ _trimAlignValue: function( val ) {
13299
+ if ( val <= this._valueMin() ) {
13300
+ return this._valueMin();
13301
+ }
13302
+ if ( val >= this._valueMax() ) {
13303
+ return this._valueMax();
13304
+ }
13305
+ var step = ( this.options.step > 0 ) ? this.options.step : 1,
13306
+ valModStep = (val - this._valueMin()) % step,
13307
+ alignValue = val - valModStep;
13308
+
13309
+ if ( Math.abs(valModStep) * 2 >= step ) {
13310
+ alignValue += ( valModStep > 0 ) ? step : ( -step );
13311
+ }
13312
+
13313
+ // Since JavaScript has problems with large floats, round
13314
+ // the final value to 5 digits after the decimal point (see #4124)
13315
+ return parseFloat( alignValue.toFixed(5) );
13316
+ },
13317
+
13318
+ _calculateNewMax: function() {
13319
+ var max = this.options.max,
13320
+ min = this._valueMin(),
13321
+ step = this.options.step,
13322
+ aboveMin = Math.floor( ( +( max - min ).toFixed( this._precision() ) ) / step ) * step;
13323
+ max = aboveMin + min;
13324
+ this.max = parseFloat( max.toFixed( this._precision() ) );
13325
+ },
13326
+
13327
+ _precision: function() {
13328
+ var precision = this._precisionOf( this.options.step );
13329
+ if ( this.options.min !== null ) {
13330
+ precision = Math.max( precision, this._precisionOf( this.options.min ) );
13331
+ }
13332
+ return precision;
13333
+ },
13334
+
13335
+ _precisionOf: function( num ) {
13336
+ var str = num.toString(),
13337
+ decimal = str.indexOf( "." );
13338
+ return decimal === -1 ? 0 : str.length - decimal - 1;
13339
+ },
13340
+
13341
+ _valueMin: function() {
13342
+ return this.options.min;
13343
+ },
13344
+
13345
+ _valueMax: function() {
13346
+ return this.max;
13347
+ },
13348
+
13349
+ _refreshValue: function() {
13350
+ var lastValPercent, valPercent, value, valueMin, valueMax,
13351
+ oRange = this.options.range,
13352
+ o = this.options,
13353
+ that = this,
13354
+ animate = ( !this._animateOff ) ? o.animate : false,
13355
+ _set = {};
13356
+
13357
+ if ( this.options.values && this.options.values.length ) {
13358
+ this.handles.each(function( i ) {
13359
+ valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
13360
+ _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13361
+ $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13362
+ if ( that.options.range === true ) {
13363
+ if ( that.orientation === "horizontal" ) {
13364
+ if ( i === 0 ) {
13365
+ that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
13366
+ }
13367
+ if ( i === 1 ) {
13368
+ that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13369
+ }
13370
+ } else {
13371
+ if ( i === 0 ) {
13372
+ that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
13373
+ }
13374
+ if ( i === 1 ) {
13375
+ that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
13376
+ }
13377
+ }
13378
+ }
13379
+ lastValPercent = valPercent;
13380
+ });
13381
+ } else {
13382
+ value = this.value();
13383
+ valueMin = this._valueMin();
13384
+ valueMax = this._valueMax();
13385
+ valPercent = ( valueMax !== valueMin ) ?
13386
+ ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
13387
+ 0;
13388
+ _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
13389
+ this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
13390
+
13391
+ if ( oRange === "min" && this.orientation === "horizontal" ) {
13392
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
13393
+ }
13394
+ if ( oRange === "max" && this.orientation === "horizontal" ) {
13395
+ this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13396
+ }
13397
+ if ( oRange === "min" && this.orientation === "vertical" ) {
13398
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
13399
+ }
13400
+ if ( oRange === "max" && this.orientation === "vertical" ) {
13401
+ this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
13402
+ }
13403
+ }
13404
+ },
13405
+
13406
+ _handleEvents: {
13407
+ keydown: function( event ) {
13408
+ var allowed, curVal, newVal, step,
13409
+ index = $( event.target ).data( "ui-slider-handle-index" );
13410
+
13411
+ switch ( event.keyCode ) {
13412
+ case $.ui.keyCode.HOME:
13413
+ case $.ui.keyCode.END:
13414
+ case $.ui.keyCode.PAGE_UP:
13415
+ case $.ui.keyCode.PAGE_DOWN:
13416
+ case $.ui.keyCode.UP:
13417
+ case $.ui.keyCode.RIGHT:
13418
+ case $.ui.keyCode.DOWN:
13419
+ case $.ui.keyCode.LEFT:
13420
+ event.preventDefault();
13421
+ if ( !this._keySliding ) {
13422
+ this._keySliding = true;
13423
+ $( event.target ).addClass( "ui-state-active" );
13424
+ allowed = this._start( event, index );
13425
+ if ( allowed === false ) {
13426
+ return;
13427
+ }
13428
+ }
13429
+ break;
13430
+ }
13431
+
13432
+ step = this.options.step;
13433
+ if ( this.options.values && this.options.values.length ) {
13434
+ curVal = newVal = this.values( index );
13435
+ } else {
13436
+ curVal = newVal = this.value();
13437
+ }
13438
+
13439
+ switch ( event.keyCode ) {
13440
+ case $.ui.keyCode.HOME:
13441
+ newVal = this._valueMin();
13442
+ break;
13443
+ case $.ui.keyCode.END:
13444
+ newVal = this._valueMax();
13445
+ break;
13446
+ case $.ui.keyCode.PAGE_UP:
13447
+ newVal = this._trimAlignValue(
13448
+ curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
13449
+ );
13450
+ break;
13451
+ case $.ui.keyCode.PAGE_DOWN:
13452
+ newVal = this._trimAlignValue(
13453
+ curVal - ( (this._valueMax() - this._valueMin()) / this.numPages ) );
13454
+ break;
13455
+ case $.ui.keyCode.UP:
13456
+ case $.ui.keyCode.RIGHT:
13457
+ if ( curVal === this._valueMax() ) {
13458
+ return;
13459
+ }
13460
+ newVal = this._trimAlignValue( curVal + step );
13461
+ break;
13462
+ case $.ui.keyCode.DOWN:
13463
+ case $.ui.keyCode.LEFT:
13464
+ if ( curVal === this._valueMin() ) {
13465
+ return;
13466
+ }
13467
+ newVal = this._trimAlignValue( curVal - step );
13468
+ break;
13469
+ }
13470
+
13471
+ this._slide( event, index, newVal );
13472
+ },
13473
+ keyup: function( event ) {
13474
+ var index = $( event.target ).data( "ui-slider-handle-index" );
13475
+
13476
+ if ( this._keySliding ) {
13477
+ this._keySliding = false;
13478
+ this._stop( event, index );
13479
+ this._change( event, index );
13480
+ $( event.target ).removeClass( "ui-state-active" );
13481
+ }
13482
+ }
13483
+ }
13484
+ });
13485
+
13486
+
13487
+ /*!
13488
+ * jQuery UI Sortable 1.11.4
13489
+ * http://jqueryui.com
13490
+ *
13491
+ * Copyright jQuery Foundation and other contributors
13492
+ * Released under the MIT license.
13493
+ * http://jquery.org/license
13494
+ *
13495
+ * http://api.jqueryui.com/sortable/
13496
+ */
13497
+
13498
+
13499
+ var sortable = $.widget("ui.sortable", $.ui.mouse, {
13500
+ version: "1.11.4",
13501
+ widgetEventPrefix: "sort",
13502
+ ready: false,
13503
+ options: {
13504
+ appendTo: "parent",
13505
+ axis: false,
13506
+ connectWith: false,
13507
+ containment: false,
13508
+ cursor: "auto",
13509
+ cursorAt: false,
13510
+ dropOnEmpty: true,
13511
+ forcePlaceholderSize: false,
13512
+ forceHelperSize: false,
13513
+ grid: false,
13514
+ handle: false,
13515
+ helper: "original",
13516
+ items: "> *",
13517
+ opacity: false,
13518
+ placeholder: false,
13519
+ revert: false,
13520
+ scroll: true,
13521
+ scrollSensitivity: 20,
13522
+ scrollSpeed: 20,
13523
+ scope: "default",
13524
+ tolerance: "intersect",
13525
+ zIndex: 1000,
13526
+
13527
+ // callbacks
13528
+ activate: null,
13529
+ beforeStop: null,
13530
+ change: null,
13531
+ deactivate: null,
13532
+ out: null,
13533
+ over: null,
13534
+ receive: null,
13535
+ remove: null,
13536
+ sort: null,
13537
+ start: null,
13538
+ stop: null,
13539
+ update: null
13540
+ },
13541
+
13542
+ _isOverAxis: function( x, reference, size ) {
13543
+ return ( x >= reference ) && ( x < ( reference + size ) );
13544
+ },
13545
+
13546
+ _isFloating: function( item ) {
13547
+ return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));
13548
+ },
13549
+
13550
+ _create: function() {
13551
+ this.containerCache = {};
13552
+ this.element.addClass("ui-sortable");
13553
+
13554
+ //Get the items
13555
+ this.refresh();
13556
+
13557
+ //Let's determine the parent's offset
13558
+ this.offset = this.element.offset();
13559
+
13560
+ //Initialize mouse events for interaction
13561
+ this._mouseInit();
13562
+
13563
+ this._setHandleClassName();
13564
+
13565
+ //We're ready to go
13566
+ this.ready = true;
13567
+
13568
+ },
13569
+
13570
+ _setOption: function( key, value ) {
13571
+ this._super( key, value );
13572
+
13573
+ if ( key === "handle" ) {
13574
+ this._setHandleClassName();
13575
+ }
13576
+ },
13577
+
13578
+ _setHandleClassName: function() {
13579
+ this.element.find( ".ui-sortable-handle" ).removeClass( "ui-sortable-handle" );
13580
+ $.each( this.items, function() {
13581
+ ( this.instance.options.handle ?
13582
+ this.item.find( this.instance.options.handle ) : this.item )
13583
+ .addClass( "ui-sortable-handle" );
13584
+ });
13585
+ },
13586
+
13587
+ _destroy: function() {
13588
+ this.element
13589
+ .removeClass( "ui-sortable ui-sortable-disabled" )
13590
+ .find( ".ui-sortable-handle" )
13591
+ .removeClass( "ui-sortable-handle" );
13592
+ this._mouseDestroy();
13593
+
13594
+ for ( var i = this.items.length - 1; i >= 0; i-- ) {
13595
+ this.items[i].item.removeData(this.widgetName + "-item");
13596
+ }
13597
+
13598
+ return this;
13599
+ },
13600
+
13601
+ _mouseCapture: function(event, overrideHandle) {
13602
+ var currentItem = null,
13603
+ validHandle = false,
13604
+ that = this;
13605
+
13606
+ if (this.reverting) {
13607
+ return false;
13608
+ }
13609
+
13610
+ if(this.options.disabled || this.options.type === "static") {
13611
+ return false;
13612
+ }
13613
+
13614
+ //We have to refresh the items data once first
13615
+ this._refreshItems(event);
13616
+
13617
+ //Find out if the clicked node (or one of its parents) is a actual item in this.items
13618
+ $(event.target).parents().each(function() {
13619
+ if($.data(this, that.widgetName + "-item") === that) {
13620
+ currentItem = $(this);
13621
+ return false;
13622
+ }
13623
+ });
13624
+ if($.data(event.target, that.widgetName + "-item") === that) {
13625
+ currentItem = $(event.target);
13626
+ }
13627
+
13628
+ if(!currentItem) {
13629
+ return false;
13630
+ }
13631
+ if(this.options.handle && !overrideHandle) {
13632
+ $(this.options.handle, currentItem).find("*").addBack().each(function() {
13633
+ if(this === event.target) {
13634
+ validHandle = true;
13635
+ }
13636
+ });
13637
+ if(!validHandle) {
13638
+ return false;
13639
+ }
13640
+ }
13641
+
13642
+ this.currentItem = currentItem;
13643
+ this._removeCurrentsFromItems();
13644
+ return true;
13645
+
13646
+ },
13647
+
13648
+ _mouseStart: function(event, overrideHandle, noActivation) {
13649
+
13650
+ var i, body,
13651
+ o = this.options;
13652
+
13653
+ this.currentContainer = this;
13654
+
13655
+ //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
13656
+ this.refreshPositions();
13657
+
13658
+ //Create and append the visible helper
13659
+ this.helper = this._createHelper(event);
13660
+
13661
+ //Cache the helper size
13662
+ this._cacheHelperProportions();
13663
+
13664
+ /*
13665
+ * - Position generation -
13666
+ * This block generates everything position related - it's the core of draggables.
13667
+ */
13668
+
13669
+ //Cache the margins of the original element
13670
+ this._cacheMargins();
13671
+
13672
+ //Get the next scrolling parent
13673
+ this.scrollParent = this.helper.scrollParent();
13674
+
13675
+ //The element's absolute position on the page minus margins
13676
+ this.offset = this.currentItem.offset();
13677
+ this.offset = {
13678
+ top: this.offset.top - this.margins.top,
13679
+ left: this.offset.left - this.margins.left
13680
+ };
13681
+
13682
+ $.extend(this.offset, {
13683
+ click: { //Where the click happened, relative to the element
13684
+ left: event.pageX - this.offset.left,
13685
+ top: event.pageY - this.offset.top
13686
+ },
13687
+ parent: this._getParentOffset(),
13688
+ relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
13689
+ });
13690
+
13691
+ // Only after we got the offset, we can change the helper's position to absolute
13692
+ // TODO: Still need to figure out a way to make relative sorting possible
13693
+ this.helper.css("position", "absolute");
13694
+ this.cssPosition = this.helper.css("position");
13695
+
13696
+ //Generate the original position
13697
+ this.originalPosition = this._generatePosition(event);
13698
+ this.originalPageX = event.pageX;
13699
+ this.originalPageY = event.pageY;
13700
+
13701
+ //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
13702
+ (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
13703
+
13704
+ //Cache the former DOM position
13705
+ this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
13706
+
13707
+ //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
13708
+ if(this.helper[0] !== this.currentItem[0]) {
13709
+ this.currentItem.hide();
13710
+ }
13711
+
13712
+ //Create the placeholder
13713
+ this._createPlaceholder();
13714
+
13715
+ //Set a containment if given in the options
13716
+ if(o.containment) {
13717
+ this._setContainment();
13718
+ }
13719
+
13720
+ if( o.cursor && o.cursor !== "auto" ) { // cursor option
13721
+ body = this.document.find( "body" );
13722
+
13723
+ // support: IE
13724
+ this.storedCursor = body.css( "cursor" );
13725
+ body.css( "cursor", o.cursor );
13726
+
13727
+ this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );
13728
+ }
13729
+
13730
+ if(o.opacity) { // opacity option
13731
+ if (this.helper.css("opacity")) {
13732
+ this._storedOpacity = this.helper.css("opacity");
13733
+ }
13734
+ this.helper.css("opacity", o.opacity);
13735
+ }
13736
+
13737
+ if(o.zIndex) { // zIndex option
13738
+ if (this.helper.css("zIndex")) {
13739
+ this._storedZIndex = this.helper.css("zIndex");
13740
+ }
13741
+ this.helper.css("zIndex", o.zIndex);
13742
+ }
13743
+
13744
+ //Prepare scrolling
13745
+ if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") {
13746
+ this.overflowOffset = this.scrollParent.offset();
13747
+ }
13748
+
13749
+ //Call callbacks
13750
+ this._trigger("start", event, this._uiHash());
13751
+
13752
+ //Recache the helper size
13753
+ if(!this._preserveHelperProportions) {
13754
+ this._cacheHelperProportions();
13755
+ }
13756
+
13757
+
13758
+ //Post "activate" events to possible containers
13759
+ if( !noActivation ) {
13760
+ for ( i = this.containers.length - 1; i >= 0; i-- ) {
13761
+ this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
13762
+ }
13763
+ }
13764
+
13765
+ //Prepare possible droppables
13766
+ if($.ui.ddmanager) {
13767
+ $.ui.ddmanager.current = this;
13768
+ }
13769
+
13770
+ if ($.ui.ddmanager && !o.dropBehaviour) {
13771
+ $.ui.ddmanager.prepareOffsets(this, event);
13772
+ }
13773
+
13774
+ this.dragging = true;
13775
+
13776
+ this.helper.addClass("ui-sortable-helper");
13777
+ this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
13778
+ return true;
13779
+
13780
+ },
13781
+
13782
+ _mouseDrag: function(event) {
13783
+ var i, item, itemElement, intersection,
13784
+ o = this.options,
13785
+ scrolled = false;
13786
+
13787
+ //Compute the helpers position
13788
+ this.position = this._generatePosition(event);
13789
+ this.positionAbs = this._convertPositionTo("absolute");
13790
+
13791
+ if (!this.lastPositionAbs) {
13792
+ this.lastPositionAbs = this.positionAbs;
13793
+ }
13794
+
13795
+ //Do scrolling
13796
+ if(this.options.scroll) {
13797
+ if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") {
13798
+
13799
+ if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
13800
+ this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
13801
+ } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
13802
+ this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
13803
+ }
13804
+
13805
+ if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
13806
+ this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
13807
+ } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
13808
+ this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
13809
+ }
13810
+
13811
+ } else {
13812
+
13813
+ if(event.pageY - this.document.scrollTop() < o.scrollSensitivity) {
13814
+ scrolled = this.document.scrollTop(this.document.scrollTop() - o.scrollSpeed);
13815
+ } else if(this.window.height() - (event.pageY - this.document.scrollTop()) < o.scrollSensitivity) {
13816
+ scrolled = this.document.scrollTop(this.document.scrollTop() + o.scrollSpeed);
13817
+ }
13818
+
13819
+ if(event.pageX - this.document.scrollLeft() < o.scrollSensitivity) {
13820
+ scrolled = this.document.scrollLeft(this.document.scrollLeft() - o.scrollSpeed);
13821
+ } else if(this.window.width() - (event.pageX - this.document.scrollLeft()) < o.scrollSensitivity) {
13822
+ scrolled = this.document.scrollLeft(this.document.scrollLeft() + o.scrollSpeed);
13823
+ }
13824
+
13825
+ }
13826
+
13827
+ if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
13828
+ $.ui.ddmanager.prepareOffsets(this, event);
13829
+ }
13830
+ }
13831
+
13832
+ //Regenerate the absolute position used for position checks
13833
+ this.positionAbs = this._convertPositionTo("absolute");
13834
+
13835
+ //Set the helper position
13836
+ if(!this.options.axis || this.options.axis !== "y") {
13837
+ this.helper[0].style.left = this.position.left+"px";
13838
+ }
13839
+ if(!this.options.axis || this.options.axis !== "x") {
13840
+ this.helper[0].style.top = this.position.top+"px";
13841
+ }
13842
+
13843
+ //Rearrange
13844
+ for (i = this.items.length - 1; i >= 0; i--) {
13845
+
13846
+ //Cache variables and intersection, continue if no intersection
13847
+ item = this.items[i];
13848
+ itemElement = item.item[0];
13849
+ intersection = this._intersectsWithPointer(item);
13850
+ if (!intersection) {
13851
+ continue;
13852
+ }
13853
+
13854
+ // Only put the placeholder inside the current Container, skip all
13855
+ // items from other containers. This works because when moving
13856
+ // an item from one container to another the
13857
+ // currentContainer is switched before the placeholder is moved.
13858
+ //
13859
+ // Without this, moving items in "sub-sortables" can cause
13860
+ // the placeholder to jitter between the outer and inner container.
13861
+ if (item.instance !== this.currentContainer) {
13862
+ continue;
13863
+ }
13864
+
13865
+ // cannot intersect with itself
13866
+ // no useless actions that have been done before
13867
+ // no action if the item moved is the parent of the item checked
13868
+ if (itemElement !== this.currentItem[0] &&
13869
+ this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
13870
+ !$.contains(this.placeholder[0], itemElement) &&
13871
+ (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
13872
+ ) {
13873
+
13874
+ this.direction = intersection === 1 ? "down" : "up";
13875
+
13876
+ if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
13877
+ this._rearrange(event, item);
13878
+ } else {
13879
+ break;
13880
+ }
13881
+
13882
+ this._trigger("change", event, this._uiHash());
13883
+ break;
13884
+ }
13885
+ }
13886
+
13887
+ //Post events to containers
13888
+ this._contactContainers(event);
13889
+
13890
+ //Interconnect with droppables
13891
+ if($.ui.ddmanager) {
13892
+ $.ui.ddmanager.drag(this, event);
13893
+ }
13894
+
13895
+ //Call callbacks
13896
+ this._trigger("sort", event, this._uiHash());
13897
+
13898
+ this.lastPositionAbs = this.positionAbs;
13899
+ return false;
13900
+
13901
+ },
13902
+
13903
+ _mouseStop: function(event, noPropagation) {
13904
+
13905
+ if(!event) {
13906
+ return;
13907
+ }
13908
+
13909
+ //If we are using droppables, inform the manager about the drop
13910
+ if ($.ui.ddmanager && !this.options.dropBehaviour) {
13911
+ $.ui.ddmanager.drop(this, event);
13912
+ }
13913
+
13914
+ if(this.options.revert) {
13915
+ var that = this,
13916
+ cur = this.placeholder.offset(),
13917
+ axis = this.options.axis,
13918
+ animation = {};
13919
+
13920
+ if ( !axis || axis === "x" ) {
13921
+ animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollLeft);
13922
+ }
13923
+ if ( !axis || axis === "y" ) {
13924
+ animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollTop);
13925
+ }
13926
+ this.reverting = true;
13927
+ $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {
13928
+ that._clear(event);
13929
+ });
13930
+ } else {
13931
+ this._clear(event, noPropagation);
13932
+ }
13933
+
13934
+ return false;
13935
+
13936
+ },
13937
+
13938
+ cancel: function() {
13939
+
13940
+ if(this.dragging) {
13941
+
13942
+ this._mouseUp({ target: null });
13943
+
13944
+ if(this.options.helper === "original") {
13945
+ this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
13946
+ } else {
13947
+ this.currentItem.show();
13948
+ }
13949
+
13950
+ //Post deactivating events to containers
13951
+ for (var i = this.containers.length - 1; i >= 0; i--){
13952
+ this.containers[i]._trigger("deactivate", null, this._uiHash(this));
13953
+ if(this.containers[i].containerCache.over) {
13954
+ this.containers[i]._trigger("out", null, this._uiHash(this));
13955
+ this.containers[i].containerCache.over = 0;
13956
+ }
13957
+ }
13958
+
13959
+ }
13960
+
13961
+ if (this.placeholder) {
13962
+ //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
13963
+ if(this.placeholder[0].parentNode) {
13964
+ this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
13965
+ }
13966
+ if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
13967
+ this.helper.remove();
13968
+ }
13969
+
13970
+ $.extend(this, {
13971
+ helper: null,
13972
+ dragging: false,
13973
+ reverting: false,
13974
+ _noFinalSort: null
13975
+ });
13976
+
13977
+ if(this.domPosition.prev) {
13978
+ $(this.domPosition.prev).after(this.currentItem);
13979
+ } else {
13980
+ $(this.domPosition.parent).prepend(this.currentItem);
13981
+ }
13982
+ }
13983
+
13984
+ return this;
13985
+
13986
+ },
13987
+
13988
+ serialize: function(o) {
13989
+
13990
+ var items = this._getItemsAsjQuery(o && o.connected),
13991
+ str = [];
13992
+ o = o || {};
13993
+
13994
+ $(items).each(function() {
13995
+ var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
13996
+ if (res) {
13997
+ str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
13998
+ }
13999
+ });
14000
+
14001
+ if(!str.length && o.key) {
14002
+ str.push(o.key + "=");
14003
+ }
14004
+
14005
+ return str.join("&");
14006
+
14007
+ },
14008
+
14009
+ toArray: function(o) {
14010
+
14011
+ var items = this._getItemsAsjQuery(o && o.connected),
14012
+ ret = [];
14013
+
14014
+ o = o || {};
14015
+
14016
+ items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
14017
+ return ret;
14018
+
14019
+ },
14020
+
14021
+ /* Be careful with the following core functions */
14022
+ _intersectsWith: function(item) {
14023
+
14024
+ var x1 = this.positionAbs.left,
14025
+ x2 = x1 + this.helperProportions.width,
14026
+ y1 = this.positionAbs.top,
14027
+ y2 = y1 + this.helperProportions.height,
14028
+ l = item.left,
14029
+ r = l + item.width,
14030
+ t = item.top,
14031
+ b = t + item.height,
14032
+ dyClick = this.offset.click.top,
14033
+ dxClick = this.offset.click.left,
14034
+ isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),
14035
+ isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),
14036
+ isOverElement = isOverElementHeight && isOverElementWidth;
14037
+
14038
+ if ( this.options.tolerance === "pointer" ||
14039
+ this.options.forcePointerForContainers ||
14040
+ (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
14041
+ ) {
14042
+ return isOverElement;
14043
+ } else {
14044
+
14045
+ return (l < x1 + (this.helperProportions.width / 2) && // Right Half
14046
+ x2 - (this.helperProportions.width / 2) < r && // Left Half
14047
+ t < y1 + (this.helperProportions.height / 2) && // Bottom Half
14048
+ y2 - (this.helperProportions.height / 2) < b ); // Top Half
14049
+
14050
+ }
14051
+ },
14052
+
14053
+ _intersectsWithPointer: function(item) {
14054
+
14055
+ var isOverElementHeight = (this.options.axis === "x") || this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
14056
+ isOverElementWidth = (this.options.axis === "y") || this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
14057
+ isOverElement = isOverElementHeight && isOverElementWidth,
14058
+ verticalDirection = this._getDragVerticalDirection(),
14059
+ horizontalDirection = this._getDragHorizontalDirection();
14060
+
14061
+ if (!isOverElement) {
14062
+ return false;
14063
+ }
14064
+
14065
+ return this.floating ?
14066
+ ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
14067
+ : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );
14068
+
14069
+ },
14070
+
14071
+ _intersectsWithSides: function(item) {
14072
+
14073
+ var isOverBottomHalf = this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
14074
+ isOverRightHalf = this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
14075
+ verticalDirection = this._getDragVerticalDirection(),
14076
+ horizontalDirection = this._getDragHorizontalDirection();
14077
+
14078
+ if (this.floating && horizontalDirection) {
14079
+ return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
14080
+ } else {
14081
+ return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
14082
+ }
14083
+
14084
+ },
14085
+
14086
+ _getDragVerticalDirection: function() {
14087
+ var delta = this.positionAbs.top - this.lastPositionAbs.top;
14088
+ return delta !== 0 && (delta > 0 ? "down" : "up");
14089
+ },
14090
+
14091
+ _getDragHorizontalDirection: function() {
14092
+ var delta = this.positionAbs.left - this.lastPositionAbs.left;
14093
+ return delta !== 0 && (delta > 0 ? "right" : "left");
14094
+ },
14095
+
14096
+ refresh: function(event) {
14097
+ this._refreshItems(event);
14098
+ this._setHandleClassName();
14099
+ this.refreshPositions();
14100
+ return this;
14101
+ },
14102
+
14103
+ _connectWith: function() {
14104
+ var options = this.options;
14105
+ return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
14106
+ },
14107
+
14108
+ _getItemsAsjQuery: function(connected) {
14109
+
14110
+ var i, j, cur, inst,
14111
+ items = [],
14112
+ queries = [],
14113
+ connectWith = this._connectWith();
14114
+
14115
+ if(connectWith && connected) {
14116
+ for (i = connectWith.length - 1; i >= 0; i--){
14117
+ cur = $(connectWith[i], this.document[0]);
14118
+ for ( j = cur.length - 1; j >= 0; j--){
14119
+ inst = $.data(cur[j], this.widgetFullName);
14120
+ if(inst && inst !== this && !inst.options.disabled) {
14121
+ queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]);
14122
+ }
14123
+ }
14124
+ }
14125
+ }
14126
+
14127
+ queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]);
14128
+
14129
+ function addItems() {
14130
+ items.push( this );
14131
+ }
14132
+ for (i = queries.length - 1; i >= 0; i--){
14133
+ queries[i][0].each( addItems );
14134
+ }
14135
+
14136
+ return $(items);
14137
+
14138
+ },
14139
+
14140
+ _removeCurrentsFromItems: function() {
14141
+
14142
+ var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
14143
+
14144
+ this.items = $.grep(this.items, function (item) {
14145
+ for (var j=0; j < list.length; j++) {
14146
+ if(list[j] === item.item[0]) {
14147
+ return false;
14148
+ }
14149
+ }
14150
+ return true;
14151
+ });
14152
+
14153
+ },
14154
+
14155
+ _refreshItems: function(event) {
14156
+
14157
+ this.items = [];
14158
+ this.containers = [this];
14159
+
14160
+ var i, j, cur, inst, targetData, _queries, item, queriesLength,
14161
+ items = this.items,
14162
+ queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
14163
+ connectWith = this._connectWith();
14164
+
14165
+ if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
14166
+ for (i = connectWith.length - 1; i >= 0; i--){
14167
+ cur = $(connectWith[i], this.document[0]);
14168
+ for (j = cur.length - 1; j >= 0; j--){
14169
+ inst = $.data(cur[j], this.widgetFullName);
14170
+ if(inst && inst !== this && !inst.options.disabled) {
14171
+ queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
14172
+ this.containers.push(inst);
14173
+ }
14174
+ }
14175
+ }
14176
+ }
14177
+
14178
+ for (i = queries.length - 1; i >= 0; i--) {
14179
+ targetData = queries[i][1];
14180
+ _queries = queries[i][0];
14181
+
14182
+ for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
14183
+ item = $(_queries[j]);
14184
+
14185
+ item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)
14186
+
14187
+ items.push({
14188
+ item: item,
14189
+ instance: targetData,
14190
+ width: 0, height: 0,
14191
+ left: 0, top: 0
14192
+ });
14193
+ }
14194
+ }
14195
+
14196
+ },
14197
+
14198
+ refreshPositions: function(fast) {
14199
+
14200
+ // Determine whether items are being displayed horizontally
14201
+ this.floating = this.items.length ?
14202
+ this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
14203
+ false;
14204
+
14205
+ //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
14206
+ if(this.offsetParent && this.helper) {
14207
+ this.offset.parent = this._getParentOffset();
14208
+ }
14209
+
14210
+ var i, item, t, p;
14211
+
14212
+ for (i = this.items.length - 1; i >= 0; i--){
14213
+ item = this.items[i];
14214
+
14215
+ //We ignore calculating positions of all connected containers when we're not over them
14216
+ if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
14217
+ continue;
14218
+ }
14219
+
14220
+ t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
14221
+
14222
+ if (!fast) {
14223
+ item.width = t.outerWidth();
14224
+ item.height = t.outerHeight();
14225
+ }
14226
+
14227
+ p = t.offset();
14228
+ item.left = p.left;
14229
+ item.top = p.top;
14230
+ }
14231
+
14232
+ if(this.options.custom && this.options.custom.refreshContainers) {
14233
+ this.options.custom.refreshContainers.call(this);
14234
+ } else {
14235
+ for (i = this.containers.length - 1; i >= 0; i--){
14236
+ p = this.containers[i].element.offset();
14237
+ this.containers[i].containerCache.left = p.left;
14238
+ this.containers[i].containerCache.top = p.top;
14239
+ this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
14240
+ this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
14241
+ }
14242
+ }
14243
+
14244
+ return this;
14245
+ },
14246
+
14247
+ _createPlaceholder: function(that) {
14248
+ that = that || this;
14249
+ var className,
14250
+ o = that.options;
14251
+
14252
+ if(!o.placeholder || o.placeholder.constructor === String) {
14253
+ className = o.placeholder;
14254
+ o.placeholder = {
14255
+ element: function() {
14256
+
14257
+ var nodeName = that.currentItem[0].nodeName.toLowerCase(),
14258
+ element = $( "<" + nodeName + ">", that.document[0] )
14259
+ .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
14260
+ .removeClass("ui-sortable-helper");
14261
+
14262
+ if ( nodeName === "tbody" ) {
14263
+ that._createTrPlaceholder(
14264
+ that.currentItem.find( "tr" ).eq( 0 ),
14265
+ $( "<tr>", that.document[ 0 ] ).appendTo( element )
14266
+ );
14267
+ } else if ( nodeName === "tr" ) {
14268
+ that._createTrPlaceholder( that.currentItem, element );
14269
+ } else if ( nodeName === "img" ) {
14270
+ element.attr( "src", that.currentItem.attr( "src" ) );
14271
+ }
14272
+
14273
+ if ( !className ) {
14274
+ element.css( "visibility", "hidden" );
14275
+ }
14276
+
14277
+ return element;
14278
+ },
14279
+ update: function(container, p) {
14280
+
14281
+ // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
14282
+ // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
14283
+ if(className && !o.forcePlaceholderSize) {
14284
+ return;
14285
+ }
14286
+
14287
+ //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
14288
+ if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
14289
+ if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
14290
+ }
14291
+ };
14292
+ }
14293
+
14294
+ //Create the placeholder
14295
+ that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
14296
+
14297
+ //Append it after the actual current item
14298
+ that.currentItem.after(that.placeholder);
14299
+
14300
+ //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
14301
+ o.placeholder.update(that, that.placeholder);
14302
+
14303
+ },
14304
+
14305
+ _createTrPlaceholder: function( sourceTr, targetTr ) {
14306
+ var that = this;
14307
+
14308
+ sourceTr.children().each(function() {
14309
+ $( "<td>&#160;</td>", that.document[ 0 ] )
14310
+ .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
14311
+ .appendTo( targetTr );
14312
+ });
14313
+ },
14314
+
14315
+ _contactContainers: function(event) {
14316
+ var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, floating, axis,
14317
+ innermostContainer = null,
14318
+ innermostIndex = null;
14319
+
14320
+ // get innermost container that intersects with item
14321
+ for (i = this.containers.length - 1; i >= 0; i--) {
14322
+
14323
+ // never consider a container that's located within the item itself
14324
+ if($.contains(this.currentItem[0], this.containers[i].element[0])) {
14325
+ continue;
14326
+ }
14327
+
14328
+ if(this._intersectsWith(this.containers[i].containerCache)) {
14329
+
14330
+ // if we've already found a container and it's more "inner" than this, then continue
14331
+ if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
14332
+ continue;
14333
+ }
14334
+
14335
+ innermostContainer = this.containers[i];
14336
+ innermostIndex = i;
14337
+
14338
+ } else {
14339
+ // container doesn't intersect. trigger "out" event if necessary
14340
+ if(this.containers[i].containerCache.over) {
14341
+ this.containers[i]._trigger("out", event, this._uiHash(this));
14342
+ this.containers[i].containerCache.over = 0;
14343
+ }
14344
+ }
14345
+
14346
+ }
14347
+
14348
+ // if no intersecting containers found, return
14349
+ if(!innermostContainer) {
14350
+ return;
14351
+ }
14352
+
14353
+ // move the item into the container if it's not there already
14354
+ if(this.containers.length === 1) {
14355
+ if (!this.containers[innermostIndex].containerCache.over) {
14356
+ this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
14357
+ this.containers[innermostIndex].containerCache.over = 1;
14358
+ }
14359
+ } else {
14360
+
14361
+ //When entering a new container, we will find the item with the least distance and append our item near it
14362
+ dist = 10000;
14363
+ itemWithLeastDistance = null;
14364
+ floating = innermostContainer.floating || this._isFloating(this.currentItem);
14365
+ posProperty = floating ? "left" : "top";
14366
+ sizeProperty = floating ? "width" : "height";
14367
+ axis = floating ? "clientX" : "clientY";
14368
+
14369
+ for (j = this.items.length - 1; j >= 0; j--) {
14370
+ if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
14371
+ continue;
14372
+ }
14373
+ if(this.items[j].item[0] === this.currentItem[0]) {
14374
+ continue;
14375
+ }
14376
+
14377
+ cur = this.items[j].item.offset()[posProperty];
14378
+ nearBottom = false;
14379
+ if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
14380
+ nearBottom = true;
14381
+ }
14382
+
14383
+ if ( Math.abs( event[ axis ] - cur ) < dist ) {
14384
+ dist = Math.abs( event[ axis ] - cur );
14385
+ itemWithLeastDistance = this.items[ j ];
14386
+ this.direction = nearBottom ? "up": "down";
14387
+ }
14388
+ }
14389
+
14390
+ //Check if dropOnEmpty is enabled
14391
+ if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
14392
+ return;
14393
+ }
14394
+
14395
+ if(this.currentContainer === this.containers[innermostIndex]) {
14396
+ if ( !this.currentContainer.containerCache.over ) {
14397
+ this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
14398
+ this.currentContainer.containerCache.over = 1;
14399
+ }
14400
+ return;
14401
+ }
14402
+
14403
+ itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
14404
+ this._trigger("change", event, this._uiHash());
14405
+ this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
14406
+ this.currentContainer = this.containers[innermostIndex];
14407
+
14408
+ //Update the placeholder
14409
+ this.options.placeholder.update(this.currentContainer, this.placeholder);
14410
+
14411
+ this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
14412
+ this.containers[innermostIndex].containerCache.over = 1;
14413
+ }
14414
+
14415
+
14416
+ },
14417
+
14418
+ _createHelper: function(event) {
14419
+
14420
+ var o = this.options,
14421
+ helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);
14422
+
14423
+ //Add the helper to the DOM if that didn't happen already
14424
+ if(!helper.parents("body").length) {
14425
+ $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
14426
+ }
14427
+
14428
+ if(helper[0] === this.currentItem[0]) {
14429
+ this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
14430
+ }
14431
+
14432
+ if(!helper[0].style.width || o.forceHelperSize) {
14433
+ helper.width(this.currentItem.width());
14434
+ }
14435
+ if(!helper[0].style.height || o.forceHelperSize) {
14436
+ helper.height(this.currentItem.height());
14437
+ }
14438
+
14439
+ return helper;
14440
+
14441
+ },
14442
+
14443
+ _adjustOffsetFromHelper: function(obj) {
14444
+ if (typeof obj === "string") {
14445
+ obj = obj.split(" ");
14446
+ }
14447
+ if ($.isArray(obj)) {
14448
+ obj = {left: +obj[0], top: +obj[1] || 0};
14449
+ }
14450
+ if ("left" in obj) {
14451
+ this.offset.click.left = obj.left + this.margins.left;
14452
+ }
14453
+ if ("right" in obj) {
14454
+ this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
14455
+ }
14456
+ if ("top" in obj) {
14457
+ this.offset.click.top = obj.top + this.margins.top;
14458
+ }
14459
+ if ("bottom" in obj) {
14460
+ this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
14461
+ }
14462
+ },
14463
+
14464
+ _getParentOffset: function() {
14465
+
14466
+
14467
+ //Get the offsetParent and cache its position
14468
+ this.offsetParent = this.helper.offsetParent();
14469
+ var po = this.offsetParent.offset();
14470
+
14471
+ // This is a special case where we need to modify a offset calculated on start, since the following happened:
14472
+ // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
14473
+ // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
14474
+ // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
14475
+ if(this.cssPosition === "absolute" && this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) {
14476
+ po.left += this.scrollParent.scrollLeft();
14477
+ po.top += this.scrollParent.scrollTop();
14478
+ }
14479
+
14480
+ // This needs to be actually done for all browsers, since pageX/pageY includes this information
14481
+ // with an ugly IE fix
14482
+ if( this.offsetParent[0] === this.document[0].body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
14483
+ po = { top: 0, left: 0 };
14484
+ }
14485
+
14486
+ return {
14487
+ top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
14488
+ left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
14489
+ };
14490
+
14491
+ },
14492
+
14493
+ _getRelativeOffset: function() {
14494
+
14495
+ if(this.cssPosition === "relative") {
14496
+ var p = this.currentItem.position();
14497
+ return {
14498
+ top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
14499
+ left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
14500
+ };
14501
+ } else {
14502
+ return { top: 0, left: 0 };
14503
+ }
14504
+
14505
+ },
14506
+
14507
+ _cacheMargins: function() {
14508
+ this.margins = {
14509
+ left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
14510
+ top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
14511
+ };
14512
+ },
14513
+
14514
+ _cacheHelperProportions: function() {
14515
+ this.helperProportions = {
14516
+ width: this.helper.outerWidth(),
14517
+ height: this.helper.outerHeight()
14518
+ };
14519
+ },
14520
+
14521
+ _setContainment: function() {
14522
+
14523
+ var ce, co, over,
14524
+ o = this.options;
14525
+ if(o.containment === "parent") {
14526
+ o.containment = this.helper[0].parentNode;
14527
+ }
14528
+ if(o.containment === "document" || o.containment === "window") {
14529
+ this.containment = [
14530
+ 0 - this.offset.relative.left - this.offset.parent.left,
14531
+ 0 - this.offset.relative.top - this.offset.parent.top,
14532
+ o.containment === "document" ? this.document.width() : this.window.width() - this.helperProportions.width - this.margins.left,
14533
+ (o.containment === "document" ? this.document.width() : this.window.height() || this.document[0].body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
14534
+ ];
14535
+ }
14536
+
14537
+ if(!(/^(document|window|parent)$/).test(o.containment)) {
14538
+ ce = $(o.containment)[0];
14539
+ co = $(o.containment).offset();
14540
+ over = ($(ce).css("overflow") !== "hidden");
14541
+
14542
+ this.containment = [
14543
+ co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
14544
+ co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
14545
+ co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
14546
+ co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
14547
+ ];
14548
+ }
14549
+
14550
+ },
14551
+
14552
+ _convertPositionTo: function(d, pos) {
14553
+
14554
+ if(!pos) {
14555
+ pos = this.position;
14556
+ }
14557
+ var mod = d === "absolute" ? 1 : -1,
14558
+ scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
14559
+ scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
14560
+
14561
+ return {
14562
+ top: (
14563
+ pos.top + // The absolute mouse position
14564
+ this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
14565
+ this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border)
14566
+ ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
14567
+ ),
14568
+ left: (
14569
+ pos.left + // The absolute mouse position
14570
+ this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent
14571
+ this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border)
14572
+ ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
14573
+ )
14574
+ };
14575
+
14576
+ },
14577
+
14578
+ _generatePosition: function(event) {
14579
+
14580
+ var top, left,
14581
+ o = this.options,
14582
+ pageX = event.pageX,
14583
+ pageY = event.pageY,
14584
+ scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
14585
+
14586
+ // This is another very weird special case that only happens for relative elements:
14587
+ // 1. If the css position is relative
14588
+ // 2. and the scroll parent is the document or similar to the offset parent
14589
+ // we have to refresh the relative offset during the scroll so there are no jumps
14590
+ if(this.cssPosition === "relative" && !(this.scrollParent[0] !== this.document[0] && this.scrollParent[0] !== this.offsetParent[0])) {
14591
+ this.offset.relative = this._getRelativeOffset();
14592
+ }
14593
+
14594
+ /*
14595
+ * - Position constraining -
14596
+ * Constrain the position to a mix of grid, containment.
14597
+ */
14598
+
14599
+ if(this.originalPosition) { //If we are not dragging yet, we won't check for options
14600
+
14601
+ if(this.containment) {
14602
+ if(event.pageX - this.offset.click.left < this.containment[0]) {
14603
+ pageX = this.containment[0] + this.offset.click.left;
14604
+ }
14605
+ if(event.pageY - this.offset.click.top < this.containment[1]) {
14606
+ pageY = this.containment[1] + this.offset.click.top;
14607
+ }
14608
+ if(event.pageX - this.offset.click.left > this.containment[2]) {
14609
+ pageX = this.containment[2] + this.offset.click.left;
14610
+ }
14611
+ if(event.pageY - this.offset.click.top > this.containment[3]) {
14612
+ pageY = this.containment[3] + this.offset.click.top;
14613
+ }
14614
+ }
14615
+
14616
+ if(o.grid) {
14617
+ top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
14618
+ pageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
14619
+
14620
+ left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
14621
+ pageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
14622
+ }
14623
+
14624
+ }
14625
+
14626
+ return {
14627
+ top: (
14628
+ pageY - // The absolute mouse position
14629
+ this.offset.click.top - // Click offset (relative to the element)
14630
+ this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent
14631
+ this.offset.parent.top + // The offsetParent's offset without borders (offset + border)
14632
+ ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
14633
+ ),
14634
+ left: (
14635
+ pageX - // The absolute mouse position
14636
+ this.offset.click.left - // Click offset (relative to the element)
14637
+ this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent
14638
+ this.offset.parent.left + // The offsetParent's offset without borders (offset + border)
14639
+ ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
14640
+ )
14641
+ };
14642
+
14643
+ },
14644
+
14645
+ _rearrange: function(event, i, a, hardRefresh) {
14646
+
14647
+ a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling));
14648
+
14649
+ //Various things done here to improve the performance:
14650
+ // 1. we create a setTimeout, that calls refreshPositions
14651
+ // 2. on the instance, we have a counter variable, that get's higher after every append
14652
+ // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
14653
+ // 4. this lets only the last addition to the timeout stack through
14654
+ this.counter = this.counter ? ++this.counter : 1;
14655
+ var counter = this.counter;
14656
+
14657
+ this._delay(function() {
14658
+ if(counter === this.counter) {
14659
+ this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
14660
+ }
14661
+ });
14662
+
14663
+ },
14664
+
14665
+ _clear: function(event, noPropagation) {
14666
+
14667
+ this.reverting = false;
14668
+ // We delay all events that have to be triggered to after the point where the placeholder has been removed and
14669
+ // everything else normalized again
14670
+ var i,
14671
+ delayedTriggers = [];
14672
+
14673
+ // We first have to update the dom position of the actual currentItem
14674
+ // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
14675
+ if(!this._noFinalSort && this.currentItem.parent().length) {
14676
+ this.placeholder.before(this.currentItem);
14677
+ }
14678
+ this._noFinalSort = null;
14679
+
14680
+ if(this.helper[0] === this.currentItem[0]) {
14681
+ for(i in this._storedCSS) {
14682
+ if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
14683
+ this._storedCSS[i] = "";
14684
+ }
14685
+ }
14686
+ this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
14687
+ } else {
14688
+ this.currentItem.show();
14689
+ }
14690
+
14691
+ if(this.fromOutside && !noPropagation) {
14692
+ delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
14693
+ }
14694
+ if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
14695
+ delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
14696
+ }
14697
+
14698
+ // Check if the items Container has Changed and trigger appropriate
14699
+ // events.
14700
+ if (this !== this.currentContainer) {
14701
+ if(!noPropagation) {
14702
+ delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
14703
+ delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
14704
+ delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
14705
+ }
14706
+ }
14707
+
14708
+
14709
+ //Post events to containers
14710
+ function delayEvent( type, instance, container ) {
14711
+ return function( event ) {
14712
+ container._trigger( type, event, instance._uiHash( instance ) );
14713
+ };
14714
+ }
14715
+ for (i = this.containers.length - 1; i >= 0; i--){
14716
+ if (!noPropagation) {
14717
+ delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
14718
+ }
14719
+ if(this.containers[i].containerCache.over) {
14720
+ delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
14721
+ this.containers[i].containerCache.over = 0;
14722
+ }
14723
+ }
14724
+
14725
+ //Do what was originally in plugins
14726
+ if ( this.storedCursor ) {
14727
+ this.document.find( "body" ).css( "cursor", this.storedCursor );
14728
+ this.storedStylesheet.remove();
14729
+ }
14730
+ if(this._storedOpacity) {
14731
+ this.helper.css("opacity", this._storedOpacity);
14732
+ }
14733
+ if(this._storedZIndex) {
14734
+ this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
14735
+ }
14736
+
14737
+ this.dragging = false;
14738
+
14739
+ if(!noPropagation) {
14740
+ this._trigger("beforeStop", event, this._uiHash());
14741
+ }
14742
+
14743
+ //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
14744
+ this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
14745
+
14746
+ if ( !this.cancelHelperRemoval ) {
14747
+ if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
14748
+ this.helper.remove();
14749
+ }
14750
+ this.helper = null;
14751
+ }
14752
+
14753
+ if(!noPropagation) {
14754
+ for (i=0; i < delayedTriggers.length; i++) {
14755
+ delayedTriggers[i].call(this, event);
14756
+ } //Trigger all delayed events
14757
+ this._trigger("stop", event, this._uiHash());
14758
+ }
14759
+
14760
+ this.fromOutside = false;
14761
+ return !this.cancelHelperRemoval;
14762
+
14763
+ },
14764
+
14765
+ _trigger: function() {
14766
+ if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
14767
+ this.cancel();
14768
+ }
14769
+ },
14770
+
14771
+ _uiHash: function(_inst) {
14772
+ var inst = _inst || this;
14773
+ return {
14774
+ helper: inst.helper,
14775
+ placeholder: inst.placeholder || $([]),
14776
+ position: inst.position,
14777
+ originalPosition: inst.originalPosition,
14778
+ offset: inst.positionAbs,
14779
+ item: inst.currentItem,
14780
+ sender: _inst ? _inst.element : null
14781
+ };
14782
+ }
14783
+
14784
+ });
14785
+
14786
+
14787
+ /*!
14788
+ * jQuery UI Spinner 1.11.4
14789
+ * http://jqueryui.com
14790
+ *
14791
+ * Copyright jQuery Foundation and other contributors
14792
+ * Released under the MIT license.
14793
+ * http://jquery.org/license
14794
+ *
14795
+ * http://api.jqueryui.com/spinner/
14796
+ */
14797
+
14798
+
14799
+ function spinner_modifier( fn ) {
14800
+ return function() {
14801
+ var previous = this.element.val();
14802
+ fn.apply( this, arguments );
14803
+ this._refresh();
14804
+ if ( previous !== this.element.val() ) {
14805
+ this._trigger( "change" );
14806
+ }
14807
+ };
14808
+ }
14809
+
14810
+ var spinner = $.widget( "ui.spinner", {
14811
+ version: "1.11.4",
14812
+ defaultElement: "<input>",
14813
+ widgetEventPrefix: "spin",
14814
+ options: {
14815
+ culture: null,
14816
+ icons: {
14817
+ down: "ui-icon-triangle-1-s",
14818
+ up: "ui-icon-triangle-1-n"
14819
+ },
14820
+ incremental: true,
14821
+ max: null,
14822
+ min: null,
14823
+ numberFormat: null,
14824
+ page: 10,
14825
+ step: 1,
14826
+
14827
+ change: null,
14828
+ spin: null,
14829
+ start: null,
14830
+ stop: null
14831
+ },
14832
+
14833
+ _create: function() {
14834
+ // handle string values that need to be parsed
14835
+ this._setOption( "max", this.options.max );
14836
+ this._setOption( "min", this.options.min );
14837
+ this._setOption( "step", this.options.step );
14838
+
14839
+ // Only format if there is a value, prevents the field from being marked
14840
+ // as invalid in Firefox, see #9573.
14841
+ if ( this.value() !== "" ) {
14842
+ // Format the value, but don't constrain.
14843
+ this._value( this.element.val(), true );
14844
+ }
14845
+
14846
+ this._draw();
14847
+ this._on( this._events );
14848
+ this._refresh();
14849
+
14850
+ // turning off autocomplete prevents the browser from remembering the
14851
+ // value when navigating through history, so we re-enable autocomplete
14852
+ // if the page is unloaded before the widget is destroyed. #7790
14853
+ this._on( this.window, {
14854
+ beforeunload: function() {
14855
+ this.element.removeAttr( "autocomplete" );
14856
+ }
14857
+ });
14858
+ },
14859
+
14860
+ _getCreateOptions: function() {
14861
+ var options = {},
14862
+ element = this.element;
14863
+
14864
+ $.each( [ "min", "max", "step" ], function( i, option ) {
14865
+ var value = element.attr( option );
14866
+ if ( value !== undefined && value.length ) {
14867
+ options[ option ] = value;
14868
+ }
14869
+ });
14870
+
14871
+ return options;
14872
+ },
14873
+
14874
+ _events: {
14875
+ keydown: function( event ) {
14876
+ if ( this._start( event ) && this._keydown( event ) ) {
14877
+ event.preventDefault();
14878
+ }
14879
+ },
14880
+ keyup: "_stop",
14881
+ focus: function() {
14882
+ this.previous = this.element.val();
14883
+ },
14884
+ blur: function( event ) {
14885
+ if ( this.cancelBlur ) {
14886
+ delete this.cancelBlur;
14887
+ return;
14888
+ }
14889
+
14890
+ this._stop();
14891
+ this._refresh();
14892
+ if ( this.previous !== this.element.val() ) {
14893
+ this._trigger( "change", event );
14894
+ }
14895
+ },
14896
+ mousewheel: function( event, delta ) {
14897
+ if ( !delta ) {
14898
+ return;
14899
+ }
14900
+ if ( !this.spinning && !this._start( event ) ) {
14901
+ return false;
14902
+ }
14903
+
14904
+ this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
14905
+ clearTimeout( this.mousewheelTimer );
14906
+ this.mousewheelTimer = this._delay(function() {
14907
+ if ( this.spinning ) {
14908
+ this._stop( event );
14909
+ }
14910
+ }, 100 );
14911
+ event.preventDefault();
14912
+ },
14913
+ "mousedown .ui-spinner-button": function( event ) {
14914
+ var previous;
14915
+
14916
+ // We never want the buttons to have focus; whenever the user is
14917
+ // interacting with the spinner, the focus should be on the input.
14918
+ // If the input is focused then this.previous is properly set from
14919
+ // when the input first received focus. If the input is not focused
14920
+ // then we need to set this.previous based on the value before spinning.
14921
+ previous = this.element[0] === this.document[0].activeElement ?
14922
+ this.previous : this.element.val();
14923
+ function checkFocus() {
14924
+ var isActive = this.element[0] === this.document[0].activeElement;
14925
+ if ( !isActive ) {
14926
+ this.element.focus();
14927
+ this.previous = previous;
14928
+ // support: IE
14929
+ // IE sets focus asynchronously, so we need to check if focus
14930
+ // moved off of the input because the user clicked on the button.
14931
+ this._delay(function() {
14932
+ this.previous = previous;
14933
+ });
14934
+ }
14935
+ }
14936
+
14937
+ // ensure focus is on (or stays on) the text field
14938
+ event.preventDefault();
14939
+ checkFocus.call( this );
14940
+
14941
+ // support: IE
14942
+ // IE doesn't prevent moving focus even with event.preventDefault()
14943
+ // so we set a flag to know when we should ignore the blur event
14944
+ // and check (again) if focus moved off of the input.
14945
+ this.cancelBlur = true;
14946
+ this._delay(function() {
14947
+ delete this.cancelBlur;
14948
+ checkFocus.call( this );
14949
+ });
14950
+
14951
+ if ( this._start( event ) === false ) {
14952
+ return;
14953
+ }
14954
+
14955
+ this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
14956
+ },
14957
+ "mouseup .ui-spinner-button": "_stop",
14958
+ "mouseenter .ui-spinner-button": function( event ) {
14959
+ // button will add ui-state-active if mouse was down while mouseleave and kept down
14960
+ if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
14961
+ return;
14962
+ }
14963
+
14964
+ if ( this._start( event ) === false ) {
14965
+ return false;
14966
+ }
14967
+ this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
14968
+ },
14969
+ // TODO: do we really want to consider this a stop?
14970
+ // shouldn't we just stop the repeater and wait until mouseup before
14971
+ // we trigger the stop event?
14972
+ "mouseleave .ui-spinner-button": "_stop"
14973
+ },
14974
+
14975
+ _draw: function() {
14976
+ var uiSpinner = this.uiSpinner = this.element
14977
+ .addClass( "ui-spinner-input" )
14978
+ .attr( "autocomplete", "off" )
14979
+ .wrap( this._uiSpinnerHtml() )
14980
+ .parent()
14981
+ // add buttons
14982
+ .append( this._buttonHtml() );
14983
+
14984
+ this.element.attr( "role", "spinbutton" );
14985
+
14986
+ // button bindings
14987
+ this.buttons = uiSpinner.find( ".ui-spinner-button" )
14988
+ .attr( "tabIndex", -1 )
14989
+ .button()
14990
+ .removeClass( "ui-corner-all" );
14991
+
14992
+ // IE 6 doesn't understand height: 50% for the buttons
14993
+ // unless the wrapper has an explicit height
14994
+ if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
14995
+ uiSpinner.height() > 0 ) {
14996
+ uiSpinner.height( uiSpinner.height() );
14997
+ }
14998
+
14999
+ // disable spinner if element was already disabled
15000
+ if ( this.options.disabled ) {
15001
+ this.disable();
15002
+ }
15003
+ },
15004
+
15005
+ _keydown: function( event ) {
15006
+ var options = this.options,
15007
+ keyCode = $.ui.keyCode;
15008
+
15009
+ switch ( event.keyCode ) {
15010
+ case keyCode.UP:
15011
+ this._repeat( null, 1, event );
15012
+ return true;
15013
+ case keyCode.DOWN:
15014
+ this._repeat( null, -1, event );
15015
+ return true;
15016
+ case keyCode.PAGE_UP:
15017
+ this._repeat( null, options.page, event );
15018
+ return true;
15019
+ case keyCode.PAGE_DOWN:
15020
+ this._repeat( null, -options.page, event );
15021
+ return true;
15022
+ }
15023
+
15024
+ return false;
15025
+ },
15026
+
15027
+ _uiSpinnerHtml: function() {
15028
+ return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
15029
+ },
15030
+
15031
+ _buttonHtml: function() {
15032
+ return "" +
15033
+ "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
15034
+ "<span class='ui-icon " + this.options.icons.up + "'>&#9650;</span>" +
15035
+ "</a>" +
15036
+ "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
15037
+ "<span class='ui-icon " + this.options.icons.down + "'>&#9660;</span>" +
15038
+ "</a>";
15039
+ },
15040
+
15041
+ _start: function( event ) {
15042
+ if ( !this.spinning && this._trigger( "start", event ) === false ) {
15043
+ return false;
15044
+ }
15045
+
15046
+ if ( !this.counter ) {
15047
+ this.counter = 1;
15048
+ }
15049
+ this.spinning = true;
15050
+ return true;
15051
+ },
15052
+
15053
+ _repeat: function( i, steps, event ) {
15054
+ i = i || 500;
15055
+
15056
+ clearTimeout( this.timer );
15057
+ this.timer = this._delay(function() {
15058
+ this._repeat( 40, steps, event );
15059
+ }, i );
15060
+
15061
+ this._spin( steps * this.options.step, event );
15062
+ },
15063
+
15064
+ _spin: function( step, event ) {
15065
+ var value = this.value() || 0;
15066
+
15067
+ if ( !this.counter ) {
15068
+ this.counter = 1;
15069
+ }
15070
+
15071
+ value = this._adjustValue( value + step * this._increment( this.counter ) );
15072
+
15073
+ if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
15074
+ this._value( value );
15075
+ this.counter++;
15076
+ }
15077
+ },
15078
+
15079
+ _increment: function( i ) {
15080
+ var incremental = this.options.incremental;
15081
+
15082
+ if ( incremental ) {
15083
+ return $.isFunction( incremental ) ?
15084
+ incremental( i ) :
15085
+ Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
15086
+ }
15087
+
15088
+ return 1;
15089
+ },
15090
+
15091
+ _precision: function() {
15092
+ var precision = this._precisionOf( this.options.step );
15093
+ if ( this.options.min !== null ) {
15094
+ precision = Math.max( precision, this._precisionOf( this.options.min ) );
15095
+ }
15096
+ return precision;
15097
+ },
15098
+
15099
+ _precisionOf: function( num ) {
15100
+ var str = num.toString(),
15101
+ decimal = str.indexOf( "." );
15102
+ return decimal === -1 ? 0 : str.length - decimal - 1;
15103
+ },
15104
+
15105
+ _adjustValue: function( value ) {
15106
+ var base, aboveMin,
15107
+ options = this.options;
15108
+
15109
+ // make sure we're at a valid step
15110
+ // - find out where we are relative to the base (min or 0)
15111
+ base = options.min !== null ? options.min : 0;
15112
+ aboveMin = value - base;
15113
+ // - round to the nearest step
15114
+ aboveMin = Math.round(aboveMin / options.step) * options.step;
15115
+ // - rounding is based on 0, so adjust back to our base
15116
+ value = base + aboveMin;
15117
+
15118
+ // fix precision from bad JS floating point math
15119
+ value = parseFloat( value.toFixed( this._precision() ) );
15120
+
15121
+ // clamp the value
15122
+ if ( options.max !== null && value > options.max) {
15123
+ return options.max;
15124
+ }
15125
+ if ( options.min !== null && value < options.min ) {
15126
+ return options.min;
15127
+ }
15128
+
15129
+ return value;
15130
+ },
15131
+
15132
+ _stop: function( event ) {
15133
+ if ( !this.spinning ) {
15134
+ return;
15135
+ }
15136
+
15137
+ clearTimeout( this.timer );
15138
+ clearTimeout( this.mousewheelTimer );
15139
+ this.counter = 0;
15140
+ this.spinning = false;
15141
+ this._trigger( "stop", event );
15142
+ },
15143
+
15144
+ _setOption: function( key, value ) {
15145
+ if ( key === "culture" || key === "numberFormat" ) {
15146
+ var prevValue = this._parse( this.element.val() );
15147
+ this.options[ key ] = value;
15148
+ this.element.val( this._format( prevValue ) );
15149
+ return;
15150
+ }
15151
+
15152
+ if ( key === "max" || key === "min" || key === "step" ) {
15153
+ if ( typeof value === "string" ) {
15154
+ value = this._parse( value );
15155
+ }
15156
+ }
15157
+ if ( key === "icons" ) {
15158
+ this.buttons.first().find( ".ui-icon" )
15159
+ .removeClass( this.options.icons.up )
15160
+ .addClass( value.up );
15161
+ this.buttons.last().find( ".ui-icon" )
15162
+ .removeClass( this.options.icons.down )
15163
+ .addClass( value.down );
15164
+ }
15165
+
15166
+ this._super( key, value );
15167
+
15168
+ if ( key === "disabled" ) {
15169
+ this.widget().toggleClass( "ui-state-disabled", !!value );
15170
+ this.element.prop( "disabled", !!value );
15171
+ this.buttons.button( value ? "disable" : "enable" );
15172
+ }
15173
+ },
15174
+
15175
+ _setOptions: spinner_modifier(function( options ) {
15176
+ this._super( options );
15177
+ }),
15178
+
15179
+ _parse: function( val ) {
15180
+ if ( typeof val === "string" && val !== "" ) {
15181
+ val = window.Globalize && this.options.numberFormat ?
15182
+ Globalize.parseFloat( val, 10, this.options.culture ) : +val;
15183
+ }
15184
+ return val === "" || isNaN( val ) ? null : val;
15185
+ },
15186
+
15187
+ _format: function( value ) {
15188
+ if ( value === "" ) {
15189
+ return "";
15190
+ }
15191
+ return window.Globalize && this.options.numberFormat ?
15192
+ Globalize.format( value, this.options.numberFormat, this.options.culture ) :
15193
+ value;
15194
+ },
15195
+
15196
+ _refresh: function() {
15197
+ this.element.attr({
15198
+ "aria-valuemin": this.options.min,
15199
+ "aria-valuemax": this.options.max,
15200
+ // TODO: what should we do with values that can't be parsed?
15201
+ "aria-valuenow": this._parse( this.element.val() )
15202
+ });
15203
+ },
15204
+
15205
+ isValid: function() {
15206
+ var value = this.value();
15207
+
15208
+ // null is invalid
15209
+ if ( value === null ) {
15210
+ return false;
15211
+ }
15212
+
15213
+ // if value gets adjusted, it's invalid
15214
+ return value === this._adjustValue( value );
15215
+ },
15216
+
15217
+ // update the value without triggering change
15218
+ _value: function( value, allowAny ) {
15219
+ var parsed;
15220
+ if ( value !== "" ) {
15221
+ parsed = this._parse( value );
15222
+ if ( parsed !== null ) {
15223
+ if ( !allowAny ) {
15224
+ parsed = this._adjustValue( parsed );
15225
+ }
15226
+ value = this._format( parsed );
15227
+ }
15228
+ }
15229
+ this.element.val( value );
15230
+ this._refresh();
15231
+ },
15232
+
15233
+ _destroy: function() {
15234
+ this.element
15235
+ .removeClass( "ui-spinner-input" )
15236
+ .prop( "disabled", false )
15237
+ .removeAttr( "autocomplete" )
15238
+ .removeAttr( "role" )
15239
+ .removeAttr( "aria-valuemin" )
15240
+ .removeAttr( "aria-valuemax" )
15241
+ .removeAttr( "aria-valuenow" );
15242
+ this.uiSpinner.replaceWith( this.element );
15243
+ },
15244
+
15245
+ stepUp: spinner_modifier(function( steps ) {
15246
+ this._stepUp( steps );
15247
+ }),
15248
+ _stepUp: function( steps ) {
15249
+ if ( this._start() ) {
15250
+ this._spin( (steps || 1) * this.options.step );
15251
+ this._stop();
15252
+ }
15253
+ },
15254
+
15255
+ stepDown: spinner_modifier(function( steps ) {
15256
+ this._stepDown( steps );
15257
+ }),
15258
+ _stepDown: function( steps ) {
15259
+ if ( this._start() ) {
15260
+ this._spin( (steps || 1) * -this.options.step );
15261
+ this._stop();
15262
+ }
15263
+ },
15264
+
15265
+ pageUp: spinner_modifier(function( pages ) {
15266
+ this._stepUp( (pages || 1) * this.options.page );
15267
+ }),
15268
+
15269
+ pageDown: spinner_modifier(function( pages ) {
15270
+ this._stepDown( (pages || 1) * this.options.page );
15271
+ }),
15272
+
15273
+ value: function( newVal ) {
15274
+ if ( !arguments.length ) {
15275
+ return this._parse( this.element.val() );
15276
+ }
15277
+ spinner_modifier( this._value ).call( this, newVal );
15278
+ },
15279
+
15280
+ widget: function() {
15281
+ return this.uiSpinner;
15282
+ }
15283
+ });
15284
+
15285
+
15286
+ /*!
15287
+ * jQuery UI Tabs 1.11.4
15288
+ * http://jqueryui.com
15289
+ *
15290
+ * Copyright jQuery Foundation and other contributors
15291
+ * Released under the MIT license.
15292
+ * http://jquery.org/license
15293
+ *
15294
+ * http://api.jqueryui.com/tabs/
15295
+ */
15296
+
15297
+
15298
+ var tabs = $.widget( "ui.tabs", {
15299
+ version: "1.11.4",
15300
+ delay: 300,
15301
+ options: {
15302
+ active: null,
15303
+ collapsible: false,
15304
+ event: "click",
15305
+ heightStyle: "content",
15306
+ hide: null,
15307
+ show: null,
15308
+
15309
+ // callbacks
15310
+ activate: null,
15311
+ beforeActivate: null,
15312
+ beforeLoad: null,
15313
+ load: null
15314
+ },
15315
+
15316
+ _isLocal: (function() {
15317
+ var rhash = /#.*$/;
15318
+
15319
+ return function( anchor ) {
15320
+ var anchorUrl, locationUrl;
15321
+
15322
+ // support: IE7
15323
+ // IE7 doesn't normalize the href property when set via script (#9317)
15324
+ anchor = anchor.cloneNode( false );
15325
+
15326
+ anchorUrl = anchor.href.replace( rhash, "" );
15327
+ locationUrl = location.href.replace( rhash, "" );
15328
+
15329
+ // decoding may throw an error if the URL isn't UTF-8 (#9518)
15330
+ try {
15331
+ anchorUrl = decodeURIComponent( anchorUrl );
15332
+ } catch ( error ) {}
15333
+ try {
15334
+ locationUrl = decodeURIComponent( locationUrl );
15335
+ } catch ( error ) {}
15336
+
15337
+ return anchor.hash.length > 1 && anchorUrl === locationUrl;
15338
+ };
15339
+ })(),
15340
+
15341
+ _create: function() {
15342
+ var that = this,
15343
+ options = this.options;
15344
+
15345
+ this.running = false;
15346
+
15347
+ this.element
15348
+ .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
15349
+ .toggleClass( "ui-tabs-collapsible", options.collapsible );
15350
+
15351
+ this._processTabs();
15352
+ options.active = this._initialActive();
15353
+
15354
+ // Take disabling tabs via class attribute from HTML
15355
+ // into account and update option properly.
15356
+ if ( $.isArray( options.disabled ) ) {
15357
+ options.disabled = $.unique( options.disabled.concat(
15358
+ $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
15359
+ return that.tabs.index( li );
15360
+ })
15361
+ ) ).sort();
15362
+ }
15363
+
15364
+ // check for length avoids error when initializing empty list
15365
+ if ( this.options.active !== false && this.anchors.length ) {
15366
+ this.active = this._findActive( options.active );
15367
+ } else {
15368
+ this.active = $();
15369
+ }
15370
+
15371
+ this._refresh();
15372
+
15373
+ if ( this.active.length ) {
15374
+ this.load( options.active );
15375
+ }
15376
+ },
15377
+
15378
+ _initialActive: function() {
15379
+ var active = this.options.active,
15380
+ collapsible = this.options.collapsible,
15381
+ locationHash = location.hash.substring( 1 );
15382
+
15383
+ if ( active === null ) {
15384
+ // check the fragment identifier in the URL
15385
+ if ( locationHash ) {
15386
+ this.tabs.each(function( i, tab ) {
15387
+ if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
15388
+ active = i;
15389
+ return false;
15390
+ }
15391
+ });
15392
+ }
15393
+
15394
+ // check for a tab marked active via a class
15395
+ if ( active === null ) {
15396
+ active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
15397
+ }
15398
+
15399
+ // no active tab, set to false
15400
+ if ( active === null || active === -1 ) {
15401
+ active = this.tabs.length ? 0 : false;
15402
+ }
15403
+ }
15404
+
15405
+ // handle numbers: negative, out of range
15406
+ if ( active !== false ) {
15407
+ active = this.tabs.index( this.tabs.eq( active ) );
15408
+ if ( active === -1 ) {
15409
+ active = collapsible ? false : 0;
15410
+ }
15411
+ }
15412
+
15413
+ // don't allow collapsible: false and active: false
15414
+ if ( !collapsible && active === false && this.anchors.length ) {
15415
+ active = 0;
15416
+ }
15417
+
15418
+ return active;
15419
+ },
15420
+
15421
+ _getCreateEventData: function() {
15422
+ return {
15423
+ tab: this.active,
15424
+ panel: !this.active.length ? $() : this._getPanelForTab( this.active )
15425
+ };
15426
+ },
15427
+
15428
+ _tabKeydown: function( event ) {
15429
+ var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
15430
+ selectedIndex = this.tabs.index( focusedTab ),
15431
+ goingForward = true;
15432
+
15433
+ if ( this._handlePageNav( event ) ) {
15434
+ return;
15435
+ }
15436
+
15437
+ switch ( event.keyCode ) {
15438
+ case $.ui.keyCode.RIGHT:
15439
+ case $.ui.keyCode.DOWN:
15440
+ selectedIndex++;
15441
+ break;
15442
+ case $.ui.keyCode.UP:
15443
+ case $.ui.keyCode.LEFT:
15444
+ goingForward = false;
15445
+ selectedIndex--;
15446
+ break;
15447
+ case $.ui.keyCode.END:
15448
+ selectedIndex = this.anchors.length - 1;
15449
+ break;
15450
+ case $.ui.keyCode.HOME:
15451
+ selectedIndex = 0;
15452
+ break;
15453
+ case $.ui.keyCode.SPACE:
15454
+ // Activate only, no collapsing
15455
+ event.preventDefault();
15456
+ clearTimeout( this.activating );
15457
+ this._activate( selectedIndex );
15458
+ return;
15459
+ case $.ui.keyCode.ENTER:
15460
+ // Toggle (cancel delayed activation, allow collapsing)
15461
+ event.preventDefault();
15462
+ clearTimeout( this.activating );
15463
+ // Determine if we should collapse or activate
15464
+ this._activate( selectedIndex === this.options.active ? false : selectedIndex );
15465
+ return;
15466
+ default:
15467
+ return;
15468
+ }
15469
+
15470
+ // Focus the appropriate tab, based on which key was pressed
15471
+ event.preventDefault();
15472
+ clearTimeout( this.activating );
15473
+ selectedIndex = this._focusNextTab( selectedIndex, goingForward );
15474
+
15475
+ // Navigating with control/command key will prevent automatic activation
15476
+ if ( !event.ctrlKey && !event.metaKey ) {
15477
+
15478
+ // Update aria-selected immediately so that AT think the tab is already selected.
15479
+ // Otherwise AT may confuse the user by stating that they need to activate the tab,
15480
+ // but the tab will already be activated by the time the announcement finishes.
15481
+ focusedTab.attr( "aria-selected", "false" );
15482
+ this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
15483
+
15484
+ this.activating = this._delay(function() {
15485
+ this.option( "active", selectedIndex );
15486
+ }, this.delay );
15487
+ }
15488
+ },
15489
+
15490
+ _panelKeydown: function( event ) {
15491
+ if ( this._handlePageNav( event ) ) {
15492
+ return;
15493
+ }
15494
+
15495
+ // Ctrl+up moves focus to the current tab
15496
+ if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
15497
+ event.preventDefault();
15498
+ this.active.focus();
15499
+ }
15500
+ },
15501
+
15502
+ // Alt+page up/down moves focus to the previous/next tab (and activates)
15503
+ _handlePageNav: function( event ) {
15504
+ if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
15505
+ this._activate( this._focusNextTab( this.options.active - 1, false ) );
15506
+ return true;
15507
+ }
15508
+ if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
15509
+ this._activate( this._focusNextTab( this.options.active + 1, true ) );
15510
+ return true;
15511
+ }
15512
+ },
15513
+
15514
+ _findNextTab: function( index, goingForward ) {
15515
+ var lastTabIndex = this.tabs.length - 1;
15516
+
15517
+ function constrain() {
15518
+ if ( index > lastTabIndex ) {
15519
+ index = 0;
15520
+ }
15521
+ if ( index < 0 ) {
15522
+ index = lastTabIndex;
15523
+ }
15524
+ return index;
15525
+ }
15526
+
15527
+ while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
15528
+ index = goingForward ? index + 1 : index - 1;
15529
+ }
15530
+
15531
+ return index;
15532
+ },
15533
+
15534
+ _focusNextTab: function( index, goingForward ) {
15535
+ index = this._findNextTab( index, goingForward );
15536
+ this.tabs.eq( index ).focus();
15537
+ return index;
15538
+ },
15539
+
15540
+ _setOption: function( key, value ) {
15541
+ if ( key === "active" ) {
15542
+ // _activate() will handle invalid values and update this.options
15543
+ this._activate( value );
15544
+ return;
15545
+ }
15546
+
15547
+ if ( key === "disabled" ) {
15548
+ // don't use the widget factory's disabled handling
15549
+ this._setupDisabled( value );
15550
+ return;
15551
+ }
15552
+
15553
+ this._super( key, value);
15554
+
15555
+ if ( key === "collapsible" ) {
15556
+ this.element.toggleClass( "ui-tabs-collapsible", value );
15557
+ // Setting collapsible: false while collapsed; open first panel
15558
+ if ( !value && this.options.active === false ) {
15559
+ this._activate( 0 );
15560
+ }
15561
+ }
15562
+
15563
+ if ( key === "event" ) {
15564
+ this._setupEvents( value );
15565
+ }
15566
+
15567
+ if ( key === "heightStyle" ) {
15568
+ this._setupHeightStyle( value );
15569
+ }
15570
+ },
15571
+
15572
+ _sanitizeSelector: function( hash ) {
15573
+ return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
15574
+ },
15575
+
15576
+ refresh: function() {
15577
+ var options = this.options,
15578
+ lis = this.tablist.children( ":has(a[href])" );
15579
+
15580
+ // get disabled tabs from class attribute from HTML
15581
+ // this will get converted to a boolean if needed in _refresh()
15582
+ options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
15583
+ return lis.index( tab );
15584
+ });
15585
+
15586
+ this._processTabs();
15587
+
15588
+ // was collapsed or no tabs
15589
+ if ( options.active === false || !this.anchors.length ) {
15590
+ options.active = false;
15591
+ this.active = $();
15592
+ // was active, but active tab is gone
15593
+ } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
15594
+ // all remaining tabs are disabled
15595
+ if ( this.tabs.length === options.disabled.length ) {
15596
+ options.active = false;
15597
+ this.active = $();
15598
+ // activate previous tab
15599
+ } else {
15600
+ this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
15601
+ }
15602
+ // was active, active tab still exists
15603
+ } else {
15604
+ // make sure active index is correct
15605
+ options.active = this.tabs.index( this.active );
15606
+ }
15607
+
15608
+ this._refresh();
15609
+ },
15610
+
15611
+ _refresh: function() {
15612
+ this._setupDisabled( this.options.disabled );
15613
+ this._setupEvents( this.options.event );
15614
+ this._setupHeightStyle( this.options.heightStyle );
15615
+
15616
+ this.tabs.not( this.active ).attr({
15617
+ "aria-selected": "false",
15618
+ "aria-expanded": "false",
15619
+ tabIndex: -1
15620
+ });
15621
+ this.panels.not( this._getPanelForTab( this.active ) )
15622
+ .hide()
15623
+ .attr({
15624
+ "aria-hidden": "true"
15625
+ });
15626
+
15627
+ // Make sure one tab is in the tab order
15628
+ if ( !this.active.length ) {
15629
+ this.tabs.eq( 0 ).attr( "tabIndex", 0 );
15630
+ } else {
15631
+ this.active
15632
+ .addClass( "ui-tabs-active ui-state-active" )
15633
+ .attr({
15634
+ "aria-selected": "true",
15635
+ "aria-expanded": "true",
15636
+ tabIndex: 0
15637
+ });
15638
+ this._getPanelForTab( this.active )
15639
+ .show()
15640
+ .attr({
15641
+ "aria-hidden": "false"
15642
+ });
15643
+ }
15644
+ },
15645
+
15646
+ _processTabs: function() {
15647
+ var that = this,
15648
+ prevTabs = this.tabs,
15649
+ prevAnchors = this.anchors,
15650
+ prevPanels = this.panels;
15651
+
15652
+ this.tablist = this._getList()
15653
+ .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
15654
+ .attr( "role", "tablist" )
15655
+
15656
+ // Prevent users from focusing disabled tabs via click
15657
+ .delegate( "> li", "mousedown" + this.eventNamespace, function( event ) {
15658
+ if ( $( this ).is( ".ui-state-disabled" ) ) {
15659
+ event.preventDefault();
15660
+ }
15661
+ })
15662
+
15663
+ // support: IE <9
15664
+ // Preventing the default action in mousedown doesn't prevent IE
15665
+ // from focusing the element, so if the anchor gets focused, blur.
15666
+ // We don't have to worry about focusing the previously focused
15667
+ // element since clicking on a non-focusable element should focus
15668
+ // the body anyway.
15669
+ .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
15670
+ if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
15671
+ this.blur();
15672
+ }
15673
+ });
15674
+
15675
+ this.tabs = this.tablist.find( "> li:has(a[href])" )
15676
+ .addClass( "ui-state-default ui-corner-top" )
15677
+ .attr({
15678
+ role: "tab",
15679
+ tabIndex: -1
15680
+ });
15681
+
15682
+ this.anchors = this.tabs.map(function() {
15683
+ return $( "a", this )[ 0 ];
15684
+ })
15685
+ .addClass( "ui-tabs-anchor" )
15686
+ .attr({
15687
+ role: "presentation",
15688
+ tabIndex: -1
15689
+ });
15690
+
15691
+ this.panels = $();
15692
+
15693
+ this.anchors.each(function( i, anchor ) {
15694
+ var selector, panel, panelId,
15695
+ anchorId = $( anchor ).uniqueId().attr( "id" ),
15696
+ tab = $( anchor ).closest( "li" ),
15697
+ originalAriaControls = tab.attr( "aria-controls" );
15698
+
15699
+ // inline tab
15700
+ if ( that._isLocal( anchor ) ) {
15701
+ selector = anchor.hash;
15702
+ panelId = selector.substring( 1 );
15703
+ panel = that.element.find( that._sanitizeSelector( selector ) );
15704
+ // remote tab
15705
+ } else {
15706
+ // If the tab doesn't already have aria-controls,
15707
+ // generate an id by using a throw-away element
15708
+ panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
15709
+ selector = "#" + panelId;
15710
+ panel = that.element.find( selector );
15711
+ if ( !panel.length ) {
15712
+ panel = that._createPanel( panelId );
15713
+ panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
15714
+ }
15715
+ panel.attr( "aria-live", "polite" );
15716
+ }
15717
+
15718
+ if ( panel.length) {
15719
+ that.panels = that.panels.add( panel );
15720
+ }
15721
+ if ( originalAriaControls ) {
15722
+ tab.data( "ui-tabs-aria-controls", originalAriaControls );
15723
+ }
15724
+ tab.attr({
15725
+ "aria-controls": panelId,
15726
+