Iglobal_Main - Version 1.2.0

Version Notes

New Features:
Duty & Fees Integrated into Tax
Order email can be sent from the store

Improvements:
Faster Speeds
Country Region Fixes
iGlobal Stores Updated API

Download this release

Release Info

Developer Matt Flamm
Extension Iglobal_Main
Version 1.2.0
Comparing to
See all releases


Code changes from version 1.1.1 to 1.2.0

Files changed (36) hide show
  1. app/code/community/Iglobal/Fee/Block/Sales/Order/Total.php +0 -65
  2. app/code/community/Iglobal/Fee/Helper/Data.php +0 -8
  3. app/code/community/Iglobal/Fee/Model/Fee.php +0 -17
  4. app/code/community/Iglobal/Fee/Model/Observer.php +0 -28
  5. app/code/community/Iglobal/Fee/Model/Sales/Order/Total/Creditmemo/Fee.php +0 -17
  6. app/code/community/Iglobal/Fee/Model/Sales/Order/Total/Invoice/Fee.php +0 -17
  7. app/code/community/Iglobal/Fee/Model/Sales/Quote/Address/Total/Fee.php +0 -51
  8. app/code/community/Iglobal/Fee/etc/config.xml +0 -169
  9. app/code/community/Iglobal/Fee/sql/fee_setup/mysql4-install-0.1.0.php +0 -25
  10. app/code/community/Iglobal/Stores/Block/Link.php +26 -26
  11. app/code/community/Iglobal/Stores/Helper/Url.php +24 -24
  12. app/code/community/Iglobal/Stores/Model/International/International.php +48 -186
  13. app/code/community/Iglobal/Stores/Model/Observer.php +2 -2
  14. app/code/community/Iglobal/Stores/Model/Order.php +279 -0
  15. app/code/community/Iglobal/Stores/Model/Rest.php +75 -0
  16. app/code/community/Iglobal/Stores/Model/Rest/Order.php +0 -86
  17. app/code/community/Iglobal/Stores/Model/Rest/Region.php +0 -42
  18. app/code/community/Iglobal/Stores/Model/Sales/Quote/Address/Total/Fee.php +17 -0
  19. app/code/community/Iglobal/Stores/controllers/CheckoutController.php +42 -42
  20. app/code/community/Iglobal/Stores/controllers/InternationalController.php +0 -32
  21. app/code/community/Iglobal/Stores/controllers/SuccessController.php +50 -386
  22. app/code/community/Iglobal/Stores/etc/config.xml +10 -0
  23. app/code/community/Iglobal/Stores/etc/system.xml +79 -59
  24. app/design/adminhtml/default/default/layout/fee.xml +0 -56
  25. app/design/adminhtml/default/default/template/fee/sales/order/refunded.phtml +0 -16
  26. app/design/adminhtml/default/default/template/fee/sales/order/total.phtml +0 -9
  27. app/design/frontend/base/default/layout/fee.xml +0 -50
  28. app/design/frontend/base/default/template/iglobal/checkout/onepage/link.phtml +30 -30
  29. app/design/frontend/base/default/template/iglobal/stores/cart.phtml +21 -24
  30. app/etc/modules/Iglobal_Fee.xml +0 -9
  31. js/iGlobal/ig_welcome_mat_default.css +0 -41
  32. js/iGlobal/ig_welcome_mat_default.js +0 -867
  33. js/iGlobal/igc.cs.magento_default_ice.js +0 -203
  34. js/iGlobal/jquery/jquery.js +0 -9603
  35. js/iGlobal/jquery/jquery.noconflict.js +0 -1
  36. package.xml +14 -12
app/code/community/Iglobal/Fee/Block/Sales/Order/Total.php DELETED
@@ -1,65 +0,0 @@
1
- <?php
2
- class Iglobal_Fee_Block_Sales_Order_Total extends Mage_Core_Block_Template
3
- {
4
- /**
5
- * Get label cell tag properties
6
- *
7
- * @return string
8
- */
9
- public function getLabelProperties()
10
- {
11
- return $this->getParentBlock()->getLabelProperties();
12
- }
13
-
14
- /**
15
- * Get order store object
16
- *
17
- * @return Mage_Sales_Model_Order
18
- */
19
- public function getOrder()
20
- {
21
- return $this->getParentBlock()->getOrder();
22
- }
23
-
24
- /**
25
- * Get totals source object
26
- *
27
- * @return Mage_Sales_Model_Order
28
- */
29
- public function getSource()
30
- {
31
- return $this->getParentBlock()->getSource();
32
- }
33
-
34
- /**
35
- * Get value cell tag properties
36
- *
37
- * @return string
38
- */
39
- public function getValueProperties()
40
- {
41
- return $this->getParentBlock()->getValueProperties();
42
- }
43
-
44
- /**
45
- * Initialize reward points totals
46
- *
47
- * @return Enterprise_Reward_Block_Sales_Order_Total
48
- */
49
- public function initTotals()
50
- {
51
- if ((float) $this->getOrder()->getBaseFeeAmount()) {
52
- $source = $this->getSource();
53
- $value = $source->getFeeAmount();
54
-
55
- $this->getParentBlock()->addTotal(new Varien_Object(array(
56
- 'code' => 'fee',
57
- 'strong' => false,
58
- 'label' => Mage::helper('fee')->formatFee($value),
59
- 'value' => $source instanceof Mage_Sales_Model_Order_Creditmemo ? - $value : $value
60
- )));
61
- }
62
-
63
- return $this;
64
- }
65
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/Iglobal/Fee/Helper/Data.php DELETED
@@ -1,8 +0,0 @@
1
- <?php
2
-
3
- class Iglobal_Fee_Helper_Data extends Mage_Core_Helper_Abstract
4
- {
5
- public function formatFee($amount){
6
- return Mage::helper('fee')->__('Customs and Duty Tax');
7
- }
8
- }
 
 
 
 
 
 
 
 
app/code/community/Iglobal/Fee/Model/Fee.php DELETED
@@ -1,17 +0,0 @@
1
- <?php
2
- class Iglobal_Fee_Model_Fee extends Varien_Object{
3
-
4
- public static function getFee(){
5
- return 0;
6
- }
7
- public static function canApply($address){
8
- return true;
9
- //put here your business logic to check if fee should be applied or not
10
- $quote = $address->getQuote();
11
- if($quote->getFeeAmount()){
12
- return true;
13
- } else {
14
- return false;
15
- }
16
- }
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/Iglobal/Fee/Model/Observer.php DELETED
@@ -1,28 +0,0 @@
1
- <?php
2
- class Iglobal_Fee_Model_Observer{
3
- public function invoiceSaveAfter(Varien_Event_Observer $observer)
4
- {
5
- $invoice = $observer->getEvent()->getInvoice();
6
- if ($invoice->getBaseFeeAmount()) {
7
- $order = $invoice->getOrder();
8
- $order->setFeeAmountInvoiced($order->getFeeAmountInvoiced() + $invoice->getFeeAmount());
9
- $order->setBaseFeeAmountInvoiced($order->getBaseFeeAmountInvoiced() + $invoice->getBaseFeeAmount());
10
- }
11
- return $this;
12
- }
13
- public function creditmemoSaveAfter(Varien_Event_Observer $observer)
14
- {
15
- /* @var $creditmemo Mage_Sales_Model_Order_Creditmemo */
16
- $creditmemo = $observer->getEvent()->getCreditmemo();
17
- if ($creditmemo->getFeeAmount()) {
18
- $order = $creditmemo->getOrder();
19
- $order->setFeeAmountRefunded($order->getFeeAmountRefunded() + $creditmemo->getFeeAmount());
20
- $order->setBaseFeeAmountRefunded($order->getBaseFeeAmountRefunded() + $creditmemo->getBaseFeeAmount());
21
- }
22
- return $this;
23
- }
24
- public function updatePaypalTotal($evt){
25
- $cart = $evt->getPaypalCart();
26
- $cart->updateTotal(Mage_Paypal_Model_Cart::TOTAL_SUBTOTAL,$cart->getSalesEntity()->getFeeAmount());
27
- }
28
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/Iglobal/Fee/Model/Sales/Order/Total/Creditmemo/Fee.php DELETED
@@ -1,17 +0,0 @@
1
- <?php
2
- class Iglobal_Fee_Model_Sales_Order_Total_Creditmemo_Fee extends Mage_Sales_Model_Order_Creditmemo_Total_Abstract
3
- {
4
- public function collect(Mage_Sales_Model_Order_Creditmemo $creditmemo)
5
- {
6
- $order = $creditmemo->getOrder();
7
- $feeAmountLeft = $order->getFeeAmountInvoiced() - $order->getFeeAmountRefunded();
8
- $basefeeAmountLeft = $order->getBaseFeeAmountInvoiced() - $order->getBaseFeeAmountRefunded();
9
- if ($basefeeAmountLeft > 0) {
10
- $creditmemo->setGrandTotal($creditmemo->getGrandTotal() + $feeAmountLeft);
11
- $creditmemo->setBaseGrandTotal($creditmemo->getBaseGrandTotal() + $basefeeAmountLeft);
12
- $creditmemo->setFeeAmount($feeAmountLeft);
13
- $creditmemo->setBaseFeeAmount($basefeeAmountLeft);
14
- }
15
- return $this;
16
- }
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/Iglobal/Fee/Model/Sales/Order/Total/Invoice/Fee.php DELETED
@@ -1,17 +0,0 @@
1
- <?php
2
- class Iglobal_Fee_Model_Sales_Order_Total_Invoice_Fee extends Mage_Sales_Model_Order_Invoice_Total_Abstract
3
- {
4
- public function collect(Mage_Sales_Model_Order_Invoice $invoice)
5
- {
6
- $order = $invoice->getOrder();
7
- $feeAmountLeft = $order->getFeeAmount() - $order->getFeeAmountInvoiced();
8
- $baseFeeAmountLeft = $order->getBaseFeeAmount() - $order->getBaseFeeAmountInvoiced();
9
-
10
- $invoice->setGrandTotal($invoice->getGrandTotal() + $feeAmountLeft);
11
- $invoice->setBaseGrandTotal($invoice->getBaseGrandTotal() + $baseFeeAmountLeft);
12
-
13
- $invoice->setFeeAmount($feeAmountLeft);
14
- $invoice->setBaseFeeAmount($baseFeeAmountLeft);
15
- return $this;
16
- }
17
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/Iglobal/Fee/Model/Sales/Quote/Address/Total/Fee.php DELETED
@@ -1,51 +0,0 @@
1
- <?php
2
- class Iglobal_Fee_Model_Sales_Quote_Address_Total_Fee extends Mage_Sales_Model_Quote_Address_Total_Abstract{
3
- protected $_code = 'fee';
4
-
5
- public function collect(Mage_Sales_Model_Quote_Address $address)
6
- {
7
- parent::collect($address);
8
-
9
- $this->_setAmount(0);
10
- $this->_setBaseAmount(0);
11
-
12
- $items = $this->_getAddressItems($address);
13
- if (!count($items)) {
14
- return $this; //this makes only address type shipping to come through
15
- }
16
-
17
-
18
- $quote = $address->getQuote();
19
-
20
- if(Iglobal_Fee_Model_Fee::canApply($address)){
21
- $exist_amount = $quote->getFeeAmount();
22
- $fee = Iglobal_Fee_Model_Fee::getFee();
23
- $balance = $exist_amount; //$fee - $exist_amount;
24
- // $balance = $fee;
25
-
26
- //$this->_setAmount($balance);
27
- //$this->_setBaseAmount($balance);
28
-
29
- $address->setFeeAmount($balance);
30
- $address->setBaseFeeAmount($balance);
31
-
32
- $quote->setFeeAmount($balance);
33
-
34
- $address->setGrandTotal($address->getGrandTotal() + $address->getFeeAmount());
35
- $address->setBaseGrandTotal($address->getBaseGrandTotal() + $address->getBaseFeeAmount());
36
- }
37
- }
38
-
39
- public function fetch(Mage_Sales_Model_Quote_Address $address)
40
- {
41
- $amt = $address->getFeeAmount();
42
- if($amt != 0){
43
- $address->addTotal(array(
44
- 'code'=>$this->getCode(),
45
- 'title'=>Mage::helper('fee')->__('Customs Duty and Tax'),
46
- 'value'=> $amt
47
- ));
48
- }
49
- return $this;
50
- }
51
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/Iglobal/Fee/etc/config.xml DELETED
@@ -1,169 +0,0 @@
1
- <?xml version="1.0"?>
2
- <config>
3
- <modules>
4
- <Iglobal_Fee>
5
- <version>0.1.0</version>
6
- </Iglobal_Fee>
7
- </modules>
8
- <frontend>
9
- <routers>
10
- <fee>
11
- <use>standard</use>
12
- <args>
13
- <module>Iglobal_Fee</module>
14
- <frontName>fee</frontName>
15
- </args>
16
- </fee>
17
- </routers>
18
- <layout>
19
- <updates>
20
- <fee>
21
- <file>fee.xml</file>
22
- </fee>
23
- </updates>
24
- </layout>
25
- </frontend>
26
- <admin>
27
- <routers>
28
- <fee>
29
- <use>admin</use>
30
- <args>
31
- <module>Iglobal_Fee</module>
32
- <frontName>fee</frontName>
33
- </args>
34
- </fee>
35
- </routers>
36
- </admin>
37
- <adminhtml>
38
- <layout>
39
- <updates>
40
- <fee>
41
- <file>fee.xml</file>
42
- </fee>
43
- </updates>
44
- </layout>
45
- </adminhtml>
46
- <global>
47
- <sales>
48
- <quote>
49
- <totals>
50
- <fee>
51
- <class>fee/sales_quote_address_total_fee</class>
52
- <before>subtotal</before>
53
- </fee>
54
- </totals>
55
- </quote>
56
- <order_invoice>
57
- <totals>
58
- <fee>
59
- <class>fee/sales_order_total_invoice_fee</class>
60
- <before>subtotal</before>
61
- </fee>
62
- </totals>
63
- </order_invoice>
64
- <order_creditmemo>
65
- <totals>
66
- <fee>
67
- <class>fee/sales_order_total_creditmemo_fee</class>
68
- <before>subtotal</before>
69
- </fee>
70
- </totals>
71
- </order_creditmemo>
72
- </sales>
73
- <events>
74
- <paypal_prepare_line_items>
75
- <observers>
76
- <paypal_prepare_line_items>
77
- <class>fee/observer</class>
78
- <method>updatePaypalTotal</method>
79
- </paypal_prepare_line_items>
80
- </observers>
81
- </paypal_prepare_line_items>
82
- <sales_order_invoice_save_after>
83
- <observers>
84
- <sales_order_invoice_save_after>
85
- <class>fee/observer</class>
86
- <method>invoiceSaveAfter</method>
87
- </sales_order_invoice_save_after>
88
- </observers>
89
- </sales_order_invoice_save_after>
90
- <sales_order_creditmemo_save_after>
91
- <observers>
92
- <sales_order_creditmemo_save_after>
93
- <class>fee/observer</class>
94
- <method>creditmemoSaveAfter</method>
95
- </sales_order_creditmemo_save_after>
96
- </observers>
97
- </sales_order_creditmemo_save_after>
98
- </events>
99
- <fieldsets>
100
- <sales_convert_quote_address>
101
- <fee_amount><to_order>*</to_order></fee_amount>
102
- <base_fee_amount><to_order>*</to_order></base_fee_amount>
103
- </sales_convert_quote_address>
104
- </fieldsets>
105
- <pdf>
106
- <totals>
107
- <fee translate="title">
108
- <title>Fee</title>
109
- <source_field>fee_amount</source_field>
110
- <font_size>7</font_size>
111
- <display_zero>0</display_zero>
112
- <sort_order>650</sort_order>
113
- <amount_prefix>-</amount_prefix>
114
- </fee>
115
- </totals>
116
- </pdf>
117
- <models>
118
- <fee>
119
- <class>Iglobal_Fee_Model</class>
120
- <resourceModel>fee_mysql4</resourceModel>
121
- </fee>
122
- <fee_mysql4>
123
- <class>Iglobal_Fee_Model_Mysql4</class>
124
- <entities>
125
- <fee>
126
- <table>fee</table>
127
- </fee>
128
- </entities>
129
- </fee_mysql4>
130
- </models>
131
- <resources>
132
- <fee_setup>
133
- <setup>
134
- <module>Iglobal_Fee</module>
135
- </setup>
136
- <connection>
137
- <use>core_setup</use>
138
- </connection>
139
- </fee_setup>
140
- <fee_write>
141
- <connection>
142
- <use>core_write</use>
143
- </connection>
144
- </fee_write>
145
- <fee_read>
146
- <connection>
147
- <use>core_read</use>
148
- </connection>
149
- </fee_read>
150
- </resources>
151
- <blocks>
152
- <fee>
153
- <class>Iglobal_Fee_Block</class>
154
- </fee>
155
- </blocks>
156
- <helpers>
157
- <fee>
158
- <class>Iglobal_Fee_Helper</class>
159
- </fee>
160
- </helpers>
161
- </global>
162
- <default>
163
- <sales>
164
- <totals_sort>
165
- <fee>15</fee>
166
- </totals_sort>
167
- </sales>
168
- </default>
169
- </config>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/Iglobal/Fee/sql/fee_setup/mysql4-install-0.1.0.php DELETED
@@ -1,25 +0,0 @@
1
- <?php
2
-
3
- $installer = $this;
4
-
5
- $installer->startSetup();
6
-
7
- $installer->run("
8
-
9
- ALTER TABLE `".$this->getTable('sales/order')."` ADD `fee_amount` DECIMAL( 10, 2 ) NOT NULL;
10
- ALTER TABLE `".$this->getTable('sales/order')."` ADD `base_fee_amount` DECIMAL( 10, 2 ) NOT NULL;
11
- ALTER TABLE `".$this->getTable('sales/quote_address')."` ADD `fee_amount` DECIMAL( 10, 2 ) NOT NULL;
12
- ALTER TABLE `".$this->getTable('sales/quote_address')."` ADD `base_fee_amount` DECIMAL( 10, 2 ) NOT NULL;
13
- ALTER TABLE `".$this->getTable('sales/order')."` ADD `fee_amount_invoiced` DECIMAL( 10, 2 ) NOT NULL;
14
- ALTER TABLE `".$this->getTable('sales/order')."` ADD `base_fee_amount_invoiced` DECIMAL( 10, 2 ) NOT NULL;
15
- ALTER TABLE `".$this->getTable('sales/invoice')."` ADD `fee_amount` DECIMAL( 10, 2 ) NOT NULL;
16
- ALTER TABLE `".$this->getTable('sales/invoice')."` ADD `base_fee_amount` DECIMAL( 10, 2 ) NOT NULL;
17
- ALTER TABLE `".$this->getTable('sales/order')."` ADD `fee_amount_refunded` DECIMAL( 10, 2 ) NOT NULL;
18
- ALTER TABLE `".$this->getTable('sales/order')."` ADD `base_fee_amount_refunded` DECIMAL( 10, 2 ) NOT NULL;
19
- ALTER TABLE `".$this->getTable('sales/creditmemo')."` ADD `fee_amount` DECIMAL( 10, 2 ) NOT NULL;
20
- ALTER TABLE `".$this->getTable('sales/creditmemo')."` ADD `base_fee_amount` DECIMAL( 10, 2 ) NOT NULL;
21
-
22
-
23
- ");
24
-
25
- $installer->endSetup();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/Iglobal/Stores/Block/Link.php CHANGED
@@ -1,27 +1,27 @@
1
- <?php
2
-
3
- //this block override returns the url to be used on the primary checkout buttons on the cart page.
4
- //If you are using a custom checkout then this may or may not still work.
5
- //If not, you will need to find how the checkout determines the url, and apply a similar method.
6
- // also refer to ../Helper/Url.php
7
-
8
- class Iglobal_Stores_Block_Link extends Mage_Checkout_Block_Onepage_Link
9
- {
10
- function getCheckoutUrl()
11
- {
12
- //$this->setTemplate('iglobal/checkout/onepage/link.phtml');
13
- //check if the country is international
14
- $countryCode = (isset($_COOKIE['igCountry']) ? $_COOKIE['igCountry'] : "");
15
- $domesticCountries = explode(",", Mage::getStoreConfig('general/country/ig_domestic_countries'));
16
- $isDomestic = in_array ($countryCode, $domesticCountries) ? true : false;
17
-
18
- //return the url
19
-
20
- if (Mage::getStoreConfig('iglobal_integration/igmat/welcome_mat_active') && Mage::getStoreConfig('iglobal_integration/apireqs/ice_toggle') && Mage::getStoreConfig('iglobal_integration/apireqs/use_iframe') && !$isDomestic){//!$isDomestic && Mage::getStoreConfig('iglobal_integration/apireqs/ice_toggle')){
21
- //return "if(!ig_isDomesticCountry()){window.location.replace (' " . $this->getUrl('iglobal/checkout', array('_secure'=>true)) . "');} else {window.location.replace ('" . $this->getUrl('checkout/onepage', array('_secure'=>true)) . "');}";
22
- return $this->getUrl('iglobal/checkout', array('_secure'=>true));
23
- } else {
24
- return $this->getUrl('checkout/onepage', array('_secure'=>true));
25
- }
26
- }
27
  }
1
+ <?php
2
+
3
+ //this block override returns the url to be used on the primary checkout buttons on the cart page.
4
+ //If you are using a custom checkout then this may or may not still work.
5
+ //If not, you will need to find how the checkout determines the url, and apply a similar method.
6
+ // also refer to ../Helper/Url.php
7
+
8
+ class Iglobal_Stores_Block_Link extends Mage_Checkout_Block_Onepage_Link
9
+ {
10
+ function getCheckoutUrl()
11
+ {
12
+ //$this->setTemplate('iglobal/checkout/onepage/link.phtml');
13
+ //check if the country is international
14
+ $countryCode = (isset($_COOKIE['igCountry']) ? $_COOKIE['igCountry'] : "");
15
+ $domesticCountries = explode(",", Mage::getStoreConfig('general/country/ig_domestic_countries'));
16
+ $isDomestic = in_array ($countryCode, $domesticCountries) ? true : false;
17
+
18
+ //return the url
19
+
20
+ if (Mage::getStoreConfig('iglobal_integration/igmat/welcome_mat_active') && Mage::getStoreConfig('iglobal_integration/apireqs/ice_toggle') && Mage::getStoreConfig('iglobal_integration/apireqs/use_iframe') && !$isDomestic){//!$isDomestic && Mage::getStoreConfig('iglobal_integration/apireqs/ice_toggle')){
21
+ //return "if(!ig_isDomesticCountry()){window.location.replace (' " . $this->getUrl('iglobal/checkout', array('_secure'=>true)) . "');} else {window.location.replace ('" . $this->getUrl('checkout/onepage', array('_secure'=>true)) . "');}";
22
+ return $this->getUrl('iglobal/checkout', array('_secure'=>true));
23
+ } else {
24
+ return $this->getUrl('checkout/onepage', array('_secure'=>true));
25
+ }
26
+ }
27
  }
app/code/community/Iglobal/Stores/Helper/Url.php CHANGED
@@ -1,24 +1,24 @@
1
- <?php
2
- class Iglobal_Stores_Helper_Url extends Mage_Checkout_Helper_Url
3
- {
4
-
5
- function getCheckoutUrl()
6
- {
7
- //check if the country is international
8
- $countryCode = (isset($_COOKIE['igCountry']) ? $_COOKIE['igCountry'] : "");
9
- $domesticCountries = explode(",", Mage::getStoreConfig('general/country/ig_domestic_countries'));
10
- $isDomestic = in_array ($countryCode, $domesticCountries) ? 1 : 0;
11
-
12
- //return the url
13
- if (Mage::getStoreConfig('iglobal_integration/igmat/welcome_mat_active') && Mage::getStoreConfig('iglobal_integration/apireqs/ice_toggle') && Mage::getStoreConfig('iglobal_integration/apireqs/use_iframe')){// check for welcome mat //!$isDomestic && Mage::getStoreConfig('iglobal_integration/apireqs/ice_toggle')){ // add checks for other admin configs
14
-
15
- // make this a javascript url
16
- return "javascript:if(!ig_isDomesticCountry()){window.location.replace (' " . $this->_getUrl('iglobal/checkout') . "');} else {window.location.replace ('" . $this->_getUrl('checkout/onepage') . "');}";
17
- //return "javascript:if(!ig_isDomesticCountry()){window.location.replace ('{$this->_getUrl('iglobal/checkout')}')return false;} else {window.location.replace ('{$this->_getUrl('checkout/onepage')}";
18
- //return $this->_getUrl('iglobal/checkout');
19
- } else {
20
- return $this->_getUrl('checkout/onepage');
21
- }
22
- }
23
-
24
- }
1
+ <?php
2
+ class Iglobal_Stores_Helper_Url extends Mage_Checkout_Helper_Url
3
+ {
4
+
5
+ function getCheckoutUrl()
6
+ {
7
+ //check if the country is international
8
+ $countryCode = (isset($_COOKIE['igCountry']) ? $_COOKIE['igCountry'] : "");
9
+ $domesticCountries = explode(",", Mage::getStoreConfig('general/country/ig_domestic_countries'));
10
+ $isDomestic = in_array ($countryCode, $domesticCountries) ? 1 : 0;
11
+
12
+ //return the url
13
+ if (Mage::getStoreConfig('iglobal_integration/igmat/welcome_mat_active') && Mage::getStoreConfig('iglobal_integration/apireqs/ice_toggle') && Mage::getStoreConfig('iglobal_integration/apireqs/use_iframe')){// check for welcome mat //!$isDomestic && Mage::getStoreConfig('iglobal_integration/apireqs/ice_toggle')){ // add checks for other admin configs
14
+
15
+ // make this a javascript url
16
+ return "javascript:if(!ig_isDomesticCountry()){window.location.replace (' " . $this->_getUrl('iglobal/checkout') . "');} else {window.location.replace ('" . $this->_getUrl('checkout/onepage') . "');}";
17
+ //return "javascript:if(!ig_isDomesticCountry()){window.location.replace ('{$this->_getUrl('iglobal/checkout')}')return false;} else {window.location.replace ('{$this->_getUrl('checkout/onepage')}";
18
+ //return $this->_getUrl('iglobal/checkout');
19
+ } else {
20
+ return $this->_getUrl('checkout/onepage');
21
+ }
22
+ }
23
+
24
+ }
app/code/community/Iglobal/Stores/Model/International/International.php CHANGED
@@ -1,187 +1,49 @@
1
- <?php
2
-
3
-
4
- class Iglobal_Stores_Model_International_International extends Mage_Core_Model_Abstract
5
- {
6
- protected $_entryPoint = null;
7
-
8
- protected function _construct()
9
- {
10
-
11
-
12
- }
13
-
14
- public function setParameters ($client) {
15
-
16
- //get all the items in the cart
17
- $cart = Mage::getModel('checkout/cart')->getQuote();
18
- //start a loop to set each one
19
- //$i = 0;
20
- foreach ($cart->getAllVisibleItems() as $index=>$item) {
21
- $itemNumber = ++$index;
22
- // This is because Magento fails to load the custom attributes hence we have to go back to the DB.
23
- $weight = "";
24
- $length = "";
25
- $width = "";
26
- $height = "";
27
-
28
- try {
29
- $allItemData = Mage::getModel('catalog/product')->load($item['product_id']);
30
- $weightUnits = "";
31
- $dimUnits = "";
32
-
33
- try {
34
- $weightUnits = "";
35
- if (!empty($allItemData['ig_weight_units'])) {
36
- $weightUnits = $allItemData->getAttributeText('ig_weight_units');
37
- }
38
- } catch (Exception $e) {
39
- $weightUnits = "";
40
- }
41
-
42
- try {
43
- $weight = "";
44
- if (!empty($allItemData['ig_weight'])) {
45
- $weight = $allItemData->getData('ig_weight');
46
- } else if (!empty($allItemData['weight'])) {
47
- $weight = $item->getWeight();
48
- }
49
-
50
- if (!empty($weight)) {
51
- if ($weightUnits=="kg") {
52
- $weight = round(floatval($weight) / 0.453592, 2);
53
- } else if ($weightUnits=="oz") {
54
- $weight = round(floatval($weight) / 16, 2);
55
- } else if ($weightUnits=="g") {
56
- $weight = round(floatval($weight) / 453.592, 2);
57
- } else {//Default is lbs
58
- $weight = round(floatval($weight), 2);
59
- }
60
- } else {
61
- $weight = "";
62
- }
63
- } catch(Exception $e) {
64
- $weight = "";
65
- }
66
-
67
- try {
68
- $dimUnits = "";
69
- if (!empty($allItemData['ig_dimension_units'])) {
70
- $dimUnits = $allItemData->getAttributeText('ig_dimension_units');
71
- }
72
- } catch (Exception $e) {
73
- $dimUnits = "";
74
- }
75
- try {
76
- $length = "";
77
- if (!empty($allItemData['ig_length'])) {
78
- $length = $allItemData->getData('ig_length');
79
- }
80
- $width = "";
81
- if (!empty($allItemData['ig_width'])) {
82
- $width = $allItemData->getData('ig_width');
83
- }
84
- $height = "";
85
- if (!empty($allItemData['ig_height'])) {
86
- $height = $allItemData->getData('ig_height');
87
- }
88
- if (!empty($length) && !empty($width) && !empty($height)) {
89
- if ($dimUnits=="cm") {
90
- $length = ceil(floatval($length) / 2.54);
91
- $width = ceil(floatval($width) / 2.54);
92
- $height = ceil(floatval($height) / 2.54);
93
- } else {//Default is inches
94
- $length = ceil(floatval($length));
95
- $width = ceil(floatval($width));
96
- $height = ceil(floatval($height));
97
- }
98
- } else {
99
- $length = "";
100
- $width = "";
101
- $height = "";
102
- }
103
- } catch(Exception $e) {
104
- $length = "";
105
- $width = "";
106
- $height = "";
107
- }
108
- } catch (Exception $outerE) {
109
-
110
- }
111
-
112
- $itemId = $item->getProductId();
113
- $itemName = $item->getName();
114
- $itemSku = $item->getProduct()->getTypeId() == 'bundle' ? substr($item->getSku(), strpos($item->getSku(), '-')+1) : $item->getSku();
115
- $itemQty = $item->getQty();
116
- $itemPrice = $item->getPrice();
117
- $itemProductUrl = Mage::getModel('catalog/product')->load($item->getProductId())->getProductUrl();
118
- $itemImageUrl = str_replace("http:", "https:",Mage::helper('catalog/image')->init($item->getProduct(), 'thumbnail'));
119
- $itemDescription = Mage::getModel('catalog/product')->load($item->getProductId())->getDescription();
120
- $itemShortDescription = Mage::getModel('catalog/product')->load($item->getProductId())->getDescription();
121
- $itemMageWeight = $item->getWeight();
122
- $itemIgWeight = $weight;
123
- $itemIgLength = $length;
124
- $itemIgWidth = $width;
125
- $itemIgHeight = $height;
126
-
127
- if($itemId) $client->setParameterPost('itemProductId'.$itemNumber, $itemId);
128
- if($itemName) $client->setParameterPost('itemDescription'.$itemNumber, $itemName);
129
- if($itemSku) $client->setParameterPost('itemSku'.$itemNumber, $itemSku);
130
- if($itemQty) $client->setParameterPost('itemQuantity'.$itemNumber, $itemQty);
131
- if($itemPrice) $client->setParameterPost('itemUnitPrice'.$itemNumber, $itemPrice);
132
- if($itemProductUrl) $client->setParameterPost('itemURL'.$itemNumber, $itemProductUrl);
133
- if($itemImageUrl) $client->setParameterPost('itemImageURL'.$itemNumber, $itemImageUrl);
134
- if($itemDescription) $client->setParameterPost('itemDescription'.$itemNumber, $itemDescription);
135
- //if($itemShortDescription) $client->setParameterPost('itemProductIdN'.$itemNumber, $itemShortDescription);
136
- if($itemIgLength) $client->setParameterPost('itemLength'.$itemNumber, $itemIgLength);
137
- if($itemIgWidth) $client->setParameterPost('itemWidth'.$itemNumber, $itemIgWidth);
138
- if($itemIgHeight) $client->setParameterPost('itemHeight'.$itemNumber, $itemIgHeight);
139
- if($itemIgWeight) {
140
- $client->setParameterPost('itemWeight'.$itemNumber, $itemIgWeight);
141
- } elseif ($itemMageWeight) {
142
- $client->setParameterPost('itemWeight'.$itemNumber, $itemMageWeight);
143
- }
144
-
145
- }
146
- }
147
-
148
- public function getTempCartId ()
149
- {
150
- //build a POST and return the response
151
-
152
- $storeNumber = Mage::getStoreConfig('iglobal_integration/apireqs/iglobalid');
153
-
154
- $client = new Varien_Http_Client('https://checkout.iglobalstores.com/iglobalstores/services/TempCartService');
155
- $client->setMethod(Varien_Http_Client::POST);
156
-
157
- $client->setParameterPost('store', $storeNumber);
158
- $this->setParameters($client);
159
-
160
- //$client->setParameterPost('itemDescription1', 'My item for testing temp carts');
161
- //$client->setParameterPost('itemQuantity1', '1');
162
- //$client->setParameterPost('itemUnitPrice1', '123.45');
163
- //set the parameters in a loop
164
-
165
- //$client->setParameterPost('address', '123 fake st');//$address);
166
- //$client->setParameterPost('address', $address);
167
-
168
- //more parameters
169
- //Zend_Debug::dump($client);
170
-
171
- Mage::log("the client data" . print_r($client, true), null, 'international.log', true);
172
-
173
- try{
174
- $response = $client->request();
175
- if ($response->isSuccessful()) {
176
- return $response->getBody();
177
- }
178
- } catch (Exception $e) {
179
- die($e);
180
- }
181
-
182
-
183
- echo "I'm in the function!";
184
- }
185
-
186
- }
187
  ?>
1
+ <?php
2
+
3
+
4
+ class Iglobal_Stores_Model_International_International extends Mage_Core_Model_Abstract
5
+ {
6
+ public function getTempCartId ()
7
+ {
8
+
9
+ //get all the items in the cart
10
+ $cart = Mage::getModel('checkout/cart')->getQuote();
11
+ $items = array();
12
+
13
+ foreach ($cart->getAllVisibleItems() as $index=>$item) {
14
+ $product = $item->getProduct();
15
+ $sku = $item->getSku();
16
+ $dimUnits = $product->getIgDemesionUnits();
17
+ $dim2inch = ['cm' => 2.54, 'in' => 1, '' => 1];
18
+ $weight = $product->getIgWeight();
19
+ if (empty($weight))
20
+ {
21
+ $weight = $item->getWeight();
22
+ }
23
+
24
+ $items[] = [
25
+ "description" => $item->getName(),
26
+ "productId" => $item->getProductId(),
27
+ "sku" => $product->getTypeId() == 'bundle' ? substr($sku, strpos($sku, '-') + 1) : $sku,
28
+ "unitPrice" => $item->getPrice(),
29
+ "quantity" => $item->getQty(),
30
+ "length" => ceil(floatval($product->getIgLength()) / $dim2inch[$dimUnits]),
31
+ "width" => ceil(floatval($product->getIgWidth()) / $dim2inch[$dimUnits]),
32
+ "height" => ceil(floatval($product->getIgHeight()) / $dim2inch[$dimUnits]),
33
+ "weight" => $weight,
34
+ "weightUnits" => strtoupper($product->getIgWeightUnits()),
35
+ "itemURL" => $product->getProductUrl(),
36
+ "imageURL" => str_replace("http:", "https:", Mage::helper('catalog/image')->init($product, 'thumbnail')),
37
+ "itemDescriptionLong" => $product->getDescription(),
38
+
39
+ ];
40
+ }
41
+
42
+ $rest = Mage::getModel('stores/rest');
43
+ $response = $rest->createTempCart([
44
+ "storeId" =>Mage::getStoreConfig('iglobal_integration/apireqs/iglobalid'),
45
+ "items" => $items,]);
46
+ return $response->tempCartUUID;
47
+ }
48
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  ?>
app/code/community/Iglobal/Stores/Model/Observer.php CHANGED
@@ -86,11 +86,11 @@ class Iglobal_Stores_Model_Observer
86
  public function orderRec () {
87
 
88
  //get array with all orders in past
89
- $rest = Mage::getModel('stores/rest_order'); // get rest model
90
 
91
  //fetch all orders for the store from iGlobal server
92
  $data = $rest->getAllOrdersSinceDate('20140526');
93
- $orderData = $data['order'];
94
  $restOrders = array();
95
 
96
  //build array of orders with keypairs "ig_order_number" => "the number as a string"
86
  public function orderRec () {
87
 
88
  //get array with all orders in past
89
+ $rest = Mage::getModel('stores/rest'); // get rest model
90
 
91
  //fetch all orders for the store from iGlobal server
92
  $data = $rest->getAllOrdersSinceDate('20140526');
93
+ $orderData = $data['order'];
94
  $restOrders = array();
95
 
96
  //build array of orders with keypairs "ig_order_number" => "the number as a string"
app/code/community/Iglobal/Stores/Model/Order.php ADDED
@@ -0,0 +1,279 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Iglobal_Stores_Model_Order extends Mage_Core_Model_Abstract
4
+ {
5
+ protected $quote = null;
6
+ protected $iglobal_order_id = null;
7
+ protected $iglobal_order = null;
8
+ protected $rest = null;
9
+ public function setQuote($quote)
10
+ {
11
+ $this->quote = $quote;
12
+ }
13
+
14
+ public function processOrder($orderid)
15
+ {
16
+ $this->iglobal_order_id = $orderid;
17
+ $this->rest = Mage::getModel('stores/rest');
18
+ $this->iglobal_order = $this->rest->getOrder($this->iglobal_order_id)->order;
19
+ Mage::register('duty_tax', $this->iglobal_order->dutyTaxesTotal);
20
+ $shippingAddress = $this->setContactInfo();
21
+ $shippingAddress = $this->setShipping($shippingAddress);
22
+ $this->setPayment($shippingAddress);
23
+ return $this->createOrder();
24
+ }
25
+
26
+ protected function setContactInfo()
27
+ {
28
+ //set customer info
29
+ $this->quote->setCustomerEmail($this->iglobal_order->email);
30
+
31
+ $_name = explode(' ', $this->iglobal_order->name, 2);
32
+ if ($this->iglobal_order->testOrder) {
33
+ $name_first = "TEST ORDER! DO NOT SHIP! - " . array_shift($_name);
34
+ $name_last = array_pop($_name);
35
+ } else {
36
+ $name_first = array_shift($_name);
37
+ $name_last = array_pop($_name);
38
+ }
39
+
40
+ $this->quote->setCustomerFirstname($name_first);
41
+ $this->quote->setCustomerLastname($name_last);
42
+
43
+ $street = $this->iglobal_order->address1;
44
+ if ($this->iglobal_order->address2)
45
+ {
46
+ $street = array($street, $this->iglobal_order->address2);
47
+ }
48
+
49
+ $region = Mage::getModel('directory/region')
50
+ ->loadbyName($this->iglobal_order->state, $this->iglobal_order->countryCode);
51
+ if (!$region->getId())
52
+ {
53
+ // Lookup region from iGlobalstores
54
+ $regionId = $this->rest->getRegionId(
55
+ $this->iglobal_order->countryCode,
56
+ $this->iglobal_order->state,
57
+ $this->iglobal_order_id);
58
+ $region->load($regionId);
59
+ if (!$region->getId())
60
+ {
61
+ // Create a new region
62
+ $region->setData([
63
+ 'country_id' => $this->iglobal_order->countryCode,
64
+ 'defalt_name' => $this->iglobal_order->state
65
+ ])->save();
66
+
67
+ }
68
+ }
69
+
70
+ $addressData = array(
71
+ 'firstname' => $name_first,
72
+ 'lastname' => $name_last,
73
+ 'street' => $street,
74
+ 'city' => $this->iglobal_order->city,
75
+ 'postcode' => $this->iglobal_order->zip,
76
+ 'telephone' => $this->iglobal_order->phone,
77
+ 'region' => $this->iglobal_order->state,
78
+ 'region_id' => $region->getId(),
79
+ 'country_id' => $this->iglobal_order->countryCode,
80
+ 'company' => '',//$this->iglobal_order->company,
81
+ );
82
+
83
+ if (!empty($this->iglobal_order->billingAddress1)) {
84
+ $_nameBilling = explode(' ', $this->iglobal_order->billingName, 2);
85
+ if ($this->iglobal_order->testOrder) {
86
+ $name_first_billing = "TEST ORDER! DO NOT SHIP! - " . array_shift($_nameBilling);
87
+ $name_last_billing = array_pop($_nameBilling);
88
+ } else {
89
+ $name_first_billing = array_shift($_nameBilling);
90
+ $name_last_billing = array_pop($_nameBilling);
91
+ }
92
+
93
+ $streetBilling = $this->iglobal_order->billingAddress1;
94
+ if ($this->iglobal_order->billingAddress2) {
95
+ $streetBilling = array($streetBilling, $this->iglobal_order->billingAddress2);
96
+ }
97
+
98
+ $billingAddressData = array(
99
+ 'firstname' => $name_first_billing,
100
+ 'lastname' => $name_last_billing,
101
+ 'street' => $streetBilling,
102
+ 'city' => $this->iglobal_order->billingCity,
103
+ 'postcode' => $this->iglobal_order->billingZip,
104
+ 'telephone' => $this->iglobal_order->billingPhone,
105
+ 'region' => $this->iglobal_order->state,
106
+ 'region_id' => $region->getId(),
107
+ 'country_id' => $this->iglobal_order->billingCountryCode,
108
+ );
109
+
110
+ } else {
111
+ $billingAddressData = $addressData;
112
+ }
113
+
114
+ if (Mage::getStoreConfig('iglobal_integration/igjq/iglogging'))
115
+ {
116
+ Mage::log('address data for order {$this->iglobal_order_id}: ' . print_r($addressData, true), null, 'iglobal.log', true);
117
+ Mage::log('billing address data for order {$this->iglobal_order_id}: ' . print_r($billingAddressData, true), null, 'iglobal.log', true);
118
+ }
119
+
120
+ $this->quote->getBillingAddress()->addData($billingAddressData);
121
+ $shippingAddress = $this->quote->getShippingAddress()->addData($addressData);
122
+ return $shippingAddress;
123
+ }
124
+
125
+ protected function setItems()
126
+ {
127
+ // @todo pull in the item details in case they have changed.
128
+ }
129
+
130
+ protected function setShipping($shippingAddress)
131
+ {
132
+ //Figure out shipping carrier name etc.
133
+ $shippers = [
134
+ 'DHL_EXPRESS' => ['DHL', 'Express - iGlobal'],
135
+ 'DHL_GLOBAL_MAIL'=> ['DHL', 'Global Mail - iGlobal'],
136
+ 'FEDEX_ECONOMY'=> ['FedExl', 'Economy - iGlobal'],
137
+ 'FEDEX_GROUND'=> ['FedEx', 'Ground - iGlobal'],
138
+ 'FEDEX_PRIORITY'=> ['FedEx', 'Priority - iGlobal'],
139
+ 'UPS_EXPEDITED'=> ['UPS', 'Expedited - iGlobal'],
140
+ 'UPS_EXPRESS'=> ['UPS', 'Express - iGlobal'],
141
+ 'UPS_EXPRESS_SAVER' => ['UPS', 'Express Saver - iGlobal'],
142
+ 'UPS_GROUND' => ['UPS', 'Canada Ground - iGlobal'],
143
+ 'UPS_STANDARD'=> ['UPS', 'Canada Standard - iGlobal'],
144
+ 'USPS_FIRST_CLASS_MAIL_INTERNATIONAL'=> ['USPS', 'First Class Mail, International - iGlobal'],
145
+ 'USPS_PRIORITY_MAIL_EXPRESS_INTERNATIONAL'=> ['USPS', 'Priority Mail Express, International - iGlobal'],
146
+ 'USPS_PRIORITY_MAIL_INTERNATIONAL'=> ['USPS', 'Priority Mail, International - iGlobal'],
147
+ 'APC_EXPEDITED_MAIL'=> ['UPS', 'APC Expedited 3-5 Days - iGlobal'],
148
+ 'APC_PRIORITY_MAIL'=> ['UPS', 'APC Priority Mail 4-9 Days - iGlobal'],
149
+ 'CANADA_POST_EXPEDITED'=> ['UPS', 'Canada Post Expedited - iGlobal'],
150
+ 'FEDEX_IPD'=> ['UPS', 'FedEx IPD - iGlobal'],
151
+ 'UPS_2ND_DAY_AIR'=> ['UPS', 'UPS 2 Day Air - iGlobal'],
152
+ 'UPS_3_DAY_AIR'=> ['UPS', 'UPS 3 Day Air - iGlobal'],
153
+ 'UPS_FREIGHT'=> ['UPS', 'UPS Freight - iGlobal'],
154
+ 'UPS_MAIL_INNOVATIONS'=> ['UPS', 'Bodyguardz - UPS Mail Innovations - iGlobal'],
155
+ 'UPS_NEXT_DAY_AIR_SAVER'=>['UPS', 'UPS Next Day Air Saver - iGlobal'],
156
+ 'UPS_WORLDEASE'=> ['UPS', 'UPS WorldEase - iGlobal'],
157
+ 'USPS_EPACKET'=> ['UPS', 'USPS ePacket - iGlobal'],
158
+ 'USPS_EXPRESS_1'=> ['UPS', 'Express 1 Mail - iGlobal'],
159
+ 'USPS_IPA'=> ['UPS', 'USPS IPA - iGlobal'],
160
+ 'LANDMARK_LGINTREGU' => ['iGlobal', 'Landmark'],
161
+ 'LANDMARK_LGINTSTD' => ['iGlobal', 'Landmark'],
162
+ 'LANDMARK_LGINTSTDU' => ['iGlobal', 'Landmark'],
163
+ 'MSI_PARCEL' => ['iGlobal', 'Landmark'],
164
+ 'MSI_PRIORITY' => ['iGlobal', 'Landmark'],
165
+ 'default' => ['iGlobal', 'International Shipping'],
166
+ ];
167
+ $carrierMethod = $this->iglobal_order->shippingCarrierServiceLevel;
168
+ if (!isset($shippers[$carrierMethod]))
169
+ {
170
+ $carrierMethod = 'default';
171
+ }
172
+ $shipper = $shippers[$carrierMethod];
173
+
174
+ //Add things to the register so they can be used by the shipping method
175
+ Mage::register('shipping_cost', $this->iglobal_order->shippingTotal);
176
+ Mage::register('shipping_carriertitle', $shipper[0]);
177
+ Mage::register('shipping_methodtitle', $shipper[1]);
178
+ $shippingAddress->setCollectShippingRates(true)
179
+ ->collectShippingRates()
180
+ ->setShippingMethod('excellence_excellence');
181
+ return $shippingAddress;
182
+ }
183
+
184
+ protected function setPayment($address)
185
+ {
186
+ $address->setPaymentMethod('iGlobalCreditCard');
187
+
188
+ //updates payment type in Magento Admin area
189
+ $paymentMethod = $this->iglobal_order->paymentProcessing->paymentGateway;
190
+ if($paymentMethod === 'iGlobal_CC'){
191
+ $paymentType = 'iGlobalCreditCard';
192
+ } else if ($paymentMethod === 'iGlobal PayPal') {
193
+ $paymentType = 'iGlobalPaypal';
194
+ } else {
195
+ $paymentType = 'iGlobal';
196
+ }
197
+
198
+ $this->quote->getPayment()->importData(array('method' => $paymentType));
199
+ }
200
+
201
+ protected function createOrder()
202
+ {
203
+
204
+ $this->quote->collectTotals()->save();
205
+ $this->quote->setIsActive(0)->save();
206
+
207
+ $service = Mage::getModel('stores/service_quote', $this->quote);
208
+ $service->submitAll();
209
+ $order = $service->getOrder();
210
+
211
+ // cleaning up
212
+ Mage::getSingleton('checkout/session')->clear();
213
+
214
+ $id = $order->getEntityId();
215
+
216
+ if (!Mage::helper('sales')->canSendNewOrderEmail($storeId) && Mage::getStoreConfig('iglobal_integration/apireqs/send_order_email')) {
217
+ $order->sendNewOrderEmail();
218
+ }
219
+ Mage::getSingleton('checkout/session')->setLastOrderId($order->getId());
220
+ Mage::getSingleton('checkout/session')->setLastRealOrderId($order->getIncrementId());
221
+
222
+
223
+ $transId = Mage::getSingleton('checkout/session')->getLastRealOrderId($order->getIncrementId());
224
+ //Save Order Invoice as paid
225
+ $commentMessage = 'Order automatically imported from iGlobal order ID: '. $this->iglobal_order_id;
226
+
227
+ try {
228
+ $order = Mage::getModel("sales/order")->load($id);
229
+ //add trans ID
230
+ $transaction_id = '34234234234'; //todo: this needs to be set dynamically
231
+ $transaction = Mage::getModel('sales/order_payment_transaction');
232
+ $transaction->setOrderPaymentObject($order->getPayment());
233
+ $transaction->setTxnType(Mage_Sales_Model_Order_Payment_Transaction::TYPE_AUTH);
234
+ $transaction->setTxnId($transaction_id);
235
+ $transaction->save();
236
+
237
+ $invoices = Mage::getModel('sales/order_invoice')->getCollection()->addAttributeToFilter('order_id', array('eq'=>$order->getId()));
238
+ $invoices->getSelect()->limit(1);
239
+ if ((int)$invoices->count() == 0 && $order->getState() == Mage_Sales_Model_Order::STATE_NEW) {
240
+ if(!$order->canInvoice()) {
241
+ $order->addStatusHistoryComment($commentMessage, false);
242
+ $order->addStatusHistoryComment('iGlobal: Order cannot be invoiced', false);
243
+ $order->save();
244
+ } else {
245
+ $order->addStatusHistoryComment($commentMessage, false);
246
+ $invoice = Mage::getModel('sales/service_order', $order)->prepareInvoice();
247
+ $invoice->setRequestedCaptureCase(Mage_Sales_Model_Order_Invoice::CAPTURE_OFFLINE);
248
+ $invoice->register();
249
+ $invoice->getOrder()->setCustomerNoteNotify(false);
250
+ $invoice->getOrder()->setIsInProcess(true);
251
+ $order->addStatusHistoryComment('Automatically INVOICED by iGlobal', false);
252
+ $transactionSave = Mage::getModel('core/resource_transaction')
253
+ ->addObject($invoice)
254
+ ->addObject($invoice->getOrder());
255
+ $transactionSave->save();
256
+ }
257
+ }
258
+ } catch (Exception $e) {
259
+ $order->addStatusHistoryComment('iGlobal Invoicer: Exception occurred during automatically invoicing. Exception message: '.$e->getMessage(), false);
260
+ $order->save();
261
+ }
262
+ $tableName = Mage::getSingleton("core/resource")->getTableName("sales_flat_order");
263
+ if ($this->iglobal_order->testOrder) {
264
+ //Set the international_order flag and the ig_order_number on the order and mark as a test order
265
+ $query = "UPDATE `" . $tableName . "` SET `international_order` = 1, `ig_order_number` = '{$this->iglobal_order_id}', `iglobal_test_order` = 1 WHERE `entity_id` = '{$id}'";
266
+ Mage::getSingleton('core/resource')->getConnection('core_write')->query($query);
267
+ } else {
268
+ //Set the international_order flag and the ig_order_number on the order
269
+ $query = "UPDATE `" . $tableName . "` SET `international_order` = 1, `ig_order_number` = '{$this->iglobal_order_id}' WHERE `entity_id` = '{$id}'";
270
+ Mage::getSingleton('core/resource')->getConnection('core_write')->query($query);
271
+ }
272
+
273
+ //Send the magento id to iGlobal
274
+ $this->rest->sendMagentoOrderId($this->iglobal_order_id, $id);
275
+ return $order;
276
+ }
277
+
278
+
279
+ }
app/code/community/Iglobal/Stores/Model/Rest.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Iglobal_Stores_Model_Rest extends Mage_Core_Model_Abstract
4
+ {
5
+ protected $_entryPoint = 'https://api.iglobalstores.com/v1/';
6
+ protected $_store = 3; // default store ID
7
+ protected $_key = '';
8
+
9
+ protected function _construct()
10
+ {
11
+ //set store ID
12
+ if (Mage::getStoreConfig('iglobal_integration/apireqs/iglobalid')) {
13
+ $this->_store = Mage::getStoreConfig('iglobal_integration/apireqs/iglobalid');
14
+ }
15
+ //Set API Key
16
+ if (Mage::getStoreConfig('iglobal_integration/apireqs/secret')) {
17
+ $this->_key = Mage::getStoreConfig('iglobal_integration/apireqs/secret');
18
+ }
19
+ }
20
+
21
+ protected function callApi($path, $data, $headers=array())
22
+ {
23
+ $client = new Zend_Http_Client($this->_entryPoint . $path);
24
+ $data = json_encode(array_merge($data, array('store' => $this->_store, 'secret' => $this->_key)));
25
+ $response = $client
26
+ ->setRawData($data, 'application/json')
27
+ ->setHeaders($headers)
28
+ ->request('POST');
29
+
30
+ if ($response->isSuccessful())
31
+ {
32
+ return json_decode($response->getBody());
33
+ }
34
+ return false;
35
+
36
+ }
37
+
38
+ public function getAllOrders()
39
+ {
40
+ $data = array('sinceDate'=>'20100101');
41
+ return $this->callApi('orderNumbers', $data);
42
+ }
43
+
44
+ public function getAllOrdersSinceDate($data)
45
+ {
46
+ $data = array('sinceDate'=>$data);
47
+ return $this->callApi('orderNumbers', $data);
48
+ }
49
+
50
+ public function getOrder($order)
51
+ {
52
+ $data = array('orderId' => $order);
53
+ return $this->callApi('orderDetail', $data);
54
+ }
55
+
56
+ public function sendMagentoOrderId($igc_order_id, $magento_order_id) {
57
+ $data = array('orderId' => $igc_order_id, 'merchantOrderId' => $magento_order_id);
58
+ return $this->callApi('updateMerchantOrderId', $data);
59
+ }
60
+
61
+ public function createTempCart(array $data)
62
+ {
63
+ return $this->callApi('createTempCart', $data);
64
+ }
65
+
66
+ public function getRegionId($countryId, $region, $orderid)
67
+ {
68
+ $data = array('countryCode'=> $countryId,'region'=> $region, 'orderId' => $orderid);
69
+ return $this->callApi(
70
+ 'magento-region',
71
+ $data,
72
+ ["serviceToken" => "31ae7155-5b9e-461f-8353-9a8c3f8ae35974ffec3a-88dc-4acb-8420-270df7967338"]
73
+ );
74
+ }
75
+ }
app/code/community/Iglobal/Stores/Model/Rest/Order.php DELETED
@@ -1,86 +0,0 @@
1
- <?php
2
-
3
- class Iglobal_Stores_Model_Rest_Order extends Mage_Core_Model_Abstract
4
- {
5
- protected $_entryPoint = null;
6
-
7
- protected function _construct()
8
- {
9
- //set store ID
10
- if (Mage::getStoreConfig('iglobal_integration/apireqs/iglobalid')){
11
- //use custom ID
12
- $this->_store = Mage::getStoreConfig('iglobal_integration/apireqs/iglobalid');
13
- } else {
14
- //default store ID
15
- $this->_store = 3;
16
- }
17
-
18
- //Set API Key
19
- if (Mage::getStoreConfig('iglobal_integration/apireqs/secret')){
20
- //use custom key
21
- $this->_key = Mage::getStoreConfig('iglobal_integration/apireqs/secret');
22
- } else {
23
- //default key
24
- $this->_key = '';
25
- }
26
-
27
- //set entryPoint
28
- $this->_entryPoint = 'https://checkout.iglobalstores.com';
29
-
30
- }
31
-
32
- protected function getRestClient()
33
- {
34
- return new Zend_Rest_Client($this->_entryPoint);
35
- }
36
-
37
- protected function addCredentials(array $data)
38
- {
39
- return array_merge($data, array('store'=>$this->_store, 'secret'=>$this->_key));
40
- }
41
-
42
- public function getOrders(array $data)
43
- {
44
- $data = array_merge($data, array('operation'=>'orderNumbers'));
45
- $client = $this->getRestClient();
46
- $result = $client->restPost('/iglobalstores/services/OrderRestService/v1.06', $this->addCredentials($data))->getBody();
47
- return json_decode(json_encode((array) simplexml_load_string($result)),1);
48
- }
49
-
50
- public function getAllOrders()
51
- {
52
- $data = array('operation'=>'orderNumbers', 'sinceDate'=>'20100101');
53
- $client = $this->getRestClient();
54
- $result = $client->restPost('/iglobalstores/services/OrderRestService/v1.06', $this->addCredentials($data))->getBody();
55
- return json_decode(json_encode((array) simplexml_load_string($result)),1);
56
- }
57
-
58
- public function getAllOrdersSinceDate($data)
59
- {
60
- $data = array('operation'=>'orderNumbers', 'sinceDate'=>$data);
61
- $client = $this->getRestClient();
62
- $result = $client->restPost('/iglobalstores/services/OrderRestService/v1.06', $this->addCredentials($data))->getBody();
63
- return json_decode(json_encode((array) simplexml_load_string($result)),1);
64
- }
65
-
66
- public function getOrder($order)
67
- {
68
- $data = array('operation'=>'orderDetail', 'orderId' => $order);
69
- $client = $this->getRestClient();
70
- $result = $client->restPost('iglobalstores/services/OrderRestService/v1.06', $this->addCredentials($data))->getBody();
71
- //echo "Rest result: <br />";
72
- //Zend_Debug::dump($result);
73
- //Mage::log("The rest result for order {$order}:" . Zend_Debug::dump($result), 'mattscustom.log', true);
74
- //Mage::log("The rest result for order {$order}:" . print_r($result, true), null, 'mattscustom.log', true);
75
- //$result = mb_convert_encoding($result, "HTML-ENTITIES", "UTF-8");
76
- return json_decode(json_encode((array) simplexml_load_string($result)),1);
77
- }
78
-
79
- public function sendMagentoOrderId($igc_order_id, $magento_order_id) {
80
- $data = array('operation'=>'updateMerchantOrderId', 'orderId' => $igc_order_id, 'merchantOrderId' => $magento_order_id);
81
- $client = $this->getRestClient();
82
- $client->restPost('iglobalstores/services/OrderRestService', $this->addCredentials($data))->getBody();
83
- }
84
-
85
- }
86
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/Iglobal/Stores/Model/Rest/Region.php DELETED
@@ -1,42 +0,0 @@
1
- <?php
2
-
3
- class Iglobal_Stores_Model_Rest_Region extends Mage_Core_Model_Abstract
4
- {
5
- protected $_entryPoint = null;
6
-
7
- protected function _construct()
8
- {
9
-
10
-
11
- //Set Service Key
12
- $this -> _key = '{31ae7155-5b9e-461f-8353-9a8c3f8ae35974ffec3a-88dc-4acb-8420-270df7967338}';
13
-
14
- //set entryPoint
15
- $this->_entryPoint = 'https://api.iglobalstores.com/v1/magento-region';
16
-
17
- }
18
-
19
- protected function getRestClient()
20
- {
21
- return new Zend_Http_Client($this->_entryPoint);
22
- }
23
-
24
- protected function addCredentials(array $data)
25
- {
26
- return array_merge($data, array('serviceToken'=>$this->_key));
27
- }
28
-
29
- public function getRegionId($countryId, $region, $order)
30
- {
31
- $data = array('countryCode'=> $countryId,'region'=> $region, 'orderId' => $order);
32
- $client = $this->getRestClient();
33
- $client->setRawData(json_encode($data), 'application/json')->setHeaders("serviceToken:31ae7155-5b9e-461f-8353-9a8c3f8ae35974ffec3a-88dc-4acb-8420-270df7967338")->request('POST');
34
- $result = $client->request()->getBody();
35
- $resArray = json_decode($result, true);
36
- //Mage::log("The region rest result for order {$order}:" . Zend_Debug::dump($result), 'mattscustom.log', true);
37
- //Mage::log("The region rest result for order {$order}:" . print_r($result, true), null, 'mattscustom.log', true);
38
- return $resArray;
39
- }
40
-
41
- }
42
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/Iglobal/Stores/Model/Sales/Quote/Address/Total/Fee.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Iglobal_Stores_Model_Sales_Quote_Address_Total_Fee extends Mage_Sales_Model_Quote_Address_Total_Tax
3
+ {
4
+ public function collect(Mage_Sales_Model_Quote_Address $address)
5
+ {
6
+
7
+ $fee = Mage::registry('duty_tax');
8
+ if ($fee) {
9
+ // Do not override taxes if there is no duty_tax set.
10
+ $this->_setAddress($address);
11
+ $this->_setAmount($fee);
12
+ $this->_setBaseAmount($fee);
13
+ } else {
14
+ parent::collect($address);
15
+ }
16
+ }
17
+ }
app/code/community/Iglobal/Stores/controllers/CheckoutController.php CHANGED
@@ -1,43 +1,43 @@
1
- <?php
2
- //
3
- // Load the iGlobal hosted checkout in an iframe, cause it's awesome
4
- //
5
- class Iglobal_Stores_CheckoutController extends Mage_Core_Controller_Front_Action
6
- {
7
- public function indexAction()
8
- {
9
- //todo: add a check to see if they are domestic and then redirect to domestic checkout
10
-
11
-
12
- $cartQty = (int) Mage::getModel('checkout/cart')->getQuote()->getItemsQty();
13
- if (!$cartQty) {
14
- $this->_redirect('checkout/cart');
15
- die();
16
- //echo "The Cart is Empty";
17
- }
18
-
19
- $tempcart = Mage::getModel('stores/international_international');
20
-
21
- if (!$tempcart) {
22
- echo "No tempcart!";
23
- die();
24
- }
25
-
26
- $cartId = $tempcart->getTempCartId();
27
-
28
- // echo out the html that will build the iframe
29
- $domCode = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>International Checkout</title> <style type="text/css"> body, html {margin: 0; padding: 0; height: 100%; overflow: hidden;} #content{position:absolute; left: 0; right: 0; bottom: 0; top: 0px;} </style></head><body><div id="content"><iframe width="100%" height="100%" frameborder="0" src="';
30
- //this is where we build the url for the checkout
31
- $subdomain = (Mage::getStoreConfig('iglobal_integration/apireqs/igsubdomain') ? Mage::getStoreConfig('iglobal_integration/apireqs/igsubdomain') : "checkout");
32
- $storeNumber = (Mage::getStoreConfig('iglobal_integration/apireqs/iglobalid') ? Mage::getStoreConfig('iglobal_integration/apireqs/iglobalid') : "3");
33
- $countryCode = (isset($_COOKIE['igCountry']) ? $_COOKIE['igCountry'] : "");
34
-
35
- $iframeUrl = 'https://' . $subdomain . '.iglobalstores.com/?store=' . $storeNumber . '&tempCartUUID=' . $cartId . '&country=' . $countryCode;
36
-
37
- $domCode = $domCode . $iframeUrl . '"/></div></body></html>';
38
-
39
- echo $domCode;
40
-
41
- }
42
-
43
  }
1
+ <?php
2
+ //
3
+ // Load the iGlobal hosted checkout in an iframe, cause it's awesome
4
+ //
5
+ class Iglobal_Stores_CheckoutController extends Mage_Core_Controller_Front_Action
6
+ {
7
+ public function indexAction()
8
+ {
9
+ //todo: add a check to see if they are domestic and then redirect to domestic checkout
10
+
11
+
12
+ $cartQty = (int) Mage::getModel('checkout/cart')->getQuote()->getItemsQty();
13
+ if (!$cartQty) {
14
+ $this->_redirect('checkout/cart');
15
+ die();
16
+ //echo "The Cart is Empty";
17
+ }
18
+
19
+ $tempcart = Mage::getModel('stores/international_international');
20
+
21
+ if (!$tempcart) {
22
+ echo "No tempcart!";
23
+ die();
24
+ }
25
+
26
+ $cartId = $tempcart->getTempCartId();
27
+
28
+ // echo out the html that will build the iframe
29
+ $domCode = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>International Checkout</title> <style type="text/css"> body, html {margin: 0; padding: 0; height: 100%; overflow: hidden;} #content{position:absolute; left: 0; right: 0; bottom: 0; top: 0px;} </style></head><body><div id="content"><iframe width="100%" height="100%" frameborder="0" src="';
30
+ //this is where we build the url for the checkout
31
+ $subdomain = (Mage::getStoreConfig('iglobal_integration/apireqs/igsubdomain') ? Mage::getStoreConfig('iglobal_integration/apireqs/igsubdomain') : "checkout");
32
+ $storeNumber = (Mage::getStoreConfig('iglobal_integration/apireqs/iglobalid') ? Mage::getStoreConfig('iglobal_integration/apireqs/iglobalid') : "3");
33
+ $countryCode = (isset($_COOKIE['igCountry']) ? $_COOKIE['igCountry'] : "");
34
+
35
+ $iframeUrl = 'https://' . $subdomain . '.iglobalstores.com/?store=' . $storeNumber . '&tempCartUUID=' . $cartId . '&country=' . $countryCode;
36
+
37
+ $domCode = $domCode . $iframeUrl . '"/></div></body></html>';
38
+
39
+ echo $domCode;
40
+
41
+ }
42
+
43
  }
app/code/community/Iglobal/Stores/controllers/InternationalController.php DELETED
@@ -1,32 +0,0 @@
1
-
2
- <?php
3
-
4
- class Iglobal_Stores_InternationalController extends Mage_Core_Controller_Front_Action
5
- {
6
- public function indexAction()
7
- {
8
- echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
9
- <html xmlns="http://www.w3.org/1999/xhtml">
10
- <head>
11
- <title>Test Layout</title>
12
- <style type="text/css">
13
- body, html
14
- {
15
- margin: 0; padding: 0; height: 100%; overflow: hidden;
16
- }
17
-
18
- #content
19
- {
20
- position:absolute; left: 0; right: 0; bottom: 0; top: 0px;
21
- }
22
- </style>
23
- </head>
24
- <body>
25
- <div id="content">
26
- <iframe width="100%" height="100%" frameborder="0" src="https://jessiesteele.iglobalstores.com/?store=324&tempCartUUID=e5fa40f6-758c-4b63-af09-0a99783c1609&country=AL" />
27
- </div>
28
- </body>
29
- </html> ';
30
- }
31
-
32
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/Iglobal/Stores/controllers/SuccessController.php CHANGED
@@ -1,386 +1,50 @@
1
- <?php
2
-
3
- class Iglobal_Stores_SuccessController extends Mage_Core_Controller_Front_Action
4
- {
5
- public function indexAction()
6
- {
7
-
8
- $_order = $this->getRequest()->getParam('orderId', null);
9
- try
10
- {
11
- $quote = Mage::getSingleton('checkout/session')->getQuote()->setStoreId(Mage::app()->getStore()->getId());
12
- $table = "sales_flat_order";
13
- $tableName = Mage::getSingleton("core/resource")->getTableName($table);
14
- $existsQuery = "SELECT `entity_id` FROM `" . $tableName. "` WHERE `ig_order_number` = '{$_order}'";
15
- $orderExists = Mage::getSingleton('core/resource')->getConnection('core_read')->fetchRow($existsQuery);
16
-
17
- if(!$_order || $orderExists) {
18
- header('Location: /');
19
- die();
20
- }
21
-
22
-
23
- $rest = Mage::getModel('stores/rest_order');
24
- $data = $rest->getOrder($_order);
25
- //Mage::log("the data in the controller for order {$_order}:" . print_r($data, true), null, 'mattscustom.log', true);
26
- //set ddp
27
- $quote->setFeeAmount($data['dutyTaxesTotal']);
28
-
29
- //set customer info
30
- $quote->setCustomerEmail($data['email']);
31
-
32
- $_name = explode(' ', $data['name'], 2);
33
- if ($data['testOrder'] == "true") {
34
- $name_first = "TEST ORDER! DO NOT SHIP! - " . array_shift($_name);
35
- $name_last = array_pop($_name);
36
- } else {
37
- $name_first = array_shift($_name);
38
- $name_last = array_pop($_name);
39
- }
40
-
41
- $quote->setCustomerFirstname($name_first);
42
- $quote->setCustomerLastname($name_last);
43
-
44
- $street = $data['address2'] ? array($data['address1'], $data['address2']) : $data['address1'];
45
-
46
- // to fix error with countries w/o zip codes
47
- if (is_array($data['zip'])){
48
- $igcZipCode = ' ';
49
- }else {
50
- $igcZipCode = $data['zip'];
51
- }
52
-
53
- $regionData = Mage::getModel('stores/rest_region');
54
- $regionReq = $rest->getRegionId($data['countryCode'], $data['state'], $_order);
55
- //Zend_Debug::dump($regionReq);
56
- echo $regionReq['magentoRegionId'];
57
- $mageRegion = $regionReq['magentoRegionId'];
58
-
59
- $addressData = array(
60
- 'firstname' => $name_first,
61
- 'lastname' => $name_last,
62
- 'street' => $street,
63
- 'city' => $data['city'],
64
- 'postcode' => $igcZipCode,
65
- 'telephone' => $data['phone'],
66
- //'region' => Mage::getModel('directory/region')->load($mageRegion)->getName(),
67
- 'region' => $data['state'],
68
- 'region_id' => $mageRegion,
69
- 'country_id' => $data['countryCode'],
70
- 'company' => '',//$data['company'],
71
- );
72
-
73
- $billingCheckVar = $data['billingAddress1'];
74
- if (!empty($billingCheckVar)){
75
- $_nameBilling = explode(' ', $data['billingName'], 2);
76
- if ($data['testOrder'] == "true") {
77
- $name_first_billing = "TEST ORDER! DO NOT SHIP! - " . array_shift($_nameBilling);
78
- $name_last_billing = array_pop($_nameBilling);
79
- } else {
80
- $name_first_billing = array_shift($_nameBilling);
81
- $name_last_billing = array_pop($_nameBilling);
82
- }
83
-
84
-
85
- $streetBilling = $data['billingAddress2'] ? array($data['billingAddress1'], $data['billingAddress2']) : $data['billingAddress1'];
86
-
87
- // to fix error with countries w/o zip codes
88
- if (is_array($data['billingZip'])){
89
- $igcZipCodeBilling = ' ';
90
- }else {
91
- $igcZipCodeBilling = $data['billingZip'];
92
- }
93
-
94
- $billingAddressData = array(
95
- 'firstname' => $name_first_billing,
96
- 'lastname' => $name_last_billing,
97
- 'street' => $streetBilling,
98
- 'city' => $data['billingCity'],
99
- 'postcode' => $igcZipCodeBilling,
100
- 'telephone' => $data['billingPhone'],
101
- //'region' => Mage::getModel('directory/region')->load($mageRegion)->getName(),
102
- 'region' => $data['state'],
103
- //'region_id' => $mageRegion,
104
- 'country_id' => $data['billingCountryCode'],
105
- );
106
-
107
- } else {
108
- $billingAddressData = $addressData;
109
- }
110
-
111
-
112
- Mage::log('address data for order {$_order}: ' . print_r($addressData, true), null, 'mattscustom.log', true);
113
-
114
- Mage::log('billing address data for order {$_order}: ' . print_r($billingAddressData, true), null, 'mattscustom.log', true);
115
-
116
- //Figure out shipping carrier name etc.
117
- $shippingRate = $data['shippingTotal'];
118
- $shippingCarrierMethod = $data['shippingCarrierServiceLevel'];
119
- switch ($shippingCarrierMethod) {
120
- case 'DHL_EXPRESS' :
121
- $shipper = 'excellence_excellence';
122
- $shippingCarrierTitle = 'DHL';
123
- $shippingMethodTitle = 'Express - iGlobal';
124
- break;
125
- case 'DHL_GLOBAL_MAIL' :
126
- $shipper = 'excellence_excellence';
127
- $shippingCarrierTitle = 'DHL';
128
- $shippingMethodTitle = 'Global Mail - iGlobal';
129
- break;
130
- case 'FEDEX_ECONOMY' :
131
- $shipper = 'excellence_excellence';
132
- $shippingCarrierTitle = 'FedExl';
133
- $shippingMethodTitle = 'Economy - iGlobal';
134
- break;
135
- case 'FEDEX_GROUND' :
136
- $shipper = 'excellence_excellence';
137
- $shippingCarrierTitle = 'FedEx';
138
- $shippingMethodTitle = 'Ground - iGlobal';
139
- break;
140
- case 'FEDEX_PRIORITY' :
141
- $shipper = 'excellence_excellence';
142
- $shippingCarrierTitle = 'FedEx';
143
- $shippingMethodTitle = 'Priority - iGlobal';
144
- break;
145
- case 'UPS_EXPEDITED' :
146
- $shipper = 'excellence_excellence';
147
- $shippingCarrierTitle = 'UPS';
148
- $shippingMethodTitle = 'Expedited - iGlobal';
149
- break;
150
- case 'UPS_EXPRESS' :
151
- $shipper = 'excellence_excellence';
152
- $shippingCarrierTitle = 'UPS';
153
- $shippingMethodTitle = 'Express - iGlobal';
154
- break;
155
- case 'UPS_EXPRESS_SAVER':
156
- $shipper = 'excellence_excellence';
157
- $shippingCarrierTitle = 'UPS';
158
- $shippingMethodTitle = 'Express Saver - iGlobal';
159
- break;
160
- case 'UPS_GROUND':
161
- $shipper = 'excellence_excellence';
162
- $shippingCarrierTitle = 'UPS';
163
- $shippingMethodTitle = 'Canada Ground - iGlobal';
164
- break;
165
- case 'UPS_STANDARD' :
166
- $shipper = 'excellence_excellence';
167
- $shippingCarrierTitle = 'UPS';
168
- $shippingMethodTitle = 'Canada Standard - iGlobal';
169
- break;
170
- case 'USPS_FIRST_CLASS_MAIL_INTERNATIONAL' :
171
- $shipper = 'excellence_excellence';
172
- $shippingCarrierTitle = 'USPS';
173
- $shippingMethodTitle = 'First Class Mail, International - iGlobal';
174
- break;
175
- case 'USPS_PRIORITY_MAIL_EXPRESS_INTERNATIONAL' :
176
- $shipper = 'excellence_excellence';
177
- $shippingCarrierTitle = 'USPS';
178
- $shippingMethodTitle = 'Priority Mail Express, International - iGlobal';
179
- break;
180
- case 'USPS_PRIORITY_MAIL_INTERNATIONAL' :
181
- $shipper = 'excellence_excellence';
182
- $shippingCarrierTitle = 'USPS';
183
- $shippingMethodTitle = 'Priority Mail, International - iGlobal';
184
- break;
185
- case 'APC_EXPEDITED_MAIL' :
186
- $shipper = 'excellence_excellence';
187
- $shippingCarrierTitle = 'UPS';
188
- $shippingMethodTitle = 'APC Expedited 3-5 Days - iGlobal';
189
- break;
190
- case 'APC_PRIORITY_MAIL' :
191
- $shipper = 'excellence_excellence';
192
- $shippingCarrierTitle = 'UPS';
193
- $shippingMethodTitle = 'APC Priority Mail 4-9 Days - iGlobal';
194
- break;
195
- case 'CANADA_POST_EXPEDITED' :
196
- $shipper = 'excellence_excellence';
197
- $shippingCarrierTitle = 'UPS';
198
- $shippingMethodTitle = 'Canada Post Expedited - iGlobal';
199
- break;
200
- case 'FEDEX_IPD' :
201
- $shipper = 'excellence_excellence';
202
- $shippingCarrierTitle = 'UPS';
203
- $shippingMethodTitle = 'FedEx IPD - iGlobal';
204
- break;
205
- case 'UPS_2ND_DAY_AIR' :
206
- $shipper = 'excellence_excellence';
207
- $shippingCarrierTitle = 'UPS';
208
- $shippingMethodTitle = 'UPS 2 Day Air - iGlobal';
209
- break;
210
- case 'UPS_3_DAY_AIR' :
211
- $shipper = 'excellence_excellence';
212
- $shippingCarrierTitle = 'UPS';
213
- $shippingMethodTitle = 'UPS 3 Day Air - iGlobal';
214
- break;
215
- case 'UPS_FREIGHT' :
216
- $shipper = 'excellence_excellence';
217
- $shippingCarrierTitle = 'UPS';
218
- $shippingMethodTitle = 'UPS Freight - iGlobal';
219
- break;
220
- case 'UPS_MAIL_INNOVATIONS' :
221
- $shipper = 'excellence_excellence';
222
- $shippingCarrierTitle = 'UPS';
223
- $shippingMethodTitle = 'Bodyguardz - UPS Mail Innovations - iGlobal';
224
- break;
225
- case 'UPS_NEXT_DAY_AIR_SAVER' :
226
- $shipper = 'excellence_excellence';
227
- $shippingCarrierTitle = 'UPS';
228
- $shippingMethodTitle = 'UPS Next Day Air Saver - iGlobal';
229
- break;
230
- case 'UPS_WORLDEASE' :
231
- $shipper = 'excellence_excellence';
232
- $shippingCarrierTitle = 'UPS';
233
- $shippingMethodTitle = 'UPS WorldEase - iGlobal';
234
- break;
235
- case 'USPS_EPACKET' :
236
- $shipper = 'excellence_excellence';
237
- $shippingCarrierTitle = 'UPS';
238
- $shippingMethodTitle = 'USPS ePacket - iGlobal';
239
- break;
240
- case 'USPS_EXPRESS_1' :
241
- $shipper = 'excellence_excellence';
242
- $shippingCarrierTitle = 'UPS';
243
- $shippingMethodTitle = 'Express 1 Mail - iGlobal';
244
- break;
245
- case 'USPS_IPA' :
246
- $shipper = 'excellence_excellence';
247
- $shippingCarrierTitle = 'UPS';
248
- $shippingMethodTitle = 'USPS IPA - iGlobal';
249
- break;
250
- case 'LANDMARK_LGINTREGU':
251
- case 'LANDMARK_LGINTSTD':
252
- case 'LANDMARK_LGINTSTDU':
253
- case 'MSI_PARCEL':
254
- case 'MSI_PRIORITY':
255
- $shipper = 'excellence_excellence';
256
- $shippingCarrierTitle = 'iGlobal';
257
- $shippingMethodTitle = 'Landmark';
258
- break;
259
- default:
260
- $shipper = 'excellence_excellence';
261
- $shippingCarrierTitle = 'iGlobal';
262
- $shippingMethodTitle = 'International Shipping';
263
- }
264
-
265
- //Add things to the register so they can be used by the shipping method
266
- Mage::register('shipping_cost', $shippingRate);
267
- Mage::register('shipping_carriertitle', $shippingCarrierTitle);
268
- Mage::register('shipping_methodtitle', $shippingMethodTitle);
269
-
270
- //set shipping info
271
- $billingAddress = $quote->getBillingAddress()->addData($billingAddressData);
272
- $shippingAddress = $quote->getShippingAddress()->addData($addressData);
273
- $shippingAddress->setCollectShippingRates(true)->collectShippingRates()
274
- ->setShippingMethod('excellence_excellence')
275
- ->setPaymentMethod('iGlobalCreditCard');
276
-
277
-
278
- //updates payment type in Magento Admin area
279
- $paymentMethod = $data ['paymentProcessing'] ['paymentGateway'];
280
- if($paymentMethod === 'iGlobal_CC'){
281
- $paymentType = 'iGlobalCreditCard';
282
- } else if ($paymentMethod === 'iGlobal PayPal') {
283
- $paymentType = 'iGlobalPaypal';
284
- } else {
285
- $paymentType = 'iGlobal';
286
- };
287
-
288
- $quote->getPayment()->importData(array('method' => $paymentType));
289
-
290
- $quote->collectTotals()->save();
291
- $quote->setIsActive(0)->save();
292
-
293
- $service = Mage::getModel('stores/service_quote', $quote);
294
- $service->submitAll();
295
- $order = $service->getOrder();
296
-
297
-
298
- // cleaning up
299
- Mage::getSingleton('checkout/session')->clear();
300
-
301
- $id = $order->getEntityId();
302
-
303
- Mage::getSingleton('checkout/session')->setLastOrderId($order->getId());
304
- Mage::getSingleton('checkout/session')->setLastRealOrderId($order->getIncrementId());
305
-
306
-
307
- $transId = Mage::getSingleton('checkout/session')->getLastRealOrderId($order->getIncrementId());
308
-
309
-
310
- //Save Order Invoice as paid
311
- $commentMessage = 'Order automatically imported from iGlobal order ID: '. $_order;
312
-
313
- try {
314
- $order = Mage::getModel("sales/order")->load($id);
315
- //add trans ID
316
- $transaction_id = '34234234234'; //todo: this needs to be set dynamically
317
- $transaction = Mage::getModel('sales/order_payment_transaction');
318
- $transaction->setOrderPaymentObject($order->getPayment());
319
- $transaction->setTxnType(Mage_Sales_Model_Order_Payment_Transaction::TYPE_AUTH);
320
- $transaction->setTxnId($transaction_id);
321
- $transaction->save();
322
-
323
- $invoices = Mage::getModel('sales/order_invoice')->getCollection()->addAttributeToFilter('order_id', array('eq'=>$order->getId()));
324
- $invoices->getSelect()->limit(1);
325
- if ((int)$invoices->count() == 0 && $order->getState() == Mage_Sales_Model_Order::STATE_NEW) {
326
- if(!$order->canInvoice()) {
327
- $order->addStatusHistoryComment($commentMessage, false);
328
- $order->addStatusHistoryComment('iGlobal: Order cannot be invoiced', false);
329
- $order->save();
330
- } else {
331
- $order->addStatusHistoryComment($commentMessage, false);
332
- $invoice = Mage::getModel('sales/service_order', $order)->prepareInvoice();
333
- $invoice->setRequestedCaptureCase(Mage_Sales_Model_Order_Invoice::CAPTURE_OFFLINE);
334
- $invoice->register();
335
- $invoice->getOrder()->setCustomerNoteNotify(false);
336
- $invoice->getOrder()->setIsInProcess(true);
337
- $order->addStatusHistoryComment('Automatically INVOICED by iGlobal', false);
338
- $transactionSave = Mage::getModel('core/resource_transaction')
339
- ->addObject($invoice)
340
- ->addObject($invoice->getOrder());
341
- $transactionSave->save();
342
- }
343
- }
344
- } catch (Exception $e) {
345
- $order->addStatusHistoryComment('iGlobal Invoicer: Exception occurred during automatically invoicing. Exception message: '.$e->getMessage(), false);
346
- $order->save();
347
- }
348
-
349
- if ($data['testOrder'] == 'true') {
350
- //Set the international_order flag and the ig_order_number on the order and mark as a test order
351
- $query = "UPDATE `" . $tableName . "` SET `international_order` = 1, `ig_order_number` = '{$_order}', `iglobal_test_order` = 1 WHERE `entity_id` = '{$id}'";
352
- Mage::getSingleton('core/resource')->getConnection('core_write')->query($query);
353
- } else {
354
- //Set the international_order flag and the ig_order_number on the order
355
- $query = "UPDATE `" . $tableName . "` SET `international_order` = 1, `ig_order_number` = '{$_order}' WHERE `entity_id` = '{$id}'";
356
- Mage::getSingleton('core/resource')->getConnection('core_write')->query($query);
357
- }
358
-
359
- //Send the magento id to iGlobal
360
- $rest->sendMagentoOrderId($_order, $id);
361
-
362
- }
363
- catch(Exception $e)
364
- {
365
- $adminEmail = false;
366
- //die($e);
367
- if (Mage::getStoreConfig('iglobal_integration/apireqs/admin_email')) {
368
- $adminEmail = Mage::getStoreConfig('iglobal_integration/apireqs/admin_email');
369
- }
370
- mail('monitoring@iglobalstores.com', 'Magento Integration Error - International order failed to import', 'International order# '. $_order .'.'. ' Exception Message: '.$e->getMessage());
371
- mail('magentomissedorders@iglobalstores.com', 'Magento Integration Error - International order failed to import', 'International order# '. $_order .'.'. ' Exception Message: '.$e->getMessage());
372
- if ($adminEmail) {
373
- mail($adminEmail, 'iGlobal Import Error - International order failed to import', 'iGlobal International order# '. $_order . " failed to import properly. We've already received notice of the problem, and are probably working on it as you read this. Until then, you may manually enter the order, or give us a call for help at 1-800-942-0721." );
374
- }
375
- Mage::log("International order #{$_order} failed to import!" .$e, Zend_Log::ERR, 'iglobal.log', true);
376
- }
377
-
378
- $this->loadLayout();
379
-
380
- $lastOrderId = Mage::getSingleton('checkout/session')->getLastOrderId();
381
- Mage::dispatchEvent('checkout_onepage_controller_success_action', array('order_ids' => array($lastOrderId)));
382
-
383
- $this->renderLayout();
384
- }
385
-
386
- }
1
+ <?php
2
+
3
+ class Iglobal_Stores_SuccessController extends Mage_Core_Controller_Front_Action
4
+ {
5
+ public function indexAction()
6
+ {
7
+
8
+
9
+ $_order = $this->getRequest()->getParam('orderId', null);
10
+ try
11
+ {
12
+ $quote = Mage::getSingleton('checkout/session')->getQuote()->setStoreId(Mage::app()->getStore()->getId());
13
+ $table = "sales_flat_order";
14
+ $tableName = Mage::getSingleton("core/resource")->getTableName($table);
15
+ $existsQuery = "SELECT `entity_id` FROM `" . $tableName. "` WHERE `ig_order_number` = '{$_order}'";
16
+ $orderExists = Mage::getSingleton('core/resource')->getConnection('core_read')->fetchRow($existsQuery);
17
+
18
+ if(!$_order || $orderExists) {
19
+ header('Location: /');
20
+ die();
21
+ }
22
+
23
+ $order = Mage::getModel('stores/order');
24
+ $order->setQuote($quote);
25
+ $order->processOrder($_order);
26
+ }
27
+ catch(Exception $e)
28
+ {
29
+ $adminEmail = false;
30
+ //die($e);
31
+ if (Mage::getStoreConfig('iglobal_integration/apireqs/admin_email')) {
32
+ $adminEmail = Mage::getStoreConfig('iglobal_integration/apireqs/admin_email');
33
+ }
34
+ mail('monitoring@iglobalstores.com', 'Magento Integration Error - International order failed to import', 'International order# '. $_order .'.'. ' Exception Message: '.$e->getMessage());
35
+ mail('magentomissedorders@iglobalstores.com', 'Magento Integration Error - International order failed to import', 'International order# '. $_order .'.'. ' Exception Message: '.$e->getMessage());
36
+ if ($adminEmail) {
37
+ mail($adminEmail, 'iGlobal Import Error - International order failed to import', 'iGlobal International order# '. $_order . " failed to import properly. We've already received notice of the problem, and are probably working on it as you read this. Until then, you may manually enter the order, or give us a call for help at 1-800-942-0721." );
38
+ }
39
+ Mage::log("International order #{$_order} failed to import!" .$e, Zend_Log::ERR, 'iglobal.log', true);
40
+ }
41
+
42
+ $this->loadLayout();
43
+
44
+ $lastOrderId = Mage::getSingleton('checkout/session')->getLastOrderId();
45
+ Mage::dispatchEvent('checkout_onepage_controller_success_action', array('order_ids' => array($lastOrderId)));
46
+
47
+ $this->renderLayout();
48
+ }
49
+
50
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/code/community/Iglobal/Stores/etc/config.xml CHANGED
@@ -181,6 +181,16 @@
181
  </routers>
182
  </admin>
183
  <global>
 
 
 
 
 
 
 
 
 
 
184
  <events>
185
  <core_block_abstract_prepare_layout_before>
186
  <observers>
181
  </routers>
182
  </admin>
183
  <global>
184
+ <sales>
185
+ <quote>
186
+ <totals>
187
+ <tax>
188
+ <class>stores/sales_quote_address_total_fee</class>
189
+ <before>subtotal</before>
190
+ </tax>
191
+ </totals>
192
+ </quote>
193
+ </sales>
194
  <events>
195
  <core_block_abstract_prepare_layout_before>
196
  <observers>
app/code/community/Iglobal/Stores/etc/system.xml CHANGED
@@ -7,15 +7,15 @@
7
  <sort_order>150</sort_order>
8
  </iglobal>
9
  </tabs>
10
-
11
  <sections>
12
  <general>
13
-
14
  <groups>
15
  <country>
16
-
17
  <fields>
18
-
19
  <ig_domestic_countries>
20
  <label>Domestic Shipping Countries</label>
21
  <comment>Hold down Ctrl to select more than one. Select each country to which you will ship. iGlobal will not service these countries, and customers will use your checkout system.</comment>
@@ -27,14 +27,14 @@
27
  <show_in_store>1</show_in_store>
28
  <can_be_empty>1</can_be_empty>
29
  </ig_domestic_countries>
30
-
31
  </fields>
32
  </country>
33
  </groups>
34
-
35
  </general>
36
  </sections>
37
-
38
  <sections>
39
  <iglobal_integration translate="label" module="stores">
40
  <label>iGlobal Integration Options</label>
@@ -44,7 +44,7 @@
44
  <show_in_default>1</show_in_default>
45
  <show_in_website>1</show_in_website>
46
  <show_in_store>1</show_in_store>
47
-
48
  <groups>
49
  <apireqs translate="label">
50
  <label>Store Setup</label>
@@ -54,9 +54,9 @@
54
  <show_in_default>1</show_in_default>
55
  <show_in_website>1</show_in_website>
56
  <show_in_store>1</show_in_store>
57
-
58
  <fields>
59
-
60
  <heading_id translate="label">
61
  <label>Store Identification</label>
62
  <frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
@@ -65,7 +65,7 @@
65
  <show_in_website>1</show_in_website>
66
  <show_in_store>0</show_in_store>
67
  </heading_id>
68
-
69
  <iglobalid>
70
  <label>iGlobal Store ID Number</label>
71
  <comment>Paste the provided 3 digit store number here.</comment>
@@ -73,9 +73,9 @@
73
  <sort_order>20</sort_order>
74
  <show_in_default>1</show_in_default>
75
  <show_in_website>1</show_in_website>
76
- <show_in_store>1</show_in_store>
77
  </iglobalid>
78
-
79
  <secret>
80
  <label>iGlobal API Key</label>
81
  <comment>Paste the provided API secret security key here.</comment>
@@ -83,9 +83,9 @@
83
  <sort_order>30</sort_order>
84
  <show_in_default>1</show_in_default>
85
  <show_in_website>1</show_in_website>
86
- <show_in_store>1</show_in_store>
87
- </secret>
88
-
89
  <igsubdomain>
90
  <label>iGlobal Hosted Checkout Subdomain</label>
91
  <comment>Paste the provided subdomain here.</comment>
@@ -93,9 +93,9 @@
93
  <sort_order>35</sort_order>
94
  <show_in_default>1</show_in_default>
95
  <show_in_website>1</show_in_website>
96
- <show_in_store>1</show_in_store>
97
- </igsubdomain>
98
-
99
  <heading_includes translate="label">
100
  <label>Included Files</label>
101
  <frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
@@ -103,8 +103,8 @@
103
  <show_in_default>1</show_in_default>
104
  <show_in_website>1</show_in_website>
105
  <show_in_store>0</show_in_store>
106
- </heading_includes>
107
-
108
  <ice>
109
  <label>ICE script</label>
110
  <comment>Paste the provided link here. Please Be sure to include "https://" at the begining.</comment>
@@ -112,9 +112,9 @@
112
  <sort_order>50</sort_order>
113
  <show_in_default>1</show_in_default>
114
  <show_in_website>1</show_in_website>
115
- <show_in_store>1</show_in_store>
116
  </ice>
117
-
118
  <ice_toggle>
119
  <label>Turn on International Checkout?</label>
120
  <comment>Turn on to enable iGlobal International Checkout. Leave this off until setup and testing has been completed!</comment>
@@ -147,29 +147,49 @@
147
  <show_in_website>1</show_in_website>
148
  <show_in_store>1</show_in_store>
149
  </use_ice>
150
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  <heading_error translate="label">
152
  <label>Error Reporting</label>
153
  <frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
154
- <sort_order>90</sort_order>
155
  <show_in_default>1</show_in_default>
156
  <show_in_website>1</show_in_website>
157
  <show_in_store>1</show_in_store>
158
- </heading_error>
159
-
160
  <admin_email>
161
  <label>Admin Email Address</label>
162
  <comment>This email address will receive notices of errors</comment>
163
  <frontend_type>text</frontend_type>
164
- <sort_order>100</sort_order>
165
  <show_in_default>1</show_in_default>
166
  <show_in_website>1</show_in_website>
167
- <show_in_store>1</show_in_store>
168
  </admin_email>
169
-
170
  </fields>
171
  </apireqs>
172
-
173
  <igmat translate="label">
174
  <label>iGlobal Welcome Mat</label>
175
  <frontend_type>text</frontend_type>
@@ -180,9 +200,9 @@
180
  <comment>
181
  <![CDATA[ <div style="padding:10px;background-color:#fff;border:1px solid #ddd;margin-bottom:7px;">iGlobal's unique welcome mat will recognize your customers' location and automatically tailor their shopping experience to make it seamless and increase your conversions! If you have any questions or problems <a href="http://www.iglobalstores.com/contact-us.html" target="_blank">contact us online</a> or call 1-800-942-0721.<br /></div>]]>
182
  </comment>
183
-
184
- <fields>
185
-
186
  <welcome_mat_active translate="label comment">
187
  <label>Use the Welcome Mat?</label>
188
  <comment>For testing purposes you may use the default Welcome Mat by leaving the "Welcome Mat Script" field blank. This may result in poor appearance or strange behavior, and should be used only for testing and development. Please contact us at 1-800-942-0721 to have use make a customized script to match your site's style and design.</comment>
@@ -193,7 +213,7 @@
193
  <show_in_website>1</show_in_website>
194
  <show_in_store>1</show_in_store>
195
  </welcome_mat_active>
196
-
197
  <welcome_mat_script translate="label comment">
198
  <label>Welcome Mat Script File</label>
199
  <frontend_type>file</frontend_type>
@@ -205,7 +225,7 @@
205
  <show_in_store>1</show_in_store>
206
  <!--<depends><welcome_mat_active>1</welcome_mat_active></depends>-->
207
  </welcome_mat_script>
208
-
209
  <welcome_mat_css translate="label comment">
210
  <label>Welcome Mat CSS File</label>
211
  <frontend_type>file</frontend_type>
@@ -217,7 +237,7 @@
217
  <show_in_store>1</show_in_store>
218
  <!--<depends><welcome_mat_active>1</welcome_mat_active></depends>-->
219
  </welcome_mat_css>
220
-
221
  <flag_parent>
222
  <label>Flag postition selector</label>
223
  <comment>Enter the code provided to customize the location of the Welcome Mat flag, or leave blank to use the default location.</comment>
@@ -225,10 +245,10 @@
225
  <sort_order>40</sort_order>
226
  <show_in_default>1</show_in_default>
227
  <show_in_website>1</show_in_website>
228
- <show_in_store>1</show_in_store>
229
- <!--<depends><welcome_mat_active>1</welcome_mat_active></depends>-->
230
  </flag_parent>
231
-
232
  <!-- <flag_method>
233
  <label>Flag attachement method</label>
234
  <comment>Enter the code provided to customize the location of the Welcome Mat flag, or leave blank to use the default location.</comment>
@@ -237,12 +257,12 @@
237
  <sort_order>41</sort_order>
238
  <show_in_default>1</show_in_default>
239
  <show_in_website>1</show_in_website>
240
- <show_in_store>1</show_in_store>
241
  <depends>
242
  <welcome_mat_active>1</welcome_mat_active>
243
- </depends>
244
  </flag_method> -->
245
-
246
  <flag_method>
247
  <label>Flag insertion method</label>
248
  <comment>Enter the code provided to customize the location of the Welcome Mat flag, or leave blank to use the default location.</comment>
@@ -250,10 +270,10 @@
250
  <sort_order>42</sort_order>
251
  <show_in_default>1</show_in_default>
252
  <show_in_website>1</show_in_website>
253
- <show_in_store>1</show_in_store>
254
- <!--<depends><welcome_mat_active>1</welcome_mat_active></depends>-->
255
  </flag_method>
256
-
257
  <flag_code>
258
  <label>Flag insertion code</label>
259
  <comment>Enter the code provided to customize the location of the Welcome Mat flag, or leave blank to use the default location.</comment>
@@ -261,10 +281,10 @@
261
  <sort_order>42</sort_order>
262
  <show_in_default>1</show_in_default>
263
  <show_in_website>1</show_in_website>
264
- <show_in_store>1</show_in_store>
265
- <!--<depends><welcome_mat_active>1</welcome_mat_active></depends>-->
266
  </flag_code>
267
-
268
  <store_logo>
269
  <label>Your Store's Logo URL</label>
270
  <comment>Enter the URL provided to customize the look of the welcome mat, showing customers your logo.</comment>
@@ -272,14 +292,14 @@
272
  <sort_order>50</sort_order>
273
  <show_in_default>1</show_in_default>
274
  <show_in_website>1</show_in_website>
275
- <show_in_store>1</show_in_store>
276
- <!--<depends><welcome_mat_active>1</welcome_mat_active></depends>-->
277
  </store_logo>
278
-
279
  </fields>
280
-
281
  </igmat>
282
-
283
  <igjq translate="label">
284
  <label>jQuery Settings</label>
285
  <frontend_type>text</frontend_type>
@@ -290,9 +310,9 @@
290
  <comment>
291
  <![CDATA[<div style="padding:10px;background-color:#fff;border:1px solid #ddd;margin-bottom:7px;">To avoid conflicts, please select Yes ONLY if you do not currently have jQuery running on your site. If you are unsure, please contact us at 1-800-942-0721 and we will assist you. </div>]]>
292
  </comment>
293
-
294
  <fields>
295
-
296
  <enabled translate="label">
297
  <label>Enabled</label>
298
  <frontend_type>select</frontend_type>
@@ -313,12 +333,12 @@
313
  <show_in_website>1</show_in_website>
314
  <show_in_store>1</show_in_store>
315
  </iglogging>
316
-
317
  </fields>
318
  </igjq>
319
-
320
  </groups>
321
-
322
  </iglobal_integration>
323
 
324
  <payment translate="label" module="payment">
7
  <sort_order>150</sort_order>
8
  </iglobal>
9
  </tabs>
10
+
11
  <sections>
12
  <general>
13
+
14
  <groups>
15
  <country>
16
+
17
  <fields>
18
+
19
  <ig_domestic_countries>
20
  <label>Domestic Shipping Countries</label>
21
  <comment>Hold down Ctrl to select more than one. Select each country to which you will ship. iGlobal will not service these countries, and customers will use your checkout system.</comment>
27
  <show_in_store>1</show_in_store>
28
  <can_be_empty>1</can_be_empty>
29
  </ig_domestic_countries>
30
+
31
  </fields>
32
  </country>
33
  </groups>
34
+
35
  </general>
36
  </sections>
37
+
38
  <sections>
39
  <iglobal_integration translate="label" module="stores">
40
  <label>iGlobal Integration Options</label>
44
  <show_in_default>1</show_in_default>
45
  <show_in_website>1</show_in_website>
46
  <show_in_store>1</show_in_store>
47
+
48
  <groups>
49
  <apireqs translate="label">
50
  <label>Store Setup</label>
54
  <show_in_default>1</show_in_default>
55
  <show_in_website>1</show_in_website>
56
  <show_in_store>1</show_in_store>
57
+
58
  <fields>
59
+
60
  <heading_id translate="label">
61
  <label>Store Identification</label>
62
  <frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
65
  <show_in_website>1</show_in_website>
66
  <show_in_store>0</show_in_store>
67
  </heading_id>
68
+
69
  <iglobalid>
70
  <label>iGlobal Store ID Number</label>
71
  <comment>Paste the provided 3 digit store number here.</comment>
73
  <sort_order>20</sort_order>
74
  <show_in_default>1</show_in_default>
75
  <show_in_website>1</show_in_website>
76
+ <show_in_store>1</show_in_store>
77
  </iglobalid>
78
+
79
  <secret>
80
  <label>iGlobal API Key</label>
81
  <comment>Paste the provided API secret security key here.</comment>
83
  <sort_order>30</sort_order>
84
  <show_in_default>1</show_in_default>
85
  <show_in_website>1</show_in_website>
86
+ <show_in_store>1</show_in_store>
87
+ </secret>
88
+
89
  <igsubdomain>
90
  <label>iGlobal Hosted Checkout Subdomain</label>
91
  <comment>Paste the provided subdomain here.</comment>
93
  <sort_order>35</sort_order>
94
  <show_in_default>1</show_in_default>
95
  <show_in_website>1</show_in_website>
96
+ <show_in_store>1</show_in_store>
97
+ </igsubdomain>
98
+
99
  <heading_includes translate="label">
100
  <label>Included Files</label>
101
  <frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
103
  <show_in_default>1</show_in_default>
104
  <show_in_website>1</show_in_website>
105
  <show_in_store>0</show_in_store>
106
+ </heading_includes>
107
+
108
  <ice>
109
  <label>ICE script</label>
110
  <comment>Paste the provided link here. Please Be sure to include "https://" at the begining.</comment>
112
  <sort_order>50</sort_order>
113
  <show_in_default>1</show_in_default>
114
  <show_in_website>1</show_in_website>
115
+ <show_in_store>1</show_in_store>
116
  </ice>
117
+
118
  <ice_toggle>
119
  <label>Turn on International Checkout?</label>
120
  <comment>Turn on to enable iGlobal International Checkout. Leave this off until setup and testing has been completed!</comment>
147
  <show_in_website>1</show_in_website>
148
  <show_in_store>1</show_in_store>
149
  </use_ice>
150
+
151
+ <heading_checkout translate="label">
152
+ <label>Checkout Options</label>
153
+ <frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
154
+ <sort_order>90</sort_order>
155
+ <show_in_default>1</show_in_default>
156
+ <show_in_website>1</show_in_website>
157
+ <show_in_store>1</show_in_store>
158
+ </heading_checkout>
159
+
160
+ <send_order_email>
161
+ <label>Send Order Email</label>
162
+ <comment>Send a confirmation email after the order is placed (iGlobal may also send a confirmation email, depending on the settings you requested)</comment>
163
+ <frontend_type>select</frontend_type>
164
+ <source_model>adminhtml/system_config_source_yesno</source_model>
165
+ <sort_order>100</sort_order>
166
+ <show_in_default>1</show_in_default>
167
+ <show_in_website>1</show_in_website>
168
+ <show_in_store>1</show_in_store>
169
+ </send_order_email>
170
+
171
  <heading_error translate="label">
172
  <label>Error Reporting</label>
173
  <frontend_model>adminhtml/system_config_form_field_heading</frontend_model>
174
+ <sort_order>110</sort_order>
175
  <show_in_default>1</show_in_default>
176
  <show_in_website>1</show_in_website>
177
  <show_in_store>1</show_in_store>
178
+ </heading_error>
179
+
180
  <admin_email>
181
  <label>Admin Email Address</label>
182
  <comment>This email address will receive notices of errors</comment>
183
  <frontend_type>text</frontend_type>
184
+ <sort_order>120</sort_order>
185
  <show_in_default>1</show_in_default>
186
  <show_in_website>1</show_in_website>
187
+ <show_in_store>1</show_in_store>
188
  </admin_email>
189
+
190
  </fields>
191
  </apireqs>
192
+
193
  <igmat translate="label">
194
  <label>iGlobal Welcome Mat</label>
195
  <frontend_type>text</frontend_type>
200
  <comment>
201
  <![CDATA[ <div style="padding:10px;background-color:#fff;border:1px solid #ddd;margin-bottom:7px;">iGlobal's unique welcome mat will recognize your customers' location and automatically tailor their shopping experience to make it seamless and increase your conversions! If you have any questions or problems <a href="http://www.iglobalstores.com/contact-us.html" target="_blank">contact us online</a> or call 1-800-942-0721.<br /></div>]]>
202
  </comment>
203
+
204
+ <fields>
205
+
206
  <welcome_mat_active translate="label comment">
207
  <label>Use the Welcome Mat?</label>
208
  <comment>For testing purposes you may use the default Welcome Mat by leaving the "Welcome Mat Script" field blank. This may result in poor appearance or strange behavior, and should be used only for testing and development. Please contact us at 1-800-942-0721 to have use make a customized script to match your site's style and design.</comment>
213
  <show_in_website>1</show_in_website>
214
  <show_in_store>1</show_in_store>
215
  </welcome_mat_active>
216
+
217
  <welcome_mat_script translate="label comment">
218
  <label>Welcome Mat Script File</label>
219
  <frontend_type>file</frontend_type>
225
  <show_in_store>1</show_in_store>
226
  <!--<depends><welcome_mat_active>1</welcome_mat_active></depends>-->
227
  </welcome_mat_script>
228
+
229
  <welcome_mat_css translate="label comment">
230
  <label>Welcome Mat CSS File</label>
231
  <frontend_type>file</frontend_type>
237
  <show_in_store>1</show_in_store>
238
  <!--<depends><welcome_mat_active>1</welcome_mat_active></depends>-->
239
  </welcome_mat_css>
240
+
241
  <flag_parent>
242
  <label>Flag postition selector</label>
243
  <comment>Enter the code provided to customize the location of the Welcome Mat flag, or leave blank to use the default location.</comment>
245
  <sort_order>40</sort_order>
246
  <show_in_default>1</show_in_default>
247
  <show_in_website>1</show_in_website>
248
+ <show_in_store>1</show_in_store>
249
+ <!--<depends><welcome_mat_active>1</welcome_mat_active></depends>-->
250
  </flag_parent>
251
+
252
  <!-- <flag_method>
253
  <label>Flag attachement method</label>
254
  <comment>Enter the code provided to customize the location of the Welcome Mat flag, or leave blank to use the default location.</comment>
257
  <sort_order>41</sort_order>
258
  <show_in_default>1</show_in_default>
259
  <show_in_website>1</show_in_website>
260
+ <show_in_store>1</show_in_store>
261
  <depends>
262
  <welcome_mat_active>1</welcome_mat_active>
263
+ </depends>
264
  </flag_method> -->
265
+
266
  <flag_method>
267
  <label>Flag insertion method</label>
268
  <comment>Enter the code provided to customize the location of the Welcome Mat flag, or leave blank to use the default location.</comment>
270
  <sort_order>42</sort_order>
271
  <show_in_default>1</show_in_default>
272
  <show_in_website>1</show_in_website>
273
+ <show_in_store>1</show_in_store>
274
+ <!--<depends><welcome_mat_active>1</welcome_mat_active></depends>-->
275
  </flag_method>
276
+
277
  <flag_code>
278
  <label>Flag insertion code</label>
279
  <comment>Enter the code provided to customize the location of the Welcome Mat flag, or leave blank to use the default location.</comment>
281
  <sort_order>42</sort_order>
282
  <show_in_default>1</show_in_default>
283
  <show_in_website>1</show_in_website>
284
+ <show_in_store>1</show_in_store>
285
+ <!--<depends><welcome_mat_active>1</welcome_mat_active></depends>-->
286
  </flag_code>
287
+
288
  <store_logo>
289
  <label>Your Store's Logo URL</label>
290
  <comment>Enter the URL provided to customize the look of the welcome mat, showing customers your logo.</comment>
292
  <sort_order>50</sort_order>
293
  <show_in_default>1</show_in_default>
294
  <show_in_website>1</show_in_website>
295
+ <show_in_store>1</show_in_store>
296
+ <!--<depends><welcome_mat_active>1</welcome_mat_active></depends>-->
297
  </store_logo>
298
+
299
  </fields>
300
+
301
  </igmat>
302
+
303
  <igjq translate="label">
304
  <label>jQuery Settings</label>
305
  <frontend_type>text</frontend_type>
310
  <comment>
311
  <![CDATA[<div style="padding:10px;background-color:#fff;border:1px solid #ddd;margin-bottom:7px;">To avoid conflicts, please select Yes ONLY if you do not currently have jQuery running on your site. If you are unsure, please contact us at 1-800-942-0721 and we will assist you. </div>]]>
312
  </comment>
313
+
314
  <fields>
315
+
316
  <enabled translate="label">
317
  <label>Enabled</label>
318
  <frontend_type>select</frontend_type>
333
  <show_in_website>1</show_in_website>
334
  <show_in_store>1</show_in_store>
335
  </iglogging>
336
+
337
  </fields>
338
  </igjq>
339
+
340
  </groups>
341
+
342
  </iglobal_integration>
343
 
344
  <payment translate="label" module="payment">
app/design/adminhtml/default/default/layout/fee.xml DELETED
@@ -1,56 +0,0 @@
1
- <?xml version="1.0"?>
2
- <layout version="0.1.0">
3
- <adminhtml_sales_order_view>
4
- <reference name="order_totals">
5
- <block type="adminhtml/sales_order_totals_item" name="fee" template="fee/sales/order/total.phtml">
6
- </block>
7
- <block type="adminhtml/sales_order_totals_item" name="fee.refunded" template="fee/sales/order/refunded.phtml">
8
- <action method="setDisplayArea"><area>footer</area></action>
9
- <action method="setAfterCondition"><condition>last</condition></action>
10
- </block>
11
- </reference>
12
- </adminhtml_sales_order_view>
13
-
14
- <adminhtml_sales_order_invoice_new>
15
- <reference name="invoice_totals">
16
- <block type="adminhtml/sales_order_totals_item" name="fee" template="fee/sales/order/total.phtml">
17
- </block>
18
- </reference>
19
- </adminhtml_sales_order_invoice_new>
20
-
21
- <adminhtml_sales_order_invoice_updateqty>
22
- <reference name="invoice_totals">
23
- <block type="adminhtml/sales_order_totals_item" name="fee" template="fee/sales/order/total.phtml">
24
- </block>
25
- </reference>
26
- </adminhtml_sales_order_invoice_updateqty>
27
-
28
- <adminhtml_sales_order_invoice_view>
29
- <reference name="invoice_totals">
30
- <block type="adminhtml/sales_order_totals_item" name="fee" template="fee/sales/order/total.phtml">
31
- </block>
32
- </reference>
33
- </adminhtml_sales_order_invoice_view>
34
-
35
- <adminhtml_sales_order_creditmemo_new>
36
- <reference name="creditmemo_totals">
37
- <block type="adminhtml/sales_order_totals_item" name="fee" template="fee/sales/order/total.phtml">
38
- </block>
39
- </reference>
40
- </adminhtml_sales_order_creditmemo_new>
41
-
42
- <adminhtml_sales_order_creditmemo_updateqty>
43
- <reference name="creditmemo_totals">
44
- <block type="adminhtml/sales_order_totals_item" name="fee" template="fee/sales/order/total.phtml">
45
- </block>
46
- </reference>
47
- </adminhtml_sales_order_creditmemo_updateqty>
48
-
49
- <adminhtml_sales_order_creditmemo_view>
50
- <reference name="creditmemo_totals">
51
- <block type="adminhtml/sales_order_totals_item" name="fee.refunded" template="fee/sales/order/refunded.phtml">
52
- <action method="setDisplayArea"><area>footer</area></action>
53
- </block>
54
- </reference>
55
- </adminhtml_sales_order_creditmemo_view>
56
- </layout>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/design/adminhtml/default/default/template/fee/sales/order/refunded.phtml DELETED
@@ -1,16 +0,0 @@
1
- <?php if($this->getSource() instanceof Mage_Sales_Model_Order){ ?>
2
- <?php if ((float) $this->getSource()->getFeeAmountRefunded()): ?>
3
- <tr>
4
- <td class="label"><strong><?php echo Mage::helper('fee')->__('Fee refunded to customer') ?></strong></td>
5
- <td><strong><?php echo $this->getSource()->getFeeAmountRefunded(); ?></strong></td>
6
- </tr>
7
- <?php endif; ?>
8
- <?php } else { ?>
9
- <?php if ((float) $this->getSource()->getFeeAmount()): ?>
10
- <tr>
11
- <td class="label"><strong><?php echo Mage::helper('fee')->__('Fee Refunded') ?></strong></td>
12
- <td><strong><?php echo $this->getSource()->getFeeAmount(); ?></strong></td>
13
- </tr>
14
- <?php endif;
15
- }?>
16
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/design/adminhtml/default/default/template/fee/sales/order/total.phtml DELETED
@@ -1,9 +0,0 @@
1
- <?php $this->setPriceDataObject($this->getSource()) ?>
2
- <?php if ((float) $this->getSource()->getFeeAmount()): ?>
3
- <tr>
4
- <td class="label"><?php echo Mage::helper('fee')->formatFee($this->getSource()->getFeeAmount()) ?></td>
5
- <td>
6
- <?php echo $this->displayPrices($this->getSource()->getBaseFeeAmount(), $this->getSource()->getFeeAmount()); ?>
7
- </td>
8
- </tr>
9
- <?php endif; ?>
 
 
 
 
 
 
 
 
 
app/design/frontend/base/default/layout/fee.xml DELETED
@@ -1,50 +0,0 @@
1
- <?xml version="1.0"?>
2
- <layout version="0.1.0">
3
- <sales_order_view>
4
- <reference name="order_totals">
5
- <block type="fee/sales_order_total" name="fee.sales.order.total" />
6
- </reference>
7
- </sales_order_view>
8
- <sales_order_print>
9
- <reference name="order_totals">
10
- <block type="fee/sales_order_total" name="fee.sales.order.total" />
11
- </reference>
12
- </sales_order_print>
13
- <sales_email_order_items>
14
- <reference name="order_totals">
15
- <block type="fee/sales_order_total" name="fee.sales.order.total" />
16
- </reference>
17
- </sales_email_order_items>
18
-
19
- <sales_order_invoice>
20
- <reference name="invoice_totals">
21
- <block type="fee/sales_order_total" name="fee.sales.order.total" />
22
- </reference>
23
- </sales_order_invoice>
24
- <sales_order_printinvoice>
25
- <reference name="invoice_totals">
26
- <block type="fee/sales_order_total" name="fee.sales.order.total" />
27
- </reference>
28
- </sales_order_printinvoice>
29
- <sales_email_order_invoice_items>
30
- <reference name="invoice_totals">
31
- <block type="fee/sales_order_total" name="fee.sales.order.total" />
32
- </reference>
33
- </sales_email_order_invoice_items>
34
-
35
- <sales_order_creditmemo>
36
- <reference name="creditmemo_totals">
37
- <block type="fee/sales_order_total" name="fee.sales.order.total" />
38
- </reference>
39
- </sales_order_creditmemo>
40
- <sales_order_printcreditmemo>
41
- <reference name="creditmemo_totals">
42
- <block type="fee/sales_order_total" name="fee.sales.order.total" />
43
- </reference>
44
- </sales_order_printcreditmemo>
45
- <sales_email_order_creditmemo_items>
46
- <reference name="creditmemo_totals">
47
- <block type="fee/sales_order_total" name="fee.sales.order.total" />
48
- </reference>
49
- </sales_email_order_creditmemo_items>
50
- </layout>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/design/frontend/base/default/template/iglobal/checkout/onepage/link.phtml CHANGED
@@ -1,30 +1,30 @@
1
- <?php
2
- /**
3
- * Magento
4
- *
5
- * NOTICE OF LICENSE
6
- *
7
- * This source file is subject to the Academic Free License (AFL 3.0)
8
- * that is bundled with this package in the file LICENSE_AFL.txt.
9
- * It is also available through the world-wide-web at this URL:
10
- * http://opensource.org/licenses/afl-3.0.php
11
- * If you did not receive a copy of the license and are unable to
12
- * obtain it through the world-wide-web, please send an email
13
- * to license@magento.com so we can send you a copy immediately.
14
- *
15
- * DISCLAIMER
16
- *
17
- * Do not edit or add to this file if you wish to upgrade Magento to newer
18
- * versions in the future. If you wish to customize Magento for your
19
- * needs please refer to http://www.magento.com for more information.
20
- *
21
- * @category design
22
- * @package base_default
23
- * @copyright Copyright (c) 2006-2015 X.commerce, Inc. (http://www.magento.com)
24
- * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
25
- */
26
- ?>
27
- <?php if ($this->isPossibleOnepageCheckout()):?>
28
- <button type="button" title="<?php echo $this->__('Proceed to Checkout') ?>" class="button btn-proceed-checkout btn-checkout<?php if ($this->isDisabled()):?> no-checkout<?php endif; ?>"<?php if ($this->isDisabled()):?> disabled="disabled"<?php endif; ?> onclick="<?php echo $this->getCheckoutUrl() ?>;"><span><span><?php echo $this->__('Proceed to Checkout') ?></span></span></button>
29
- <?php endif?>
30
-
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Academic Free License (AFL 3.0)
8
+ * that is bundled with this package in the file LICENSE_AFL.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/afl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magento.com so we can send you a copy immediately.
14
+ *
15
+ * DISCLAIMER
16
+ *
17
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
18
+ * versions in the future. If you wish to customize Magento for your
19
+ * needs please refer to http://www.magento.com for more information.
20
+ *
21
+ * @category design
22
+ * @package base_default
23
+ * @copyright Copyright (c) 2006-2015 X.commerce, Inc. (http://www.magento.com)
24
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
25
+ */
26
+ ?>
27
+ <?php if ($this->isPossibleOnepageCheckout()):?>
28
+ <button type="button" title="<?php echo $this->__('Proceed to Checkout') ?>" class="button btn-proceed-checkout btn-checkout<?php if ($this->isDisabled()):?> no-checkout<?php endif; ?>"<?php if ($this->isDisabled()):?> disabled="disabled"<?php endif; ?> onclick="<?php echo $this->getCheckoutUrl() ?>;"><span><span><?php echo $this->__('Proceed to Checkout') ?></span></span></button>
29
+ <?php endif?>
30
+
app/design/frontend/base/default/template/iglobal/stores/cart.phtml CHANGED
@@ -15,9 +15,10 @@
15
 
16
 
17
  foreach ($cart->getAllVisibleItems() as $item) {
18
-
19
  echo '<div class="igItemDetails '.$item->getName().'">';
20
-
 
21
  /* figure this item type problem out, okay?
22
 
23
  $options = $item->getOptionByCode('simple_product')->getProduct()->getTypeInstance(true)->getOrderOptions($item->getProduct());
@@ -27,7 +28,7 @@
27
  if(isset($options['options'])){
28
 
29
  echo '<span class="igItemOptions"><dl class="igOptionsList">';
30
-
31
  $optionArray = $options['options'];
32
  foreach ($optionArray as $optionDetails) {
33
  echo '<dt>' . $optionDetails['label'] . '</dt>';
@@ -51,13 +52,13 @@
51
 
52
  echo '<span class="igPrice">'.$item->getPrice().'</span>';
53
 
54
- echo '<span class="igUrl">'.Mage::getModel('catalog/product')->load($item->getProductId())->getProductUrl().'</span>';
55
 
56
  echo '<span class="igImage">'. str_replace("http:", "https:",Mage::helper('catalog/image')->init($item->getProduct(), 'thumbnail')).'</span>';
57
 
58
- echo '<span class="igDescription">'. Mage::getModel('catalog/product')->load($item->getProductId())->getDescription().'</span>';
59
 
60
- echo '<span class="igShortDescription">'. Mage::getModel('catalog/product')->load($item->getProductId())->getShortDescription().'</span>';
61
 
62
  echo '<span class="MageWeight">'.$item->getWeight().'</span>';
63
 
@@ -67,7 +68,7 @@
67
 
68
  //starts here
69
 
70
- $sku = $item->getProduct()->getTypeId() == 'bundle' ? substr($item->getSku(), strpos($item->getSku(), '-')+1) : $item->getSku();
71
 
72
  $id = $item->getProductId();
73
 
@@ -87,10 +88,6 @@
87
 
88
  try {
89
 
90
-
91
-
92
- $allItemData = Mage::getModel('catalog/product')->load($item['product_id']);
93
-
94
  $weightUnits = "";
95
 
96
  $dimUnits = "";
@@ -99,9 +96,9 @@
99
 
100
  $weightUnits = "";
101
 
102
- if (!empty($allItemData['ig_weight_units'])) {
103
 
104
- $weightUnits = $allItemData->getAttributeText('ig_weight_units');
105
 
106
  }
107
 
@@ -115,11 +112,11 @@
115
 
116
  $weight = "";
117
 
118
- if (!empty($allItemData['ig_weight'])) {
119
 
120
- $weight = $allItemData->getData('ig_weight');
121
 
122
- } else if (!empty($allItemData['weight'])) {
123
 
124
  $weight = $item->getWeight();
125
 
@@ -161,9 +158,9 @@
161
 
162
  $dimUnits = "";
163
 
164
- if (!empty($allItemData['ig_dimension_units'])) {
165
 
166
- $dimUnits = $allItemData->getAttributeText('ig_dimension_units');
167
 
168
  }
169
 
@@ -177,25 +174,25 @@
177
 
178
  $length = "";
179
 
180
- if (!empty($allItemData['ig_length'])) {
181
 
182
- $length = $allItemData->getData('ig_length');
183
 
184
  }
185
 
186
  $width = "";
187
 
188
- if (!empty($allItemData['ig_width'])) {
189
 
190
- $width = $allItemData->getData('ig_width');
191
 
192
  }
193
 
194
  $height = "";
195
 
196
- if (!empty($allItemData['ig_height'])) {
197
 
198
- $height = $allItemData->getData('ig_height');
199
 
200
  }
201
 
15
 
16
 
17
  foreach ($cart->getAllVisibleItems() as $item) {
18
+
19
  echo '<div class="igItemDetails '.$item->getName().'">';
20
+ $product = $item->getProduct();
21
+
22
  /* figure this item type problem out, okay?
23
 
24
  $options = $item->getOptionByCode('simple_product')->getProduct()->getTypeInstance(true)->getOrderOptions($item->getProduct());
28
  if(isset($options['options'])){
29
 
30
  echo '<span class="igItemOptions"><dl class="igOptionsList">';
31
+
32
  $optionArray = $options['options'];
33
  foreach ($optionArray as $optionDetails) {
34
  echo '<dt>' . $optionDetails['label'] . '</dt>';
52
 
53
  echo '<span class="igPrice">'.$item->getPrice().'</span>';
54
 
55
+ echo '<span class="igUrl">'.$product->getProductUrl().'</span>';
56
 
57
  echo '<span class="igImage">'. str_replace("http:", "https:",Mage::helper('catalog/image')->init($item->getProduct(), 'thumbnail')).'</span>';
58
 
59
+ echo '<span class="igDescription">'.$product->getDescription().'</span>';
60
 
61
+ echo '<span class="igShortDescription">'.$product->getShortDescription().'</span>';
62
 
63
  echo '<span class="MageWeight">'.$item->getWeight().'</span>';
64
 
68
 
69
  //starts here
70
 
71
+ $sku = $product->getTypeId() == 'bundle' ? substr($item->getSku(), strpos($item->getSku(), '-')+1) : $item->getSku();
72
 
73
  $id = $item->getProductId();
74
 
88
 
89
  try {
90
 
 
 
 
 
91
  $weightUnits = "";
92
 
93
  $dimUnits = "";
96
 
97
  $weightUnits = "";
98
 
99
+ if (!empty($product['ig_weight_units'])) {
100
 
101
+ $weightUnits = $product->getAttributeText('ig_weight_units');
102
 
103
  }
104
 
112
 
113
  $weight = "";
114
 
115
+ if (!empty($product['ig_weight'])) {
116
 
117
+ $weight = $product->getData('ig_weight');
118
 
119
+ } else if (!empty($product['weight'])) {
120
 
121
  $weight = $item->getWeight();
122
 
158
 
159
  $dimUnits = "";
160
 
161
+ if (!empty($product['ig_dimension_units'])) {
162
 
163
+ $dimUnits = $product->getAttributeText('ig_dimension_units');
164
 
165
  }
166
 
174
 
175
  $length = "";
176
 
177
+ if (!empty($product['ig_length'])) {
178
 
179
+ $length = $product->getData('ig_length');
180
 
181
  }
182
 
183
  $width = "";
184
 
185
+ if (!empty($product['ig_width'])) {
186
 
187
+ $width = $product->getData('ig_width');
188
 
189
  }
190
 
191
  $height = "";
192
 
193
+ if (!empty($product['ig_height'])) {
194
 
195
+ $height = $product->getData('ig_height');
196
 
197
  }
198
 
app/etc/modules/Iglobal_Fee.xml DELETED
@@ -1,9 +0,0 @@
1
- <?xml version="1.0"?>
2
- <config>
3
- <modules>
4
- <Iglobal_Fee>
5
- <active>true</active>
6
- <codePool>community</codePool>
7
- </Iglobal_Fee>
8
- </modules>
9
- </config>
 
 
 
 
 
 
 
 
 
js/iGlobal/ig_welcome_mat_default.css DELETED
@@ -1,41 +0,0 @@
1
- /* iGlobal Welcome Mat Styles */
2
- /* Authored by iGlobal Stores (www.iglobalstores.com) */
3
-
4
- /* Google Fonts - If you're using your own fonts, you can remove these */
5
- @font-face { font-family: 'PT Sans'; font-style: normal; font-weight: 400; src: local('PT Sans'), local('PTSans-Regular'), url(http://themes.googleusercontent.com/static/fonts/ptsans/v5/7YGmE4Ls5b94ct65u07hVQLUuEpTyoUstqEm5AMlJo4.woff) format('woff'); }
6
- @font-face { font-family: 'PT Sans'; font-style: normal; font-weight: 700; src: local('PT Sans Bold'), local('PTSans-Bold'), url(http://themes.googleusercontent.com/static/fonts/ptsans/v5/0XxGQsSc1g4rdRdjJKZrNL3hpw3pgy2gAi-Ip7WPMi0.woff) format('woff'); }
7
-
8
- /* igFlag controls the placement of the country flag on your website */
9
- #igFlag { width: 30px; }
10
- #igFlag img { max-width: 25px; margin-bottom: -3px; cursor: pointer; margin-left: 5px; }
11
-
12
- /* Begin Modal Styles */
13
- #igSplashElement { position: fixed; width: 600px; background-color: #fff; -webkit-box-shadow: 0px 0px 60px 0px rgba(0, 0, 0, 0.5); box-shadow: 0px 0px 60px 0px rgba(0, 0, 0, 0.5); font-family: 'PT Sans','Helvetica Neue', Helvetica, Arial, sans-serif; /* Set your preferred font here */ color: #666; }
14
- .closeButton { position: absolute; top: 3px; right: 3px; }
15
- .close { cursor: pointer; }
16
- .igModalHeader { width: 560px; background-color: #fff; text-align: center; color: #999; overflow: auto; padding: 20px; }
17
- .logoWrapper { float: left; width: 180px; } /* If your logo is wider than 180px, you may wish to widen this and decrease the width of the .messageWrapper */
18
- .messageWrapper { float: right; width: 380px; margin-right: -20px;}
19
- .modalLogo { float: left; margin: 10px; width: 170px; }
20
- .igModalHeader img.headerFlag { max-width: 50px; margin-top: -15px; }
21
- .headerZero { margin-bottom: 8px; }
22
- .headerOne { font-size: 30px; padding-left: 0.5em; color: #0068AC; /* Set the color of your choice here */ text-transform: uppercase; }
23
- .headerTwo { color: #999; margin-top: 7px; font-size: 12px; }
24
- .igModalBody { text-align: center; background-color: white; width: 100%; min-height: 320px; }
25
- .countryDropDownWrapper { width: 250px; min-height: 25px; -webkit-border-radius: 10px; border-radius: 10px; background: url(https://iglobalstores.com/images/downarrow.png) no-repeat 94% center; border: 2px solid #0068AC; /* Set the color of your choice here */ margin: 0 auto; padding: 0; cursor: pointer; }
26
- #countrySelect { position: relative; height: 35px; padding: 7px 10px; margin: 0px; font-size: 14px; line-height: 14px; color: #333 !important; text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); cursor: pointer; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; -o-user-select: none; user-select: none; background: none !important; border: 0 !important; -webkit-appearance: none; -moz-appearance: window; appearance: none; ms-appearance: none; overflow: hidden; }
27
- select::-ms-expand { display: none; }
28
- ul.featureList { padding: 20px; margin: 0; -webkit-padding-start: 0; background-color: #999; color: #e8e8e8; }
29
- ul.featureList li { list-style-type: none; padding: 10px 20px; font-size: 18px; }
30
- ul.featureList li strong { color: white; }
31
- ul.featureList li img { padding-top: 5px; max-width: 80px; margin-bottom: -15px; }
32
- .igWelcomeCTAButton { background: white; width: 100%; height: 100px;}
33
- .igWelcomeCTAButton button { width: 225px; height: 50px; -webkit-border-radius: 3px; border-radius: 3px; color: white; margin: 20px auto; border: none; font-size: 20px; font-weight: normal; background-color: #596069; opacity: 1; text-shadow: none; float: none;}
34
-
35
- @media screen and (max-width: 600px) { /* Responsive design sets a width of 400px for all devices <= 600px */
36
- #igSplashElement { width: 400px; margin-left: -200px !important; }
37
- .igModalHeader { width: 360px; }
38
- .logoWrapper { float: none; width: auto; }
39
- .modalLogo { float: none; margin: 10px auto; }
40
- .messageWrapper { clear: both; }
41
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/iGlobal/ig_welcome_mat_default.js DELETED
@@ -1,867 +0,0 @@
1
- // iGlobal Welcome Mat Script
2
- // Authored by iGlobal Stores (www.iglobalstores.com)
3
- // Copyright iGlobal Stores 2013
4
-
5
- //
6
- // Store specific settings
7
- //
8
-
9
- //default settings - these will be overwritten by any settings made in Magento
10
- var ig_storeId = 3;
11
- var ig_cookieDomain = window.location.hostname;// If you prefer, you can put your domain here, like so "yourdomain.com";
12
- var ig_countries = {"AL":"Albania","DZ":"Algeria","AS":"American Samoa","AD":"Andorra","AO":"Angola","AI":"Anguilla","AG":"Antigua","AR":"Argentina","AM":"Armenia","AW":"Aruba","AU":"Australia","AT":"Austria","AZ":"Azerbaijan","BS":"Bahamas","BH":"Bahrain","BD":"Bangladesh","BB":"Barbados","BE":"Belgium","BZ":"Belize","BJ":"Benin","BM":"Bermuda","BT":"Bhutan","BO":"Bolivia","BQ":"Bonaire, St. Eustatius & Saba","BA":"Bosnia & Herzegovina","BW":"Botswana","BR":"Brazil","BN":"Brunei","BG":"Bulgaria","BF":"Burkina Faso","BI":"Burundi","KH":"Cambodia","CM":"Cameroon","CA":"Canada","IC":"Canary Islands","CV":"Cape Verde","KY":"Cayman Islands","CF":"Central African Republic","TD":"Chad","CL":"Chile","CN":"China - People's Republic of","CO":"Colombia","KM":"Comoros","CG":"Congo","CK":"Cook Islands","CR":"Costa Rica","HR":"Croatia","CW":"Curaçao","CY":"Cyprus","CZ":"Czech Republic","DK":"Denmark","DJ":"Djibouti","DM":"Dominica","DO":"Dominican Republic","EC":"Ecuador","EG":"Egypt","SV":"El Salvador","GQ":"Equatorial Guinea","ER":"Eritrea","EE":"Estonia","ET":"Ethiopia","FK":"Falkland Islands","FO":"Faroe Islands (Denmark)","FJ":"Fiji","FI":"Finland","FR":"France","GF":"French Guiana","GA":"Gabon","GM":"Gambia","GE":"Georgia","DE":"Germany","GH":"Ghana","GI":"Gibraltar","GR":"Greece","GL":"Greenland (Denmark)","GD":"Grenada","GP":"Guadeloupe","GU":"Guam","GT":"Guatemala","GG":"Guernsey","GN":"Guinea","GW":"Guinea-Bissau","GY":"Guyana","HT":"Haiti","HN":"Honduras","HK":"Hong Kong","HU":"Hungary","IS":"Iceland","IN":"India","ID":"Indonesia","IE":"Ireland - Republic Of","IL":"Israel","IT":"Italy","CI":"Ivory Coast","JM":"Jamaica","JP":"Japan","JE":"Jersey","JO":"Jordan","KZ":"Kazakhstan","KE":"Kenya","KI":"Kiribati","KR":"Korea, Republic of (South Korea)","KW":"Kuwait","KG":"Kyrgyzstan","LA":"Laos","LV":"Latvia","LS":"Lesotho","LR":"Liberia","LI":"Liechtenstein","LT":"Lithuania","LU":"Luxembourg","MO":"Macau","MK":"Macedonia","MG":"Madagascar","MW":"Malawi","MY":"Malaysia","MV":"Maldives","ML":"Mali","MT":"Malta","MH":"Marshall Islands","MQ":"Martinique","MR":"Mauritania","MU":"Mauritius","YT":"Mayotte","MX":"Mexico","FM":"Micronesia - Federated States of","MD":"Moldova","MC":"Monaco","MN":"Mongolia","ME":"Montenegro","MS":"Montserrat","MA":"Morocco","MZ":"Mozambique","MM":"Myanmar","NA":"Namibia","NR":"Nauru, Republic of","NP":"Nepal","NL":"Netherlands (Holland)","NV":"Nevis","NC":"New Caledonia","NZ":"New Zealand","NI":"Nicaragua","NE":"Niger","NG":"Nigeria","NU":"Niue Island","NO":"Norway","OM":"Oman","PK":"Pakistan","PW":"Palau","PA":"Panama","PG":"Papua New Guinea","PY":"Paraguay","PE":"Peru","PH":"Philippines","PL":"Poland","PT":"Portugal","PR":"Puerto Rico","QA":"Qatar","RE":"Reunion","RO":"Romania","RU":"Russia","RW":"Rwanda","SM":"San Marino","ST":"Sao Tome & Principe","SA":"Saudi Arabia","SN":"Senegal","RS":"Serbia & Montenegro","SC":"Seychelles","SL":"Sierra Leone","SG":"Singapore","SK":"Slovakia","SI":"Slovenia","SB":"Solomon Islands","ZA":"South Africa","SS":"South Sudan","ES":"Spain","LK":"Sri Lanka","BL":"St. Barthelemy","EU":"St. Eustatius","KN":"St. Kitts and Nevis","LC":"St. Lucia","MF":"St. Maarten","VC":"St. Vincent","SR":"Suriname","SZ":"Swaziland","SE":"Sweden","CH":"Switzerland","PF":"Tahiti","TW":"Taiwan","TJ":"Tajikistan","TZ":"Tanzania","TH":"Thailand","TL":"Timor-Leste","TG":"Togo","TO":"Tonga","TT":"Trinidad and Tobago","TN":"Tunisia","TR":"Turkey","TM":"Turkmenistan","TC":"Turks and Caicos Islands","TV":"Tuvalu","UG":"Uganda","UA":"Ukraine","AE":"United Arab Emirates","GB":"United Kingdom","US":"United States","UY":"Uruguay","UZ":"Uzbekistan","VU":"Vanuatu","VE":"Venezuela","VN":"Vietnam","VG":"Virgin Islands (British)","VI":"Virgin Islands (U.S.)","WS":"Western Samoa","YE":"Yemen","ZM":"Zambia","ZW":"Zimbabwe"};
13
- var ig_domesticCountryCodes = ['US'];
14
- var ig_logoUrl = "http://iglobalstores.com/images/iglobal-stores.png";
15
- var ig_flagLocation = "body";
16
- var ig_flagMethod = "prepend";
17
- var ig_flagCode = '<div id="igFlag"></div>';
18
- var ajaxPath = '/iglobal/ajax/matdata';
19
- //ajaxPath = '/magento/index.php/iglobal/ajax/matdata'; //override used on some testing installs
20
-
21
- var hrefMagento = false,
22
- hrefIndex = false,
23
- url = window.location.toString(),
24
- ajaxPath = "";
25
-
26
- hrefMagento = url.indexOf('/magento');
27
- hrefIndex = url.indexOf('/index.php');
28
-
29
- if (hrefMagento != -1 && hrefIndex != -1) {
30
- ajaxPath = '/magento/index.php/iglobal/ajax/matdata';
31
- } else if (hrefMagento != -1 && hrefIndex == -1) {
32
- ajaxPath = '/magento/iglobal/ajax/matdata';
33
- } else if (hrefMagento == -1 && hrefIndex != -1) {
34
- ajaxPath = '/iglobal/ajax/matdata';
35
- }
36
-
37
-
38
- // Set internal JQuery Variable
39
- // Can set to existing $ on page, or can include Jquery here, and set igJq to jquery-no-conflict
40
- //
41
- igJq = jQuery; //Sets internal jquery variable to the existing $ on the page.
42
-
43
- //set my dynamic variables with ajax call to use Magento Configs.
44
- //countries are set in general>country options
45
- //other settings are in the iGlobal tab
46
- var ajaxResult = igJq.ajax({
47
- async: false,
48
- global: false,
49
- url: ajaxPath,
50
- //dataType: 'json',
51
- success: function(data){
52
-
53
- var ajaxResult = eval("(" + data + ")");
54
- //console.log(ajaxResult);
55
- //store ID
56
- if (ajaxResult.storeId && ajaxResult.storeId != "Your Store ID Goes Here"){
57
- // store ID is set
58
- ig_storeId = ajaxResult.storeId;
59
- }
60
-
61
- //flag placement parent
62
- if (ajaxResult.flag_parent){
63
- // store ID is set
64
- ig_flagLocation = ajaxResult.flag_parent;
65
- }
66
-
67
- // TODO: flag placement method
68
- if (ajaxResult.flag_method){
69
- // store ID is set
70
- ig_flagMethod = ajaxResult.flag_method;
71
- ig_flagMethod = ig_flagMethod.toLowerCase();
72
- }
73
-
74
- // TODO: flag placement code
75
- if (ajaxResult.flag_code){
76
- // store ID is set
77
- ig_flagCode = ajaxResult.flag_code;
78
- }
79
-
80
- //serviced country list
81
- if (ajaxResult.servicedCountries){
82
- // store ID is set
83
- ig_countries = ajaxResult.servicedCountries;
84
- }
85
-
86
-
87
- //domestic countries list
88
- if (ajaxResult.domesticCountries){
89
- // store ID is set
90
- ig_domestic = ajaxResult.domesticCountries;
91
- ig_domesticCountryCodes = ig_domestic.split(",")
92
- //console.log(ig_domesticCountryCodes);
93
- }
94
-
95
-
96
- //logo URL
97
- if (ajaxResult.storeLogo){
98
- // store ID is set
99
- ig_logoUrl = ajaxResult.storeLogo;
100
- }
101
-
102
- }
103
- });
104
-
105
-
106
-
107
-
108
- igJq(function(){
109
- if (ig_flagMethod == "prepend"){
110
- igJq(ig_flagLocation).prepend(ig_flagCode);
111
- }
112
- else if (ig_flagMethod == "append"){
113
- igJq(ig_flagLocation).append(ig_flagCode);
114
- }
115
- else if (ig_flagMethod == "before"){
116
- igJq(ig_flagLocation).before(ig_flagCode);
117
- }
118
- else if (ig_flagMethod == "after"){
119
- igJq(ig_flagLocation).after(ig_flagCode);
120
- }
121
- else {
122
- igJq(ig_flagLocation).prepend(ig_flagCode);
123
- }
124
- });
125
-
126
- //
127
- // END Store specific settings
128
- //
129
-
130
- ///////////////////////////////////////////////////////////////////////////////
131
-
132
- //
133
- // Begin jquery jsonp plugin
134
- //
135
- /*
136
- * jQuery JSONP Core Plugin 2.4.0 (2012-08-21)
137
- *
138
- * https://github.com/jaubourg/jquery-jsonp
139
- *
140
- * Copyright (c) 2012 Julian Aubourg
141
- *
142
- * This document is licensed as free software under the terms of the
143
- * MIT License: http://www.opensource.org/licenses/mit-license.php
144
- */
145
- ( function( igJq ) {
146
-
147
- // ###################### UTILITIES ##
148
-
149
- // Noop
150
- function noop() {
151
- }
152
-
153
- // Generic callback
154
- function genericCallback( data ) {
155
- lastValue = [ data ];
156
- }
157
-
158
- // Call if defined
159
- function callIfDefined( method , object , parameters ) {
160
- return method && method.apply( object.context || object , parameters );
161
- }
162
-
163
- // Give joining character given url
164
- function qMarkOrAmp( url ) {
165
- return /\?/ .test( url ) ? "&" : "?";
166
- }
167
-
168
- var // String constants (for better minification)
169
- STR_ASYNC = "async",
170
- STR_CHARSET = "charset",
171
- STR_EMPTY = "",
172
- STR_ERROR = "error",
173
- STR_INSERT_BEFORE = "insertBefore",
174
- STR_JQUERY_JSONP = "_jqjsp",
175
- STR_ON = "on",
176
- STR_ON_CLICK = STR_ON + "click",
177
- STR_ON_ERROR = STR_ON + STR_ERROR,
178
- STR_ON_LOAD = STR_ON + "load",
179
- STR_ON_READY_STATE_CHANGE = STR_ON + "readystatechange",
180
- STR_READY_STATE = "readyState",
181
- STR_REMOVE_CHILD = "removeChild",
182
- STR_SCRIPT_TAG = "<script>",
183
- STR_SUCCESS = "success",
184
- STR_TIMEOUT = "timeout",
185
-
186
- // Window
187
- win = window,
188
- // Deferred
189
- Deferred = igJq.Deferred,
190
- // Head element
191
- head = igJq( "head" )[ 0 ] || document.documentElement,
192
- // Page cache
193
- pageCache = {},
194
- // Counter
195
- count = 0,
196
- // Last returned value
197
- lastValue,
198
-
199
- // ###################### DEFAULT OPTIONS ##
200
- xOptionsDefaults = {
201
- //beforeSend: undefined,
202
- //cache: false,
203
- callback: STR_JQUERY_JSONP,
204
- //callbackParameter: undefined,
205
- //charset: undefined,
206
- //complete: undefined,
207
- //context: undefined,
208
- //data: "",
209
- //dataFilter: undefined,
210
- //error: undefined,
211
- //pageCache: false,
212
- //success: undefined,
213
- //timeout: 0,
214
- //traditional: false,
215
- url: location.href
216
- },
217
-
218
- // opera demands sniffing :/
219
- opera = win.opera,
220
-
221
- // IE < 10
222
- oldIE = !!igJq( "<div>" ).html( "<!--[if IE]><i><![endif]-->" ).find("i").length;
223
-
224
- // ###################### MAIN FUNCTION ##
225
- function jsonp( xOptions ) {
226
-
227
- // Build data with default
228
- xOptions = igJq.extend( {} , xOptionsDefaults , xOptions );
229
-
230
- // References to xOptions members (for better minification)
231
- var successCallback = xOptions.success,
232
- errorCallback = xOptions.error,
233
- completeCallback = xOptions.complete,
234
- dataFilter = xOptions.dataFilter,
235
- callbackParameter = xOptions.callbackParameter,
236
- successCallbackName = xOptions.callback,
237
- cacheFlag = xOptions.cache,
238
- pageCacheFlag = xOptions.pageCache,
239
- charset = xOptions.charset,
240
- url = xOptions.url,
241
- data = xOptions.data,
242
- timeout = xOptions.timeout,
243
- pageCached,
244
-
245
- // Abort/done flag
246
- done = 0,
247
-
248
- // Life-cycle functions
249
- cleanUp = noop,
250
-
251
- // Support vars
252
- supportOnload,
253
- supportOnreadystatechange,
254
-
255
- // Request execution vars
256
- firstChild,
257
- script,
258
- scriptAfter,
259
- timeoutTimer;
260
-
261
- // If we have Deferreds:
262
- // - substitute callbacks
263
- // - promote xOptions to a promise
264
- Deferred && Deferred(function( defer ) {
265
- defer.done( successCallback ).fail( errorCallback );
266
- successCallback = defer.resolve;
267
- errorCallback = defer.reject;
268
- }).promise( xOptions );
269
-
270
- // Create the abort method
271
- xOptions.abort = function() {
272
- !( done++ ) && cleanUp();
273
- };
274
-
275
- // Call beforeSend if provided (early abort if false returned)
276
- if ( callIfDefined( xOptions.beforeSend , xOptions , [ xOptions ] ) === !1 || done ) {
277
- return xOptions;
278
- }
279
-
280
- // Control entries
281
- url = url || STR_EMPTY;
282
- data = data ? ( (typeof data) == "string" ? data : igJq.param( data , xOptions.traditional ) ) : STR_EMPTY;
283
-
284
- // Build final url
285
- url += data ? ( qMarkOrAmp( url ) + data ) : STR_EMPTY;
286
-
287
- // Add callback parameter if provided as option
288
- callbackParameter && ( url += qMarkOrAmp( url ) + encodeURIComponent( callbackParameter ) + "=?" );
289
-
290
- // Add anticache parameter if needed
291
- !cacheFlag && !pageCacheFlag && ( url += qMarkOrAmp( url ) + "_" + ( new Date() ).getTime() + "=" );
292
-
293
- // Replace last ? by callback parameter
294
- url = url.replace( /=\?(&|$)/ , "=" + successCallbackName + "$1" );
295
-
296
- // Success notifier
297
- function notifySuccess( json ) {
298
-
299
- if ( !( done++ ) ) {
300
-
301
- cleanUp();
302
- // Pagecache if needed
303
- pageCacheFlag && ( pageCache [ url ] = { s: [ json ] } );
304
- // Apply the data filter if provided
305
- dataFilter && ( json = dataFilter.apply( xOptions , [ json ] ) );
306
- // Call success then complete
307
- callIfDefined( successCallback , xOptions , [ json , STR_SUCCESS, xOptions ] );
308
- callIfDefined( completeCallback , xOptions , [ xOptions , STR_SUCCESS ] );
309
-
310
- }
311
- }
312
-
313
- // Error notifier
314
- function notifyError( type ) {
315
-
316
- if ( !( done++ ) ) {
317
-
318
- // Clean up
319
- cleanUp();
320
- // If pure error (not timeout), cache if needed
321
- pageCacheFlag && type != STR_TIMEOUT && ( pageCache[ url ] = type );
322
- // Call error then complete
323
- callIfDefined( errorCallback , xOptions , [ xOptions , type ] );
324
- callIfDefined( completeCallback , xOptions , [ xOptions , type ] );
325
-
326
- }
327
- }
328
-
329
- // Check page cache
330
- if ( pageCacheFlag && ( pageCached = pageCache[ url ] ) ) {
331
-
332
- pageCached.s ? notifySuccess( pageCached.s[ 0 ] ) : notifyError( pageCached );
333
-
334
- } else {
335
-
336
- // Install the generic callback
337
- // (BEWARE: global namespace pollution ahoy)
338
- win[ successCallbackName ] = genericCallback;
339
-
340
- // Create the script tag
341
- script = igJq( STR_SCRIPT_TAG )[ 0 ];
342
- script.id = STR_JQUERY_JSONP + count++;
343
-
344
- // Set charset if provided
345
- if ( charset ) {
346
- script[ STR_CHARSET ] = charset;
347
- }
348
-
349
- opera && opera.version() < 11.60 ?
350
- // onerror is not supported: do not set as async and assume in-order execution.
351
- // Add a trailing script to emulate the event
352
- ( ( scriptAfter = igJq( STR_SCRIPT_TAG )[ 0 ] ).text = "document.getElementById('" + script.id + "')." + STR_ON_ERROR + "()" )
353
- :
354
- // onerror is supported: set the script as async to avoid requests blocking each others
355
- ( script[ STR_ASYNC ] = STR_ASYNC )
356
-
357
- ;
358
-
359
- // Internet Explorer: event/htmlFor trick
360
- if ( oldIE ) {
361
- script.htmlFor = script.id;
362
- script.event = STR_ON_CLICK;
363
- }
364
-
365
- // Attached event handlers
366
- script[ STR_ON_LOAD ] = script[ STR_ON_ERROR ] = script[ STR_ON_READY_STATE_CHANGE ] = function ( result ) {
367
-
368
- // Test readyState if it exists
369
- if ( !script[ STR_READY_STATE ] || !/i/.test( script[ STR_READY_STATE ] ) ) {
370
-
371
- try {
372
-
373
- script[ STR_ON_CLICK ] && script[ STR_ON_CLICK ]();
374
-
375
- } catch( _ ) {}
376
-
377
- result = lastValue;
378
- lastValue = 0;
379
- result ? notifySuccess( result[ 0 ] ) : notifyError( STR_ERROR );
380
-
381
- }
382
- };
383
-
384
- // Set source
385
- script.src = url;
386
-
387
- // Re-declare cleanUp function
388
- cleanUp = function( i ) {
389
- timeoutTimer && clearTimeout( timeoutTimer );
390
- script[ STR_ON_READY_STATE_CHANGE ] = script[ STR_ON_LOAD ] = script[ STR_ON_ERROR ] = null;
391
- head[ STR_REMOVE_CHILD ]( script );
392
- scriptAfter && head[ STR_REMOVE_CHILD ]( scriptAfter );
393
- };
394
-
395
- // Append main script
396
- head[ STR_INSERT_BEFORE ]( script , ( firstChild = head.firstChild ) );
397
-
398
- // Append trailing script if needed
399
- scriptAfter && head[ STR_INSERT_BEFORE ]( scriptAfter , firstChild );
400
-
401
- // If a timeout is needed, install it
402
- timeoutTimer = timeout > 0 && setTimeout( function() {
403
- notifyError( STR_TIMEOUT );
404
- } , timeout );
405
-
406
- }
407
-
408
- return xOptions;
409
- }
410
-
411
- // ###################### SETUP FUNCTION ##
412
- jsonp.setup = function( xOptions ) {
413
- igJq.extend( xOptionsDefaults , xOptions );
414
- };
415
-
416
- // ###################### INSTALL in jQuery ##
417
- igJq.jsonp = jsonp;
418
-
419
- } )( igJq );
420
- //
421
- // End jquery jsonp plugin
422
- //
423
-
424
- //
425
- // Begin embedded easyModal.js
426
- //
427
- /**
428
- * easyModal.js v1.1.0
429
- * A minimal jQuery modal that works with your CSS.
430
- * Author: Flavius Matis - http://flaviusmatis.github.com/
431
- * URL: https://github.com/flaviusmatis/easyModal.js
432
- */
433
-
434
- (function(igJq){
435
-
436
- var methods = {
437
- init : function(options) {
438
-
439
- var defaults = {
440
- top: '100',
441
- autoOpen: false,
442
- overlayOpacity: 0.5,
443
- overlayColor: '#000',
444
- overlayClose: true,
445
- overlayParent: 'body',
446
- closeOnEscape: true,
447
- closeButtonClass: '.close',
448
- onOpen: false,
449
- onClose: false
450
- };
451
-
452
- options = igJq.extend(defaults, options);
453
-
454
- return this.each(function() {
455
-
456
- var o = options;
457
-
458
- var $overlay = igJq('<div class="lean-overlay"></div>');
459
-
460
- $overlay.css({
461
- 'display': 'none',
462
- 'position': 'fixed',
463
- 'z-index': 2000,
464
- 'top': 0,
465
- 'left': 0,
466
- 'height': 100 + '%',
467
- 'width': 100+ '%',
468
- 'background': o.overlayColor,
469
- 'opacity': o.overlayOpacity
470
- }).appendTo(o.overlayParent);
471
-
472
- var $modal = igJq(this);
473
-
474
- $modal.css({
475
- 'display': 'none',
476
- 'position' : 'absolute',
477
- 'z-index': 2001,
478
- 'left' : 50 + '%',
479
- 'top' : parseInt(o.top) > -1 ? o.top + 'px' : 50 + '%'
480
- });
481
-
482
- $modal.bind('openModal', function(){
483
- igJq(this).css({
484
- 'display' : 'block',
485
- 'margin-left' : -($modal.outerWidth()/2) + 'px',
486
- 'margin-top' : (parseInt(o.top) > -1 ? 0 : -($modal.outerHeight()/2)) + 'px'
487
- });
488
- $overlay.fadeIn(200, function(){
489
- if (o.onOpen && typeof (o.onOpen) === 'function') {
490
- // onOpen callback receives as argument the modal window
491
- o.onOpen($modal[0]);
492
- }
493
- });
494
- });
495
-
496
- $modal.bind('closeModal', function(){
497
- igJq(this).css('display', 'none');
498
- $overlay.fadeOut(200, function(){
499
- if (o.onClose && typeof(o.onClose) === 'function') {
500
- // onClose callback receives as argument the modal window
501
- o.onClose($modal[0]);
502
- }
503
- });
504
- });
505
-
506
- // Close on overlay click
507
- $overlay.click(function() {
508
- if (o.overlayClose)
509
- $modal.trigger('closeModal');
510
- });
511
-
512
- igJq(document).keydown(function(e) {
513
- // ESCAPE key pressed
514
- if (o.closeOnEscape && e.keyCode == 27) {
515
- $modal.trigger('closeModal');
516
- }
517
- });
518
-
519
- // Close when button pressed
520
- $modal.on('click', o.closeButtonClass, function(e) {
521
- $modal.trigger('closeModal');
522
- e.preventDefault();
523
- });
524
-
525
- // Automatically open modal if option set
526
- if (o.autoOpen)
527
- $modal.trigger('openModal');
528
-
529
- });
530
-
531
- }
532
- };
533
-
534
- igJq.fn.easyModal = function(method) {
535
-
536
- // Method calling logic
537
- if (methods[method]) {
538
- return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
539
- } else if (typeof method === 'object' || ! method) {
540
- return methods.init.apply(this, arguments);
541
- } else {
542
- igJq.error('Method ' + method + ' does not exist on jQuery.easyModal');
543
- }
544
-
545
- };
546
-
547
- })(igJq);
548
- //
549
- // End embedded easyModal.js
550
- //
551
-
552
-
553
- //
554
- // Begin embedded jquery cookie plugin, for readying and writing cookies easily
555
- //
556
- (function (factory) {
557
- if (typeof define === 'function' && define.amd) {
558
- // AMD. Register as anonymous module.
559
- define(['jquery'], factory);
560
- } else {
561
- // Browser globals.
562
- factory(igJq);
563
- }
564
- }(function (igJq) {
565
-
566
- var pluses = /\+/g;
567
-
568
- function raw(s) {
569
- return s;
570
- }
571
-
572
- function decoded(s) {
573
- return decodeURIComponent(s.replace(pluses, ' '));
574
- }
575
-
576
- function converted(s) {
577
- if (s.indexOf('"') === 0) {
578
- // This is a quoted cookie as according to RFC2068, unescape
579
- s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
580
- }
581
- try {
582
- return config.json ? JSON.parse(s) : s;
583
- } catch(er) {}
584
- }
585
-
586
- var config = igJq.cookie = function (key, value, options) {
587
-
588
- // write
589
- if (value !== undefined) {
590
- options = igJq.extend({}, config.defaults, options);
591
-
592
- if (typeof options.expires === 'number') {
593
- var days = options.expires, t = options.expires = new Date();
594
- t.setDate(t.getDate() + days);
595
- }
596
-
597
- value = config.json ? JSON.stringify(value) : String(value);
598
-
599
- return (document.cookie = [
600
- config.raw ? key : encodeURIComponent(key),
601
- '=',
602
- config.raw ? value : encodeURIComponent(value),
603
- options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
604
- options.path ? '; path=' + options.path : '',
605
- options.domain ? '; domain=' + options.domain : '',
606
- options.secure ? '; secure' : ''
607
- ].join(''));
608
- }
609
-
610
- // read
611
- var decode = config.raw ? raw : decoded;
612
- var cookies = document.cookie.split('; ');
613
- var result = key ? undefined : {};
614
- for (var i = 0, l = cookies.length; i < l; i++) {
615
- var parts = cookies[i].split('=');
616
- var name = decode(parts.shift());
617
- var cookie = decode(parts.join('='));
618
-
619
- if (key && key === name) {
620
- result = converted(cookie);
621
- break;
622
- }
623
-
624
- if (!key) {
625
- result[name] = converted(cookie);
626
- }
627
- }
628
-
629
- return result;
630
- };
631
-
632
- config.defaults = {};
633
-
634
- igJq.removeCookie = function (key, options) {
635
- if (igJq.cookie(key) !== undefined) {
636
- // Must not alter options, thus extending a fresh object...
637
- igJq.cookie(key, '', igJq.extend({}, options, { expires: -1 }));
638
- return true;
639
- }
640
- return false;
641
- };
642
-
643
- }));
644
- //
645
- // End embedded jquery cookie plugin, for readying and writing cookies easily
646
- //
647
-
648
-
649
- //
650
- // Begin iGlobal Stores Splash code
651
- //
652
-
653
- function ig_getParameterByName(name) {
654
- name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
655
- var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
656
- results = regex.exec(location.search);
657
- return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
658
- }
659
-
660
- function ig_createSplashHtml() {
661
- var ig_splashHtml = '<div id="igSplashElement" style="display:none;">';
662
- ig_splashHtml += ig_createSplashContentsHtml();
663
- ig_splashHtml += '</div><!--/#igSplashElement -->';
664
- return ig_splashHtml;
665
- }
666
-
667
- function ig_createSplashContentsHtml() { // Feel free to edit the HTML below to match your site
668
- var ig_splashHtml = '' +
669
- '<img src="https://d1vyngmisxigjx.cloudfront.net/images/close-square.png" alt="Close" class="closeButton close" />' +
670
- '<div class="igModalHeader">' +
671
- '<div class="logoWrapper">' +
672
- '<img class="modalLogo" src="'+ig_logoUrl+'" alt="" />' +
673
- '</div><!--/.logoWrapper -->' +
674
- '<div class="messageWrapper">' +
675
- '<p class="headerZero">Thanks for visiting us from</p>' +
676
- '<img src="https://d1vyngmisxigjx.cloudfront.net/images/flags/96x64/'+((ig_country)?ig_country.toUpperCase():'undefined')+'.png" alt="Flag of '+ig_countries[ig_country]+'" class="headerFlag">' +
677
- '<span class="headerOne">' +ig_countries[ig_country]+'</span><!--/.headerOne-->' +
678
- '<p class="countryP" style="font-size: 12px;">Not in '+ig_countries[ig_country]+'? Please select your country below.</p> ' +
679
- '<div class="countryDropDownWrapper">' +
680
- '<select id="countrySelect" class=".coreUISelect" onchange="ig_countrySelected();"> ' +
681
- '<option value="">Select your country</option>';
682
-
683
- for(var countryCode in ig_countries){
684
- ig_splashHtml += '<option '+((countryCode===ig_country)?'selected="selected" ':'')+'value="'+countryCode+'">'+ig_countries[countryCode]+'</option>';
685
- }
686
-
687
- ig_splashHtml += '' +
688
- '</select>' +
689
- '</div><!--/.countryDropDownWrapper -->' +
690
- '</div><!--/.messageWrapper -->' +
691
- '</div><!--/.igModalHeader -->' +
692
- '<div class="igModalBody">';
693
-
694
- if (ig_isDomesticCountry()) {
695
- //Don't show international shopping features
696
- ig_splashHtml += '' +
697
- '<ul class="featureList">' +
698
- '<div class="igFeatureHeader">Welcome to our website!</div>' +
699
- '</ul>';
700
- } else {
701
- //Show international shopping features
702
- ig_splashHtml += ''+
703
- '<ul class="featureList">' +
704
- '<div class="igFeatureHeader">We offer the following services to shoppers in ' +ig_countries[ig_country]+'.</div>' +
705
- '<li><img src="https://d1vyngmisxigjx.cloudfront.net/images/currencies-icon.png" alt="Your Currency"> See totals and pay in <strong>your currency</strong>' +
706
- '</li>' +
707
- '<li><img src="https://d1vyngmisxigjx.cloudfront.net/images/payment-methods-icon.png" alt="Multiple Payment Methods"> <strong>Multiple payment methods</strong> available' +
708
- '</li>' +
709
- '<li><img src="https://d1vyngmisxigjx.cloudfront.net/images/prepay-duty-tax-icon.png" alt="Prepay Duties and Taxes"> Option to <strong>prepay duties and taxes</strong>' +
710
- '</li>' +
711
- '<li><img src="https://d1vyngmisxigjx.cloudfront.net/images/shipping-icon.png" alt="Shipping Options"> <strong>Multiple shipping options</strong> available' +
712
- '</li>' +
713
- '</ul>';
714
- }
715
-
716
- ig_splashHtml += '' +
717
- '<div class="igWelcomeCTAButton">' +
718
- '<button class="close">Start Shopping</button>' +
719
- '</div><!--/.igWelcomeCTAButton -->' +
720
- '</div><!--/.igModalBody -->' +
721
- '<div class="igModalFooter">' +
722
- '</div><!--/.igModalFooter-->';
723
-
724
- return ig_splashHtml;
725
- }
726
-
727
- function ig_countrySelected() {
728
- var countryCode = igJq("select#countrySelect").val();
729
- ig_setCountry(ig_validateCountryCode(countryCode));
730
- igJq("#igSplashElement").html(ig_createSplashContentsHtml());
731
- ig_alertIceOfCountryChange();
732
- location.reload();
733
- }
734
-
735
- //Called by auto popup logic for first time non domestic country customers. Also called by ALL customers clicking the nested flag on the page
736
- function ig_showTheSplash() {
737
- //Construct the modal
738
- igJq("body").append(ig_createSplashHtml());
739
-
740
- //init easyModal.js modal, after modal content was placed on the page (line above)
741
- igJq("#igSplashElement").easyModal({
742
- onClose: function(myModal){
743
- //on close, let's remove the modal contents and the modal smokescreen created by easyModal.js
744
- igJq("#igSplashElement").remove();
745
- igJq(".lean-overlay").remove();
746
- }
747
- });
748
-
749
- //Fire the modal!
750
- igJq("#igSplashElement").trigger('openModal');
751
-
752
- //Set cookie for Splash shown
753
- if (ig_validateCountryCode(igJq.cookie("igCountry"))) { // Only set the splashShown cookie, if there is a valid countryCookie
754
- igJq.cookie('igSplash', 'igSplash', { expires: 7, path: '/', domain: ig_cookieDomain });
755
- }
756
- }
757
-
758
- function ig_createNestContents() {
759
- return '<img onclick="ig_showTheSplash();" src="https://d1vyngmisxigjx.cloudfront.net/images/flags/96x64/'+((ig_country)?ig_country.toUpperCase():'undefined')+'.png" class="igWelcomeFlagHeader" alt="Select your country." />';
760
- }
761
-
762
- function ig_placeNestHtml() {
763
- igJq(function(){
764
- if (igJq("#igFlag")) {
765
- igJq("#igFlag").html(ig_createNestContents());
766
- }
767
- });
768
- }
769
-
770
- function ig_setCountry(country) {
771
- ig_country = country;
772
- if (ig_country) {
773
- //Set country cookie
774
- igJq.cookie('igCountry', ig_country, { expires: 365, path: '/', domain: ig_cookieDomain });
775
- }
776
- ig_placeNestHtml();
777
- }
778
-
779
- function ig_alertIceOfCountryChange() {
780
- try {
781
- ig_ice_countryChanged(); // let the ICE script know that the country has changed, if there is an ICE script
782
- } catch (err) {
783
- //do nothing
784
- }
785
- }
786
-
787
- function ig_validateCountryCode(countryCode) {
788
- //Return the country code if valid, return null if not valid
789
- var countryDisplayName = ig_countries[countryCode];
790
- if (typeof countryDisplayName !== 'undefined' && countryDisplayName) {
791
- return countryCode;
792
- } else {
793
- return null;
794
- }
795
- }
796
-
797
- function ig_isDomesticCountry() {
798
- return ig_country && igJq.inArray(ig_country, ig_domesticCountryCodes) >= 0;
799
- }
800
-
801
- function ig_detectCountryCallback(countryCode) {
802
- ig_setCountry(ig_validateCountryCode(countryCode));
803
- ig_finishLoading();
804
- }
805
-
806
- function ig_detectCountryCallbackError() { // Error handling method for when the jsonp call to get the countryCode fails, if it will get called?
807
- console.log("Couldn't detect country");
808
- ig_finishLoading();
809
- }
810
-
811
- function ig_detectCountry() {
812
- igJq.jsonp({
813
- url: 'https://iprecon.iglobalstores.com/iGlobalIp.js?p=igcCallback',
814
- callback:'igcCallback',
815
- success: function(json, textStatus, xOptions){ig_detectCountryCallback(json);},
816
- error: function(){ig_detectCountryCallbackError();}
817
- });
818
- }
819
-
820
- function ig_pingIglobal() {
821
- try { // Don't break if this doesn't work
822
- if (!ig_countryParam) {//Only ping iGlobal for real visitors, not url parameter testing
823
- igJq.ajax({//we do not need to trap errors like 503's, for this call
824
- dataType: "jsonp",
825
- url: 'https://iprecon.iglobalstores.com/ping.js?s='+ig_storeId+'&c='+((ig_country)?ig_country:'')
826
- });
827
- }
828
- } catch (err) {
829
- // do nothing
830
- }
831
- }
832
-
833
- //function ig_errorPingIglobal() {
834
- // console.log("Couldn't update iGlobal");
835
- //}
836
-
837
- function ig_finishLoading() {
838
- ig_placeNestHtml();
839
- if (!ig_isDomesticCountry() && (!ig_splashCookie || !ig_country || ig_countryParam)) {
840
- igJq(ig_showTheSplash); //Schedule Showing the Splash
841
- }
842
- //Removed to avoid circular onReady dependency with iCE Script
843
- // ig_alertIceOfCountryChange();
844
- ig_pingIglobal();
845
- }
846
-
847
- var ig_country = null;
848
- var ig_countryCookie = ig_validateCountryCode(igJq.cookie("igCountry"));
849
- var ig_countryParam = ig_validateCountryCode(ig_getParameterByName("igCountry"));
850
- var ig_splashCookie = igJq.cookie("igSplash");
851
-
852
- //set country to URL parameter igCountry
853
- if (!ig_country && ig_countryParam) {
854
- ig_country = ig_countryParam;
855
- }
856
-
857
- //else set country to countryCookie
858
- if (!ig_country && ig_countryCookie) {
859
- ig_country = ig_countryCookie;
860
- }
861
-
862
- //else set country to countryIP from iGlobal's IP Recognition Service
863
- if (!ig_country) {
864
- ig_detectCountry();
865
- } else { // else go with whatever country we have, even no country
866
- ig_finishLoading();
867
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/iGlobal/igc.cs.magento_default_ice.js DELETED
@@ -1,203 +0,0 @@
1
- $igc =jQuery
2
-
3
-
4
- //These are the Key variables used in customizing this script. By changing these, many Magento themes will operate correctly with iGlobal technology. Some themes require further customization by defining the item details below.
5
- //identify the store
6
- var igStoreId = "3"; //this can be set by updating the "iGlobal Store ID Number" in Magento conficuration options
7
- var igSubdomain = "checkout"; //this can be set by updating the "iGlobal Hosted Checkout Subdomain" in Magento conficuration options
8
- var igCartUrl = "/checkout/cart";
9
- var ajaxPath = '/iglobal/ajax/icedata';
10
- //ajaxPath = '/magento/index.php/iglobal/ajax/icedata'; //override used on some testing installs
11
-
12
- $igc.post (
13
- ajaxPath,
14
- function(data){
15
-
16
- //console.log(data);
17
- var result = eval("(" + data + ")");
18
-
19
- if (result.storeId){
20
- // store ID is set
21
- igStoreId = result.storeId;
22
- }
23
-
24
- if (result.subdomain){
25
- // subdomain is set
26
- igSubdomain = result.subdomain;
27
- }
28
-
29
- if (result.cartUrl){
30
- // subdomain is set
31
- igCartUrl = result.cartUrl;
32
- }
33
-
34
- }
35
- );
36
- //}
37
-
38
- function igcCheckout() {
39
-
40
- igcGoToCheckout(igStoreId);
41
- }
42
-
43
- function getSelectedCountry() {
44
- return ig_country;
45
- }
46
-
47
- function getSubDomain() {
48
- return igSubdomain;
49
- }
50
-
51
- function igcGetItems() {
52
-
53
- var items = new Array();
54
- var itemRows = $igc(".igItemDetails");//products rows
55
-
56
- $igc(itemRows).each(function() {
57
- var qty = $igc(this).find('.igQty').text();
58
- var price = $igc(this).find('.igPrice').text();
59
- var imgURL = $igc(this).find('.igImage').text();
60
- var itemURL = $igc(this).find('.igUrl').text();
61
- var descTxt = '<span class="itemDescription">' + $igc(this).find('.igName').text() + '</span>';// + $igc(this).find('.igItemOptions').html();
62
- var sku = $igc(this).find('.igSku').text();
63
- var pid =$igc(this).find('.igID').text();
64
- if ($igc(this).find('.ig_itemWeight').text()){
65
- var weight = $igc(this).find('.ig_itemWeight').text();
66
- } else {
67
- var weight = $igc(this).find('.MageWeight').text();
68
- }
69
- var weight = $igc(this).find('.ig_itemWeight').text();
70
- var length = $igc(this).find('.ig_itemLength').text();
71
- var width = $igc(this).find('.ig_itemWidth').text();
72
- var height = $igc(this).find('.ig_itemHeight').text();
73
-
74
-
75
- if(qty){
76
- items.push({
77
- "itemDescription":$igc.trim(descTxt),
78
- "itemQuantity":$igc.trim(qty),
79
- "itemUnitPrice": $igc.trim(price),
80
- "itemURL": itemURL,
81
- "itemImageURL": imgURL,
82
- "itemSku": sku,
83
- "itemProductId": pid,
84
- "itemWeight": weight,
85
- "itemLength": length,
86
- "itemWidth": width,
87
- "itemHeight": height
88
- });
89
- }
90
- });
91
- return items;
92
- }
93
-
94
- var oldButton = "";
95
- var oldOnClick = "";
96
-
97
- function ig_recordOnClick () {
98
- //record click actions
99
- oldButton = $igc(':button[title="Proceed to Checkout"]'); //this is the jQuery selector for your checkout button
100
- oldOnClick = oldButton.attr('onclick'); //this is the attribute or click function that moves from the cart to checkout. defining this lets us move international customers to your iGlobal hosted checkout automatically.
101
- //console.log(oldOnClick);
102
- }
103
-
104
- //domestic configuration
105
-
106
- function ig_domesticActions () {
107
- $igc(oldButton).off(); // remove event handler if it was added by ig_internationalActions()
108
- //replace old onclick attr
109
- $igc(oldButton).attr('onclick',oldOnClick);
110
-
111
- //hide the shipping estimate and discount codes for int'l visitors
112
- $igc(".shipping").show();
113
- $igc(".discount").show();
114
- $igc('a[title="Checkout with Multiple Addresses"]').show();
115
- }
116
-
117
-
118
- //international configuration
119
-
120
- function ig_internationalActions () {
121
-
122
- //take over button
123
- $igc(oldButton).attr('onclick','');
124
- $igc(oldButton).click(function(){
125
- igcCheckout();
126
- });
127
- //hide the shipping estimate and discount codes for int'l visitors
128
- $igc(".shipping").hide();
129
- $igc(".discount").hide();
130
- $igc('a[title="Checkout with Multiple Addresses"]').hide();
131
-
132
- }
133
-
134
- //for when the country is changed
135
- function ig_ice_countryChanged() {
136
-
137
- if (window.location.href.indexOf("cart") != -1) {
138
-
139
- if ( !ig_isDomesticCountry() ){
140
-
141
- ig_internationalActions ();
142
-
143
- } else {
144
-
145
- ig_domesticActions ();
146
-
147
- }
148
- }
149
-
150
- if ((window.location.href.indexOf("checkout") != -1) && (window.location.href.indexOf("cart") == -1)) {
151
-
152
- if ( !ig_isDomesticCountry() ){
153
-
154
- alert('You are using the domestic checkout for an international order. Please return to your cart and checkout again.');
155
- window.location.replace(igCartUrl);
156
-
157
- }
158
- }
159
- }
160
-
161
-
162
- $igc(document).ready(function(){
163
-
164
-
165
- if ((window.location.href.indexOf("checkout") != -1) && (window.location.href.indexOf("cart") == -1)) {
166
-
167
- if ( !ig_isDomesticCountry() ){
168
-
169
- alert('You are using the domestic checkout for an international order. Please return to your cart and checkout again.');
170
- //window.location.replace(igCartUrl);
171
-
172
- }
173
- }
174
-
175
- //button logic
176
- if(!$igc("#welcome_mat_deactivated").length){ //welcome mat active, take button or set country
177
- if(ig_country){
178
-
179
- ig_recordOnClick();
180
-
181
- if(!ig_isDomesticCountry()){
182
-
183
- ig_internationalActions ();
184
-
185
- }
186
- } else {
187
- alert("Please select your country from the list, and click the Checkout button again.");
188
- ig_showTheSplash();
189
- return false;
190
- }
191
-
192
- } else {
193
- //add additional button b/c no welcome mat
194
- var igButton = $igc('<br /><img>').attr("src","https://checkout.iglobalstores.com/images/iglobal-button2.png").attr("class","igButton").css({cursor:"pointer"});
195
-
196
- $igc(".totals .checkout-types").append($igc("<li>").append(igButton));
197
-
198
- $igc(igButton).click(function() {
199
- igcCheckout();
200
- });
201
-
202
- }
203
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/iGlobal/jquery/jquery.js DELETED
@@ -1,9603 +0,0 @@
1
- /*!
2
- * @package jQuery Library.
3
- * @author: A.A.Treitjak
4
- * @copyright: 2012 - 2013 BelVG.com
5
- */
6
-
7
- /*!
8
- * jQuery JavaScript Library v1.9.1
9
- * http://jquery.com/
10
- *
11
- * Includes Sizzle.js
12
- * http://sizzlejs.com/
13
- *
14
- * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors
15
- * Released under the MIT license
16
- * http://jquery.org/license
17
- *
18
- * Date: 2013-2-4
19
- */
20
- (function( window, undefined ) {
21
-
22
- // Can't do this because several apps including ASP.NET trace
23
- // the stack via arguments.caller.callee and Firefox dies if
24
- // you try to trace through "use strict" call chains. (#13335)
25
- // Support: Firefox 18+
26
- //"use strict";
27
- var
28
- // The deferred used on DOM ready
29
- readyList,
30
-
31
- // A central reference to the root jQuery(document)
32
- rootjQuery,
33
-
34
- // Support: IE<9
35
- // For `typeof node.method` instead of `node.method !== undefined`
36
- core_strundefined = typeof undefined,
37
-
38
- // Use the correct document accordingly with window argument (sandbox)
39
- document = window.document,
40
- location = window.location,
41
-
42
- // Map over jQuery in case of overwrite
43
- _jQuery = window.jQuery,
44
-
45
- // Map over the $ in case of overwrite
46
- _$ = window.$,
47
-
48
- // [[Class]] -> type pairs
49
- class2type = {},
50
-
51
- // List of deleted data cache ids, so we can reuse them
52
- core_deletedIds = [],
53
-
54
- core_version = "1.9.1",
55
-
56
- // Save a reference to some core methods
57
- core_concat = core_deletedIds.concat,
58
- core_push = core_deletedIds.push,
59
- core_slice = core_deletedIds.slice,
60
- core_indexOf = core_deletedIds.indexOf,
61
- core_toString = class2type.toString,
62
- core_hasOwn = class2type.hasOwnProperty,
63
- core_trim = core_version.trim,
64
-
65
- // Define a local copy of jQuery
66
- jQuery = function( selector, context ) {
67
- // The jQuery object is actually just the init constructor 'enhanced'
68
- return new jQuery.fn.init( selector, context, rootjQuery );
69
- },
70
-
71
- // Used for matching numbers
72
- core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
73
-
74
- // Used for splitting on whitespace
75
- core_rnotwhite = /\S+/g,
76
-
77
- // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
78
- rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
79
-
80
- // A simple way to check for HTML strings
81
- // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
82
- // Strict HTML recognition (#11290: must start with <)
83
- rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,
84
-
85
- // Match a standalone tag
86
- rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
87
-
88
- // JSON RegExp
89
- rvalidchars = /^[\],:{}\s]*$/,
90
- rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
91
- rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
92
- rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,
93
-
94
- // Matches dashed string for camelizing
95
- rmsPrefix = /^-ms-/,
96
- rdashAlpha = /-([\da-z])/gi,
97
-
98
- // Used by jQuery.camelCase as callback to replace()
99
- fcamelCase = function( all, letter ) {
100
- return letter.toUpperCase();
101
- },
102
-
103
- // The ready event handler
104
- completed = function( event ) {
105
-
106
- // readyState === "complete" is good enough for us to call the dom ready in oldIE
107
- if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
108
- detach();
109
- jQuery.ready();
110
- }
111
- },
112
- // Clean-up method for dom ready events
113
- detach = function() {
114
- if ( document.addEventListener ) {
115
- document.removeEventListener( "DOMContentLoaded", completed, false );
116
- window.removeEventListener( "load", completed, false );
117
-
118
- } else {
119
- document.detachEvent( "onreadystatechange", completed );
120
- window.detachEvent( "onload", completed );
121
- }
122
- };
123
-
124
- jQuery.fn = jQuery.prototype = {
125
- // The current version of jQuery being used
126
- jquery: core_version,
127
-
128
- constructor: jQuery,
129
- init: function( selector, context, rootjQuery ) {
130
- var match, elem;
131
-
132
- // HANDLE: $(""), $(null), $(undefined), $(false)
133
- if ( !selector ) {
134
- return this;
135
- }
136
-
137
- // Handle HTML strings
138
- if ( typeof selector === "string" ) {
139
- if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
140
- // Assume that strings that start and end with <> are HTML and skip the regex check
141
- match = [ null, selector, null ];
142
-
143
- } else {
144
- match = rquickExpr.exec( selector );
145
- }
146
-
147
- // Match html or make sure no context is specified for #id
148
- if ( match && (match[1] || !context) ) {
149
-
150
- // HANDLE: $(html) -> $(array)
151
- if ( match[1] ) {
152
- context = context instanceof jQuery ? context[0] : context;
153
-
154
- // scripts is true for back-compat
155
- jQuery.merge( this, jQuery.parseHTML(
156
- match[1],
157
- context && context.nodeType ? context.ownerDocument || context : document,
158
- true
159
- ) );
160
-
161
- // HANDLE: $(html, props)
162
- if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
163
- for ( match in context ) {
164
- // Properties of context are called as methods if possible
165
- if ( jQuery.isFunction( this[ match ] ) ) {
166
- this[ match ]( context[ match ] );
167
-
168
- // ...and otherwise set as attributes
169
- } else {
170
- this.attr( match, context[ match ] );
171
- }
172
- }
173
- }
174
-
175
- return this;
176
-
177
- // HANDLE: $(#id)
178
- } else {
179
- elem = document.getElementById( match[2] );
180
-
181
- // Check parentNode to catch when Blackberry 4.6 returns
182
- // nodes that are no longer in the document #6963
183
- if ( elem && elem.parentNode ) {
184
- // Handle the case where IE and Opera return items
185
- // by name instead of ID
186
- if ( elem.id !== match[2] ) {
187
- return rootjQuery.find( selector );
188
- }
189
-
190
- // Otherwise, we inject the element directly into the jQuery object
191
- this.length = 1;
192
- this[0] = elem;
193
- }
194
-
195
- this.context = document;
196
- this.selector = selector;
197
- return this;
198
- }
199
-
200
- // HANDLE: $(expr, $(...))
201
- } else if ( !context || context.jquery ) {
202
- return ( context || rootjQuery ).find( selector );
203
-
204
- // HANDLE: $(expr, context)
205
- // (which is just equivalent to: $(context).find(expr)
206
- } else {
207
- return this.constructor( context ).find( selector );
208
- }
209
-
210
- // HANDLE: $(DOMElement)
211
- } else if ( selector.nodeType ) {
212
- this.context = this[0] = selector;
213
- this.length = 1;
214
- return this;
215
-
216
- // HANDLE: $(function)
217
- // Shortcut for document ready
218
- } else if ( jQuery.isFunction( selector ) ) {
219
- return rootjQuery.ready( selector );
220
- }
221
-
222
- if ( selector.selector !== undefined ) {
223
- this.selector = selector.selector;
224
- this.context = selector.context;
225
- }
226
-
227
- return jQuery.makeArray( selector, this );
228
- },
229
-
230
- // Start with an empty selector
231
- selector: "",
232
-
233
- // The default length of a jQuery object is 0
234
- length: 0,
235
-
236
- // The number of elements contained in the matched element set
237
- size: function() {
238
- return this.length;
239
- },
240
-
241
- toArray: function() {
242
- return core_slice.call( this );
243
- },
244
-
245
- // Get the Nth element in the matched element set OR
246
- // Get the whole matched element set as a clean array
247
- get: function( num ) {
248
- return num == null ?
249
-
250
- // Return a 'clean' array
251
- this.toArray() :
252
-
253
- // Return just the object
254
- ( num < 0 ? this[ this.length + num ] : this[ num ] );
255
- },
256
-
257
- // Take an array of elements and push it onto the stack
258
- // (returning the new matched element set)
259
- pushStack: function( elems ) {
260
-
261
- // Build a new jQuery matched element set
262
- var ret = jQuery.merge( this.constructor(), elems );
263
-
264
- // Add the old object onto the stack (as a reference)
265
- ret.prevObject = this;
266
- ret.context = this.context;
267
-
268
- // Return the newly-formed element set
269
- return ret;
270
- },
271
-
272
- // Execute a callback for every element in the matched set.
273
- // (You can seed the arguments with an array of args, but this is
274
- // only used internally.)
275
- each: function( callback, args ) {
276
- return jQuery.each( this, callback, args );
277
- },
278
-
279
- ready: function( fn ) {
280
- // Add the callback
281
- jQuery.ready.promise().done( fn );
282
-
283
- return this;
284
- },
285
-
286
- slice: function() {
287
- return this.pushStack( core_slice.apply( this, arguments ) );
288
- },
289
-
290
- first: function() {
291
- return this.eq( 0 );
292
- },
293
-
294
- last: function() {
295
- return this.eq( -1 );
296
- },
297
-
298
- eq: function( i ) {
299
- var len = this.length,
300
- j = +i + ( i < 0 ? len : 0 );
301
- return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
302
- },
303
-
304
- map: function( callback ) {
305
- return this.pushStack( jQuery.map(this, function( elem, i ) {
306
- return callback.call( elem, i, elem );
307
- }));
308
- },
309
-
310
- end: function() {
311
- return this.prevObject || this.constructor(null);
312
- },
313
-
314
- // For internal use only.
315
- // Behaves like an Array's method, not like a jQuery method.
316
- push: core_push,
317
- sort: [].sort,
318
- splice: [].splice
319
- };
320
-
321
- // Give the init function the jQuery prototype for later instantiation
322
- jQuery.fn.init.prototype = jQuery.fn;
323
-
324
- jQuery.extend = jQuery.fn.extend = function() {
325
- var src, copyIsArray, copy, name, options, clone,
326
- target = arguments[0] || {},
327
- i = 1,
328
- length = arguments.length,
329
- deep = false;
330
-
331
- // Handle a deep copy situation
332
- if ( typeof target === "boolean" ) {
333
- deep = target;
334
- target = arguments[1] || {};
335
- // skip the boolean and the target
336
- i = 2;
337
- }
338
-
339
- // Handle case when target is a string or something (possible in deep copy)
340
- if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
341
- target = {};
342
- }
343
-
344
- // extend jQuery itself if only one argument is passed
345
- if ( length === i ) {
346
- target = this;
347
- --i;
348
- }
349
-
350
- for ( ; i < length; i++ ) {
351
- // Only deal with non-null/undefined values
352
- if ( (options = arguments[ i ]) != null ) {
353
- // Extend the base object
354
- for ( name in options ) {
355
- src = target[ name ];
356
- copy = options[ name ];
357
-
358
- // Prevent never-ending loop
359
- if ( target === copy ) {
360
- continue;
361
- }
362
-
363
- // Recurse if we're merging plain objects or arrays
364
- if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
365
- if ( copyIsArray ) {
366
- copyIsArray = false;
367
- clone = src && jQuery.isArray(src) ? src : [];
368
-
369
- } else {
370
- clone = src && jQuery.isPlainObject(src) ? src : {};
371
- }
372
-
373
- // Never move original objects, clone them
374
- target[ name ] = jQuery.extend( deep, clone, copy );
375
-
376
- // Don't bring in undefined values
377
- } else if ( copy !== undefined ) {
378
- target[ name ] = copy;
379
- }
380
- }
381
- }
382
- }
383
-
384
- // Return the modified object
385
- return target;
386
- };
387
-
388
- jQuery.extend({
389
- noConflict: function( deep ) {
390
- if ( window.$ === jQuery ) {
391
- window.$ = _$;
392
- }
393
-
394
- if ( deep && window.jQuery === jQuery ) {
395
- window.jQuery = _jQuery;
396
- }
397
-
398
- return jQuery;
399
- },
400
-
401
- // Is the DOM ready to be used? Set to true once it occurs.
402
- isReady: false,
403
-
404
- // A counter to track how many items to wait for before
405
- // the ready event fires. See #6781
406
- readyWait: 1,
407
-
408
- // Hold (or release) the ready event
409
- holdReady: function( hold ) {
410
- if ( hold ) {
411
- jQuery.readyWait++;
412
- } else {
413
- jQuery.ready( true );
414
- }
415
- },
416
-
417
- // Handle when the DOM is ready
418
- ready: function( wait ) {
419
-
420
- // Abort if there are pending holds or we're already ready
421
- if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
422
- return;
423
- }
424
-
425
- // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
426
- if ( !document.body ) {
427
- return setTimeout( jQuery.ready );
428
- }
429
-
430
- // Remember that the DOM is ready
431
- jQuery.isReady = true;
432
-
433
- // If a normal DOM Ready event fired, decrement, and wait if need be
434
- if ( wait !== true && --jQuery.readyWait > 0 ) {
435
- return;
436
- }
437
-
438
- // If there are functions bound, to execute
439
- readyList.resolveWith( document, [ jQuery ] );
440
-
441
- // Trigger any bound ready events
442
- if ( jQuery.fn.trigger ) {
443
- jQuery( document ).trigger("ready").off("ready");
444
- }
445
- },
446
-
447
- // See test/unit/core.js for details concerning isFunction.
448
- // Since version 1.3, DOM methods and functions like alert
449
- // aren't supported. They return false on IE (#2968).
450
- isFunction: function( obj ) {
451
- return jQuery.type(obj) === "function";
452
- },
453
-
454
- isArray: Array.isArray || function( obj ) {
455
- return jQuery.type(obj) === "array";
456
- },
457
-
458
- isWindow: function( obj ) {
459
- return obj != null && obj == obj.window;
460
- },
461
-
462
- isNumeric: function( obj ) {
463
- return !isNaN( parseFloat(obj) ) && isFinite( obj );
464
- },
465
-
466
- type: function( obj ) {
467
- if ( obj == null ) {
468
- return String( obj );
469
- }
470
- return typeof obj === "object" || typeof obj === "function" ?
471
- class2type[ core_toString.call(obj) ] || "object" :
472
- typeof obj;
473
- },
474
-
475
- isPlainObject: function( obj ) {
476
- // Must be an Object.
477
- // Because of IE, we also have to check the presence of the constructor property.
478
- // Make sure that DOM nodes and window objects don't pass through, as well
479
- if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
480
- return false;
481
- }
482
-
483
- try {
484
- // Not own constructor property must be Object
485
- if ( obj.constructor &&
486
- !core_hasOwn.call(obj, "constructor") &&
487
- !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
488
- return false;
489
- }
490
- } catch ( e ) {
491
- // IE8,9 Will throw exceptions on certain host objects #9897
492
- return false;
493
- }
494
-
495
- // Own properties are enumerated firstly, so to speed up,
496
- // if last one is own, then all properties are own.
497
-
498
- var key;
499
- for ( key in obj ) {}
500
-
501
- return key === undefined || core_hasOwn.call( obj, key );
502
- },
503
-
504
- isEmptyObject: function( obj ) {
505
- var name;
506
- for ( name in obj ) {
507
- return false;
508
- }
509
- return true;
510
- },
511
-
512
- error: function( msg ) {
513
- throw new Error( msg );
514
- },
515
-
516
- // data: string of html
517
- // context (optional): If specified, the fragment will be created in this context, defaults to document
518
- // keepScripts (optional): If true, will include scripts passed in the html string
519
- parseHTML: function( data, context, keepScripts ) {
520
- if ( !data || typeof data !== "string" ) {
521
- return null;
522
- }
523
- if ( typeof context === "boolean" ) {
524
- keepScripts = context;
525
- context = false;
526
- }
527
- context = context || document;
528
-
529
- var parsed = rsingleTag.exec( data ),
530
- scripts = !keepScripts && [];
531
-
532
- // Single tag
533
- if ( parsed ) {
534
- return [ context.createElement( parsed[1] ) ];
535
- }
536
-
537
- parsed = jQuery.buildFragment( [ data ], context, scripts );
538
- if ( scripts ) {
539
- jQuery( scripts ).remove();
540
- }
541
- return jQuery.merge( [], parsed.childNodes );
542
- },
543
-
544
- parseJSON: function( data ) {
545
- // Attempt to parse using the native JSON parser first
546
- if ( window.JSON && window.JSON.parse ) {
547
- return window.JSON.parse( data );
548
- }
549
-
550
- if ( data === null ) {
551
- return data;
552
- }
553
-
554
- if ( typeof data === "string" ) {
555
-
556
- // Make sure leading/trailing whitespace is removed (IE can't handle it)
557
- data = jQuery.trim( data );
558
-
559
- if ( data ) {
560
- // Make sure the incoming data is actual JSON
561
- // Logic borrowed from http://json.org/json2.js
562
- if ( rvalidchars.test( data.replace( rvalidescape, "@" )
563
- .replace( rvalidtokens, "]" )
564
- .replace( rvalidbraces, "")) ) {
565
-
566
- return ( new Function( "return " + data ) )();
567
- }
568
- }
569
- }
570
-
571
- jQuery.error( "Invalid JSON: " + data );
572
- },
573
-
574
- // Cross-browser xml parsing
575
- parseXML: function( data ) {
576
- var xml, tmp;
577
- if ( !data || typeof data !== "string" ) {
578
- return null;
579
- }
580
- try {
581
- if ( window.DOMParser ) { // Standard
582
- tmp = new DOMParser();
583
- xml = tmp.parseFromString( data , "text/xml" );
584
- } else { // IE
585
- xml = new ActiveXObject( "Microsoft.XMLDOM" );
586
- xml.async = "false";
587
- xml.loadXML( data );
588
- }
589
- } catch( e ) {
590
- xml = undefined;
591
- }
592
- if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
593
- jQuery.error( "Invalid XML: " + data );
594
- }
595
- return xml;
596
- },
597
-
598
- noop: function() {},
599
-
600
- // Evaluates a script in a global context
601
- // Workarounds based on findings by Jim Driscoll
602
- // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
603
- globalEval: function( data ) {
604
- if ( data && jQuery.trim( data ) ) {
605
- // We use execScript on Internet Explorer
606
- // We use an anonymous function so that context is window
607
- // rather than jQuery in Firefox
608
- ( window.execScript || function( data ) {
609
- window[ "eval" ].call( window, data );
610
- } )( data );
611
- }
612
- },
613
-
614
- // Convert dashed to camelCase; used by the css and data modules
615
- // Microsoft forgot to hump their vendor prefix (#9572)
616
- camelCase: function( string ) {
617
- return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
618
- },
619
-
620
- nodeName: function( elem, name ) {
621
- return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
622
- },
623
-
624
- // args is for internal usage only
625
- each: function( obj, callback, args ) {
626
- var value,
627
- i = 0,
628
- length = obj.length,
629
- isArray = isArraylike( obj );
630
-
631
- if ( args ) {
632
- if ( isArray ) {
633
- for ( ; i < length; i++ ) {
634
- value = callback.apply( obj[ i ], args );
635
-
636
- if ( value === false ) {
637
- break;
638
- }
639
- }
640
- } else {
641
- for ( i in obj ) {
642
- value = callback.apply( obj[ i ], args );
643
-
644
- if ( value === false ) {
645
- break;
646
- }
647
- }
648
- }
649
-
650
- // A special, fast, case for the most common use of each
651
- } else {
652
- if ( isArray ) {
653
- for ( ; i < length; i++ ) {
654
- value = callback.call( obj[ i ], i, obj[ i ] );
655
-
656
- if ( value === false ) {
657
- break;
658
- }
659
- }
660
- } else {
661
- for ( i in obj ) {
662
- value = callback.call( obj[ i ], i, obj[ i ] );
663
-
664
- if ( value === false ) {
665
- break;
666
- }
667
- }
668
- }
669
- }
670
-
671
- return obj;
672
- },
673
-
674
- // Use native String.trim function wherever possible
675
- trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
676
- function( text ) {
677
- return text == null ?
678
- "" :
679
- core_trim.call( text );
680
- } :
681
-
682
- // Otherwise use our own trimming functionality
683
- function( text ) {
684
- return text == null ?
685
- "" :
686
- ( text + "" ).replace( rtrim, "" );
687
- },
688
-
689
- // results is for internal usage only
690
- makeArray: function( arr, results ) {
691
- var ret = results || [];
692
-
693
- if ( arr != null ) {
694
- if ( isArraylike( Object(arr) ) ) {
695
- jQuery.merge( ret,
696
- typeof arr === "string" ?
697
- [ arr ] : arr
698
- );
699
- } else {
700
- core_push.call( ret, arr );
701
- }
702
- }
703
-
704
- return ret;
705
- },
706
-
707
- inArray: function( elem, arr, i ) {
708
- var len;
709
-
710
- if ( arr ) {
711
- if ( core_indexOf ) {
712
- return core_indexOf.call( arr, elem, i );
713
- }
714
-
715
- len = arr.length;
716
- i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
717
-
718
- for ( ; i < len; i++ ) {
719
- // Skip accessing in sparse arrays
720
- if ( i in arr && arr[ i ] === elem ) {
721
- return i;
722
- }
723
- }
724
- }
725
-
726
- return -1;
727
- },
728
-
729
- merge: function( first, second ) {
730
- var l = second.length,
731
- i = first.length,
732
- j = 0;
733
-
734
- if ( typeof l === "number" ) {
735
- for ( ; j < l; j++ ) {
736
- first[ i++ ] = second[ j ];
737
- }
738
- } else {
739
- while ( second[j] !== undefined ) {
740
- first[ i++ ] = second[ j++ ];
741
- }
742
- }
743
-
744
- first.length = i;
745
-
746
- return first;
747
- },
748
-
749
- grep: function( elems, callback, inv ) {
750
- var retVal,
751
- ret = [],
752
- i = 0,
753
- length = elems.length;
754
- inv = !!inv;
755
-
756
- // Go through the array, only saving the items
757
- // that pass the validator function
758
- for ( ; i < length; i++ ) {
759
- retVal = !!callback( elems[ i ], i );
760
- if ( inv !== retVal ) {
761
- ret.push( elems[ i ] );
762
- }
763
- }
764
-
765
- return ret;
766
- },
767
-
768
- // arg is for internal usage only
769
- map: function( elems, callback, arg ) {
770
- var value,
771
- i = 0,
772
- length = elems.length,
773
- isArray = isArraylike( elems ),
774
- ret = [];
775
-
776
- // Go through the array, translating each of the items to their
777
- if ( isArray ) {
778
- for ( ; i < length; i++ ) {
779
- value = callback( elems[ i ], i, arg );
780
-
781
- if ( value != null ) {
782
- ret[ ret.length ] = value;
783
- }
784
- }
785
-
786
- // Go through every key on the object,
787
- } else {
788
- for ( i in elems ) {
789
- value = callback( elems[ i ], i, arg );
790
-
791
- if ( value != null ) {
792
- ret[ ret.length ] = value;
793
- }
794
- }
795
- }
796
-
797
- // Flatten any nested arrays
798
- return core_concat.apply( [], ret );
799
- },
800
-
801
- // A global GUID counter for objects
802
- guid: 1,
803
-
804
- // Bind a function to a context, optionally partially applying any
805
- // arguments.
806
- proxy: function( fn, context ) {
807
- var args, proxy, tmp;
808
-
809
- if ( typeof context === "string" ) {
810
- tmp = fn[ context ];
811
- context = fn;
812
- fn = tmp;
813
- }
814
-
815
- // Quick check to determine if target is callable, in the spec
816
- // this throws a TypeError, but we will just return undefined.
817
- if ( !jQuery.isFunction( fn ) ) {
818
- return undefined;
819
- }
820
-
821
- // Simulated bind
822
- args = core_slice.call( arguments, 2 );
823
- proxy = function() {
824
- return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
825
- };
826
-
827
- // Set the guid of unique handler to the same of original handler, so it can be removed
828
- proxy.guid = fn.guid = fn.guid || jQuery.guid++;
829
-
830
- return proxy;
831
- },
832
-
833
- // Multifunctional method to get and set values of a collection
834
- // The value/s can optionally be executed if it's a function
835
- access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
836
- var i = 0,
837
- length = elems.length,
838
- bulk = key == null;
839
-
840
- // Sets many values
841
- if ( jQuery.type( key ) === "object" ) {
842
- chainable = true;
843
- for ( i in key ) {
844
- jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
845
- }
846
-
847
- // Sets one value
848
- } else if ( value !== undefined ) {
849
- chainable = true;
850
-
851
- if ( !jQuery.isFunction( value ) ) {
852
- raw = true;
853
- }
854
-
855
- if ( bulk ) {
856
- // Bulk operations run against the entire set
857
- if ( raw ) {
858
- fn.call( elems, value );
859
- fn = null;
860
-
861
- // ...except when executing function values
862
- } else {
863
- bulk = fn;
864
- fn = function( elem, key, value ) {
865
- return bulk.call( jQuery( elem ), value );
866
- };
867
- }
868
- }
869
-
870
- if ( fn ) {
871
- for ( ; i < length; i++ ) {
872
- fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
873
- }
874
- }
875
- }
876
-
877
- return chainable ?
878
- elems :
879
-
880
- // Gets
881
- bulk ?
882
- fn.call( elems ) :
883
- length ? fn( elems[0], key ) : emptyGet;
884
- },
885
-
886
- now: function() {
887
- return ( new Date() ).getTime();
888
- }
889
- });
890
-
891
- jQuery.ready.promise = function( obj ) {
892
- if ( !readyList ) {
893
-
894
- readyList = jQuery.Deferred();
895
-
896
- // Catch cases where $(document).ready() is called after the browser event has already occurred.
897
- // we once tried to use readyState "interactive" here, but it caused issues like the one
898
- // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
899
- if ( document.readyState === "complete" ) {
900
- // Handle it asynchronously to allow scripts the opportunity to delay ready
901
- setTimeout( jQuery.ready );
902
-
903
- // Standards-based browsers support DOMContentLoaded
904
- } else if ( document.addEventListener ) {
905
- // Use the handy event callback
906
- document.addEventListener( "DOMContentLoaded", completed, false );
907
-
908
- // A fallback to window.onload, that will always work
909
- window.addEventListener( "load", completed, false );
910
-
911
- // If IE event model is used
912
- } else {
913
- // Ensure firing before onload, maybe late but safe also for iframes
914
- document.attachEvent( "onreadystatechange", completed );
915
-
916
- // A fallback to window.onload, that will always work
917
- window.attachEvent( "onload", completed );
918
-
919
- // If IE and not a frame
920
- // continually check to see if the document is ready
921
- var top = false;
922
-
923
- try {
924
- top = window.frameElement == null && document.documentElement;
925
- } catch(e) {}
926
-
927
- if ( top && top.doScroll ) {
928
- (function doScrollCheck() {
929
- if ( !jQuery.isReady ) {
930
-
931
- try {
932
- // Use the trick by Diego Perini
933
- // http://javascript.nwbox.com/IEContentLoaded/
934
- top.doScroll("left");
935
- } catch(e) {
936
- return setTimeout( doScrollCheck, 50 );
937
- }
938
-
939
- // detach all dom ready events
940
- detach();
941
-
942
- // and execute any waiting functions
943
- jQuery.ready();
944
- }
945
- })();
946
- }
947
- }
948
- }
949
- return readyList.promise( obj );
950
- };
951
-
952
- // Populate the class2type map
953
- jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
954
- class2type[ "[object " + name + "]" ] = name.toLowerCase();
955
- });
956
-
957
- function isArraylike( obj ) {
958
- var length = obj.length,
959
- type = jQuery.type( obj );
960
-
961
- if ( jQuery.isWindow( obj ) ) {
962
- return false;
963
- }
964
-
965
- if ( obj.nodeType === 1 && length ) {
966
- return true;
967
- }
968
-
969
- return type === "array" || type !== "function" &&
970
- ( length === 0 ||
971
- typeof length === "number" && length > 0 && ( length - 1 ) in obj );
972
- }
973
-
974
- // All jQuery objects should point back to these
975
- rootjQuery = jQuery(document);
976
- // String to Object options format cache
977
- var optionsCache = {};
978
-
979
- // Convert String-formatted options into Object-formatted ones and store in cache
980
- function createOptions( options ) {
981
- var object = optionsCache[ options ] = {};
982
- jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
983
- object[ flag ] = true;
984
- });
985
- return object;
986
- }
987
-
988
- /*
989
- * Create a callback list using the following parameters:
990
- *
991
- * options: an optional list of space-separated options that will change how
992
- * the callback list behaves or a more traditional option object
993
- *
994
- * By default a callback list will act like an event callback list and can be
995
- * "fired" multiple times.
996
- *
997
- * Possible options:
998
- *
999
- * once: will ensure the callback list can only be fired once (like a Deferred)
1000
- *
1001
- * memory: will keep track of previous values and will call any callback added
1002
- * after the list has been fired right away with the latest "memorized"
1003
- * values (like a Deferred)
1004
- *
1005
- * unique: will ensure a callback can only be added once (no duplicate in the list)
1006
- *
1007
- * stopOnFalse: interrupt callings when a callback returns false
1008
- *
1009
- */
1010
- jQuery.Callbacks = function( options ) {
1011
-
1012
- // Convert options from String-formatted to Object-formatted if needed
1013
- // (we check in cache first)
1014
- options = typeof options === "string" ?
1015
- ( optionsCache[ options ] || createOptions( options ) ) :
1016
- jQuery.extend( {}, options );
1017
-
1018
- var // Flag to know if list is currently firing
1019
- firing,
1020
- // Last fire value (for non-forgettable lists)
1021
- memory,
1022
- // Flag to know if list was already fired
1023
- fired,
1024
- // End of the loop when firing
1025
- firingLength,
1026
- // Index of currently firing callback (modified by remove if needed)
1027
- firingIndex,
1028
- // First callback to fire (used internally by add and fireWith)
1029
- firingStart,
1030
- // Actual callback list
1031
- list = [],
1032
- // Stack of fire calls for repeatable lists
1033
- stack = !options.once && [],
1034
- // Fire callbacks
1035
- fire = function( data ) {
1036
- memory = options.memory && data;
1037
- fired = true;
1038
- firingIndex = firingStart || 0;
1039
- firingStart = 0;
1040
- firingLength = list.length;
1041
- firing = true;
1042
- for ( ; list && firingIndex < firingLength; firingIndex++ ) {
1043
- if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
1044
- memory = false; // To prevent further calls using add
1045
- break;
1046
- }
1047
- }
1048
- firing = false;
1049
- if ( list ) {
1050
- if ( stack ) {
1051
- if ( stack.length ) {
1052
- fire( stack.shift() );
1053
- }
1054
- } else if ( memory ) {
1055
- list = [];
1056
- } else {
1057
- self.disable();
1058
- }
1059
- }
1060
- },
1061
- // Actual Callbacks object
1062
- self = {
1063
- // Add a callback or a collection of callbacks to the list
1064
- add: function() {
1065
- if ( list ) {
1066
- // First, we save the current length
1067
- var start = list.length;
1068
- (function add( args ) {
1069
- jQuery.each( args, function( _, arg ) {
1070
- var type = jQuery.type( arg );
1071
- if ( type === "function" ) {
1072
- if ( !options.unique || !self.has( arg ) ) {
1073
- list.push( arg );
1074
- }
1075
- } else if ( arg && arg.length && type !== "string" ) {
1076
- // Inspect recursively
1077
- add( arg );
1078
- }
1079
- });
1080
- })( arguments );
1081
- // Do we need to add the callbacks to the
1082
- // current firing batch?
1083
- if ( firing ) {
1084
- firingLength = list.length;
1085
- // With memory, if we're not firing then
1086
- // we should call right away
1087
- } else if ( memory ) {
1088
- firingStart = start;
1089
- fire( memory );
1090
- }
1091
- }
1092
- return this;
1093
- },
1094
- // Remove a callback from the list
1095
- remove: function() {
1096
- if ( list ) {
1097
- jQuery.each( arguments, function( _, arg ) {
1098
- var index;
1099
- while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
1100
- list.splice( index, 1 );
1101
- // Handle firing indexes
1102
- if ( firing ) {
1103
- if ( index <= firingLength ) {
1104
- firingLength--;
1105
- }
1106
- if ( index <= firingIndex ) {
1107
- firingIndex--;
1108
- }
1109
- }
1110
- }
1111
- });
1112
- }
1113
- return this;
1114
- },
1115
- // Check if a given callback is in the list.
1116
- // If no argument is given, return whether or not list has callbacks attached.
1117
- has: function( fn ) {
1118
- return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
1119
- },
1120
- // Remove all callbacks from the list
1121
- empty: function() {
1122
- list = [];
1123
- return this;
1124
- },
1125
- // Have the list do nothing anymore
1126
- disable: function() {
1127
- list = stack = memory = undefined;
1128
- return this;
1129
- },
1130
- // Is it disabled?
1131
- disabled: function() {
1132
- return !list;
1133
- },
1134
- // Lock the list in its current state
1135
- lock: function() {
1136
- stack = undefined;
1137
- if ( !memory ) {
1138
- self.disable();
1139
- }
1140
- return this;
1141
- },
1142
- // Is it locked?
1143
- locked: function() {
1144
- return !stack;
1145
- },
1146
- // Call all callbacks with the given context and arguments
1147
- fireWith: function( context, args ) {
1148
- args = args || [];
1149
- args = [ context, args.slice ? args.slice() : args ];
1150
- if ( list && ( !fired || stack ) ) {
1151
- if ( firing ) {
1152
- stack.push( args );
1153
- } else {
1154
- fire( args );
1155
- }
1156
- }
1157
- return this;
1158
- },
1159
- // Call all the callbacks with the given arguments
1160
- fire: function() {
1161
- self.fireWith( this, arguments );
1162
- return this;
1163
- },
1164
- // To know if the callbacks have already been called at least once
1165
- fired: function() {
1166
- return !!fired;
1167
- }
1168
- };
1169
-
1170
- return self;
1171
- };
1172
- jQuery.extend({
1173
-
1174
- Deferred: function( func ) {
1175
- var tuples = [
1176
- // action, add listener, listener list, final state
1177
- [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
1178
- [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
1179
- [ "notify", "progress", jQuery.Callbacks("memory") ]
1180
- ],
1181
- state = "pending",
1182
- promise = {
1183
- state: function() {
1184
- return state;
1185
- },
1186
- always: function() {
1187
- deferred.done( arguments ).fail( arguments );
1188
- return this;
1189
- },
1190
- then: function( /* fnDone, fnFail, fnProgress */ ) {
1191
- var fns = arguments;
1192
- return jQuery.Deferred(function( newDefer ) {
1193
- jQuery.each( tuples, function( i, tuple ) {
1194
- var action = tuple[ 0 ],
1195
- fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
1196
- // deferred[ done | fail | progress ] for forwarding actions to newDefer
1197
- deferred[ tuple[1] ](function() {
1198
- var returned = fn && fn.apply( this, arguments );
1199
- if ( returned && jQuery.isFunction( returned.promise ) ) {
1200
- returned.promise()
1201
- .done( newDefer.resolve )
1202
- .fail( newDefer.reject )
1203
- .progress( newDefer.notify );
1204
- } else {
1205
- newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
1206
- }
1207
- });
1208
- });
1209
- fns = null;
1210
- }).promise();
1211
- },
1212
- // Get a promise for this deferred
1213
- // If obj is provided, the promise aspect is added to the object
1214
- promise: function( obj ) {
1215
- return obj != null ? jQuery.extend( obj, promise ) : promise;
1216
- }
1217
- },
1218
- deferred = {};
1219
-
1220
- // Keep pipe for back-compat
1221
- promise.pipe = promise.then;
1222
-
1223
- // Add list-specific methods
1224
- jQuery.each( tuples, function( i, tuple ) {
1225
- var list = tuple[ 2 ],
1226
- stateString = tuple[ 3 ];
1227
-
1228
- // promise[ done | fail | progress ] = list.add
1229
- promise[ tuple[1] ] = list.add;
1230
-
1231
- // Handle state
1232
- if ( stateString ) {
1233
- list.add(function() {
1234
- // state = [ resolved | rejected ]
1235
- state = stateString;
1236
-
1237
- // [ reject_list | resolve_list ].disable; progress_list.lock
1238
- }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
1239
- }
1240
-
1241
- // deferred[ resolve | reject | notify ]
1242
- deferred[ tuple[0] ] = function() {
1243
- deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
1244
- return this;
1245
- };
1246
- deferred[ tuple[0] + "With" ] = list.fireWith;
1247
- });
1248
-
1249
- // Make the deferred a promise
1250
- promise.promise( deferred );
1251
-
1252
- // Call given func if any
1253
- if ( func ) {
1254
- func.call( deferred, deferred );
1255
- }
1256
-
1257
- // All done!
1258
- return deferred;
1259
- },
1260
-
1261
- // Deferred helper
1262
- when: function( subordinate /* , ..., subordinateN */ ) {
1263
- var i = 0,
1264
- resolveValues = core_slice.call( arguments ),
1265
- length = resolveValues.length,
1266
-
1267
- // the count of uncompleted subordinates
1268
- remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
1269
-
1270
- // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
1271
- deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
1272
-
1273
- // Update function for both resolve and progress values
1274
- updateFunc = function( i, contexts, values ) {
1275
- return function( value ) {
1276
- contexts[ i ] = this;
1277
- values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
1278
- if( values === progressValues ) {
1279
- deferred.notifyWith( contexts, values );
1280
- } else if ( !( --remaining ) ) {
1281
- deferred.resolveWith( contexts, values );
1282
- }
1283
- };
1284
- },
1285
-
1286
- progressValues, progressContexts, resolveContexts;
1287
-
1288
- // add listeners to Deferred subordinates; treat others as resolved
1289
- if ( length > 1 ) {
1290
- progressValues = new Array( length );
1291
- progressContexts = new Array( length );
1292
- resolveContexts = new Array( length );
1293
- for ( ; i < length; i++ ) {
1294
- if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
1295
- resolveValues[ i ].promise()
1296
- .done( updateFunc( i, resolveContexts, resolveValues ) )
1297
- .fail( deferred.reject )
1298
- .progress( updateFunc( i, progressContexts, progressValues ) );
1299
- } else {
1300
- --remaining;
1301
- }
1302
- }
1303
- }
1304
-
1305
- // if we're not waiting on anything, resolve the master
1306
- if ( !remaining ) {
1307
- deferred.resolveWith( resolveContexts, resolveValues );
1308
- }
1309
-
1310
- return deferred.promise();
1311
- }
1312
- });
1313
- jQuery.support = (function() {
1314
-
1315
- var support, all, a,
1316
- input, select, fragment,
1317
- opt, eventName, isSupported, i,
1318
- div = document.createElement("div");
1319
-
1320
- // Setup
1321
- div.setAttribute( "className", "t" );
1322
- div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
1323
-
1324
- // Support tests won't run in some limited or non-browser environments
1325
- all = div.getElementsByTagName("*");
1326
- a = div.getElementsByTagName("a")[ 0 ];
1327
- if ( !all || !a || !all.length ) {
1328
- return {};
1329
- }
1330
-
1331
- // First batch of tests
1332
- select = document.createElement("select");
1333
- opt = select.appendChild( document.createElement("option") );
1334
- input = div.getElementsByTagName("input")[ 0 ];
1335
-
1336
- a.style.cssText = "top:1px;float:left;opacity:.5";
1337
- support = {
1338
- // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
1339
- getSetAttribute: div.className !== "t",
1340
-
1341
- // IE strips leading whitespace when .innerHTML is used
1342
- leadingWhitespace: div.firstChild.nodeType === 3,
1343
-
1344
- // Make sure that tbody elements aren't automatically inserted
1345
- // IE will insert them into empty tables
1346
- tbody: !div.getElementsByTagName("tbody").length,
1347
-
1348
- // Make sure that link elements get serialized correctly by innerHTML
1349
- // This requires a wrapper element in IE
1350
- htmlSerialize: !!div.getElementsByTagName("link").length,
1351
-
1352
- // Get the style information from getAttribute
1353
- // (IE uses .cssText instead)
1354
- style: /top/.test( a.getAttribute("style") ),
1355
-
1356
- // Make sure that URLs aren't manipulated
1357
- // (IE normalizes it by default)
1358
- hrefNormalized: a.getAttribute("href") === "/a",
1359
-
1360
- // Make sure that element opacity exists
1361
- // (IE uses filter instead)
1362
- // Use a regex to work around a WebKit issue. See #5145
1363
- opacity: /^0.5/.test( a.style.opacity ),
1364
-
1365
- // Verify style float existence
1366
- // (IE uses styleFloat instead of cssFloat)
1367
- cssFloat: !!a.style.cssFloat,
1368
-
1369
- // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
1370
- checkOn: !!input.value,
1371
-
1372
- // Make sure that a selected-by-default option has a working selected property.
1373
- // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
1374
- optSelected: opt.selected,
1375
-
1376
- // Tests for enctype support on a form (#6743)
1377
- enctype: !!document.createElement("form").enctype,
1378
-
1379
- // Makes sure cloning an html5 element does not cause problems
1380
- // Where outerHTML is undefined, this still works
1381
- html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
1382
-
1383
- // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
1384
- boxModel: document.compatMode === "CSS1Compat",
1385
-
1386
- // Will be defined later
1387
- deleteExpando: true,
1388
- noCloneEvent: true,
1389
- inlineBlockNeedsLayout: false,
1390
- shrinkWrapBlocks: false,
1391
- reliableMarginRight: true,
1392
- boxSizingReliable: true,
1393
- pixelPosition: false
1394
- };
1395
-
1396
- // Make sure checked status is properly cloned
1397
- input.checked = true;
1398
- support.noCloneChecked = input.cloneNode( true ).checked;
1399
-
1400
- // Make sure that the options inside disabled selects aren't marked as disabled
1401
- // (WebKit marks them as disabled)
1402
- select.disabled = true;
1403
- support.optDisabled = !opt.disabled;
1404
-
1405
- // Support: IE<9
1406
- try {
1407
- delete div.test;
1408
- } catch( e ) {
1409
- support.deleteExpando = false;
1410
- }
1411
-
1412
- // Check if we can trust getAttribute("value")
1413
- input = document.createElement("input");
1414
- input.setAttribute( "value", "" );
1415
- support.input = input.getAttribute( "value" ) === "";
1416
-
1417
- // Check if an input maintains its value after becoming a radio
1418
- input.value = "t";
1419
- input.setAttribute( "type", "radio" );
1420
- support.radioValue = input.value === "t";
1421
-
1422
- // #11217 - WebKit loses check when the name is after the checked attribute
1423
- input.setAttribute( "checked", "t" );
1424
- input.setAttribute( "name", "t" );
1425
-
1426
- fragment = document.createDocumentFragment();
1427
- fragment.appendChild( input );
1428
-
1429
- // Check if a disconnected checkbox will retain its checked
1430
- // value of true after appended to the DOM (IE6/7)
1431
- support.appendChecked = input.checked;
1432
-
1433
- // WebKit doesn't clone checked state correctly in fragments
1434
- support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
1435
-
1436
- // Support: IE<9
1437
- // Opera does not clone events (and typeof div.attachEvent === undefined).
1438
- // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
1439
- if ( div.attachEvent ) {
1440
- div.attachEvent( "onclick", function() {
1441
- support.noCloneEvent = false;
1442
- });
1443
-
1444
- div.cloneNode( true ).click();
1445
- }
1446
-
1447
- // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)
1448
- // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php
1449
- for ( i in { submit: true, change: true, focusin: true }) {
1450
- div.setAttribute( eventName = "on" + i, "t" );
1451
-
1452
- support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false;
1453
- }
1454
-
1455
- div.style.backgroundClip = "content-box";
1456
- div.cloneNode( true ).style.backgroundClip = "";
1457
- support.clearCloneStyle = div.style.backgroundClip === "content-box";
1458
-
1459
- // Run tests that need a body at doc ready
1460
- jQuery(function() {
1461
- var container, marginDiv, tds,
1462
- divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
1463
- body = document.getElementsByTagName("body")[0];
1464
-
1465
- if ( !body ) {
1466
- // Return for frameset docs that don't have a body
1467
- return;
1468
- }
1469
-
1470
- container = document.createElement("div");
1471
- container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
1472
-
1473
- body.appendChild( container ).appendChild( div );
1474
-
1475
- // Support: IE8
1476
- // Check if table cells still have offsetWidth/Height when they are set
1477
- // to display:none and there are still other visible table cells in a
1478
- // table row; if so, offsetWidth/Height are not reliable for use when
1479
- // determining if an element has been hidden directly using
1480
- // display:none (it is still safe to use offsets if a parent element is
1481
- // hidden; don safety goggles and see bug #4512 for more information).
1482
- div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
1483
- tds = div.getElementsByTagName("td");
1484
- tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
1485
- isSupported = ( tds[ 0 ].offsetHeight === 0 );
1486
-
1487
- tds[ 0 ].style.display = "";
1488
- tds[ 1 ].style.display = "none";
1489
-
1490
- // Support: IE8
1491
- // Check if empty table cells still have offsetWidth/Height
1492
- support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
1493
-
1494
- // Check box-sizing and margin behavior
1495
- div.innerHTML = "";
1496
- 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%;";
1497
- support.boxSizing = ( div.offsetWidth === 4 );
1498
- support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
1499
-
1500
- // Use window.getComputedStyle because jsdom on node.js will break without it.
1501
- if ( window.getComputedStyle ) {
1502
- support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
1503
- support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
1504
-
1505
- // Check if div with explicit width and no margin-right incorrectly
1506
- // gets computed margin-right based on width of container. (#3333)
1507
- // Fails in WebKit before Feb 2011 nightlies
1508
- // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
1509
- marginDiv = div.appendChild( document.createElement("div") );
1510
- marginDiv.style.cssText = div.style.cssText = divReset;
1511
- marginDiv.style.marginRight = marginDiv.style.width = "0";
1512
- div.style.width = "1px";
1513
-
1514
- support.reliableMarginRight =
1515
- !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
1516
- }
1517
-
1518
- if ( typeof div.style.zoom !== core_strundefined ) {
1519
- // Support: IE<8
1520
- // Check if natively block-level elements act like inline-block
1521
- // elements when setting their display to 'inline' and giving
1522
- // them layout
1523
- div.innerHTML = "";
1524
- div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
1525
- support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
1526
-
1527
- // Support: IE6
1528
- // Check if elements with layout shrink-wrap their children
1529
- div.style.display = "block";
1530
- div.innerHTML = "<div></div>";
1531
- div.firstChild.style.width = "5px";
1532
- support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
1533
-
1534
- if ( support.inlineBlockNeedsLayout ) {
1535
- // Prevent IE 6 from affecting layout for positioned elements #11048
1536
- // Prevent IE from shrinking the body in IE 7 mode #12869
1537
- // Support: IE<8
1538
- body.style.zoom = 1;
1539
- }
1540
- }
1541
-
1542
- body.removeChild( container );
1543
-
1544
- // Null elements to avoid leaks in IE
1545
- container = div = tds = marginDiv = null;
1546
- });
1547
-
1548
- // Null elements to avoid leaks in IE
1549
- all = select = fragment = opt = a = input = null;
1550
-
1551
- return support;
1552
- })();
1553
-
1554
- var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
1555
- rmultiDash = /([A-Z])/g;
1556
-
1557
- function internalData( elem, name, data, pvt /* Internal Use Only */ ){
1558
- if ( !jQuery.acceptData( elem ) ) {
1559
- return;
1560
- }
1561
-
1562
- var thisCache, ret,
1563
- internalKey = jQuery.expando,
1564
- getByName = typeof name === "string",
1565
-
1566
- // We have to handle DOM nodes and JS objects differently because IE6-7
1567
- // can't GC object references properly across the DOM-JS boundary
1568
- isNode = elem.nodeType,
1569
-
1570
- // Only DOM nodes need the global jQuery cache; JS object data is
1571
- // attached directly to the object so GC can occur automatically
1572
- cache = isNode ? jQuery.cache : elem,
1573
-
1574
- // Only defining an ID for JS objects if its cache already exists allows
1575
- // the code to shortcut on the same path as a DOM node with no cache
1576
- id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
1577
-
1578
- // Avoid doing any more work than we need to when trying to get data on an
1579
- // object that has no data at all
1580
- if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
1581
- return;
1582
- }
1583
-
1584
- if ( !id ) {
1585
- // Only DOM nodes need a new unique ID for each element since their data
1586
- // ends up in the global cache
1587
- if ( isNode ) {
1588
- elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;
1589
- } else {
1590
- id = internalKey;
1591
- }
1592
- }
1593
-
1594
- if ( !cache[ id ] ) {
1595
- cache[ id ] = {};
1596
-
1597
- // Avoids exposing jQuery metadata on plain JS objects when the object
1598
- // is serialized using JSON.stringify
1599
- if ( !isNode ) {
1600
- cache[ id ].toJSON = jQuery.noop;
1601
- }
1602
- }
1603
-
1604
- // An object can be passed to jQuery.data instead of a key/value pair; this gets
1605
- // shallow copied over onto the existing cache
1606
- if ( typeof name === "object" || typeof name === "function" ) {
1607
- if ( pvt ) {
1608
- cache[ id ] = jQuery.extend( cache[ id ], name );
1609
- } else {
1610
- cache[ id ].data = jQuery.extend( cache[ id ].data, name );
1611
- }
1612
- }
1613
-
1614
- thisCache = cache[ id ];
1615
-
1616
- // jQuery data() is stored in a separate object inside the object's internal data
1617
- // cache in order to avoid key collisions between internal data and user-defined
1618
- // data.
1619
- if ( !pvt ) {
1620
- if ( !thisCache.data ) {
1621
- thisCache.data = {};
1622
- }
1623
-
1624
- thisCache = thisCache.data;
1625
- }
1626
-
1627
- if ( data !== undefined ) {
1628
- thisCache[ jQuery.camelCase( name ) ] = data;
1629
- }
1630
-
1631
- // Check for both converted-to-camel and non-converted data property names
1632
- // If a data property was specified
1633
- if ( getByName ) {
1634
-
1635
- // First Try to find as-is property data
1636
- ret = thisCache[ name ];
1637
-
1638
- // Test for null|undefined property data
1639
- if ( ret == null ) {
1640
-
1641
- // Try to find the camelCased property
1642
- ret = thisCache[ jQuery.camelCase( name ) ];
1643
- }
1644
- } else {
1645
- ret = thisCache;
1646
- }
1647
-
1648
- return ret;
1649
- }
1650
-
1651
- function internalRemoveData( elem, name, pvt ) {
1652
- if ( !jQuery.acceptData( elem ) ) {
1653
- return;
1654
- }
1655
-
1656
- var i, l, thisCache,
1657
- isNode = elem.nodeType,
1658
-
1659
- // See jQuery.data for more information
1660
- cache = isNode ? jQuery.cache : elem,
1661
- id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
1662
-
1663
- // If there is already no cache entry for this object, there is no
1664
- // purpose in continuing
1665
- if ( !cache[ id ] ) {
1666
- return;
1667
- }
1668
-
1669
- if ( name ) {
1670
-
1671
- thisCache = pvt ? cache[ id ] : cache[ id ].data;
1672
-
1673
- if ( thisCache ) {
1674
-
1675
- // Support array or space separated string names for data keys
1676
- if ( !jQuery.isArray( name ) ) {
1677
-
1678
- // try the string as a key before any manipulation
1679
- if ( name in thisCache ) {
1680
- name = [ name ];
1681
- } else {
1682
-
1683
- // split the camel cased version by spaces unless a key with the spaces exists
1684
- name = jQuery.camelCase( name );
1685
- if ( name in thisCache ) {
1686
- name = [ name ];
1687
- } else {
1688
- name = name.split(" ");
1689
- }
1690
- }
1691
- } else {
1692
- // If "name" is an array of keys...
1693
- // When data is initially created, via ("key", "val") signature,
1694
- // keys will be converted to camelCase.
1695
- // Since there is no way to tell _how_ a key was added, remove
1696
- // both plain key and camelCase key. #12786
1697
- // This will only penalize the array argument path.
1698
- name = name.concat( jQuery.map( name, jQuery.camelCase ) );
1699
- }
1700
-
1701
- for ( i = 0, l = name.length; i < l; i++ ) {
1702
- delete thisCache[ name[i] ];
1703
- }
1704
-
1705
- // If there is no data left in the cache, we want to continue
1706
- // and let the cache object itself get destroyed
1707
- if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
1708
- return;
1709
- }
1710
- }
1711
- }
1712
-
1713
- // See jQuery.data for more information
1714
- if ( !pvt ) {
1715
- delete cache[ id ].data;
1716
-
1717
- // Don't destroy the parent cache unless the internal data object
1718
- // had been the only thing left in it
1719
- if ( !isEmptyDataObject( cache[ id ] ) ) {
1720
- return;
1721
- }
1722
- }
1723
-
1724
- // Destroy the cache
1725
- if ( isNode ) {
1726
- jQuery.cleanData( [ elem ], true );
1727
-
1728
- // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
1729
- } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
1730
- delete cache[ id ];
1731
-
1732
- // When all else fails, null
1733
- } else {
1734
- cache[ id ] = null;
1735
- }
1736
- }
1737
-
1738
- jQuery.extend({
1739
- cache: {},
1740
-
1741
- // Unique for each copy of jQuery on the page
1742
- // Non-digits removed to match rinlinejQuery
1743
- expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
1744
-
1745
- // The following elements throw uncatchable exceptions if you
1746
- // attempt to add expando properties to them.
1747
- noData: {
1748
- "embed": true,
1749
- // Ban all objects except for Flash (which handle expandos)
1750
- "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
1751
- "applet": true
1752
- },
1753
-
1754
- hasData: function( elem ) {
1755
- elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
1756
- return !!elem && !isEmptyDataObject( elem );
1757
- },
1758
-
1759
- data: function( elem, name, data ) {
1760
- return internalData( elem, name, data );
1761
- },
1762
-
1763
- removeData: function( elem, name ) {
1764
- return internalRemoveData( elem, name );
1765
- },
1766
-
1767
- // For internal use only.
1768
- _data: function( elem, name, data ) {
1769
- return internalData( elem, name, data, true );
1770
- },
1771
-
1772
- _removeData: function( elem, name ) {
1773
- return internalRemoveData( elem, name, true );
1774
- },
1775
-
1776
- // A method for determining if a DOM node can handle the data expando
1777
- acceptData: function( elem ) {
1778
- // Do not set data on non-element because it will not be cleared (#8335).
1779
- if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {
1780
- return false;
1781
- }
1782
-
1783
- var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
1784
-
1785
- // nodes accept data unless otherwise specified; rejection can be conditional
1786
- return !noData || noData !== true && elem.getAttribute("classid") === noData;
1787
- }
1788
- });
1789
-
1790
- jQuery.fn.extend({
1791
- data: function( key, value ) {
1792
- var attrs, name,
1793
- elem = this[0],
1794
- i = 0,
1795
- data = null;
1796
-
1797
- // Gets all values
1798
- if ( key === undefined ) {
1799
- if ( this.length ) {
1800
- data = jQuery.data( elem );
1801
-
1802
- if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
1803
- attrs = elem.attributes;
1804
- for ( ; i < attrs.length; i++ ) {
1805
- name = attrs[i].name;
1806
-
1807
- if ( !name.indexOf( "data-" ) ) {
1808
- name = jQuery.camelCase( name.slice(5) );
1809
-
1810
- dataAttr( elem, name, data[ name ] );
1811
- }
1812
- }
1813
- jQuery._data( elem, "parsedAttrs", true );
1814
- }
1815
- }
1816
-
1817
- return data;
1818
- }
1819
-
1820
- // Sets multiple values
1821
- if ( typeof key === "object" ) {
1822
- return this.each(function() {
1823
- jQuery.data( this, key );
1824
- });
1825
- }
1826
-
1827
- return jQuery.access( this, function( value ) {
1828
-
1829
- if ( value === undefined ) {
1830
- // Try to fetch any internally stored data first
1831
- return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;
1832
- }
1833
-
1834
- this.each(function() {
1835
- jQuery.data( this, key, value );
1836
- });
1837
- }, null, value, arguments.length > 1, null, true );
1838
- },
1839
-
1840
- removeData: function( key ) {
1841
- return this.each(function() {
1842
- jQuery.removeData( this, key );
1843
- });
1844
- }
1845
- });
1846
-
1847
- function dataAttr( elem, key, data ) {
1848
- // If nothing was found internally, try to fetch any
1849
- // data from the HTML5 data-* attribute
1850
- if ( data === undefined && elem.nodeType === 1 ) {
1851
-
1852
- var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
1853
-
1854
- data = elem.getAttribute( name );
1855
-
1856
- if ( typeof data === "string" ) {
1857
- try {
1858
- data = data === "true" ? true :
1859
- data === "false" ? false :
1860
- data === "null" ? null :
1861
- // Only convert to a number if it doesn't change the string
1862
- +data + "" === data ? +data :
1863
- rbrace.test( data ) ? jQuery.parseJSON( data ) :
1864
- data;
1865
- } catch( e ) {}
1866
-
1867
- // Make sure we set the data so it isn't changed later
1868
- jQuery.data( elem, key, data );
1869
-
1870
- } else {
1871
- data = undefined;
1872
- }
1873
- }
1874
-
1875
- return data;
1876
- }
1877
-
1878
- // checks a cache object for emptiness
1879
- function isEmptyDataObject( obj ) {
1880
- var name;
1881
- for ( name in obj ) {
1882
-
1883
- // if the public data object is empty, the private is still empty
1884
- if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
1885
- continue;
1886
- }
1887
- if ( name !== "toJSON" ) {
1888
- return false;
1889
- }
1890
- }
1891
-
1892
- return true;
1893
- }
1894
- jQuery.extend({
1895
- queue: function( elem, type, data ) {
1896
- var queue;
1897
-
1898
- if ( elem ) {
1899
- type = ( type || "fx" ) + "queue";
1900
- queue = jQuery._data( elem, type );
1901
-
1902
- // Speed up dequeue by getting out quickly if this is just a lookup
1903
- if ( data ) {
1904
- if ( !queue || jQuery.isArray(data) ) {
1905
- queue = jQuery._data( elem, type, jQuery.makeArray(data) );
1906
- } else {
1907
- queue.push( data );
1908
- }
1909
- }
1910
- return queue || [];
1911
- }
1912
- },
1913
-
1914
- dequeue: function( elem, type ) {
1915
- type = type || "fx";
1916
-
1917
- var queue = jQuery.queue( elem, type ),
1918
- startLength = queue.length,
1919
- fn = queue.shift(),
1920
- hooks = jQuery._queueHooks( elem, type ),
1921
- next = function() {
1922
- jQuery.dequeue( elem, type );
1923
- };
1924
-
1925
- // If the fx queue is dequeued, always remove the progress sentinel
1926
- if ( fn === "inprogress" ) {
1927
- fn = queue.shift();
1928
- startLength--;
1929
- }
1930
-
1931
- hooks.cur = fn;
1932
- if ( fn ) {
1933
-
1934
- // Add a progress sentinel to prevent the fx queue from being
1935
- // automatically dequeued
1936
- if ( type === "fx" ) {
1937
- queue.unshift( "inprogress" );
1938
- }
1939
-
1940
- // clear up the last queue stop function
1941
- delete hooks.stop;
1942
- fn.call( elem, next, hooks );
1943
- }
1944
-
1945
- if ( !startLength && hooks ) {
1946
- hooks.empty.fire();
1947
- }
1948
- },
1949
-
1950
- // not intended for public consumption - generates a queueHooks object, or returns the current one
1951
- _queueHooks: function( elem, type ) {
1952
- var key = type + "queueHooks";
1953
- return jQuery._data( elem, key ) || jQuery._data( elem, key, {
1954
- empty: jQuery.Callbacks("once memory").add(function() {
1955
- jQuery._removeData( elem, type + "queue" );
1956
- jQuery._removeData( elem, key );
1957
- })
1958
- });
1959
- }
1960
- });
1961
-
1962
- jQuery.fn.extend({
1963
- queue: function( type, data ) {
1964
- var setter = 2;
1965
-
1966
- if ( typeof type !== "string" ) {
1967
- data = type;
1968
- type = "fx";
1969
- setter--;
1970
- }
1971
-
1972
- if ( arguments.length < setter ) {
1973
- return jQuery.queue( this[0], type );
1974
- }
1975
-
1976
- return data === undefined ?
1977
- this :
1978
- this.each(function() {
1979
- var queue = jQuery.queue( this, type, data );
1980
-
1981
- // ensure a hooks for this queue
1982
- jQuery._queueHooks( this, type );
1983
-
1984
- if ( type === "fx" && queue[0] !== "inprogress" ) {
1985
- jQuery.dequeue( this, type );
1986
- }
1987
- });
1988
- },
1989
- dequeue: function( type ) {
1990
- return this.each(function() {
1991
- jQuery.dequeue( this, type );
1992
- });
1993
- },
1994
- // Based off of the plugin by Clint Helfers, with permission.
1995
- // http://blindsignals.com/index.php/2009/07/jquery-delay/
1996
- delay: function( time, type ) {
1997
- time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
1998
- type = type || "fx";
1999
-
2000
- return this.queue( type, function( next, hooks ) {
2001
- var timeout = setTimeout( next, time );
2002
- hooks.stop = function() {
2003
- clearTimeout( timeout );
2004
- };
2005
- });
2006
- },
2007
- clearQueue: function( type ) {
2008
- return this.queue( type || "fx", [] );
2009
- },
2010
- // Get a promise resolved when queues of a certain type
2011
- // are emptied (fx is the type by default)
2012
- promise: function( type, obj ) {
2013
- var tmp,
2014
- count = 1,
2015
- defer = jQuery.Deferred(),
2016
- elements = this,
2017
- i = this.length,
2018
- resolve = function() {
2019
- if ( !( --count ) ) {
2020
- defer.resolveWith( elements, [ elements ] );
2021
- }
2022
- };
2023
-
2024
- if ( typeof type !== "string" ) {
2025
- obj = type;
2026
- type = undefined;
2027
- }
2028
- type = type || "fx";
2029
-
2030
- while( i-- ) {
2031
- tmp = jQuery._data( elements[ i ], type + "queueHooks" );
2032
- if ( tmp && tmp.empty ) {
2033
- count++;
2034
- tmp.empty.add( resolve );
2035
- }
2036
- }
2037
- resolve();
2038
- return defer.promise( obj );
2039
- }
2040
- });
2041
- var nodeHook, boolHook,
2042
- rclass = /[\t\r\n]/g,
2043
- rreturn = /\r/g,
2044
- rfocusable = /^(?:input|select|textarea|button|object)$/i,
2045
- rclickable = /^(?:a|area)$/i,
2046
- rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,
2047
- ruseDefault = /^(?:checked|selected)$/i,
2048
- getSetAttribute = jQuery.support.getSetAttribute,
2049
- getSetInput = jQuery.support.input;
2050
-
2051
- jQuery.fn.extend({
2052
- attr: function( name, value ) {
2053
- return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
2054
- },
2055
-
2056
- removeAttr: function( name ) {
2057
- return this.each(function() {
2058
- jQuery.removeAttr( this, name );
2059
- });
2060
- },
2061
-
2062
- prop: function( name, value ) {
2063
- return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
2064
- },
2065
-
2066
- removeProp: function( name ) {
2067
- name = jQuery.propFix[ name ] || name;
2068
- return this.each(function() {
2069
- // try/catch handles cases where IE balks (such as removing a property on window)
2070
- try {
2071
- this[ name ] = undefined;
2072
- delete this[ name ];
2073
- } catch( e ) {}
2074
- });
2075
- },
2076
-
2077
- addClass: function( value ) {
2078
- var classes, elem, cur, clazz, j,
2079
- i = 0,
2080
- len = this.length,
2081
- proceed = typeof value === "string" && value;
2082
-
2083
- if ( jQuery.isFunction( value ) ) {
2084
- return this.each(function( j ) {
2085
- jQuery( this ).addClass( value.call( this, j, this.className ) );
2086
- });
2087
- }
2088
-
2089
- if ( proceed ) {
2090
- // The disjunction here is for better compressibility (see removeClass)
2091
- classes = ( value || "" ).match( core_rnotwhite ) || [];
2092
-
2093
- for ( ; i < len; i++ ) {
2094
- elem = this[ i ];
2095
- cur = elem.nodeType === 1 && ( elem.className ?
2096
- ( " " + elem.className + " " ).replace( rclass, " " ) :
2097
- " "
2098
- );
2099
-
2100
- if ( cur ) {
2101
- j = 0;
2102
- while ( (clazz = classes[j++]) ) {
2103
- if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
2104
- cur += clazz + " ";
2105
- }
2106
- }
2107
- elem.className = jQuery.trim( cur );
2108
-
2109
- }
2110
- }
2111
- }
2112
-
2113
- return this;
2114
- },
2115
-
2116
- removeClass: function( value ) {
2117
- var classes, elem, cur, clazz, j,
2118
- i = 0,
2119
- len = this.length,
2120
- proceed = arguments.length === 0 || typeof value === "string" && value;
2121
-
2122
- if ( jQuery.isFunction( value ) ) {
2123
- return this.each(function( j ) {
2124
- jQuery( this ).removeClass( value.call( this, j, this.className ) );
2125
- });
2126
- }
2127
- if ( proceed ) {
2128
- classes = ( value || "" ).match( core_rnotwhite ) || [];
2129
-
2130
- for ( ; i < len; i++ ) {
2131
- elem = this[ i ];
2132
- // This expression is here for better compressibility (see addClass)
2133
- cur = elem.nodeType === 1 && ( elem.className ?
2134
- ( " " + elem.className + " " ).replace( rclass, " " ) :
2135
- ""
2136
- );
2137
-
2138
- if ( cur ) {
2139
- j = 0;
2140
- while ( (clazz = classes[j++]) ) {
2141
- // Remove *all* instances
2142
- while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
2143
- cur = cur.replace( " " + clazz + " ", " " );
2144
- }
2145
- }
2146
- elem.className = value ? jQuery.trim( cur ) : "";
2147
- }
2148
- }
2149
- }
2150
-
2151
- return this;
2152
- },
2153
-
2154
- toggleClass: function( value, stateVal ) {
2155
- var type = typeof value,
2156
- isBool = typeof stateVal === "boolean";
2157
-
2158
- if ( jQuery.isFunction( value ) ) {
2159
- return this.each(function( i ) {
2160
- jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
2161
- });
2162
- }
2163
-
2164
- return this.each(function() {
2165
- if ( type === "string" ) {
2166
- // toggle individual class names
2167
- var className,
2168
- i = 0,
2169
- self = jQuery( this ),
2170
- state = stateVal,
2171
- classNames = value.match( core_rnotwhite ) || [];
2172
-
2173
- while ( (className = classNames[ i++ ]) ) {
2174
- // check each className given, space separated list
2175
- state = isBool ? state : !self.hasClass( className );
2176
- self[ state ? "addClass" : "removeClass" ]( className );
2177
- }
2178
-
2179
- // Toggle whole class name
2180
- } else if ( type === core_strundefined || type === "boolean" ) {
2181
- if ( this.className ) {
2182
- // store className if set
2183
- jQuery._data( this, "__className__", this.className );
2184
- }
2185
-
2186
- // If the element has a class name or if we're passed "false",
2187
- // then remove the whole classname (if there was one, the above saved it).
2188
- // Otherwise bring back whatever was previously saved (if anything),
2189
- // falling back to the empty string if nothing was stored.
2190
- this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
2191
- }
2192
- });
2193
- },
2194
-
2195
- hasClass: function( selector ) {
2196
- var className = " " + selector + " ",
2197
- i = 0,
2198
- l = this.length;
2199
- for ( ; i < l; i++ ) {
2200
- if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
2201
- return true;
2202
- }
2203
- }
2204
-
2205
- return false;
2206
- },
2207
-
2208
- val: function( value ) {
2209
- var ret, hooks, isFunction,
2210
- elem = this[0];
2211
-
2212
- if ( !arguments.length ) {
2213
- if ( elem ) {
2214
- hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
2215
-
2216
- if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
2217
- return ret;
2218
- }
2219
-
2220
- ret = elem.value;
2221
-
2222
- return typeof ret === "string" ?
2223
- // handle most common string cases
2224
- ret.replace(rreturn, "") :
2225
- // handle cases where value is null/undef or number
2226
- ret == null ? "" : ret;
2227
- }
2228
-
2229
- return;
2230
- }
2231
-
2232
- isFunction = jQuery.isFunction( value );
2233
-
2234
- return this.each(function( i ) {
2235
- var val,
2236
- self = jQuery(this);
2237
-
2238
- if ( this.nodeType !== 1 ) {
2239
- return;
2240
- }
2241
-
2242
- if ( isFunction ) {
2243
- val = value.call( this, i, self.val() );
2244
- } else {
2245
- val = value;
2246
- }
2247
-
2248
- // Treat null/undefined as ""; convert numbers to string
2249
- if ( val == null ) {
2250
- val = "";
2251
- } else if ( typeof val === "number" ) {
2252
- val += "";
2253
- } else if ( jQuery.isArray( val ) ) {
2254
- val = jQuery.map(val, function ( value ) {
2255
- return value == null ? "" : value + "";
2256
- });
2257
- }
2258
-
2259
- hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
2260
-
2261
- // If set returns undefined, fall back to normal setting
2262
- if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
2263
- this.value = val;
2264
- }
2265
- });
2266
- }
2267
- });
2268
-
2269
- jQuery.extend({
2270
- valHooks: {
2271
- option: {
2272
- get: function( elem ) {
2273
- // attributes.value is undefined in Blackberry 4.7 but
2274
- // uses .value. See #6932
2275
- var val = elem.attributes.value;
2276
- return !val || val.specified ? elem.value : elem.text;
2277
- }
2278
- },
2279
- select: {
2280
- get: function( elem ) {
2281
- var value, option,
2282
- options = elem.options,
2283
- index = elem.selectedIndex,
2284
- one = elem.type === "select-one" || index < 0,
2285
- values = one ? null : [],
2286
- max = one ? index + 1 : options.length,
2287
- i = index < 0 ?
2288
- max :
2289
- one ? index : 0;
2290
-
2291
- // Loop through all the selected options
2292
- for ( ; i < max; i++ ) {
2293
- option = options[ i ];
2294
-
2295
- // oldIE doesn't update selected after form reset (#2551)
2296
- if ( ( option.selected || i === index ) &&
2297
- // Don't return options that are disabled or in a disabled optgroup
2298
- ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
2299
- ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
2300
-
2301
- // Get the specific value for the option
2302
- value = jQuery( option ).val();
2303
-
2304
- // We don't need an array for one selects
2305
- if ( one ) {
2306
- return value;
2307
- }
2308
-
2309
- // Multi-Selects return an array
2310
- values.push( value );
2311
- }
2312
- }
2313
-
2314
- return values;
2315
- },
2316
-
2317
- set: function( elem, value ) {
2318
- var values = jQuery.makeArray( value );
2319
-
2320
- jQuery(elem).find("option").each(function() {
2321
- this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
2322
- });
2323
-
2324
- if ( !values.length ) {
2325
- elem.selectedIndex = -1;
2326
- }
2327
- return values;
2328
- }
2329
- }
2330
- },
2331
-
2332
- attr: function( elem, name, value ) {
2333
- var hooks, notxml, ret,
2334
- nType = elem.nodeType;
2335
-
2336
- // don't get/set attributes on text, comment and attribute nodes
2337
- if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2338
- return;
2339
- }
2340
-
2341
- // Fallback to prop when attributes are not supported
2342
- if ( typeof elem.getAttribute === core_strundefined ) {
2343
- return jQuery.prop( elem, name, value );
2344
- }
2345
-
2346
- notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2347
-
2348
- // All attributes are lowercase
2349
- // Grab necessary hook if one is defined
2350
- if ( notxml ) {
2351
- name = name.toLowerCase();
2352
- hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
2353
- }
2354
-
2355
- if ( value !== undefined ) {
2356
-
2357
- if ( value === null ) {
2358
- jQuery.removeAttr( elem, name );
2359
-
2360
- } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
2361
- return ret;
2362
-
2363
- } else {
2364
- elem.setAttribute( name, value + "" );
2365
- return value;
2366
- }
2367
-
2368
- } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
2369
- return ret;
2370
-
2371
- } else {
2372
-
2373
- // In IE9+, Flash objects don't have .getAttribute (#12945)
2374
- // Support: IE9+
2375
- if ( typeof elem.getAttribute !== core_strundefined ) {
2376
- ret = elem.getAttribute( name );
2377
- }
2378
-
2379
- // Non-existent attributes return null, we normalize to undefined
2380
- return ret == null ?
2381
- undefined :
2382
- ret;
2383
- }
2384
- },
2385
-
2386
- removeAttr: function( elem, value ) {
2387
- var name, propName,
2388
- i = 0,
2389
- attrNames = value && value.match( core_rnotwhite );
2390
-
2391
- if ( attrNames && elem.nodeType === 1 ) {
2392
- while ( (name = attrNames[i++]) ) {
2393
- propName = jQuery.propFix[ name ] || name;
2394
-
2395
- // Boolean attributes get special treatment (#10870)
2396
- if ( rboolean.test( name ) ) {
2397
- // Set corresponding property to false for boolean attributes
2398
- // Also clear defaultChecked/defaultSelected (if appropriate) for IE<8
2399
- if ( !getSetAttribute && ruseDefault.test( name ) ) {
2400
- elem[ jQuery.camelCase( "default-" + name ) ] =
2401
- elem[ propName ] = false;
2402
- } else {
2403
- elem[ propName ] = false;
2404
- }
2405
-
2406
- // See #9699 for explanation of this approach (setting first, then removal)
2407
- } else {
2408
- jQuery.attr( elem, name, "" );
2409
- }
2410
-
2411
- elem.removeAttribute( getSetAttribute ? name : propName );
2412
- }
2413
- }
2414
- },
2415
-
2416
- attrHooks: {
2417
- type: {
2418
- set: function( elem, value ) {
2419
- if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
2420
- // Setting the type on a radio button after the value resets the value in IE6-9
2421
- // Reset value to default in case type is set after value during creation
2422
- var val = elem.value;
2423
- elem.setAttribute( "type", value );
2424
- if ( val ) {
2425
- elem.value = val;
2426
- }
2427
- return value;
2428
- }
2429
- }
2430
- }
2431
- },
2432
-
2433
- propFix: {
2434
- tabindex: "tabIndex",
2435
- readonly: "readOnly",
2436
- "for": "htmlFor",
2437
- "class": "className",
2438
- maxlength: "maxLength",
2439
- cellspacing: "cellSpacing",
2440
- cellpadding: "cellPadding",
2441
- rowspan: "rowSpan",
2442
- colspan: "colSpan",
2443
- usemap: "useMap",
2444
- frameborder: "frameBorder",
2445
- contenteditable: "contentEditable"
2446
- },
2447
-
2448
- prop: function( elem, name, value ) {
2449
- var ret, hooks, notxml,
2450
- nType = elem.nodeType;
2451
-
2452
- // don't get/set properties on text, comment and attribute nodes
2453
- if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2454
- return;
2455
- }
2456
-
2457
- notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2458
-
2459
- if ( notxml ) {
2460
- // Fix name and attach hooks
2461
- name = jQuery.propFix[ name ] || name;
2462
- hooks = jQuery.propHooks[ name ];
2463
- }
2464
-
2465
- if ( value !== undefined ) {
2466
- if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
2467
- return ret;
2468
-
2469
- } else {
2470
- return ( elem[ name ] = value );
2471
- }
2472
-
2473
- } else {
2474
- if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
2475
- return ret;
2476
-
2477
- } else {
2478
- return elem[ name ];
2479
- }
2480
- }
2481
- },
2482
-
2483
- propHooks: {
2484
- tabIndex: {
2485
- get: function( elem ) {
2486
- // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
2487
- // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
2488
- var attributeNode = elem.getAttributeNode("tabindex");
2489
-
2490
- return attributeNode && attributeNode.specified ?
2491
- parseInt( attributeNode.value, 10 ) :
2492
- rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
2493
- 0 :
2494
- undefined;
2495
- }
2496
- }
2497
- }
2498
- });
2499
-
2500
- // Hook for boolean attributes
2501
- boolHook = {
2502
- get: function( elem, name ) {
2503
- var
2504
- // Use .prop to determine if this attribute is understood as boolean
2505
- prop = jQuery.prop( elem, name ),
2506
-
2507
- // Fetch it accordingly
2508
- attr = typeof prop === "boolean" && elem.getAttribute( name ),
2509
- detail = typeof prop === "boolean" ?
2510
-
2511
- getSetInput && getSetAttribute ?
2512
- attr != null :
2513
- // oldIE fabricates an empty string for missing boolean attributes
2514
- // and conflates checked/selected into attroperties
2515
- ruseDefault.test( name ) ?
2516
- elem[ jQuery.camelCase( "default-" + name ) ] :
2517
- !!attr :
2518
-
2519
- // fetch an attribute node for properties not recognized as boolean
2520
- elem.getAttributeNode( name );
2521
-
2522
- return detail && detail.value !== false ?
2523
- name.toLowerCase() :
2524
- undefined;
2525
- },
2526
- set: function( elem, value, name ) {
2527
- if ( value === false ) {
2528
- // Remove boolean attributes when set to false
2529
- jQuery.removeAttr( elem, name );
2530
- } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
2531
- // IE<8 needs the *property* name
2532
- elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
2533
-
2534
- // Use defaultChecked and defaultSelected for oldIE
2535
- } else {
2536
- elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
2537
- }
2538
-
2539
- return name;
2540
- }
2541
- };
2542
-
2543
- // fix oldIE value attroperty
2544
- if ( !getSetInput || !getSetAttribute ) {
2545
- jQuery.attrHooks.value = {
2546
- get: function( elem, name ) {
2547
- var ret = elem.getAttributeNode( name );
2548
- return jQuery.nodeName( elem, "input" ) ?
2549
-
2550
- // Ignore the value *property* by using defaultValue
2551
- elem.defaultValue :
2552
-
2553
- ret && ret.specified ? ret.value : undefined;
2554
- },
2555
- set: function( elem, value, name ) {
2556
- if ( jQuery.nodeName( elem, "input" ) ) {
2557
- // Does not return so that setAttribute is also used
2558
- elem.defaultValue = value;
2559
- } else {
2560
- // Use nodeHook if defined (#1954); otherwise setAttribute is fine
2561
- return nodeHook && nodeHook.set( elem, value, name );
2562
- }
2563
- }
2564
- };
2565
- }
2566
-
2567
- // IE6/7 do not support getting/setting some attributes with get/setAttribute
2568
- if ( !getSetAttribute ) {
2569
-
2570
- // Use this for any attribute in IE6/7
2571
- // This fixes almost every IE6/7 issue
2572
- nodeHook = jQuery.valHooks.button = {
2573
- get: function( elem, name ) {
2574
- var ret = elem.getAttributeNode( name );
2575
- return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ?
2576
- ret.value :
2577
- undefined;
2578
- },
2579
- set: function( elem, value, name ) {
2580
- // Set the existing or create a new attribute node
2581
- var ret = elem.getAttributeNode( name );
2582
- if ( !ret ) {
2583
- elem.setAttributeNode(
2584
- (ret = elem.ownerDocument.createAttribute( name ))
2585
- );
2586
- }
2587
-
2588
- ret.value = value += "";
2589
-
2590
- // Break association with cloned elements by also using setAttribute (#9646)
2591
- return name === "value" || value === elem.getAttribute( name ) ?
2592
- value :
2593
- undefined;
2594
- }
2595
- };
2596
-
2597
- // Set contenteditable to false on removals(#10429)
2598
- // Setting to empty string throws an error as an invalid value
2599
- jQuery.attrHooks.contenteditable = {
2600
- get: nodeHook.get,
2601
- set: function( elem, value, name ) {
2602
- nodeHook.set( elem, value === "" ? false : value, name );
2603
- }
2604
- };
2605
-
2606
- // Set width and height to auto instead of 0 on empty string( Bug #8150 )
2607
- // This is for removals
2608
- jQuery.each([ "width", "height" ], function( i, name ) {
2609
- jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2610
- set: function( elem, value ) {
2611
- if ( value === "" ) {
2612
- elem.setAttribute( name, "auto" );
2613
- return value;
2614
- }
2615
- }
2616
- });
2617
- });
2618
- }
2619
-
2620
-
2621
- // Some attributes require a special call on IE
2622
- // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2623
- if ( !jQuery.support.hrefNormalized ) {
2624
- jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
2625
- jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2626
- get: function( elem ) {
2627
- var ret = elem.getAttribute( name, 2 );
2628
- return ret == null ? undefined : ret;
2629
- }
2630
- });
2631
- });
2632
-
2633
- // href/src property should get the full normalized URL (#10299/#12915)
2634
- jQuery.each([ "href", "src" ], function( i, name ) {
2635
- jQuery.propHooks[ name ] = {
2636
- get: function( elem ) {
2637
- return elem.getAttribute( name, 4 );
2638
- }
2639
- };
2640
- });
2641
- }
2642
-
2643
- if ( !jQuery.support.style ) {
2644
- jQuery.attrHooks.style = {
2645
- get: function( elem ) {
2646
- // Return undefined in the case of empty string
2647
- // Note: IE uppercases css property names, but if we were to .toLowerCase()
2648
- // .cssText, that would destroy case senstitivity in URL's, like in "background"
2649
- return elem.style.cssText || undefined;
2650
- },
2651
- set: function( elem, value ) {
2652
- return ( elem.style.cssText = value + "" );
2653
- }
2654
- };
2655
- }
2656
-
2657
- // Safari mis-reports the default selected property of an option
2658
- // Accessing the parent's selectedIndex property fixes it
2659
- if ( !jQuery.support.optSelected ) {
2660
- jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
2661
- get: function( elem ) {
2662
- var parent = elem.parentNode;
2663
-
2664
- if ( parent ) {
2665
- parent.selectedIndex;
2666
-
2667
- // Make sure that it also works with optgroups, see #5701
2668
- if ( parent.parentNode ) {
2669
- parent.parentNode.selectedIndex;
2670
- }
2671
- }
2672
- return null;
2673
- }
2674
- });
2675
- }
2676
-
2677
- // IE6/7 call enctype encoding
2678
- if ( !jQuery.support.enctype ) {
2679
- jQuery.propFix.enctype = "encoding";
2680
- }
2681
-
2682
- // Radios and checkboxes getter/setter
2683
- if ( !jQuery.support.checkOn ) {
2684
- jQuery.each([ "radio", "checkbox" ], function() {
2685
- jQuery.valHooks[ this ] = {
2686
- get: function( elem ) {
2687
- // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
2688
- return elem.getAttribute("value") === null ? "on" : elem.value;
2689
- }
2690
- };
2691
- });
2692
- }
2693
- jQuery.each([ "radio", "checkbox" ], function() {
2694
- jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
2695
- set: function( elem, value ) {
2696
- if ( jQuery.isArray( value ) ) {
2697
- return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
2698
- }
2699
- }
2700
- });
2701
- });
2702
- var rformElems = /^(?:input|select|textarea)$/i,
2703
- rkeyEvent = /^key/,
2704
- rmouseEvent = /^(?:mouse|contextmenu)|click/,
2705
- rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
2706
- rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
2707
-
2708
- function returnTrue() {
2709
- return true;
2710
- }
2711
-
2712
- function returnFalse() {
2713
- return false;
2714
- }
2715
-
2716
- /*
2717
- * Helper functions for managing events -- not part of the public interface.
2718
- * Props to Dean Edwards' addEvent library for many of the ideas.
2719
- */
2720
- jQuery.event = {
2721
-
2722
- global: {},
2723
-
2724
- add: function( elem, types, handler, data, selector ) {
2725
- var tmp, events, t, handleObjIn,
2726
- special, eventHandle, handleObj,
2727
- handlers, type, namespaces, origType,
2728
- elemData = jQuery._data( elem );
2729
-
2730
- // Don't attach events to noData or text/comment nodes (but allow plain objects)
2731
- if ( !elemData ) {
2732
- return;
2733
- }
2734
-
2735
- // Caller can pass in an object of custom data in lieu of the handler
2736
- if ( handler.handler ) {
2737
- handleObjIn = handler;
2738
- handler = handleObjIn.handler;
2739
- selector = handleObjIn.selector;
2740
- }
2741
-
2742
- // Make sure that the handler has a unique ID, used to find/remove it later
2743
- if ( !handler.guid ) {
2744
- handler.guid = jQuery.guid++;
2745
- }
2746
-
2747
- // Init the element's event structure and main handler, if this is the first
2748
- if ( !(events = elemData.events) ) {
2749
- events = elemData.events = {};
2750
- }
2751
- if ( !(eventHandle = elemData.handle) ) {
2752
- eventHandle = elemData.handle = function( e ) {
2753
- // Discard the second event of a jQuery.event.trigger() and
2754
- // when an event is called after a page has unloaded
2755
- return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
2756
- jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
2757
- undefined;
2758
- };
2759
- // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
2760
- eventHandle.elem = elem;
2761
- }
2762
-
2763
- // Handle multiple events separated by a space
2764
- // jQuery(...).bind("mouseover mouseout", fn);
2765
- types = ( types || "" ).match( core_rnotwhite ) || [""];
2766
- t = types.length;
2767
- while ( t-- ) {
2768
- tmp = rtypenamespace.exec( types[t] ) || [];
2769
- type = origType = tmp[1];
2770
- namespaces = ( tmp[2] || "" ).split( "." ).sort();
2771
-
2772
- // If event changes its type, use the special event handlers for the changed type
2773
- special = jQuery.event.special[ type ] || {};
2774
-
2775
- // If selector defined, determine special event api type, otherwise given type
2776
- type = ( selector ? special.delegateType : special.bindType ) || type;
2777
-
2778
- // Update special based on newly reset type
2779
- special = jQuery.event.special[ type ] || {};
2780
-
2781
- // handleObj is passed to all event handlers
2782
- handleObj = jQuery.extend({
2783
- type: type,
2784
- origType: origType,
2785
- data: data,
2786
- handler: handler,
2787
- guid: handler.guid,
2788
- selector: selector,
2789
- needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
2790
- namespace: namespaces.join(".")
2791
- }, handleObjIn );
2792
-
2793
- // Init the event handler queue if we're the first
2794
- if ( !(handlers = events[ type ]) ) {
2795
- handlers = events[ type ] = [];
2796
- handlers.delegateCount = 0;
2797
-
2798
- // Only use addEventListener/attachEvent if the special events handler returns false
2799
- if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
2800
- // Bind the global event handler to the element
2801
- if ( elem.addEventListener ) {
2802
- elem.addEventListener( type, eventHandle, false );
2803
-
2804
- } else if ( elem.attachEvent ) {
2805
- elem.attachEvent( "on" + type, eventHandle );
2806
- }
2807
- }
2808
- }
2809
-
2810
- if ( special.add ) {
2811
- special.add.call( elem, handleObj );
2812
-
2813
- if ( !handleObj.handler.guid ) {
2814
- handleObj.handler.guid = handler.guid;
2815
- }
2816
- }
2817
-
2818
- // Add to the element's handler list, delegates in front
2819
- if ( selector ) {
2820
- handlers.splice( handlers.delegateCount++, 0, handleObj );
2821
- } else {
2822
- handlers.push( handleObj );
2823
- }
2824
-
2825
- // Keep track of which events have ever been used, for event optimization
2826
- jQuery.event.global[ type ] = true;
2827
- }
2828
-
2829
- // Nullify elem to prevent memory leaks in IE
2830
- elem = null;
2831
- },
2832
-
2833
- // Detach an event or set of events from an element
2834
- remove: function( elem, types, handler, selector, mappedTypes ) {
2835
- var j, handleObj, tmp,
2836
- origCount, t, events,
2837
- special, handlers, type,
2838
- namespaces, origType,
2839
- elemData = jQuery.hasData( elem ) && jQuery._data( elem );
2840
-
2841
- if ( !elemData || !(events = elemData.events) ) {
2842
- return;
2843
- }
2844
-
2845
- // Once for each type.namespace in types; type may be omitted
2846
- types = ( types || "" ).match( core_rnotwhite ) || [""];
2847
- t = types.length;
2848
- while ( t-- ) {
2849
- tmp = rtypenamespace.exec( types[t] ) || [];
2850
- type = origType = tmp[1];
2851
- namespaces = ( tmp[2] || "" ).split( "." ).sort();
2852
-
2853
- // Unbind all events (on this namespace, if provided) for the element
2854
- if ( !type ) {
2855
- for ( type in events ) {
2856
- jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
2857
- }
2858
- continue;
2859
- }
2860
-
2861
- special = jQuery.event.special[ type ] || {};
2862
- type = ( selector ? special.delegateType : special.bindType ) || type;
2863
- handlers = events[ type ] || [];
2864
- tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
2865
-
2866
- // Remove matching events
2867
- origCount = j = handlers.length;
2868
- while ( j-- ) {
2869
- handleObj = handlers[ j ];
2870
-
2871
- if ( ( mappedTypes || origType === handleObj.origType ) &&
2872
- ( !handler || handler.guid === handleObj.guid ) &&
2873
- ( !tmp || tmp.test( handleObj.namespace ) ) &&
2874
- ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
2875
- handlers.splice( j, 1 );
2876
-
2877
- if ( handleObj.selector ) {
2878
- handlers.delegateCount--;
2879
- }
2880
- if ( special.remove ) {
2881
- special.remove.call( elem, handleObj );
2882
- }
2883
- }
2884
- }
2885
-
2886
- // Remove generic event handler if we removed something and no more handlers exist
2887
- // (avoids potential for endless recursion during removal of special event handlers)
2888
- if ( origCount && !handlers.length ) {
2889
- if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
2890
- jQuery.removeEvent( elem, type, elemData.handle );
2891
- }
2892
-
2893
- delete events[ type ];
2894
- }
2895
- }
2896
-
2897
- // Remove the expando if it's no longer used
2898
- if ( jQuery.isEmptyObject( events ) ) {
2899
- delete elemData.handle;
2900
-
2901
- // removeData also checks for emptiness and clears the expando if empty
2902
- // so use it instead of delete
2903
- jQuery._removeData( elem, "events" );
2904
- }
2905
- },
2906
-
2907
- trigger: function( event, data, elem, onlyHandlers ) {
2908
- var handle, ontype, cur,
2909
- bubbleType, special, tmp, i,
2910
- eventPath = [ elem || document ],
2911
- type = core_hasOwn.call( event, "type" ) ? event.type : event,
2912
- namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
2913
-
2914
- cur = tmp = elem = elem || document;
2915
-
2916
- // Don't do events on text and comment nodes
2917
- if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
2918
- return;
2919
- }
2920
-
2921
- // focus/blur morphs to focusin/out; ensure we're not firing them right now
2922
- if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
2923
- return;
2924
- }
2925
-
2926
- if ( type.indexOf(".") >= 0 ) {
2927
- // Namespaced trigger; create a regexp to match event type in handle()
2928
- namespaces = type.split(".");
2929
- type = namespaces.shift();
2930
- namespaces.sort();
2931
- }
2932
- ontype = type.indexOf(":") < 0 && "on" + type;
2933
-
2934
- // Caller can pass in a jQuery.Event object, Object, or just an event type string
2935
- event = event[ jQuery.expando ] ?
2936
- event :
2937
- new jQuery.Event( type, typeof event === "object" && event );
2938
-
2939
- event.isTrigger = true;
2940
- event.namespace = namespaces.join(".");
2941
- event.namespace_re = event.namespace ?
2942
- new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
2943
- null;
2944
-
2945
- // Clean up the event in case it is being reused
2946
- event.result = undefined;
2947
- if ( !event.target ) {
2948
- event.target = elem;
2949
- }
2950
-
2951
- // Clone any incoming data and prepend the event, creating the handler arg list
2952
- data = data == null ?
2953
- [ event ] :
2954
- jQuery.makeArray( data, [ event ] );
2955
-
2956
- // Allow special events to draw outside the lines
2957
- special = jQuery.event.special[ type ] || {};
2958
- if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
2959
- return;
2960
- }
2961
-
2962
- // Determine event propagation path in advance, per W3C events spec (#9951)
2963
- // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
2964
- if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
2965
-
2966
- bubbleType = special.delegateType || type;
2967
- if ( !rfocusMorph.test( bubbleType + type ) ) {
2968
- cur = cur.parentNode;
2969
- }
2970
- for ( ; cur; cur = cur.parentNode ) {
2971
- eventPath.push( cur );
2972
- tmp = cur;
2973
- }
2974
-
2975
- // Only add window if we got to document (e.g., not plain obj or detached DOM)
2976
- if ( tmp === (elem.ownerDocument || document) ) {
2977
- eventPath.push( tmp.defaultView || tmp.parentWindow || window );
2978
- }
2979
- }
2980
-
2981
- // Fire handlers on the event path
2982
- i = 0;
2983
- while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
2984
-
2985
- event.type = i > 1 ?
2986
- bubbleType :
2987
- special.bindType || type;
2988
-
2989
- // jQuery handler
2990
- handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
2991
- if ( handle ) {
2992
- handle.apply( cur, data );
2993
- }
2994
-
2995
- // Native handler
2996
- handle = ontype && cur[ ontype ];
2997
- if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
2998
- event.preventDefault();
2999
- }
3000
- }
3001
- event.type = type;
3002
-
3003
- // If nobody prevented the default action, do it now
3004
- if ( !onlyHandlers && !event.isDefaultPrevented() ) {
3005
-
3006
- if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
3007
- !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
3008
-
3009
- // Call a native DOM method on the target with the same name name as the event.
3010
- // Can't use an .isFunction() check here because IE6/7 fails that test.
3011
- // Don't do default actions on window, that's where global variables be (#6170)
3012
- if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
3013
-
3014
- // Don't re-trigger an onFOO event when we call its FOO() method
3015
- tmp = elem[ ontype ];
3016
-
3017
- if ( tmp ) {
3018
- elem[ ontype ] = null;
3019
- }
3020
-
3021
- // Prevent re-triggering of the same event, since we already bubbled it above
3022
- jQuery.event.triggered = type;
3023
- try {
3024
- elem[ type ]();
3025
- } catch ( e ) {
3026
- // IE<9 dies on focus/blur to hidden element (#1486,#12518)
3027
- // only reproducible on winXP IE8 native, not IE9 in IE8 mode
3028
- }
3029
- jQuery.event.triggered = undefined;
3030
-
3031
- if ( tmp ) {
3032
- elem[ ontype ] = tmp;
3033
- }
3034
- }
3035
- }
3036
- }
3037
-
3038
- return event.result;
3039
- },
3040
-
3041
- dispatch: function( event ) {
3042
-
3043
- // Make a writable jQuery.Event from the native event object
3044
- event = jQuery.event.fix( event );
3045
-
3046
- var i, ret, handleObj, matched, j,
3047
- handlerQueue = [],
3048
- args = core_slice.call( arguments ),
3049
- handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
3050
- special = jQuery.event.special[ event.type ] || {};
3051
-
3052
- // Use the fix-ed jQuery.Event rather than the (read-only) native event
3053
- args[0] = event;
3054
- event.delegateTarget = this;
3055
-
3056
- // Call the preDispatch hook for the mapped type, and let it bail if desired
3057
- if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
3058
- return;
3059
- }
3060
-
3061
- // Determine handlers
3062
- handlerQueue = jQuery.event.handlers.call( this, event, handlers );
3063
-
3064
- // Run delegates first; they may want to stop propagation beneath us
3065
- i = 0;
3066
- while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
3067
- event.currentTarget = matched.elem;
3068
-
3069
- j = 0;
3070
- while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
3071
-
3072
- // Triggered event must either 1) have no namespace, or
3073
- // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
3074
- if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
3075
-
3076
- event.handleObj = handleObj;
3077
- event.data = handleObj.data;
3078
-
3079
- ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
3080
- .apply( matched.elem, args );
3081
-
3082
- if ( ret !== undefined ) {
3083
- if ( (event.result = ret) === false ) {
3084
- event.preventDefault();
3085
- event.stopPropagation();
3086
- }
3087
- }
3088
- }
3089
- }
3090
- }
3091
-
3092
- // Call the postDispatch hook for the mapped type
3093
- if ( special.postDispatch ) {
3094
- special.postDispatch.call( this, event );
3095
- }
3096
-
3097
- return event.result;
3098
- },
3099
-
3100
- handlers: function( event, handlers ) {
3101
- var sel, handleObj, matches, i,
3102
- handlerQueue = [],
3103
- delegateCount = handlers.delegateCount,
3104
- cur = event.target;
3105
-
3106
- // Find delegate handlers
3107
- // Black-hole SVG <use> instance trees (#13180)
3108
- // Avoid non-left-click bubbling in Firefox (#3861)
3109
- if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
3110
-
3111
- for ( ; cur != this; cur = cur.parentNode || this ) {
3112
-
3113
- // Don't check non-elements (#13208)
3114
- // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
3115
- if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
3116
- matches = [];
3117
- for ( i = 0; i < delegateCount; i++ ) {
3118
- handleObj = handlers[ i ];
3119
-
3120
- // Don't conflict with Object.prototype properties (#13203)
3121
- sel = handleObj.selector + " ";
3122
-
3123
- if ( matches[ sel ] === undefined ) {
3124
- matches[ sel ] = handleObj.needsContext ?
3125
- jQuery( sel, this ).index( cur ) >= 0 :
3126
- jQuery.find( sel, this, null, [ cur ] ).length;
3127
- }
3128
- if ( matches[ sel ] ) {
3129
- matches.push( handleObj );
3130
- }
3131
- }
3132
- if ( matches.length ) {
3133
- handlerQueue.push({ elem: cur, handlers: matches });
3134
- }
3135
- }
3136
- }
3137
- }
3138
-
3139
- // Add the remaining (directly-bound) handlers
3140
- if ( delegateCount < handlers.length ) {
3141
- handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
3142
- }
3143
-
3144
- return handlerQueue;
3145
- },
3146
-
3147
- fix: function( event ) {
3148
- if ( event[ jQuery.expando ] ) {
3149
- return event;
3150
- }
3151
-
3152
- // Create a writable copy of the event object and normalize some properties
3153
- var i, prop, copy,
3154
- type = event.type,
3155
- originalEvent = event,
3156
- fixHook = this.fixHooks[ type ];
3157
-
3158
- if ( !fixHook ) {
3159
- this.fixHooks[ type ] = fixHook =
3160
- rmouseEvent.test( type ) ? this.mouseHooks :
3161
- rkeyEvent.test( type ) ? this.keyHooks :
3162
- {};
3163
- }
3164
- copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
3165
-
3166
- event = new jQuery.Event( originalEvent );
3167
-
3168
- i = copy.length;
3169
- while ( i-- ) {
3170
- prop = copy[ i ];
3171
- event[ prop ] = originalEvent[ prop ];
3172
- }
3173
-
3174
- // Support: IE<9
3175
- // Fix target property (#1925)
3176
- if ( !event.target ) {
3177
- event.target = originalEvent.srcElement || document;
3178
- }
3179
-
3180
- // Support: Chrome 23+, Safari?
3181
- // Target should not be a text node (#504, #13143)
3182
- if ( event.target.nodeType === 3 ) {
3183
- event.target = event.target.parentNode;
3184
- }
3185
-
3186
- // Support: IE<9
3187
- // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
3188
- event.metaKey = !!event.metaKey;
3189
-
3190
- return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
3191
- },
3192
-
3193
- // Includes some event props shared by KeyEvent and MouseEvent
3194
- props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
3195
-
3196
- fixHooks: {},
3197
-
3198
- keyHooks: {
3199
- props: "char charCode key keyCode".split(" "),
3200
- filter: function( event, original ) {
3201
-
3202
- // Add which for key events
3203
- if ( event.which == null ) {
3204
- event.which = original.charCode != null ? original.charCode : original.keyCode;
3205
- }
3206
-
3207
- return event;
3208
- }
3209
- },
3210
-
3211
- mouseHooks: {
3212
- props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
3213
- filter: function( event, original ) {
3214
- var body, eventDoc, doc,
3215
- button = original.button,
3216
- fromElement = original.fromElement;
3217
-
3218
- // Calculate pageX/Y if missing and clientX/Y available
3219
- if ( event.pageX == null && original.clientX != null ) {
3220
- eventDoc = event.target.ownerDocument || document;
3221
- doc = eventDoc.documentElement;
3222
- body = eventDoc.body;
3223
-
3224
- event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
3225
- event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
3226
- }
3227
-
3228
- // Add relatedTarget, if necessary
3229
- if ( !event.relatedTarget && fromElement ) {
3230
- event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
3231
- }
3232
-
3233
- // Add which for click: 1 === left; 2 === middle; 3 === right
3234
- // Note: button is not normalized, so don't use it
3235
- if ( !event.which && button !== undefined ) {
3236
- event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
3237
- }
3238
-
3239
- return event;
3240
- }
3241
- },
3242
-
3243
- special: {
3244
- load: {
3245
- // Prevent triggered image.load events from bubbling to window.load
3246
- noBubble: true
3247
- },
3248
- click: {
3249
- // For checkbox, fire native event so checked state will be right
3250
- trigger: function() {
3251
- if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
3252
- this.click();
3253
- return false;
3254
- }
3255
- }
3256
- },
3257
- focus: {
3258
- // Fire native event if possible so blur/focus sequence is correct
3259
- trigger: function() {
3260
- if ( this !== document.activeElement && this.focus ) {
3261
- try {
3262
- this.focus();
3263
- return false;
3264
- } catch ( e ) {
3265
- // Support: IE<9
3266
- // If we error on focus to hidden element (#1486, #12518),
3267
- // let .trigger() run the handlers
3268
- }
3269
- }
3270
- },
3271
- delegateType: "focusin"
3272
- },
3273
- blur: {
3274
- trigger: function() {
3275
- if ( this === document.activeElement && this.blur ) {
3276
- this.blur();
3277
- return false;
3278
- }
3279
- },
3280
- delegateType: "focusout"
3281
- },
3282
-
3283
- beforeunload: {
3284
- postDispatch: function( event ) {
3285
-
3286
- // Even when returnValue equals to undefined Firefox will still show alert
3287
- if ( event.result !== undefined ) {
3288
- event.originalEvent.returnValue = event.result;
3289
- }
3290
- }
3291
- }
3292
- },
3293
-
3294
- simulate: function( type, elem, event, bubble ) {
3295
- // Piggyback on a donor event to simulate a different one.
3296
- // Fake originalEvent to avoid donor's stopPropagation, but if the
3297
- // simulated event prevents default then we do the same on the donor.
3298
- var e = jQuery.extend(
3299
- new jQuery.Event(),
3300
- event,
3301
- { type: type,
3302
- isSimulated: true,
3303
- originalEvent: {}
3304
- }
3305
- );
3306
- if ( bubble ) {
3307
- jQuery.event.trigger( e, null, elem );
3308
- } else {
3309
- jQuery.event.dispatch.call( elem, e );
3310
- }
3311
- if ( e.isDefaultPrevented() ) {
3312
- event.preventDefault();
3313
- }
3314
- }
3315
- };
3316
-
3317
- jQuery.removeEvent = document.removeEventListener ?
3318
- function( elem, type, handle ) {
3319
- if ( elem.removeEventListener ) {
3320
- elem.removeEventListener( type, handle, false );
3321
- }
3322
- } :
3323
- function( elem, type, handle ) {
3324
- var name = "on" + type;
3325
-
3326
- if ( elem.detachEvent ) {
3327
-
3328
- // #8545, #7054, preventing memory leaks for custom events in IE6-8
3329
- // detachEvent needed property on element, by name of that event, to properly expose it to GC
3330
- if ( typeof elem[ name ] === core_strundefined ) {
3331
- elem[ name ] = null;
3332
- }
3333
-
3334
- elem.detachEvent( name, handle );
3335
- }
3336
- };
3337
-
3338
- jQuery.Event = function( src, props ) {
3339
- // Allow instantiation without the 'new' keyword
3340
- if ( !(this instanceof jQuery.Event) ) {
3341
- return new jQuery.Event( src, props );
3342
- }
3343
-
3344
- // Event object
3345
- if ( src && src.type ) {
3346
- this.originalEvent = src;
3347
- this.type = src.type;
3348
-
3349
- // Events bubbling up the document may have been marked as prevented
3350
- // by a handler lower down the tree; reflect the correct value.
3351
- this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
3352
- src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
3353
-
3354
- // Event type
3355
- } else {
3356
- this.type = src;
3357
- }
3358
-
3359
- // Put explicitly provided properties onto the event object
3360
- if ( props ) {
3361
- jQuery.extend( this, props );
3362
- }
3363
-
3364
- // Create a timestamp if incoming event doesn't have one
3365
- this.timeStamp = src && src.timeStamp || jQuery.now();
3366
-
3367
- // Mark it as fixed
3368
- this[ jQuery.expando ] = true;
3369
- };
3370
-
3371
- // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
3372
- // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
3373
- jQuery.Event.prototype = {
3374
- isDefaultPrevented: returnFalse,
3375
- isPropagationStopped: returnFalse,
3376
- isImmediatePropagationStopped: returnFalse,
3377
-
3378
- preventDefault: function() {
3379
- var e = this.originalEvent;
3380
-
3381
- this.isDefaultPrevented = returnTrue;
3382
- if ( !e ) {
3383
- return;
3384
- }
3385
-
3386
- // If preventDefault exists, run it on the original event
3387
- if ( e.preventDefault ) {
3388
- e.preventDefault();
3389
-
3390
- // Support: IE
3391
- // Otherwise set the returnValue property of the original event to false
3392
- } else {
3393
- e.returnValue = false;
3394
- }
3395
- },
3396
- stopPropagation: function() {
3397
- var e = this.originalEvent;
3398
-
3399
- this.isPropagationStopped = returnTrue;
3400
- if ( !e ) {
3401
- return;
3402
- }
3403
- // If stopPropagation exists, run it on the original event
3404
- if ( e.stopPropagation ) {
3405
- e.stopPropagation();
3406
- }
3407
-
3408
- // Support: IE
3409
- // Set the cancelBubble property of the original event to true
3410
- e.cancelBubble = true;
3411
- },
3412
- stopImmediatePropagation: function() {
3413
- this.isImmediatePropagationStopped = returnTrue;
3414
- this.stopPropagation();
3415
- }
3416
- };
3417
-
3418
- // Create mouseenter/leave events using mouseover/out and event-time checks
3419
- jQuery.each({
3420
- mouseenter: "mouseover",
3421
- mouseleave: "mouseout"
3422
- }, function( orig, fix ) {
3423
- jQuery.event.special[ orig ] = {
3424
- delegateType: fix,
3425
- bindType: fix,
3426
-
3427
- handle: function( event ) {
3428
- var ret,
3429
- target = this,
3430
- related = event.relatedTarget,
3431
- handleObj = event.handleObj;
3432
-
3433
- // For mousenter/leave call the handler if related is outside the target.
3434
- // NB: No relatedTarget if the mouse left/entered the browser window
3435
- if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
3436
- event.type = handleObj.origType;
3437
- ret = handleObj.handler.apply( this, arguments );
3438
- event.type = fix;
3439
- }
3440
- return ret;
3441
- }
3442
- };
3443
- });
3444
-
3445
- // IE submit delegation
3446
- if ( !jQuery.support.submitBubbles ) {
3447
-
3448
- jQuery.event.special.submit = {
3449
- setup: function() {
3450
- // Only need this for delegated form submit events
3451
- if ( jQuery.nodeName( this, "form" ) ) {
3452
- return false;
3453
- }
3454
-
3455
- // Lazy-add a submit handler when a descendant form may potentially be submitted
3456
- jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
3457
- // Node name check avoids a VML-related crash in IE (#9807)
3458
- var elem = e.target,
3459
- form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
3460
- if ( form && !jQuery._data( form, "submitBubbles" ) ) {
3461
- jQuery.event.add( form, "submit._submit", function( event ) {
3462
- event._submit_bubble = true;
3463
- });
3464
- jQuery._data( form, "submitBubbles", true );
3465
- }
3466
- });
3467
- // return undefined since we don't need an event listener
3468
- },
3469
-
3470
- postDispatch: function( event ) {
3471
- // If form was submitted by the user, bubble the event up the tree
3472
- if ( event._submit_bubble ) {
3473
- delete event._submit_bubble;
3474
- if ( this.parentNode && !event.isTrigger ) {
3475
- jQuery.event.simulate( "submit", this.parentNode, event, true );
3476
- }
3477
- }
3478
- },
3479
-
3480
- teardown: function() {
3481
- // Only need this for delegated form submit events
3482
- if ( jQuery.nodeName( this, "form" ) ) {
3483
- return false;
3484
- }
3485
-
3486
- // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
3487
- jQuery.event.remove( this, "._submit" );
3488
- }
3489
- };
3490
- }
3491
-
3492
- // IE change delegation and checkbox/radio fix
3493
- if ( !jQuery.support.changeBubbles ) {
3494
-
3495
- jQuery.event.special.change = {
3496
-
3497
- setup: function() {
3498
-
3499
- if ( rformElems.test( this.nodeName ) ) {
3500
- // IE doesn't fire change on a check/radio until blur; trigger it on click
3501
- // after a propertychange. Eat the blur-change in special.change.handle.
3502
- // This still fires onchange a second time for check/radio after blur.
3503
- if ( this.type === "checkbox" || this.type === "radio" ) {
3504
- jQuery.event.add( this, "propertychange._change", function( event ) {
3505
- if ( event.originalEvent.propertyName === "checked" ) {
3506
- this._just_changed = true;
3507
- }
3508
- });
3509
- jQuery.event.add( this, "click._change", function( event ) {
3510
- if ( this._just_changed && !event.isTrigger ) {
3511
- this._just_changed = false;
3512
- }
3513
- // Allow triggered, simulated change events (#11500)
3514
- jQuery.event.simulate( "change", this, event, true );
3515
- });
3516
- }
3517
- return false;
3518
- }
3519
- // Delegated event; lazy-add a change handler on descendant inputs
3520
- jQuery.event.add( this, "beforeactivate._change", function( e ) {
3521
- var elem = e.target;
3522
-
3523
- if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
3524
- jQuery.event.add( elem, "change._change", function( event ) {
3525
- if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
3526
- jQuery.event.simulate( "change", this.parentNode, event, true );
3527
- }
3528
- });
3529
- jQuery._data( elem, "changeBubbles", true );
3530
- }
3531
- });
3532
- },
3533
-
3534
- handle: function( event ) {
3535
- var elem = event.target;
3536
-
3537
- // Swallow native change events from checkbox/radio, we already triggered them above
3538
- if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
3539
- return event.handleObj.handler.apply( this, arguments );
3540
- }
3541
- },
3542
-
3543
- teardown: function() {
3544
- jQuery.event.remove( this, "._change" );
3545
-
3546
- return !rformElems.test( this.nodeName );
3547
- }
3548
- };
3549
- }
3550
-
3551
- // Create "bubbling" focus and blur events
3552
- if ( !jQuery.support.focusinBubbles ) {
3553
- jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
3554
-
3555
- // Attach a single capturing handler while someone wants focusin/focusout
3556
- var attaches = 0,
3557
- handler = function( event ) {
3558
- jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
3559
- };
3560
-
3561
- jQuery.event.special[ fix ] = {
3562
- setup: function() {
3563
- if ( attaches++ === 0 ) {
3564
- document.addEventListener( orig, handler, true );
3565
- }
3566
- },
3567
- teardown: function() {
3568
- if ( --attaches === 0 ) {
3569
- document.removeEventListener( orig, handler, true );
3570
- }
3571
- }
3572
- };
3573
- });
3574
- }
3575
-
3576
- jQuery.fn.extend({
3577
-
3578
- on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
3579
- var type, origFn;
3580
-
3581
- // Types can be a map of types/handlers
3582
- if ( typeof types === "object" ) {
3583
- // ( types-Object, selector, data )
3584
- if ( typeof selector !== "string" ) {
3585
- // ( types-Object, data )
3586
- data = data || selector;
3587
- selector = undefined;
3588
- }
3589
- for ( type in types ) {
3590
- this.on( type, selector, data, types[ type ], one );
3591
- }
3592
- return this;
3593
- }
3594
-
3595
- if ( data == null && fn == null ) {
3596
- // ( types, fn )
3597
- fn = selector;
3598
- data = selector = undefined;
3599
- } else if ( fn == null ) {
3600
- if ( typeof selector === "string" ) {
3601
- // ( types, selector, fn )
3602
- fn = data;
3603
- data = undefined;
3604
- } else {
3605
- // ( types, data, fn )
3606
- fn = data;
3607
- data = selector;
3608
- selector = undefined;
3609
- }
3610
- }
3611
- if ( fn === false ) {
3612
- fn = returnFalse;
3613
- } else if ( !fn ) {
3614
- return this;
3615
- }
3616
-
3617
- if ( one === 1 ) {
3618
- origFn = fn;
3619
- fn = function( event ) {
3620
- // Can use an empty set, since event contains the info
3621
- jQuery().off( event );
3622
- return origFn.apply( this, arguments );
3623
- };
3624
- // Use same guid so caller can remove using origFn
3625
- fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
3626
- }
3627
- return this.each( function() {
3628
- jQuery.event.add( this, types, fn, data, selector );
3629
- });
3630
- },
3631
- one: function( types, selector, data, fn ) {
3632
- return this.on( types, selector, data, fn, 1 );
3633
- },
3634
- off: function( types, selector, fn ) {
3635
- var handleObj, type;
3636
- if ( types && types.preventDefault && types.handleObj ) {
3637
- // ( event ) dispatched jQuery.Event
3638
- handleObj = types.handleObj;
3639
- jQuery( types.delegateTarget ).off(
3640
- handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
3641
- handleObj.selector,
3642
- handleObj.handler
3643
- );
3644
- return this;
3645
- }
3646
- if ( typeof types === "object" ) {
3647
- // ( types-object [, selector] )
3648
- for ( type in types ) {
3649
- this.off( type, selector, types[ type ] );
3650
- }
3651
- return this;
3652
- }
3653
- if ( selector === false || typeof selector === "function" ) {
3654
- // ( types [, fn] )
3655
- fn = selector;
3656
- selector = undefined;
3657
- }
3658
- if ( fn === false ) {
3659
- fn = returnFalse;
3660
- }
3661
- return this.each(function() {
3662
- jQuery.event.remove( this, types, fn, selector );
3663
- });
3664
- },
3665
-
3666
- bind: function( types, data, fn ) {
3667
- return this.on( types, null, data, fn );
3668
- },
3669
- unbind: function( types, fn ) {
3670
- return this.off( types, null, fn );
3671
- },
3672
-
3673
- delegate: function( selector, types, data, fn ) {
3674
- return this.on( types, selector, data, fn );
3675
- },
3676
- undelegate: function( selector, types, fn ) {
3677
- // ( namespace ) or ( selector, types [, fn] )
3678
- return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
3679
- },
3680
-
3681
- trigger: function( type, data ) {
3682
- return this.each(function() {
3683
- jQuery.event.trigger( type, data, this );
3684
- });
3685
- },
3686
- triggerHandler: function( type, data ) {
3687
- var elem = this[0];
3688
- if ( elem ) {
3689
- return jQuery.event.trigger( type, data, elem, true );
3690
- }
3691
- }
3692
- });
3693
- /*!
3694
- * Sizzle CSS Selector Engine
3695
- * Copyright 2012 jQuery Foundation and other contributors
3696
- * Released under the MIT license
3697
- * http://sizzlejs.com/
3698
- */
3699
- (function( window, undefined ) {
3700
-
3701
- var i,
3702
- cachedruns,
3703
- Expr,
3704
- getText,
3705
- isXML,
3706
- compile,
3707
- hasDuplicate,
3708
- outermostContext,
3709
-
3710
- // Local document vars
3711
- setDocument,
3712
- document,
3713
- docElem,
3714
- documentIsXML,
3715
- rbuggyQSA,
3716
- rbuggyMatches,
3717
- matches,
3718
- contains,
3719
- sortOrder,
3720
-
3721
- // Instance-specific data
3722
- expando = "sizzle" + -(new Date()),
3723
- preferredDoc = window.document,
3724
- support = {},
3725
- dirruns = 0,
3726
- done = 0,
3727
- classCache = createCache(),
3728
- tokenCache = createCache(),
3729
- compilerCache = createCache(),
3730
-
3731
- // General-purpose constants
3732
- strundefined = typeof undefined,
3733
- MAX_NEGATIVE = 1 << 31,
3734
-
3735
- // Array methods
3736
- arr = [],
3737
- pop = arr.pop,
3738
- push = arr.push,
3739
- slice = arr.slice,
3740
- // Use a stripped-down indexOf if we can't use a native one
3741
- indexOf = arr.indexOf || function( elem ) {
3742
- var i = 0,
3743
- len = this.length;
3744
- for ( ; i < len; i++ ) {
3745
- if ( this[i] === elem ) {
3746
- return i;
3747
- }
3748
- }
3749
- return -1;
3750
- },
3751
-
3752
-
3753
- // Regular expressions
3754
-
3755
- // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
3756
- whitespace = "[\\x20\\t\\r\\n\\f]",
3757
- // http://www.w3.org/TR/css3-syntax/#characters
3758
- characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
3759
-
3760
- // Loosely modeled on CSS identifier characters
3761
- // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
3762
- // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
3763
- identifier = characterEncoding.replace( "w", "w#" ),
3764
-
3765
- // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
3766
- operators = "([*^$|!~]?=)",
3767
- attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
3768
- "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
3769
-
3770
- // Prefer arguments quoted,
3771
- // then not containing pseudos/brackets,
3772
- // then attribute selectors/non-parenthetical expressions,
3773
- // then anything else
3774
- // These preferences are here to reduce the number of selectors
3775
- // needing tokenize in the PSEUDO preFilter
3776
- pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
3777
-
3778
- // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
3779
- rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
3780
-
3781
- rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
3782
- rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),
3783
- rpseudo = new RegExp( pseudos ),
3784
- ridentifier = new RegExp( "^" + identifier + "$" ),
3785
-
3786
- matchExpr = {
3787
- "ID": new RegExp( "^#(" + characterEncoding + ")" ),
3788
- "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
3789
- "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),
3790
- "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
3791
- "ATTR": new RegExp( "^" + attributes ),
3792
- "PSEUDO": new RegExp( "^" + pseudos ),
3793
- "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
3794
- "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
3795
- "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
3796
- // For use in libraries implementing .is()
3797
- // We use this for POS matching in `select`
3798
- "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
3799
- whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
3800
- },
3801
-
3802
- rsibling = /[\x20\t\r\n\f]*[+~]/,
3803
-
3804
- rnative = /^[^{]+\{\s*\[native code/,
3805
-
3806
- // Easily-parseable/retrievable ID or TAG or CLASS selectors
3807
- rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
3808
-
3809
- rinputs = /^(?:input|select|textarea|button)$/i,
3810
- rheader = /^h\d$/i,
3811
-
3812
- rescape = /'|\\/g,
3813
- rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
3814
-
3815
- // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
3816
- runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,
3817
- funescape = function( _, escaped ) {
3818
- var high = "0x" + escaped - 0x10000;
3819
- // NaN means non-codepoint
3820
- return high !== high ?
3821
- escaped :
3822
- // BMP codepoint
3823
- high < 0 ?
3824
- String.fromCharCode( high + 0x10000 ) :
3825
- // Supplemental Plane codepoint (surrogate pair)
3826
- String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
3827
- };
3828
-
3829
- // Use a stripped-down slice if we can't use a native one
3830
- try {
3831
- slice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType;
3832
- } catch ( e ) {
3833
- slice = function( i ) {
3834
- var elem,
3835
- results = [];
3836
- while ( (elem = this[i++]) ) {
3837
- results.push( elem );
3838
- }
3839
- return results;
3840
- };
3841
- }
3842
-
3843
- /**
3844
- * For feature detection
3845
- * @param {Function} fn The function to test for native support
3846
- */
3847
- function isNative( fn ) {
3848
- return rnative.test( fn + "" );
3849
- }
3850
-
3851
- /**
3852
- * Create key-value caches of limited size
3853
- * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
3854
- * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
3855
- * deleting the oldest entry
3856
- */
3857
- function createCache() {
3858
- var cache,
3859
- keys = [];
3860
-
3861
- return (cache = function( key, value ) {
3862
- // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
3863
- if ( keys.push( key += " " ) > Expr.cacheLength ) {
3864
- // Only keep the most recent entries
3865
- delete cache[ keys.shift() ];
3866
- }
3867
- return (cache[ key ] = value);
3868
- });
3869
- }
3870
-
3871
- /**
3872
- * Mark a function for special use by Sizzle
3873
- * @param {Function} fn The function to mark
3874
- */
3875
- function markFunction( fn ) {
3876
- fn[ expando ] = true;
3877
- return fn;
3878
- }
3879
-
3880
- /**
3881
- * Support testing using an element
3882
- * @param {Function} fn Passed the created div and expects a boolean result
3883
- */
3884
- function assert( fn ) {
3885
- var div = document.createElement("div");
3886
-
3887
- try {
3888
- return fn( div );
3889
- } catch (e) {
3890
- return false;
3891
- } finally {
3892
- // release memory in IE
3893
- div = null;
3894
- }
3895
- }
3896
-
3897
- function Sizzle( selector, context, results, seed ) {
3898
- var match, elem, m, nodeType,
3899
- // QSA vars
3900
- i, groups, old, nid, newContext, newSelector;
3901
-
3902
- if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
3903
- setDocument( context );
3904
- }
3905
-
3906
- context = context || document;
3907
- results = results || [];
3908
-
3909
- if ( !selector || typeof selector !== "string" ) {
3910
- return results;
3911
- }
3912
-
3913
- if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
3914
- return [];
3915
- }
3916
-
3917
- if ( !documentIsXML && !seed ) {
3918
-
3919
- // Shortcuts
3920
- if ( (match = rquickExpr.exec( selector )) ) {
3921
- // Speed-up: Sizzle("#ID")
3922
- if ( (m = match[1]) ) {
3923
- if ( nodeType === 9 ) {
3924
- elem = context.getElementById( m );
3925
- // Check parentNode to catch when Blackberry 4.6 returns
3926
- // nodes that are no longer in the document #6963
3927
- if ( elem && elem.parentNode ) {
3928
- // Handle the case where IE, Opera, and Webkit return items
3929
- // by name instead of ID
3930
- if ( elem.id === m ) {
3931
- results.push( elem );
3932
- return results;
3933
- }
3934
- } else {
3935
- return results;
3936
- }
3937
- } else {
3938
- // Context is not a document
3939
- if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
3940
- contains( context, elem ) && elem.id === m ) {
3941
- results.push( elem );
3942
- return results;
3943
- }
3944
- }
3945
-
3946
- // Speed-up: Sizzle("TAG")
3947
- } else if ( match[2] ) {
3948
- push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );
3949
- return results;
3950
-
3951
- // Speed-up: Sizzle(".CLASS")
3952
- } else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) {
3953
- push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );
3954
- return results;
3955
- }
3956
- }
3957
-
3958
- // QSA path
3959
- if ( support.qsa && !rbuggyQSA.test(selector) ) {
3960
- old = true;
3961
- nid = expando;
3962
- newContext = context;
3963
- newSelector = nodeType === 9 && selector;
3964
-
3965
- // qSA works strangely on Element-rooted queries
3966
- // We can work around this by specifying an extra ID on the root
3967
- // and working up from there (Thanks to Andrew Dupont for the technique)
3968
- // IE 8 doesn't work on object elements
3969
- if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
3970
- groups = tokenize( selector );
3971
-
3972
- if ( (old = context.getAttribute("id")) ) {
3973
- nid = old.replace( rescape, "\\$&" );
3974
- } else {
3975
- context.setAttribute( "id", nid );
3976
- }
3977
- nid = "[id='" + nid + "'] ";
3978
-
3979
- i = groups.length;
3980
- while ( i-- ) {
3981
- groups[i] = nid + toSelector( groups[i] );
3982
- }
3983
- newContext = rsibling.test( selector ) && context.parentNode || context;
3984
- newSelector = groups.join(",");
3985
- }
3986
-
3987
- if ( newSelector ) {
3988
- try {
3989
- push.apply( results, slice.call( newContext.querySelectorAll(
3990
- newSelector
3991
- ), 0 ) );
3992
- return results;
3993
- } catch(qsaError) {
3994
- } finally {
3995
- if ( !old ) {
3996
- context.removeAttribute("id");
3997
- }
3998
- }
3999
- }
4000
- }
4001
- }
4002
-
4003
- // All others
4004
- return select( selector.replace( rtrim, "$1" ), context, results, seed );
4005
- }
4006
-
4007
- /**
4008
- * Detect xml
4009
- * @param {Element|Object} elem An element or a document
4010
- */
4011
- isXML = Sizzle.isXML = function( elem ) {
4012
- // documentElement is verified for cases where it doesn't yet exist
4013
- // (such as loading iframes in IE - #4833)
4014
- var documentElement = elem && (elem.ownerDocument || elem).documentElement;
4015
- return documentElement ? documentElement.nodeName !== "HTML" : false;
4016
- };
4017
-
4018
- /**
4019
- * Sets document-related variables once based on the current document
4020
- * @param {Element|Object} [doc] An element or document object to use to set the document
4021
- * @returns {Object} Returns the current document
4022
- */
4023
- setDocument = Sizzle.setDocument = function( node ) {
4024
- var doc = node ? node.ownerDocument || node : preferredDoc;
4025
-
4026
- // If no document and documentElement is available, return
4027
- if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
4028
- return document;
4029
- }
4030
-
4031
- // Set our document
4032
- document = doc;
4033
- docElem = doc.documentElement;
4034
-
4035
- // Support tests
4036
- documentIsXML = isXML( doc );
4037
-
4038
- // Check if getElementsByTagName("*") returns only elements
4039
- support.tagNameNoComments = assert(function( div ) {
4040
- div.appendChild( doc.createComment("") );
4041
- return !div.getElementsByTagName("*").length;
4042
- });
4043
-
4044
- // Check if attributes should be retrieved by attribute nodes
4045
- support.attributes = assert(function( div ) {
4046
- div.innerHTML = "<select></select>";
4047
- var type = typeof div.lastChild.getAttribute("multiple");
4048
- // IE8 returns a string for some attributes even when not present
4049
- return type !== "boolean" && type !== "string";
4050
- });
4051
-
4052
- // Check if getElementsByClassName can be trusted
4053
- support.getByClassName = assert(function( div ) {
4054
- // Opera can't find a second classname (in 9.6)
4055
- div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";
4056
- if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {
4057
- return false;
4058
- }
4059
-
4060
- // Safari 3.2 caches class attributes and doesn't catch changes
4061
- div.lastChild.className = "e";
4062
- return div.getElementsByClassName("e").length === 2;
4063
- });
4064
-
4065
- // Check if getElementById returns elements by name
4066
- // Check if getElementsByName privileges form controls or returns elements by ID
4067
- support.getByName = assert(function( div ) {
4068
- // Inject content
4069
- div.id = expando + 0;
4070
- div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
4071
- docElem.insertBefore( div, docElem.firstChild );
4072
-
4073
- // Test
4074
- var pass = doc.getElementsByName &&
4075
- // buggy browsers will return fewer than the correct 2
4076
- doc.getElementsByName( expando ).length === 2 +
4077
- // buggy browsers will return more than the correct 0
4078
- doc.getElementsByName( expando + 0 ).length;
4079
- support.getIdNotName = !doc.getElementById( expando );
4080
-
4081
- // Cleanup
4082
- docElem.removeChild( div );
4083
-
4084
- return pass;
4085
- });
4086
-
4087
- // IE6/7 return modified attributes
4088
- Expr.attrHandle = assert(function( div ) {
4089
- div.innerHTML = "<a href='#'></a>";
4090
- return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
4091
- div.firstChild.getAttribute("href") === "#";
4092
- }) ?
4093
- {} :
4094
- {
4095
- "href": function( elem ) {
4096
- return elem.getAttribute( "href", 2 );
4097
- },
4098
- "type": function( elem ) {
4099
- return elem.getAttribute("type");
4100
- }
4101
- };
4102
-
4103
- // ID find and filter
4104
- if ( support.getIdNotName ) {
4105
- Expr.find["ID"] = function( id, context ) {
4106
- if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
4107
- var m = context.getElementById( id );
4108
- // Check parentNode to catch when Blackberry 4.6 returns
4109
- // nodes that are no longer in the document #6963
4110
- return m && m.parentNode ? [m] : [];
4111
- }
4112
- };
4113
- Expr.filter["ID"] = function( id ) {
4114
- var attrId = id.replace( runescape, funescape );
4115
- return function( elem ) {
4116
- return elem.getAttribute("id") === attrId;
4117
- };
4118
- };
4119
- } else {
4120
- Expr.find["ID"] = function( id, context ) {
4121
- if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
4122
- var m = context.getElementById( id );
4123
-
4124
- return m ?
4125
- m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
4126
- [m] :
4127
- undefined :
4128
- [];
4129
- }
4130
- };
4131
- Expr.filter["ID"] = function( id ) {
4132
- var attrId = id.replace( runescape, funescape );
4133
- return function( elem ) {
4134
- var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
4135
- return node && node.value === attrId;
4136
- };
4137
- };
4138
- }
4139
-
4140
- // Tag
4141
- Expr.find["TAG"] = support.tagNameNoComments ?
4142
- function( tag, context ) {
4143
- if ( typeof context.getElementsByTagName !== strundefined ) {
4144
- return context.getElementsByTagName( tag );
4145
- }
4146
- } :
4147
- function( tag, context ) {
4148
- var elem,
4149
- tmp = [],
4150
- i = 0,
4151
- results = context.getElementsByTagName( tag );
4152
-
4153
- // Filter out possible comments
4154
- if ( tag === "*" ) {
4155
- while ( (elem = results[i++]) ) {
4156
- if ( elem.nodeType === 1 ) {
4157
- tmp.push( elem );
4158
- }
4159
- }
4160
-
4161
- return tmp;
4162
- }
4163
- return results;
4164
- };
4165
-
4166
- // Name
4167
- Expr.find["NAME"] = support.getByName && function( tag, context ) {
4168
- if ( typeof context.getElementsByName !== strundefined ) {
4169
- return context.getElementsByName( name );
4170
- }
4171
- };
4172
-
4173
- // Class
4174
- Expr.find["CLASS"] = support.getByClassName && function( className, context ) {
4175
- if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) {
4176
- return context.getElementsByClassName( className );
4177
- }
4178
- };
4179
-
4180
- // QSA and matchesSelector support
4181
-
4182
- // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
4183
- rbuggyMatches = [];
4184
-
4185
- // qSa(:focus) reports false when true (Chrome 21),
4186
- // no need to also add to buggyMatches since matches checks buggyQSA
4187
- // A support test would require too much code (would include document ready)
4188
- rbuggyQSA = [ ":focus" ];
4189
-
4190
- if ( (support.qsa = isNative(doc.querySelectorAll)) ) {
4191
- // Build QSA regex
4192
- // Regex strategy adopted from Diego Perini
4193
- assert(function( div ) {
4194
- // Select is set to empty string on purpose
4195
- // This is to test IE's treatment of not explictly
4196
- // setting a boolean content attribute,
4197
- // since its presence should be enough
4198
- // http://bugs.jquery.com/ticket/12359
4199
- div.innerHTML = "<select><option selected=''></option></select>";
4200
-
4201
- // IE8 - Some boolean attributes are not treated correctly
4202
- if ( !div.querySelectorAll("[selected]").length ) {
4203
- rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );
4204
- }
4205
-
4206
- // Webkit/Opera - :checked should return selected option elements
4207
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
4208
- // IE8 throws error here and will not see later tests
4209
- if ( !div.querySelectorAll(":checked").length ) {
4210
- rbuggyQSA.push(":checked");
4211
- }
4212
- });
4213
-
4214
- assert(function( div ) {
4215
-
4216
- // Opera 10-12/IE8 - ^= $= *= and empty values
4217
- // Should not select anything
4218
- div.innerHTML = "<input type='hidden' i=''/>";
4219
- if ( div.querySelectorAll("[i^='']").length ) {
4220
- rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );
4221
- }
4222
-
4223
- // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
4224
- // IE8 throws error here and will not see later tests
4225
- if ( !div.querySelectorAll(":enabled").length ) {
4226
- rbuggyQSA.push( ":enabled", ":disabled" );
4227
- }
4228
-
4229
- // Opera 10-11 does not throw on post-comma invalid pseudos
4230
- div.querySelectorAll("*,:x");
4231
- rbuggyQSA.push(",.*:");
4232
- });
4233
- }
4234
-
4235
- if ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector ||
4236
- docElem.mozMatchesSelector ||
4237
- docElem.webkitMatchesSelector ||
4238
- docElem.oMatchesSelector ||
4239
- docElem.msMatchesSelector) )) ) {
4240
-
4241
- assert(function( div ) {
4242
- // Check to see if it's possible to do matchesSelector
4243
- // on a disconnected node (IE 9)
4244
- support.disconnectedMatch = matches.call( div, "div" );
4245
-
4246
- // This should fail with an exception
4247
- // Gecko does not error, returns false instead
4248
- matches.call( div, "[s!='']:x" );
4249
- rbuggyMatches.push( "!=", pseudos );
4250
- });
4251
- }
4252
-
4253
- rbuggyQSA = new RegExp( rbuggyQSA.join("|") );
4254
- rbuggyMatches = new RegExp( rbuggyMatches.join("|") );
4255
-
4256
- // Element contains another
4257
- // Purposefully does not implement inclusive descendent
4258
- // As in, an element does not contain itself
4259
- contains = isNative(docElem.contains) || docElem.compareDocumentPosition ?
4260
- function( a, b ) {
4261
- var adown = a.nodeType === 9 ? a.documentElement : a,
4262
- bup = b && b.parentNode;
4263
- return a === bup || !!( bup && bup.nodeType === 1 && (
4264
- adown.contains ?
4265
- adown.contains( bup ) :
4266
- a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
4267
- ));
4268
- } :
4269
- function( a, b ) {
4270
- if ( b ) {
4271
- while ( (b = b.parentNode) ) {
4272
- if ( b === a ) {
4273
- return true;
4274
- }
4275
- }
4276
- }
4277
- return false;
4278
- };
4279
-
4280
- // Document order sorting
4281
- sortOrder = docElem.compareDocumentPosition ?
4282
- function( a, b ) {
4283
- var compare;
4284
-
4285
- if ( a === b ) {
4286
- hasDuplicate = true;
4287
- return 0;
4288
- }
4289
-
4290
- if ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) {
4291
- if ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) {
4292
- if ( a === doc || contains( preferredDoc, a ) ) {
4293
- return -1;
4294
- }
4295
- if ( b === doc || contains( preferredDoc, b ) ) {
4296
- return 1;
4297
- }
4298
- return 0;
4299
- }
4300
- return compare & 4 ? -1 : 1;
4301
- }
4302
-
4303
- return a.compareDocumentPosition ? -1 : 1;
4304
- } :
4305
- function( a, b ) {
4306
- var cur,
4307
- i = 0,
4308
- aup = a.parentNode,
4309
- bup = b.parentNode,
4310
- ap = [ a ],
4311
- bp = [ b ];
4312
-
4313
- // Exit early if the nodes are identical
4314
- if ( a === b ) {
4315
- hasDuplicate = true;
4316
- return 0;
4317
-
4318
- // Parentless nodes are either documents or disconnected
4319
- } else if ( !aup || !bup ) {
4320
- return a === doc ? -1 :
4321
- b === doc ? 1 :
4322
- aup ? -1 :
4323
- bup ? 1 :
4324
- 0;
4325
-
4326
- // If the nodes are siblings, we can do a quick check
4327
- } else if ( aup === bup ) {
4328
- return siblingCheck( a, b );
4329
- }
4330
-
4331
- // Otherwise we need full lists of their ancestors for comparison
4332
- cur = a;
4333
- while ( (cur = cur.parentNode) ) {
4334
- ap.unshift( cur );
4335
- }
4336
- cur = b;
4337
- while ( (cur = cur.parentNode) ) {
4338
- bp.unshift( cur );
4339
- }
4340
-
4341
- // Walk down the tree looking for a discrepancy
4342
- while ( ap[i] === bp[i] ) {
4343
- i++;
4344
- }
4345
-
4346
- return i ?
4347
- // Do a sibling check if the nodes have a common ancestor
4348
- siblingCheck( ap[i], bp[i] ) :
4349
-
4350
- // Otherwise nodes in our document sort first
4351
- ap[i] === preferredDoc ? -1 :
4352
- bp[i] === preferredDoc ? 1 :
4353
- 0;
4354
- };
4355
-
4356
- // Always assume the presence of duplicates if sort doesn't
4357
- // pass them to our comparison function (as in Google Chrome).
4358
- hasDuplicate = false;
4359
- [0, 0].sort( sortOrder );
4360
- support.detectDuplicates = hasDuplicate;
4361
-
4362
- return document;
4363
- };
4364
-
4365
- Sizzle.matches = function( expr, elements ) {
4366
- return Sizzle( expr, null, null, elements );
4367
- };
4368
-
4369
- Sizzle.matchesSelector = function( elem, expr ) {
4370
- // Set document vars if needed
4371
- if ( ( elem.ownerDocument || elem ) !== document ) {
4372
- setDocument( elem );
4373
- }
4374
-
4375
- // Make sure that attribute selectors are quoted
4376
- expr = expr.replace( rattributeQuotes, "='$1']" );
4377
-
4378
- // rbuggyQSA always contains :focus, so no need for an existence check
4379
- if ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) {
4380
- try {
4381
- var ret = matches.call( elem, expr );
4382
-
4383
- // IE 9's matchesSelector returns false on disconnected nodes
4384
- if ( ret || support.disconnectedMatch ||
4385
- // As well, disconnected nodes are said to be in a document
4386
- // fragment in IE 9
4387
- elem.document && elem.document.nodeType !== 11 ) {
4388
- return ret;
4389
- }
4390
- } catch(e) {}
4391
- }
4392
-
4393
- return Sizzle( expr, document, null, [elem] ).length > 0;
4394
- };
4395
-
4396
- Sizzle.contains = function( context, elem ) {
4397
- // Set document vars if needed
4398
- if ( ( context.ownerDocument || context ) !== document ) {
4399
- setDocument( context );
4400
- }
4401
- return contains( context, elem );
4402
- };
4403
-
4404
- Sizzle.attr = function( elem, name ) {
4405
- var val;
4406
-
4407
- // Set document vars if needed
4408
- if ( ( elem.ownerDocument || elem ) !== document ) {
4409
- setDocument( elem );
4410
- }
4411
-
4412
- if ( !documentIsXML ) {
4413
- name = name.toLowerCase();
4414
- }
4415
- if ( (val = Expr.attrHandle[ name ]) ) {
4416
- return val( elem );
4417
- }
4418
- if ( documentIsXML || support.attributes ) {
4419
- return elem.getAttribute( name );
4420
- }
4421
- return ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ?
4422
- name :
4423
- val && val.specified ? val.value : null;
4424
- };
4425
-
4426
- Sizzle.error = function( msg ) {
4427
- throw new Error( "Syntax error, unrecognized expression: " + msg );
4428
- };
4429
-
4430
- // Document sorting and removing duplicates
4431
- Sizzle.uniqueSort = function( results ) {
4432
- var elem,
4433
- duplicates = [],
4434
- i = 1,
4435
- j = 0;
4436
-
4437
- // Unless we *know* we can detect duplicates, assume their presence
4438
- hasDuplicate = !support.detectDuplicates;
4439
- results.sort( sortOrder );
4440
-
4441
- if ( hasDuplicate ) {
4442
- for ( ; (elem = results[i]); i++ ) {
4443
- if ( elem === results[ i - 1 ] ) {
4444
- j = duplicates.push( i );
4445
- }
4446
- }
4447
- while ( j-- ) {
4448
- results.splice( duplicates[ j ], 1 );
4449
- }
4450
- }
4451
-
4452
- return results;
4453
- };
4454
-
4455
- function siblingCheck( a, b ) {
4456
- var cur = b && a,
4457
- diff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE );
4458
-
4459
- // Use IE sourceIndex if available on both nodes
4460
- if ( diff ) {
4461
- return diff;
4462
- }
4463
-
4464
- // Check if b follows a
4465
- if ( cur ) {
4466
- while ( (cur = cur.nextSibling) ) {
4467
- if ( cur === b ) {
4468
- return -1;
4469
- }
4470
- }
4471
- }
4472
-
4473
- return a ? 1 : -1;
4474
- }
4475
-
4476
- // Returns a function to use in pseudos for input types
4477
- function createInputPseudo( type ) {
4478
- return function( elem ) {
4479
- var name = elem.nodeName.toLowerCase();
4480
- return name === "input" && elem.type === type;
4481
- };
4482
- }
4483
-
4484
- // Returns a function to use in pseudos for buttons
4485
- function createButtonPseudo( type ) {
4486
- return function( elem ) {
4487
- var name = elem.nodeName.toLowerCase();
4488
- return (name === "input" || name === "button") && elem.type === type;
4489
- };
4490
- }
4491
-
4492
- // Returns a function to use in pseudos for positionals
4493
- function createPositionalPseudo( fn ) {
4494
- return markFunction(function( argument ) {
4495
- argument = +argument;
4496
- return markFunction(function( seed, matches ) {
4497
- var j,
4498
- matchIndexes = fn( [], seed.length, argument ),
4499
- i = matchIndexes.length;
4500
-
4501
- // Match elements found at the specified indexes
4502
- while ( i-- ) {
4503
- if ( seed[ (j = matchIndexes[i]) ] ) {
4504
- seed[j] = !(matches[j] = seed[j]);
4505
- }
4506
- }
4507
- });
4508
- });
4509
- }
4510
-
4511
- /**
4512
- * Utility function for retrieving the text value of an array of DOM nodes
4513
- * @param {Array|Element} elem
4514
- */
4515
- getText = Sizzle.getText = function( elem ) {
4516
- var node,
4517
- ret = "",
4518
- i = 0,
4519
- nodeType = elem.nodeType;
4520
-
4521
- if ( !nodeType ) {
4522
- // If no nodeType, this is expected to be an array
4523
- for ( ; (node = elem[i]); i++ ) {
4524
- // Do not traverse comment nodes
4525
- ret += getText( node );
4526
- }
4527
- } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
4528
- // Use textContent for elements
4529
- // innerText usage removed for consistency of new lines (see #11153)
4530
- if ( typeof elem.textContent === "string" ) {
4531
- return elem.textContent;
4532
- } else {
4533
- // Traverse its children
4534
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
4535
- ret += getText( elem );
4536
- }
4537
- }
4538
- } else if ( nodeType === 3 || nodeType === 4 ) {
4539
- return elem.nodeValue;
4540
- }
4541
- // Do not include comment or processing instruction nodes
4542
-
4543
- return ret;
4544
- };
4545
-
4546
- Expr = Sizzle.selectors = {
4547
-
4548
- // Can be adjusted by the user
4549
- cacheLength: 50,
4550
-
4551
- createPseudo: markFunction,
4552
-
4553
- match: matchExpr,
4554
-
4555
- find: {},
4556
-
4557
- relative: {
4558
- ">": { dir: "parentNode", first: true },
4559
- " ": { dir: "parentNode" },
4560
- "+": { dir: "previousSibling", first: true },
4561
- "~": { dir: "previousSibling" }
4562
- },
4563
-
4564
- preFilter: {
4565
- "ATTR": function( match ) {
4566
- match[1] = match[1].replace( runescape, funescape );
4567
-
4568
- // Move the given value to match[3] whether quoted or unquoted
4569
- match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
4570
-
4571
- if ( match[2] === "~=" ) {
4572
- match[3] = " " + match[3] + " ";
4573
- }
4574
-
4575
- return match.slice( 0, 4 );
4576
- },
4577
-
4578
- "CHILD": function( match ) {
4579
- /* matches from matchExpr["CHILD"]
4580
- 1 type (only|nth|...)
4581
- 2 what (child|of-type)
4582
- 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
4583
- 4 xn-component of xn+y argument ([+-]?\d*n|)
4584
- 5 sign of xn-component
4585
- 6 x of xn-component
4586
- 7 sign of y-component
4587
- 8 y of y-component
4588
- */
4589
- match[1] = match[1].toLowerCase();
4590
-
4591
- if ( match[1].slice( 0, 3 ) === "nth" ) {
4592
- // nth-* requires argument
4593
- if ( !match[3] ) {
4594
- Sizzle.error( match[0] );
4595
- }
4596
-
4597
- // numeric x and y parameters for Expr.filter.CHILD
4598
- // remember that false/true cast respectively to 0/1
4599
- match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
4600
- match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
4601
-
4602
- // other types prohibit arguments
4603
- } else if ( match[3] ) {
4604
- Sizzle.error( match[0] );
4605
- }
4606
-
4607
- return match;
4608
- },
4609
-
4610
- "PSEUDO": function( match ) {
4611
- var excess,
4612
- unquoted = !match[5] && match[2];
4613
-
4614
- if ( matchExpr["CHILD"].test( match[0] ) ) {
4615
- return null;
4616
- }
4617
-
4618
- // Accept quoted arguments as-is
4619
- if ( match[4] ) {
4620
- match[2] = match[4];
4621
-
4622
- // Strip excess characters from unquoted arguments
4623
- } else if ( unquoted && rpseudo.test( unquoted ) &&
4624
- // Get excess from tokenize (recursively)
4625
- (excess = tokenize( unquoted, true )) &&
4626
- // advance to the next closing parenthesis
4627
- (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
4628
-
4629
- // excess is a negative index
4630
- match[0] = match[0].slice( 0, excess );
4631
- match[2] = unquoted.slice( 0, excess );
4632
- }
4633
-
4634
- // Return only captures needed by the pseudo filter method (type and argument)
4635
- return match.slice( 0, 3 );
4636
- }
4637
- },
4638
-
4639
- filter: {
4640
-
4641
- "TAG": function( nodeName ) {
4642
- if ( nodeName === "*" ) {
4643
- return function() { return true; };
4644
- }
4645
-
4646
- nodeName = nodeName.replace( runescape, funescape ).toLowerCase();
4647
- return function( elem ) {
4648
- return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
4649
- };
4650
- },
4651
-
4652
- "CLASS": function( className ) {
4653
- var pattern = classCache[ className + " " ];
4654
-
4655
- return pattern ||
4656
- (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
4657
- classCache( className, function( elem ) {
4658
- return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
4659
- });
4660
- },
4661
-
4662
- "ATTR": function( name, operator, check ) {
4663
- return function( elem ) {
4664
- var result = Sizzle.attr( elem, name );
4665
-
4666
- if ( result == null ) {
4667
- return operator === "!=";
4668
- }
4669
- if ( !operator ) {
4670
- return true;
4671
- }
4672
-
4673
- result += "";
4674
-
4675
- return operator === "=" ? result === check :
4676
- operator === "!=" ? result !== check :
4677
- operator === "^=" ? check && result.indexOf( check ) === 0 :
4678
- operator === "*=" ? check && result.indexOf( check ) > -1 :
4679
- operator === "$=" ? check && result.slice( -check.length ) === check :
4680
- operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
4681
- operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
4682
- false;
4683
- };
4684
- },
4685
-
4686
- "CHILD": function( type, what, argument, first, last ) {
4687
- var simple = type.slice( 0, 3 ) !== "nth",
4688
- forward = type.slice( -4 ) !== "last",
4689
- ofType = what === "of-type";
4690
-
4691
- return first === 1 && last === 0 ?
4692
-
4693
- // Shortcut for :nth-*(n)
4694
- function( elem ) {
4695
- return !!elem.parentNode;
4696
- } :
4697
-
4698
- function( elem, context, xml ) {
4699
- var cache, outerCache, node, diff, nodeIndex, start,
4700
- dir = simple !== forward ? "nextSibling" : "previousSibling",
4701
- parent = elem.parentNode,
4702
- name = ofType && elem.nodeName.toLowerCase(),
4703
- useCache = !xml && !ofType;
4704
-
4705
- if ( parent ) {
4706
-
4707
- // :(first|last|only)-(child|of-type)
4708
- if ( simple ) {
4709
- while ( dir ) {
4710
- node = elem;
4711
- while ( (node = node[ dir ]) ) {
4712
- if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
4713
- return false;
4714
- }
4715
- }
4716
- // Reverse direction for :only-* (if we haven't yet done so)
4717
- start = dir = type === "only" && !start && "nextSibling";
4718
- }
4719
- return true;
4720
- }
4721
-
4722
- start = [ forward ? parent.firstChild : parent.lastChild ];
4723
-
4724
- // non-xml :nth-child(...) stores cache data on `parent`
4725
- if ( forward && useCache ) {
4726
- // Seek `elem` from a previously-cached index
4727
- outerCache = parent[ expando ] || (parent[ expando ] = {});
4728
- cache = outerCache[ type ] || [];
4729
- nodeIndex = cache[0] === dirruns && cache[1];
4730
- diff = cache[0] === dirruns && cache[2];
4731
- node = nodeIndex && parent.childNodes[ nodeIndex ];
4732
-
4733
- while ( (node = ++nodeIndex && node && node[ dir ] ||
4734
-
4735
- // Fallback to seeking `elem` from the start
4736
- (diff = nodeIndex = 0) || start.pop()) ) {
4737
-
4738
- // When found, cache indexes on `parent` and break
4739
- if ( node.nodeType === 1 && ++diff && node === elem ) {
4740
- outerCache[ type ] = [ dirruns, nodeIndex, diff ];
4741
- break;
4742
- }
4743
- }
4744
-
4745
- // Use previously-cached element index if available
4746
- } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
4747
- diff = cache[1];
4748
-
4749
- // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
4750
- } else {
4751
- // Use the same loop as above to seek `elem` from the start
4752
- while ( (node = ++nodeIndex && node && node[ dir ] ||
4753
- (diff = nodeIndex = 0) || start.pop()) ) {
4754
-
4755
- if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
4756
- // Cache the index of each encountered element
4757
- if ( useCache ) {
4758
- (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
4759
- }
4760
-
4761
- if ( node === elem ) {
4762
- break;
4763
- }
4764
- }
4765
- }
4766
- }
4767
-
4768
- // Incorporate the offset, then check against cycle size
4769
- diff -= last;
4770
- return diff === first || ( diff % first === 0 && diff / first >= 0 );
4771
- }
4772
- };
4773
- },
4774
-
4775
- "PSEUDO": function( pseudo, argument ) {
4776
- // pseudo-class names are case-insensitive
4777
- // http://www.w3.org/TR/selectors/#pseudo-classes
4778
- // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
4779
- // Remember that setFilters inherits from pseudos
4780
- var args,
4781
- fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
4782
- Sizzle.error( "unsupported pseudo: " + pseudo );
4783
-
4784
- // The user may use createPseudo to indicate that
4785
- // arguments are needed to create the filter function
4786
- // just as Sizzle does
4787
- if ( fn[ expando ] ) {
4788
- return fn( argument );
4789
- }
4790
-
4791
- // But maintain support for old signatures
4792
- if ( fn.length > 1 ) {
4793
- args = [ pseudo, pseudo, "", argument ];
4794
- return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
4795
- markFunction(function( seed, matches ) {
4796
- var idx,
4797
- matched = fn( seed, argument ),
4798
- i = matched.length;
4799
- while ( i-- ) {
4800
- idx = indexOf.call( seed, matched[i] );
4801
- seed[ idx ] = !( matches[ idx ] = matched[i] );
4802
- }
4803
- }) :
4804
- function( elem ) {
4805
- return fn( elem, 0, args );
4806
- };
4807
- }
4808
-
4809
- return fn;
4810
- }
4811
- },
4812
-
4813
- pseudos: {
4814
- // Potentially complex pseudos
4815
- "not": markFunction(function( selector ) {
4816
- // Trim the selector passed to compile
4817
- // to avoid treating leading and trailing
4818
- // spaces as combinators
4819
- var input = [],
4820
- results = [],
4821
- matcher = compile( selector.replace( rtrim, "$1" ) );
4822
-
4823
- return matcher[ expando ] ?
4824
- markFunction(function( seed, matches, context, xml ) {
4825
- var elem,
4826
- unmatched = matcher( seed, null, xml, [] ),
4827
- i = seed.length;
4828
-
4829
- // Match elements unmatched by `matcher`
4830
- while ( i-- ) {
4831
- if ( (elem = unmatched[i]) ) {
4832
- seed[i] = !(matches[i] = elem);
4833
- }
4834
- }
4835
- }) :
4836
- function( elem, context, xml ) {
4837
- input[0] = elem;
4838
- matcher( input, null, xml, results );
4839
- return !results.pop();
4840
- };
4841
- }),
4842
-
4843
- "has": markFunction(function( selector ) {
4844
- return function( elem ) {
4845
- return Sizzle( selector, elem ).length > 0;
4846
- };
4847
- }),
4848
-
4849
- "contains": markFunction(function( text ) {
4850
- return function( elem ) {
4851
- return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
4852
- };
4853
- }),
4854
-
4855
- // "Whether an element is represented by a :lang() selector
4856
- // is based solely on the element's language value
4857
- // being equal to the identifier C,
4858
- // or beginning with the identifier C immediately followed by "-".
4859
- // The matching of C against the element's language value is performed case-insensitively.
4860
- // The identifier C does not have to be a valid language name."
4861
- // http://www.w3.org/TR/selectors/#lang-pseudo
4862
- "lang": markFunction( function( lang ) {
4863
- // lang value must be a valid identifider
4864
- if ( !ridentifier.test(lang || "") ) {
4865
- Sizzle.error( "unsupported lang: " + lang );
4866
- }
4867
- lang = lang.replace( runescape, funescape ).toLowerCase();
4868
- return function( elem ) {
4869
- var elemLang;
4870
- do {
4871
- if ( (elemLang = documentIsXML ?
4872
- elem.getAttribute("xml:lang") || elem.getAttribute("lang") :
4873
- elem.lang) ) {
4874
-
4875
- elemLang = elemLang.toLowerCase();
4876
- return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
4877
- }
4878
- } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
4879
- return false;
4880
- };
4881
- }),
4882
-
4883
- // Miscellaneous
4884
- "target": function( elem ) {
4885
- var hash = window.location && window.location.hash;
4886
- return hash && hash.slice( 1 ) === elem.id;
4887
- },
4888
-
4889
- "root": function( elem ) {
4890
- return elem === docElem;
4891
- },
4892
-
4893
- "focus": function( elem ) {
4894
- return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
4895
- },
4896
-
4897
- // Boolean properties
4898
- "enabled": function( elem ) {
4899
- return elem.disabled === false;
4900
- },
4901
-
4902
- "disabled": function( elem ) {
4903
- return elem.disabled === true;
4904
- },
4905
-
4906
- "checked": function( elem ) {
4907
- // In CSS3, :checked should return both checked and selected elements
4908
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
4909
- var nodeName = elem.nodeName.toLowerCase();
4910
- return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
4911
- },
4912
-
4913
- "selected": function( elem ) {
4914
- // Accessing this property makes selected-by-default
4915
- // options in Safari work properly
4916
- if ( elem.parentNode ) {
4917
- elem.parentNode.selectedIndex;
4918
- }
4919
-
4920
- return elem.selected === true;
4921
- },
4922
-
4923
- // Contents
4924
- "empty": function( elem ) {
4925
- // http://www.w3.org/TR/selectors/#empty-pseudo
4926
- // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
4927
- // not comment, processing instructions, or others
4928
- // Thanks to Diego Perini for the nodeName shortcut
4929
- // Greater than "@" means alpha characters (specifically not starting with "#" or "?")
4930
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
4931
- if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
4932
- return false;
4933
- }
4934
- }
4935
- return true;
4936
- },
4937
-
4938
- "parent": function( elem ) {
4939
- return !Expr.pseudos["empty"]( elem );
4940
- },
4941
-
4942
- // Element/input types
4943
- "header": function( elem ) {
4944
- return rheader.test( elem.nodeName );
4945
- },
4946
-
4947
- "input": function( elem ) {
4948
- return rinputs.test( elem.nodeName );
4949
- },
4950
-
4951
- "button": function( elem ) {
4952
- var name = elem.nodeName.toLowerCase();
4953
- return name === "input" && elem.type === "button" || name === "button";
4954
- },
4955
-
4956
- "text": function( elem ) {
4957
- var attr;
4958
- // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
4959
- // use getAttribute instead to test this case
4960
- return elem.nodeName.toLowerCase() === "input" &&
4961
- elem.type === "text" &&
4962
- ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
4963
- },
4964
-
4965
- // Position-in-collection
4966
- "first": createPositionalPseudo(function() {
4967
- return [ 0 ];
4968
- }),
4969
-
4970
- "last": createPositionalPseudo(function( matchIndexes, length ) {
4971
- return [ length - 1 ];
4972
- }),
4973
-
4974
- "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
4975
- return [ argument < 0 ? argument + length : argument ];
4976
- }),
4977
-
4978
- "even": createPositionalPseudo(function( matchIndexes, length ) {
4979
- var i = 0;
4980
- for ( ; i < length; i += 2 ) {
4981
- matchIndexes.push( i );
4982
- }
4983
- return matchIndexes;
4984
- }),
4985
-
4986
- "odd": createPositionalPseudo(function( matchIndexes, length ) {
4987
- var i = 1;
4988
- for ( ; i < length; i += 2 ) {
4989
- matchIndexes.push( i );
4990
- }
4991
- return matchIndexes;
4992
- }),
4993
-
4994
- "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
4995
- var i = argument < 0 ? argument + length : argument;
4996
- for ( ; --i >= 0; ) {
4997
- matchIndexes.push( i );
4998
- }
4999
- return matchIndexes;
5000
- }),
5001
-
5002
- "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
5003
- var i = argument < 0 ? argument + length : argument;
5004
- for ( ; ++i < length; ) {
5005
- matchIndexes.push( i );
5006
- }
5007
- return matchIndexes;
5008
- })
5009
- }
5010
- };
5011
-
5012
- // Add button/input type pseudos
5013
- for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
5014
- Expr.pseudos[ i ] = createInputPseudo( i );
5015
- }
5016
- for ( i in { submit: true, reset: true } ) {
5017
- Expr.pseudos[ i ] = createButtonPseudo( i );
5018
- }
5019
-
5020
- function tokenize( selector, parseOnly ) {
5021
- var matched, match, tokens, type,
5022
- soFar, groups, preFilters,
5023
- cached = tokenCache[ selector + " " ];
5024
-
5025
- if ( cached ) {
5026
- return parseOnly ? 0 : cached.slice( 0 );
5027
- }
5028
-
5029
- soFar = selector;
5030
- groups = [];
5031
- preFilters = Expr.preFilter;
5032
-
5033
- while ( soFar ) {
5034
-
5035
- // Comma and first run
5036
- if ( !matched || (match = rcomma.exec( soFar )) ) {
5037
- if ( match ) {
5038
- // Don't consume trailing commas as valid
5039
- soFar = soFar.slice( match[0].length ) || soFar;
5040
- }
5041
- groups.push( tokens = [] );
5042
- }
5043
-
5044
- matched = false;
5045
-
5046
- // Combinators
5047
- if ( (match = rcombinators.exec( soFar )) ) {
5048
- matched = match.shift();
5049
- tokens.push( {
5050
- value: matched,
5051
- // Cast descendant combinators to space
5052
- type: match[0].replace( rtrim, " " )
5053
- } );
5054
- soFar = soFar.slice( matched.length );
5055
- }
5056
-
5057
- // Filters
5058
- for ( type in Expr.filter ) {
5059
- if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
5060
- (match = preFilters[ type ]( match ))) ) {
5061
- matched = match.shift();
5062
- tokens.push( {
5063
- value: matched,
5064
- type: type,
5065
- matches: match
5066
- } );
5067
- soFar = soFar.slice( matched.length );
5068
- }
5069
- }
5070
-
5071
- if ( !matched ) {
5072
- break;
5073
- }
5074
- }
5075
-
5076
- // Return the length of the invalid excess
5077
- // if we're just parsing
5078
- // Otherwise, throw an error or return tokens
5079
- return parseOnly ?
5080
- soFar.length :
5081
- soFar ?
5082
- Sizzle.error( selector ) :
5083
- // Cache the tokens
5084
- tokenCache( selector, groups ).slice( 0 );
5085
- }
5086
-
5087
- function toSelector( tokens ) {
5088
- var i = 0,
5089
- len = tokens.length,
5090
- selector = "";
5091
- for ( ; i < len; i++ ) {
5092
- selector += tokens[i].value;
5093
- }
5094
- return selector;
5095
- }
5096
-
5097
- function addCombinator( matcher, combinator, base ) {
5098
- var dir = combinator.dir,
5099
- checkNonElements = base && dir === "parentNode",
5100
- doneName = done++;
5101
-
5102
- return combinator.first ?
5103
- // Check against closest ancestor/preceding element
5104
- function( elem, context, xml ) {
5105
- while ( (elem = elem[ dir ]) ) {
5106
- if ( elem.nodeType === 1 || checkNonElements ) {
5107
- return matcher( elem, context, xml );
5108
- }
5109
- }
5110
- } :
5111
-
5112
- // Check against all ancestor/preceding elements
5113
- function( elem, context, xml ) {
5114
- var data, cache, outerCache,
5115
- dirkey = dirruns + " " + doneName;
5116
-
5117
- // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
5118
- if ( xml ) {
5119
- while ( (elem = elem[ dir ]) ) {
5120
- if ( elem.nodeType === 1 || checkNonElements ) {
5121
- if ( matcher( elem, context, xml ) ) {
5122
- return true;
5123
- }
5124
- }
5125
- }
5126
- } else {
5127
- while ( (elem = elem[ dir ]) ) {
5128
- if ( elem.nodeType === 1 || checkNonElements ) {
5129
- outerCache = elem[ expando ] || (elem[ expando ] = {});
5130
- if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
5131
- if ( (data = cache[1]) === true || data === cachedruns ) {
5132
- return data === true;
5133
- }
5134
- } else {
5135
- cache = outerCache[ dir ] = [ dirkey ];
5136
- cache[1] = matcher( elem, context, xml ) || cachedruns;
5137
- if ( cache[1] === true ) {
5138
- return true;
5139
- }
5140
- }
5141
- }
5142
- }
5143
- }
5144
- };
5145
- }
5146
-
5147
- function elementMatcher( matchers ) {
5148
- return matchers.length > 1 ?
5149
- function( elem, context, xml ) {
5150
- var i = matchers.length;
5151
- while ( i-- ) {
5152
- if ( !matchers[i]( elem, context, xml ) ) {
5153
- return false;
5154
- }
5155
- }
5156
- return true;
5157
- } :
5158
- matchers[0];
5159
- }
5160
-
5161
- function condense( unmatched, map, filter, context, xml ) {
5162
- var elem,
5163
- newUnmatched = [],
5164
- i = 0,
5165
- len = unmatched.length,
5166
- mapped = map != null;
5167
-
5168
- for ( ; i < len; i++ ) {
5169
- if ( (elem = unmatched[i]) ) {
5170
- if ( !filter || filter( elem, context, xml ) ) {
5171
- newUnmatched.push( elem );
5172
- if ( mapped ) {
5173
- map.push( i );
5174
- }
5175
- }
5176
- }
5177
- }
5178
-
5179
- return newUnmatched;
5180
- }
5181
-
5182
- function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
5183
- if ( postFilter && !postFilter[ expando ] ) {
5184
- postFilter = setMatcher( postFilter );
5185
- }
5186
- if ( postFinder && !postFinder[ expando ] ) {
5187
- postFinder = setMatcher( postFinder, postSelector );
5188
- }
5189
- return markFunction(function( seed, results, context, xml ) {
5190
- var temp, i, elem,
5191
- preMap = [],
5192
- postMap = [],
5193
- preexisting = results.length,
5194
-
5195
- // Get initial elements from seed or context
5196
- elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
5197
-
5198
- // Prefilter to get matcher input, preserving a map for seed-results synchronization
5199
- matcherIn = preFilter && ( seed || !selector ) ?
5200
- condense( elems, preMap, preFilter, context, xml ) :
5201
- elems,
5202
-
5203
- matcherOut = matcher ?
5204
- // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
5205
- postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
5206
-
5207
- // ...intermediate processing is necessary
5208
- [] :
5209
-
5210
- // ...otherwise use results directly
5211
- results :
5212
- matcherIn;
5213
-
5214
- // Find primary matches
5215
- if ( matcher ) {
5216
- matcher( matcherIn, matcherOut, context, xml );
5217
- }
5218
-
5219
- // Apply postFilter
5220
- if ( postFilter ) {
5221
- temp = condense( matcherOut, postMap );
5222
- postFilter( temp, [], context, xml );
5223
-
5224
- // Un-match failing elements by moving them back to matcherIn
5225
- i = temp.length;
5226
- while ( i-- ) {
5227
- if ( (elem = temp[i]) ) {
5228
- matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
5229
- }
5230
- }
5231
- }
5232
-
5233
- if ( seed ) {
5234
- if ( postFinder || preFilter ) {
5235
- if ( postFinder ) {
5236
- // Get the final matcherOut by condensing this intermediate into postFinder contexts
5237
- temp = [];
5238
- i = matcherOut.length;
5239
- while ( i-- ) {
5240
- if ( (elem = matcherOut[i]) ) {
5241
- // Restore matcherIn since elem is not yet a final match
5242
- temp.push( (matcherIn[i] = elem) );
5243
- }
5244
- }
5245
- postFinder( null, (matcherOut = []), temp, xml );
5246
- }
5247
-
5248
- // Move matched elements from seed to results to keep them synchronized
5249
- i = matcherOut.length;
5250
- while ( i-- ) {
5251
- if ( (elem = matcherOut[i]) &&
5252
- (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
5253
-
5254
- seed[temp] = !(results[temp] = elem);
5255
- }
5256
- }
5257
- }
5258
-
5259
- // Add elements to results, through postFinder if defined
5260
- } else {
5261
- matcherOut = condense(
5262
- matcherOut === results ?
5263
- matcherOut.splice( preexisting, matcherOut.length ) :
5264
- matcherOut
5265
- );
5266
- if ( postFinder ) {
5267
- postFinder( null, results, matcherOut, xml );
5268
- } else {
5269
- push.apply( results, matcherOut );
5270
- }
5271
- }
5272
- });
5273
- }
5274
-
5275
- function matcherFromTokens( tokens ) {
5276
- var checkContext, matcher, j,
5277
- len = tokens.length,
5278
- leadingRelative = Expr.relative[ tokens[0].type ],
5279
- implicitRelative = leadingRelative || Expr.relative[" "],
5280
- i = leadingRelative ? 1 : 0,
5281
-
5282
- // The foundational matcher ensures that elements are reachable from top-level context(s)
5283
- matchContext = addCombinator( function( elem ) {
5284
- return elem === checkContext;
5285
- }, implicitRelative, true ),
5286
- matchAnyContext = addCombinator( function( elem ) {
5287
- return indexOf.call( checkContext, elem ) > -1;
5288
- }, implicitRelative, true ),
5289
- matchers = [ function( elem, context, xml ) {
5290
- return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
5291
- (checkContext = context).nodeType ?
5292
- matchContext( elem, context, xml ) :
5293
- matchAnyContext( elem, context, xml ) );
5294
- } ];
5295
-
5296
- for ( ; i < len; i++ ) {
5297
- if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
5298
- matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
5299
- } else {
5300
- matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
5301
-
5302
- // Return special upon seeing a positional matcher
5303
- if ( matcher[ expando ] ) {
5304
- // Find the next relative operator (if any) for proper handling
5305
- j = ++i;
5306
- for ( ; j < len; j++ ) {
5307
- if ( Expr.relative[ tokens[j].type ] ) {
5308
- break;
5309
- }
5310
- }
5311
- return setMatcher(
5312
- i > 1 && elementMatcher( matchers ),
5313
- i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ),
5314
- matcher,
5315
- i < j && matcherFromTokens( tokens.slice( i, j ) ),
5316
- j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
5317
- j < len && toSelector( tokens )
5318
- );
5319
- }
5320
- matchers.push( matcher );
5321
- }
5322
- }
5323
-
5324
- return elementMatcher( matchers );
5325
- }
5326
-
5327
- function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
5328
- // A counter to specify which element is currently being matched
5329
- var matcherCachedRuns = 0,
5330
- bySet = setMatchers.length > 0,
5331
- byElement = elementMatchers.length > 0,
5332
- superMatcher = function( seed, context, xml, results, expandContext ) {
5333
- var elem, j, matcher,
5334
- setMatched = [],
5335
- matchedCount = 0,
5336
- i = "0",
5337
- unmatched = seed && [],
5338
- outermost = expandContext != null,
5339
- contextBackup = outermostContext,
5340
- // We must always have either seed elements or context
5341
- elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
5342
- // Use integer dirruns iff this is the outermost matcher
5343
- dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);
5344
-
5345
- if ( outermost ) {
5346
- outermostContext = context !== document && context;
5347
- cachedruns = matcherCachedRuns;
5348
- }
5349
-
5350
- // Add elements passing elementMatchers directly to results
5351
- // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
5352
- for ( ; (elem = elems[i]) != null; i++ ) {
5353
- if ( byElement && elem ) {
5354
- j = 0;
5355
- while ( (matcher = elementMatchers[j++]) ) {
5356
- if ( matcher( elem, context, xml ) ) {
5357
- results.push( elem );
5358
- break;
5359
- }
5360
- }
5361
- if ( outermost ) {
5362
- dirruns = dirrunsUnique;
5363
- cachedruns = ++matcherCachedRuns;
5364
- }
5365
- }
5366
-
5367
- // Track unmatched elements for set filters
5368
- if ( bySet ) {
5369
- // They will have gone through all possible matchers
5370
- if ( (elem = !matcher && elem) ) {
5371
- matchedCount--;
5372
- }
5373
-
5374
- // Lengthen the array for every element, matched or not
5375
- if ( seed ) {
5376
- unmatched.push( elem );
5377
- }
5378
- }
5379
- }
5380
-
5381
- // Apply set filters to unmatched elements
5382
- matchedCount += i;
5383
- if ( bySet && i !== matchedCount ) {
5384
- j = 0;
5385
- while ( (matcher = setMatchers[j++]) ) {
5386
- matcher( unmatched, setMatched, context, xml );
5387
- }
5388
-
5389
- if ( seed ) {
5390
- // Reintegrate element matches to eliminate the need for sorting
5391
- if ( matchedCount > 0 ) {
5392
- while ( i-- ) {
5393
- if ( !(unmatched[i] || setMatched[i]) ) {
5394
- setMatched[i] = pop.call( results );
5395
- }
5396
- }
5397
- }
5398
-
5399
- // Discard index placeholder values to get only actual matches
5400
- setMatched = condense( setMatched );
5401
- }
5402
-
5403
- // Add matches to results
5404
- push.apply( results, setMatched );
5405
-
5406
- // Seedless set matches succeeding multiple successful matchers stipulate sorting
5407
- if ( outermost && !seed && setMatched.length > 0 &&
5408
- ( matchedCount + setMatchers.length ) > 1 ) {
5409
-
5410
- Sizzle.uniqueSort( results );
5411
- }
5412
- }
5413
-
5414
- // Override manipulation of globals by nested matchers
5415
- if ( outermost ) {
5416
- dirruns = dirrunsUnique;
5417
- outermostContext = contextBackup;
5418
- }
5419
-
5420
- return unmatched;
5421
- };
5422
-
5423
- return bySet ?
5424
- markFunction( superMatcher ) :
5425
- superMatcher;
5426
- }
5427
-
5428
- compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
5429
- var i,
5430
- setMatchers = [],
5431
- elementMatchers = [],
5432
- cached = compilerCache[ selector + " " ];
5433
-
5434
- if ( !cached ) {
5435
- // Generate a function of recursive functions that can be used to check each element
5436
- if ( !group ) {
5437
- group = tokenize( selector );
5438
- }
5439
- i = group.length;
5440
- while ( i-- ) {
5441
- cached = matcherFromTokens( group[i] );
5442
- if ( cached[ expando ] ) {
5443
- setMatchers.push( cached );
5444
- } else {
5445
- elementMatchers.push( cached );
5446
- }
5447
- }
5448
-
5449
- // Cache the compiled function
5450
- cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
5451
- }
5452
- return cached;
5453
- };
5454
-
5455
- function multipleContexts( selector, contexts, results ) {
5456
- var i = 0,
5457
- len = contexts.length;
5458
- for ( ; i < len; i++ ) {
5459
- Sizzle( selector, contexts[i], results );
5460
- }
5461
- return results;
5462
- }
5463
-
5464
- function select( selector, context, results, seed ) {
5465
- var i, tokens, token, type, find,
5466
- match = tokenize( selector );
5467
-
5468
- if ( !seed ) {
5469
- // Try to minimize operations if there is only one group
5470
- if ( match.length === 1 ) {
5471
-
5472
- // Take a shortcut and set the context if the root selector is an ID
5473
- tokens = match[0] = match[0].slice( 0 );
5474
- if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
5475
- context.nodeType === 9 && !documentIsXML &&
5476
- Expr.relative[ tokens[1].type ] ) {
5477
-
5478
- context = Expr.find["ID"]( token.matches[0].replace( runescape, funescape ), context )[0];
5479
- if ( !context ) {
5480
- return results;
5481
- }
5482
-
5483
- selector = selector.slice( tokens.shift().value.length );
5484
- }
5485
-
5486
- // Fetch a seed set for right-to-left matching
5487
- i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
5488
- while ( i-- ) {
5489
- token = tokens[i];
5490
-
5491
- // Abort if we hit a combinator
5492
- if ( Expr.relative[ (type = token.type) ] ) {
5493
- break;
5494
- }
5495
- if ( (find = Expr.find[ type ]) ) {
5496
- // Search, expanding context for leading sibling combinators
5497
- if ( (seed = find(
5498
- token.matches[0].replace( runescape, funescape ),
5499
- rsibling.test( tokens[0].type ) && context.parentNode || context
5500
- )) ) {
5501
-
5502
- // If seed is empty or no tokens remain, we can return early
5503
- tokens.splice( i, 1 );
5504
- selector = seed.length && toSelector( tokens );
5505
- if ( !selector ) {
5506
- push.apply( results, slice.call( seed, 0 ) );
5507
- return results;
5508
- }
5509
-
5510
- break;
5511
- }
5512
- }
5513
- }
5514
- }
5515
- }
5516
-
5517
- // Compile and execute a filtering function
5518
- // Provide `match` to avoid retokenization if we modified the selector above
5519
- compile( selector, match )(
5520
- seed,
5521
- context,
5522
- documentIsXML,
5523
- results,
5524
- rsibling.test( selector )
5525
- );
5526
- return results;
5527
- }
5528
-
5529
- // Deprecated
5530
- Expr.pseudos["nth"] = Expr.pseudos["eq"];
5531
-
5532
- // Easy API for creating new setFilters
5533
- function setFilters() {}
5534
- Expr.filters = setFilters.prototype = Expr.pseudos;
5535
- Expr.setFilters = new setFilters();
5536
-
5537
- // Initialize with the default document
5538
- setDocument();
5539
-
5540
- // Override sizzle attribute retrieval
5541
- Sizzle.attr = jQuery.attr;
5542
- jQuery.find = Sizzle;
5543
- jQuery.expr = Sizzle.selectors;
5544
- jQuery.expr[":"] = jQuery.expr.pseudos;
5545
- jQuery.unique = Sizzle.uniqueSort;
5546
- jQuery.text = Sizzle.getText;
5547
- jQuery.isXMLDoc = Sizzle.isXML;
5548
- jQuery.contains = Sizzle.contains;
5549
-
5550
-
5551
- })( window );
5552
- var runtil = /Until$/,
5553
- rparentsprev = /^(?:parents|prev(?:Until|All))/,
5554
- isSimple = /^.[^:#\[\.,]*$/,
5555
- rneedsContext = jQuery.expr.match.needsContext,
5556
- // methods guaranteed to produce a unique set when starting from a unique set
5557
- guaranteedUnique = {
5558
- children: true,
5559
- contents: true,
5560
- next: true,
5561
- prev: true
5562
- };
5563
-
5564
- jQuery.fn.extend({
5565
- find: function( selector ) {
5566
- var i, ret, self,
5567
- len = this.length;
5568
-
5569
- if ( typeof selector !== "string" ) {
5570
- self = this;
5571
- return this.pushStack( jQuery( selector ).filter(function() {
5572
- for ( i = 0; i < len; i++ ) {
5573
- if ( jQuery.contains( self[ i ], this ) ) {
5574
- return true;
5575
- }
5576
- }
5577
- }) );
5578
- }
5579
-
5580
- ret = [];
5581
- for ( i = 0; i < len; i++ ) {
5582
- jQuery.find( selector, this[ i ], ret );
5583
- }
5584
-
5585
- // Needed because $( selector, context ) becomes $( context ).find( selector )
5586
- ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
5587
- ret.selector = ( this.selector ? this.selector + " " : "" ) + selector;
5588
- return ret;
5589
- },
5590
-
5591
- has: function( target ) {
5592
- var i,
5593
- targets = jQuery( target, this ),
5594
- len = targets.length;
5595
-
5596
- return this.filter(function() {
5597
- for ( i = 0; i < len; i++ ) {
5598
- if ( jQuery.contains( this, targets[i] ) ) {
5599
- return true;
5600
- }
5601
- }
5602
- });
5603
- },
5604
-
5605
- not: function( selector ) {
5606
- return this.pushStack( winnow(this, selector, false) );
5607
- },
5608
-
5609
- filter: function( selector ) {
5610
- return this.pushStack( winnow(this, selector, true) );
5611
- },
5612
-
5613
- is: function( selector ) {
5614
- return !!selector && (
5615
- typeof selector === "string" ?
5616
- // If this is a positional/relative selector, check membership in the returned set
5617
- // so $("p:first").is("p:last") won't return true for a doc with two "p".
5618
- rneedsContext.test( selector ) ?
5619
- jQuery( selector, this.context ).index( this[0] ) >= 0 :
5620
- jQuery.filter( selector, this ).length > 0 :
5621
- this.filter( selector ).length > 0 );
5622
- },
5623
-
5624
- closest: function( selectors, context ) {
5625
- var cur,
5626
- i = 0,
5627
- l = this.length,
5628
- ret = [],
5629
- pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
5630
- jQuery( selectors, context || this.context ) :
5631
- 0;
5632
-
5633
- for ( ; i < l; i++ ) {
5634
- cur = this[i];
5635
-
5636
- while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
5637
- if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
5638
- ret.push( cur );
5639
- break;
5640
- }
5641
- cur = cur.parentNode;
5642
- }
5643
- }
5644
-
5645
- return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );
5646
- },
5647
-
5648
- // Determine the position of an element within
5649
- // the matched set of elements
5650
- index: function( elem ) {
5651
-
5652
- // No argument, return index in parent
5653
- if ( !elem ) {
5654
- return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
5655
- }
5656
-
5657
- // index in selector
5658
- if ( typeof elem === "string" ) {
5659
- return jQuery.inArray( this[0], jQuery( elem ) );
5660
- }
5661
-
5662
- // Locate the position of the desired element
5663
- return jQuery.inArray(
5664
- // If it receives a jQuery object, the first element is used
5665
- elem.jquery ? elem[0] : elem, this );
5666
- },
5667
-
5668
- add: function( selector, context ) {
5669
- var set = typeof selector === "string" ?
5670
- jQuery( selector, context ) :
5671
- jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
5672
- all = jQuery.merge( this.get(), set );
5673
-
5674
- return this.pushStack( jQuery.unique(all) );
5675
- },
5676
-
5677
- addBack: function( selector ) {
5678
- return this.add( selector == null ?
5679
- this.prevObject : this.prevObject.filter(selector)
5680
- );
5681
- }
5682
- });
5683
-
5684
- jQuery.fn.andSelf = jQuery.fn.addBack;
5685
-
5686
- function sibling( cur, dir ) {
5687
- do {
5688
- cur = cur[ dir ];
5689
- } while ( cur && cur.nodeType !== 1 );
5690
-
5691
- return cur;
5692
- }
5693
-
5694
- jQuery.each({
5695
- parent: function( elem ) {
5696
- var parent = elem.parentNode;
5697
- return parent && parent.nodeType !== 11 ? parent : null;
5698
- },
5699
- parents: function( elem ) {
5700
- return jQuery.dir( elem, "parentNode" );
5701
- },
5702
- parentsUntil: function( elem, i, until ) {
5703
- return jQuery.dir( elem, "parentNode", until );
5704
- },
5705
- next: function( elem ) {
5706
- return sibling( elem, "nextSibling" );
5707
- },
5708
- prev: function( elem ) {
5709
- return sibling( elem, "previousSibling" );
5710
- },
5711
- nextAll: function( elem ) {
5712
- return jQuery.dir( elem, "nextSibling" );
5713
- },
5714
- prevAll: function( elem ) {
5715
- return jQuery.dir( elem, "previousSibling" );
5716
- },
5717
- nextUntil: function( elem, i, until ) {
5718
- return jQuery.dir( elem, "nextSibling", until );
5719
- },
5720
- prevUntil: function( elem, i, until ) {
5721
- return jQuery.dir( elem, "previousSibling", until );
5722
- },
5723
- siblings: function( elem ) {
5724
- return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
5725
- },
5726
- children: function( elem ) {
5727
- return jQuery.sibling( elem.firstChild );
5728
- },
5729
- contents: function( elem ) {
5730
- return jQuery.nodeName( elem, "iframe" ) ?
5731
- elem.contentDocument || elem.contentWindow.document :
5732
- jQuery.merge( [], elem.childNodes );
5733
- }
5734
- }, function( name, fn ) {
5735
- jQuery.fn[ name ] = function( until, selector ) {
5736
- var ret = jQuery.map( this, fn, until );
5737
-
5738
- if ( !runtil.test( name ) ) {
5739
- selector = until;
5740
- }
5741
-
5742
- if ( selector && typeof selector === "string" ) {
5743
- ret = jQuery.filter( selector, ret );
5744
- }
5745
-
5746
- ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
5747
-
5748
- if ( this.length > 1 && rparentsprev.test( name ) ) {
5749
- ret = ret.reverse();
5750
- }
5751
-
5752
- return this.pushStack( ret );
5753
- };
5754
- });
5755
-
5756
- jQuery.extend({
5757
- filter: function( expr, elems, not ) {
5758
- if ( not ) {
5759
- expr = ":not(" + expr + ")";
5760
- }
5761
-
5762
- return elems.length === 1 ?
5763
- jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
5764
- jQuery.find.matches(expr, elems);
5765
- },
5766
-
5767
- dir: function( elem, dir, until ) {
5768
- var matched = [],
5769
- cur = elem[ dir ];
5770
-
5771
- while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
5772
- if ( cur.nodeType === 1 ) {
5773
- matched.push( cur );
5774
- }
5775
- cur = cur[dir];
5776
- }
5777
- return matched;
5778
- },
5779
-
5780
- sibling: function( n, elem ) {
5781
- var r = [];
5782
-
5783
- for ( ; n; n = n.nextSibling ) {
5784
- if ( n.nodeType === 1 && n !== elem ) {
5785
- r.push( n );
5786
- }
5787
- }
5788
-
5789
- return r;
5790
- }
5791
- });
5792
-
5793
- // Implement the identical functionality for filter and not
5794
- function winnow( elements, qualifier, keep ) {
5795
-
5796
- // Can't pass null or undefined to indexOf in Firefox 4
5797
- // Set to 0 to skip string check
5798
- qualifier = qualifier || 0;
5799
-
5800
- if ( jQuery.isFunction( qualifier ) ) {
5801
- return jQuery.grep(elements, function( elem, i ) {
5802
- var retVal = !!qualifier.call( elem, i, elem );
5803
- return retVal === keep;
5804
- });
5805
-
5806
- } else if ( qualifier.nodeType ) {
5807
- return jQuery.grep(elements, function( elem ) {
5808
- return ( elem === qualifier ) === keep;
5809
- });
5810
-
5811
- } else if ( typeof qualifier === "string" ) {
5812
- var filtered = jQuery.grep(elements, function( elem ) {
5813
- return elem.nodeType === 1;
5814
- });
5815
-
5816
- if ( isSimple.test( qualifier ) ) {
5817
- return jQuery.filter(qualifier, filtered, !keep);
5818
- } else {
5819
- qualifier = jQuery.filter( qualifier, filtered );
5820
- }
5821
- }
5822
-
5823
- return jQuery.grep(elements, function( elem ) {
5824
- return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
5825
- });
5826
- }
5827
- function createSafeFragment( document ) {
5828
- var list = nodeNames.split( "|" ),
5829
- safeFrag = document.createDocumentFragment();
5830
-
5831
- if ( safeFrag.createElement ) {
5832
- while ( list.length ) {
5833
- safeFrag.createElement(
5834
- list.pop()
5835
- );
5836
- }
5837
- }
5838
- return safeFrag;
5839
- }
5840
-
5841
- var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
5842
- "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
5843
- rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
5844
- rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
5845
- rleadingWhitespace = /^\s+/,
5846
- rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
5847
- rtagName = /<([\w:]+)/,
5848
- rtbody = /<tbody/i,
5849
- rhtml = /<|&#?\w+;/,
5850
- rnoInnerhtml = /<(?:script|style|link)/i,
5851
- manipulation_rcheckableType = /^(?:checkbox|radio)$/i,
5852
- // checked="checked" or checked
5853
- rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5854
- rscriptType = /^$|\/(?:java|ecma)script/i,
5855
- rscriptTypeMasked = /^true\/(.*)/,
5856
- rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
5857
-
5858
- // We have to close these tags to support XHTML (#13200)
5859
- wrapMap = {
5860
- option: [ 1, "<select multiple='multiple'>", "</select>" ],
5861
- legend: [ 1, "<fieldset>", "</fieldset>" ],
5862
- area: [ 1, "<map>", "</map>" ],
5863
- param: [ 1, "<object>", "</object>" ],
5864
- thead: [ 1, "<table>", "</table>" ],
5865
- tr: [ 2, "<table><tbody>", "</tbody></table>" ],
5866
- col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
5867
- td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
5868
-
5869
- // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
5870
- // unless wrapped in a div with non-breaking characters in front of it.
5871
- _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
5872
- },
5873
- safeFragment = createSafeFragment( document ),
5874
- fragmentDiv = safeFragment.appendChild( document.createElement("div") );
5875
-
5876
- wrapMap.optgroup = wrapMap.option;
5877
- wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
5878
- wrapMap.th = wrapMap.td;
5879
-
5880
- jQuery.fn.extend({
5881
- text: function( value ) {
5882
- return jQuery.access( this, function( value ) {
5883
- return value === undefined ?
5884
- jQuery.text( this ) :
5885
- this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
5886
- }, null, value, arguments.length );
5887
- },
5888
-
5889
- wrapAll: function( html ) {
5890
- if ( jQuery.isFunction( html ) ) {
5891
- return this.each(function(i) {
5892
- jQuery(this).wrapAll( html.call(this, i) );
5893
- });
5894
- }
5895
-
5896
- if ( this[0] ) {
5897
- // The elements to wrap the target around
5898
- var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
5899
-
5900
- if ( this[0].parentNode ) {
5901
- wrap.insertBefore( this[0] );
5902
- }
5903
-
5904
- wrap.map(function() {
5905
- var elem = this;
5906
-
5907
- while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
5908
- elem = elem.firstChild;
5909
- }
5910
-
5911
- return elem;
5912
- }).append( this );
5913
- }
5914
-
5915
- return this;
5916
- },
5917
-
5918
- wrapInner: function( html ) {
5919
- if ( jQuery.isFunction( html ) ) {
5920
- return this.each(function(i) {
5921
- jQuery(this).wrapInner( html.call(this, i) );
5922
- });
5923
- }
5924
-
5925
- return this.each(function() {
5926
- var self = jQuery( this ),
5927
- contents = self.contents();
5928
-
5929
- if ( contents.length ) {
5930
- contents.wrapAll( html );
5931
-
5932
- } else {
5933
- self.append( html );
5934
- }
5935
- });
5936
- },
5937
-
5938
- wrap: function( html ) {
5939
- var isFunction = jQuery.isFunction( html );
5940
-
5941
- return this.each(function(i) {
5942
- jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
5943
- });
5944
- },
5945
-
5946
- unwrap: function() {
5947
- return this.parent().each(function() {
5948
- if ( !jQuery.nodeName( this, "body" ) ) {
5949
- jQuery( this ).replaceWith( this.childNodes );
5950
- }
5951
- }).end();
5952
- },
5953
-
5954
- append: function() {
5955
- return this.domManip(arguments, true, function( elem ) {
5956
- if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5957
- this.appendChild( elem );
5958
- }
5959
- });
5960
- },
5961
-
5962
- prepend: function() {
5963
- return this.domManip(arguments, true, function( elem ) {
5964
- if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5965
- this.insertBefore( elem, this.firstChild );
5966
- }
5967
- });
5968
- },
5969
-
5970
- before: function() {
5971
- return this.domManip( arguments, false, function( elem ) {
5972
- if ( this.parentNode ) {
5973
- this.parentNode.insertBefore( elem, this );
5974
- }
5975
- });
5976
- },
5977
-
5978
- after: function() {
5979
- return this.domManip( arguments, false, function( elem ) {
5980
- if ( this.parentNode ) {
5981
- this.parentNode.insertBefore( elem, this.nextSibling );
5982
- }
5983
- });
5984
- },
5985
-
5986
- // keepData is for internal use only--do not document
5987
- remove: function( selector, keepData ) {
5988
- var elem,
5989
- i = 0;
5990
-
5991
- for ( ; (elem = this[i]) != null; i++ ) {
5992
- if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) {
5993
- if ( !keepData && elem.nodeType === 1 ) {
5994
- jQuery.cleanData( getAll( elem ) );
5995
- }
5996
-
5997
- if ( elem.parentNode ) {
5998
- if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
5999
- setGlobalEval( getAll( elem, "script" ) );
6000
- }
6001
- elem.parentNode.removeChild( elem );
6002
- }
6003
- }
6004
- }
6005
-
6006
- return this;
6007
- },
6008
-
6009
- empty: function() {
6010
- var elem,
6011
- i = 0;
6012
-
6013
- for ( ; (elem = this[i]) != null; i++ ) {
6014
- // Remove element nodes and prevent memory leaks
6015
- if ( elem.nodeType === 1 ) {
6016
- jQuery.cleanData( getAll( elem, false ) );
6017
- }
6018
-
6019
- // Remove any remaining nodes
6020
- while ( elem.firstChild ) {
6021
- elem.removeChild( elem.firstChild );
6022
- }
6023
-
6024
- // If this is a select, ensure that it displays empty (#12336)
6025
- // Support: IE<9
6026
- if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
6027
- elem.options.length = 0;
6028
- }
6029
- }
6030
-
6031
- return this;
6032
- },
6033
-
6034
- clone: function( dataAndEvents, deepDataAndEvents ) {
6035
- dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
6036
- deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
6037
-
6038
- return this.map( function () {
6039
- return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
6040
- });
6041
- },
6042
-
6043
- html: function( value ) {
6044
- return jQuery.access( this, function( value ) {
6045
- var elem = this[0] || {},
6046
- i = 0,
6047
- l = this.length;
6048
-
6049
- if ( value === undefined ) {
6050
- return elem.nodeType === 1 ?
6051
- elem.innerHTML.replace( rinlinejQuery, "" ) :
6052
- undefined;
6053
- }
6054
-
6055
- // See if we can take a shortcut and just use innerHTML
6056
- if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
6057
- ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
6058
- ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
6059
- !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
6060
-
6061
- value = value.replace( rxhtmlTag, "<$1></$2>" );
6062
-
6063
- try {
6064
- for (; i < l; i++ ) {
6065
- // Remove element nodes and prevent memory leaks
6066
- elem = this[i] || {};
6067
- if ( elem.nodeType === 1 ) {
6068
- jQuery.cleanData( getAll( elem, false ) );
6069
- elem.innerHTML = value;
6070
- }
6071
- }
6072
-
6073
- elem = 0;
6074
-
6075
- // If using innerHTML throws an exception, use the fallback method
6076
- } catch(e) {}
6077
- }
6078
-
6079
- if ( elem ) {
6080
- this.empty().append( value );
6081
- }
6082
- }, null, value, arguments.length );
6083
- },
6084
-
6085
- replaceWith: function( value ) {
6086
- var isFunc = jQuery.isFunction( value );
6087
-
6088
- // Make sure that the elements are removed from the DOM before they are inserted
6089
- // this can help fix replacing a parent with child elements
6090
- if ( !isFunc && typeof value !== "string" ) {
6091
- value = jQuery( value ).not( this ).detach();
6092
- }
6093
-
6094
- return this.domManip( [ value ], true, function( elem ) {
6095
- var next = this.nextSibling,
6096
- parent = this.parentNode;
6097
-
6098
- if ( parent ) {
6099
- jQuery( this ).remove();
6100
- parent.insertBefore( elem, next );
6101
- }
6102
- });
6103
- },
6104
-
6105
- detach: function( selector ) {
6106
- return this.remove( selector, true );
6107
- },
6108
-
6109
- domManip: function( args, table, callback ) {
6110
-
6111
- // Flatten any nested arrays
6112
- args = core_concat.apply( [], args );
6113
-
6114
- var first, node, hasScripts,
6115
- scripts, doc, fragment,
6116
- i = 0,
6117
- l = this.length,
6118
- set = this,
6119
- iNoClone = l - 1,
6120
- value = args[0],
6121
- isFunction = jQuery.isFunction( value );
6122
-
6123
- // We can't cloneNode fragments that contain checked, in WebKit
6124
- if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {
6125
- return this.each(function( index ) {
6126
- var self = set.eq( index );
6127
- if ( isFunction ) {
6128
- args[0] = value.call( this, index, table ? self.html() : undefined );
6129
- }
6130
- self.domManip( args, table, callback );
6131
- });
6132
- }
6133
-
6134
- if ( l ) {
6135
- fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
6136
- first = fragment.firstChild;
6137
-
6138
- if ( fragment.childNodes.length === 1 ) {
6139
- fragment = first;
6140
- }
6141
-
6142
- if ( first ) {
6143
- table = table && jQuery.nodeName( first, "tr" );
6144
- scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
6145
- hasScripts = scripts.length;
6146
-
6147
- // Use the original fragment for the last item instead of the first because it can end up
6148
- // being emptied incorrectly in certain situations (#8070).
6149
- for ( ; i < l; i++ ) {
6150
- node = fragment;
6151
-
6152
- if ( i !== iNoClone ) {
6153
- node = jQuery.clone( node, true, true );
6154
-
6155
- // Keep references to cloned scripts for later restoration
6156
- if ( hasScripts ) {
6157
- jQuery.merge( scripts, getAll( node, "script" ) );
6158
- }
6159
- }
6160
-
6161
- callback.call(
6162
- table && jQuery.nodeName( this[i], "table" ) ?
6163
- findOrAppend( this[i], "tbody" ) :
6164
- this[i],
6165
- node,
6166
- i
6167
- );
6168
- }
6169
-
6170
- if ( hasScripts ) {
6171
- doc = scripts[ scripts.length - 1 ].ownerDocument;
6172
-
6173
- // Reenable scripts
6174
- jQuery.map( scripts, restoreScript );
6175
-
6176
- // Evaluate executable scripts on first document insertion
6177
- for ( i = 0; i < hasScripts; i++ ) {
6178
- node = scripts[ i ];
6179
- if ( rscriptType.test( node.type || "" ) &&
6180
- !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
6181
-
6182
- if ( node.src ) {
6183
- // Hope ajax is available...
6184
- jQuery.ajax({
6185
- url: node.src,
6186
- type: "GET",
6187
- dataType: "script",
6188
- async: false,
6189
- global: false,
6190
- "throws": true
6191
- });
6192
- } else {
6193
- jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
6194
- }
6195
- }
6196
- }
6197
- }
6198
-
6199
- // Fix #11809: Avoid leaking memory
6200
- fragment = first = null;
6201
- }
6202
- }
6203
-
6204
- return this;
6205
- }
6206
- });
6207
-
6208
- function findOrAppend( elem, tag ) {
6209
- return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
6210
- }
6211
-
6212
- // Replace/restore the type attribute of script elements for safe DOM manipulation
6213
- function disableScript( elem ) {
6214
- var attr = elem.getAttributeNode("type");
6215
- elem.type = ( attr && attr.specified ) + "/" + elem.type;
6216
- return elem;
6217
- }
6218
- function restoreScript( elem ) {
6219
- var match = rscriptTypeMasked.exec( elem.type );
6220
- if ( match ) {
6221
- elem.type = match[1];
6222
- } else {
6223
- elem.removeAttribute("type");
6224
- }
6225
- return elem;
6226
- }
6227
-
6228
- // Mark scripts as having already been evaluated
6229
- function setGlobalEval( elems, refElements ) {
6230
- var elem,
6231
- i = 0;
6232
- for ( ; (elem = elems[i]) != null; i++ ) {
6233
- jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
6234
- }
6235
- }
6236
-
6237
- function cloneCopyEvent( src, dest ) {
6238
-
6239
- if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
6240
- return;
6241
- }
6242
-
6243
- var type, i, l,
6244
- oldData = jQuery._data( src ),
6245
- curData = jQuery._data( dest, oldData ),
6246
- events = oldData.events;
6247
-
6248
- if ( events ) {
6249
- delete curData.handle;
6250
- curData.events = {};
6251
-
6252
- for ( type in events ) {
6253
- for ( i = 0, l = events[ type ].length; i < l; i++ ) {
6254
- jQuery.event.add( dest, type, events[ type ][ i ] );
6255
- }
6256
- }
6257
- }
6258
-
6259
- // make the cloned public data object a copy from the original
6260
- if ( curData.data ) {
6261
- curData.data = jQuery.extend( {}, curData.data );
6262
- }
6263
- }
6264
-
6265
- function fixCloneNodeIssues( src, dest ) {
6266
- var nodeName, e, data;
6267
-
6268
- // We do not need to do anything for non-Elements
6269
- if ( dest.nodeType !== 1 ) {
6270
- return;
6271
- }
6272
-
6273
- nodeName = dest.nodeName.toLowerCase();
6274
-
6275
- // IE6-8 copies events bound via attachEvent when using cloneNode.
6276
- if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {
6277
- data = jQuery._data( dest );
6278
-
6279
- for ( e in data.events ) {
6280
- jQuery.removeEvent( dest, e, data.handle );
6281
- }
6282
-
6283
- // Event data gets referenced instead of copied if the expando gets copied too
6284
- dest.removeAttribute( jQuery.expando );
6285
- }
6286
-
6287
- // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
6288
- if ( nodeName === "script" && dest.text !== src.text ) {
6289
- disableScript( dest ).text = src.text;
6290
- restoreScript( dest );
6291
-
6292
- // IE6-10 improperly clones children of object elements using classid.
6293
- // IE10 throws NoModificationAllowedError if parent is null, #12132.
6294
- } else if ( nodeName === "object" ) {
6295
- if ( dest.parentNode ) {
6296
- dest.outerHTML = src.outerHTML;
6297
- }
6298
-
6299
- // This path appears unavoidable for IE9. When cloning an object
6300
- // element in IE9, the outerHTML strategy above is not sufficient.
6301
- // If the src has innerHTML and the destination does not,
6302
- // copy the src.innerHTML into the dest.innerHTML. #10324
6303
- if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
6304
- dest.innerHTML = src.innerHTML;
6305
- }
6306
-
6307
- } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) {
6308
- // IE6-8 fails to persist the checked state of a cloned checkbox
6309
- // or radio button. Worse, IE6-7 fail to give the cloned element
6310
- // a checked appearance if the defaultChecked value isn't also set
6311
-
6312
- dest.defaultChecked = dest.checked = src.checked;
6313
-
6314
- // IE6-7 get confused and end up setting the value of a cloned
6315
- // checkbox/radio button to an empty string instead of "on"
6316
- if ( dest.value !== src.value ) {
6317
- dest.value = src.value;
6318
- }
6319
-
6320
- // IE6-8 fails to return the selected option to the default selected
6321
- // state when cloning options
6322
- } else if ( nodeName === "option" ) {
6323
- dest.defaultSelected = dest.selected = src.defaultSelected;
6324
-
6325
- // IE6-8 fails to set the defaultValue to the correct value when
6326
- // cloning other types of input fields
6327
- } else if ( nodeName === "input" || nodeName === "textarea" ) {
6328
- dest.defaultValue = src.defaultValue;
6329
- }
6330
- }
6331
-
6332
- jQuery.each({
6333
- appendTo: "append",
6334
- prependTo: "prepend",
6335
- insertBefore: "before",
6336
- insertAfter: "after",
6337
- replaceAll: "replaceWith"
6338
- }, function( name, original ) {
6339
- jQuery.fn[ name ] = function( selector ) {
6340
- var elems,
6341
- i = 0,
6342
- ret = [],
6343
- insert = jQuery( selector ),
6344
- last = insert.length - 1;
6345
-
6346
- for ( ; i <= last; i++ ) {
6347
- elems = i === last ? this : this.clone(true);
6348
- jQuery( insert[i] )[ original ]( elems );
6349
-
6350
- // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
6351
- core_push.apply( ret, elems.get() );
6352
- }
6353
-
6354
- return this.pushStack( ret );
6355
- };
6356
- });
6357
-
6358
- function getAll( context, tag ) {
6359
- var elems, elem,
6360
- i = 0,
6361
- found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) :
6362
- typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) :
6363
- undefined;
6364
-
6365
- if ( !found ) {
6366
- for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
6367
- if ( !tag || jQuery.nodeName( elem, tag ) ) {
6368
- found.push( elem );
6369
- } else {
6370
- jQuery.merge( found, getAll( elem, tag ) );
6371
- }
6372
- }
6373
- }
6374
-
6375
- return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
6376
- jQuery.merge( [ context ], found ) :
6377
- found;
6378
- }
6379
-
6380
- // Used in buildFragment, fixes the defaultChecked property
6381
- function fixDefaultChecked( elem ) {
6382
- if ( manipulation_rcheckableType.test( elem.type ) ) {
6383
- elem.defaultChecked = elem.checked;
6384
- }
6385
- }
6386
-
6387
- jQuery.extend({
6388
- clone: function( elem, dataAndEvents, deepDataAndEvents ) {
6389
- var destElements, node, clone, i, srcElements,
6390
- inPage = jQuery.contains( elem.ownerDocument, elem );
6391
-
6392
- if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
6393
- clone = elem.cloneNode( true );
6394
-
6395
- // IE<=8 does not properly clone detached, unknown element nodes
6396
- } else {
6397
- fragmentDiv.innerHTML = elem.outerHTML;
6398
- fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
6399
- }
6400
-
6401
- if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
6402
- (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
6403
-
6404
- // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
6405
- destElements = getAll( clone );
6406
- srcElements = getAll( elem );
6407
-
6408
- // Fix all IE cloning issues
6409
- for ( i = 0; (node = srcElements[i]) != null; ++i ) {
6410
- // Ensure that the destination node is not null; Fixes #9587
6411
- if ( destElements[i] ) {
6412
- fixCloneNodeIssues( node, destElements[i] );
6413
- }
6414
- }
6415
- }
6416
-
6417
- // Copy the events from the original to the clone
6418
- if ( dataAndEvents ) {
6419
- if ( deepDataAndEvents ) {
6420
- srcElements = srcElements || getAll( elem );
6421
- destElements = destElements || getAll( clone );
6422
-
6423
- for ( i = 0; (node = srcElements[i]) != null; i++ ) {
6424
- cloneCopyEvent( node, destElements[i] );
6425
- }
6426
- } else {
6427
- cloneCopyEvent( elem, clone );
6428
- }
6429
- }
6430
-
6431
- // Preserve script evaluation history
6432
- destElements = getAll( clone, "script" );
6433
- if ( destElements.length > 0 ) {
6434
- setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
6435
- }
6436
-
6437
- destElements = srcElements = node = null;
6438
-
6439
- // Return the cloned set
6440
- return clone;
6441
- },
6442
-
6443
- buildFragment: function( elems, context, scripts, selection ) {
6444
- var j, elem, contains,
6445
- tmp, tag, tbody, wrap,
6446
- l = elems.length,
6447
-
6448
- // Ensure a safe fragment
6449
- safe = createSafeFragment( context ),
6450
-
6451
- nodes = [],
6452
- i = 0;
6453
-
6454
- for ( ; i < l; i++ ) {
6455
- elem = elems[ i ];
6456
-
6457
- if ( elem || elem === 0 ) {
6458
-
6459
- // Add nodes directly
6460
- if ( jQuery.type( elem ) === "object" ) {
6461
- jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
6462
-
6463
- // Convert non-html into a text node
6464
- } else if ( !rhtml.test( elem ) ) {
6465
- nodes.push( context.createTextNode( elem ) );
6466
-
6467
- // Convert html into DOM nodes
6468
- } else {
6469
- tmp = tmp || safe.appendChild( context.createElement("div") );
6470
-
6471
- // Deserialize a standard representation
6472
- tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
6473
- wrap = wrapMap[ tag ] || wrapMap._default;
6474
-
6475
- tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
6476
-
6477
- // Descend through wrappers to the right content
6478
- j = wrap[0];
6479
- while ( j-- ) {
6480
- tmp = tmp.lastChild;
6481
- }
6482
-
6483
- // Manually add leading whitespace removed by IE
6484
- if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
6485
- nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
6486
- }
6487
-
6488
- // Remove IE's autoinserted <tbody> from table fragments
6489
- if ( !jQuery.support.tbody ) {
6490
-
6491
- // String was a <table>, *may* have spurious <tbody>
6492
- elem = tag === "table" && !rtbody.test( elem ) ?
6493
- tmp.firstChild :
6494
-
6495
- // String was a bare <thead> or <tfoot>
6496
- wrap[1] === "<table>" && !rtbody.test( elem ) ?
6497
- tmp :
6498
- 0;
6499
-
6500
- j = elem && elem.childNodes.length;
6501
- while ( j-- ) {
6502
- if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
6503
- elem.removeChild( tbody );
6504
- }
6505
- }
6506
- }
6507
-
6508
- jQuery.merge( nodes, tmp.childNodes );
6509
-
6510
- // Fix #12392 for WebKit and IE > 9
6511
- tmp.textContent = "";
6512
-
6513
- // Fix #12392 for oldIE
6514
- while ( tmp.firstChild ) {
6515
- tmp.removeChild( tmp.firstChild );
6516
- }
6517
-
6518
- // Remember the top-level container for proper cleanup
6519
- tmp = safe.lastChild;
6520
- }
6521
- }
6522
- }
6523
-
6524
- // Fix #11356: Clear elements from fragment
6525
- if ( tmp ) {
6526
- safe.removeChild( tmp );
6527
- }
6528
-
6529
- // Reset defaultChecked for any radios and checkboxes
6530
- // about to be appended to the DOM in IE 6/7 (#8060)
6531
- if ( !jQuery.support.appendChecked ) {
6532
- jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
6533
- }
6534
-
6535
- i = 0;
6536
- while ( (elem = nodes[ i++ ]) ) {
6537
-
6538
- // #4087 - If origin and destination elements are the same, and this is
6539
- // that element, do not do anything
6540
- if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
6541
- continue;
6542
- }
6543
-
6544
- contains = jQuery.contains( elem.ownerDocument, elem );
6545
-
6546
- // Append to fragment
6547
- tmp = getAll( safe.appendChild( elem ), "script" );
6548
-
6549
- // Preserve script evaluation history
6550
- if ( contains ) {
6551
- setGlobalEval( tmp );
6552
- }
6553
-
6554
- // Capture executables
6555
- if ( scripts ) {
6556
- j = 0;
6557
- while ( (elem = tmp[ j++ ]) ) {
6558
- if ( rscriptType.test( elem.type || "" ) ) {
6559
- scripts.push( elem );
6560
- }
6561
- }
6562
- }
6563
- }
6564
-
6565
- tmp = null;
6566
-
6567
- return safe;
6568
- },
6569
-
6570
- cleanData: function( elems, /* internal */ acceptData ) {
6571
- var elem, type, id, data,
6572
- i = 0,
6573
- internalKey = jQuery.expando,
6574
- cache = jQuery.cache,
6575
- deleteExpando = jQuery.support.deleteExpando,
6576
- special = jQuery.event.special;
6577
-
6578
- for ( ; (elem = elems[i]) != null; i++ ) {
6579
-
6580
- if ( acceptData || jQuery.acceptData( elem ) ) {
6581
-
6582
- id = elem[ internalKey ];
6583
- data = id && cache[ id ];
6584
-
6585
- if ( data ) {
6586
- if ( data.events ) {
6587
- for ( type in data.events ) {
6588
- if ( special[ type ] ) {
6589
- jQuery.event.remove( elem, type );
6590
-
6591
- // This is a shortcut to avoid jQuery.event.remove's overhead
6592
- } else {
6593
- jQuery.removeEvent( elem, type, data.handle );
6594
- }
6595
- }
6596
- }
6597
-
6598
- // Remove cache only if it was not already removed by jQuery.event.remove
6599
- if ( cache[ id ] ) {
6600
-
6601
- delete cache[ id ];
6602
-
6603
- // IE does not allow us to delete expando properties from nodes,
6604
- // nor does it have a removeAttribute function on Document nodes;
6605
- // we must handle all of these cases
6606
- if ( deleteExpando ) {
6607
- delete elem[ internalKey ];
6608
-
6609
- } else if ( typeof elem.removeAttribute !== core_strundefined ) {
6610
- elem.removeAttribute( internalKey );
6611
-
6612
- } else {
6613
- elem[ internalKey ] = null;
6614
- }
6615
-
6616
- core_deletedIds.push( id );
6617
- }
6618
- }
6619
- }
6620
- }
6621
- }
6622
- });
6623
- var iframe, getStyles, curCSS,
6624
- ralpha = /alpha\([^)]*\)/i,
6625
- ropacity = /opacity\s*=\s*([^)]*)/,
6626
- rposition = /^(top|right|bottom|left)$/,
6627
- // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
6628
- // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6629
- rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6630
- rmargin = /^margin/,
6631
- rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
6632
- rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
6633
- rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ),
6634
- elemdisplay = { BODY: "block" },
6635
-
6636
- cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6637
- cssNormalTransform = {
6638
- letterSpacing: 0,
6639
- fontWeight: 400
6640
- },
6641
-
6642
- cssExpand = [ "Top", "Right", "Bottom", "Left" ],
6643
- cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
6644
-
6645
- // return a css property mapped to a potentially vendor prefixed property
6646
- function vendorPropName( style, name ) {
6647
-
6648
- // shortcut for names that are not vendor prefixed
6649
- if ( name in style ) {
6650
- return name;
6651
- }
6652
-
6653
- // check for vendor prefixed names
6654
- var capName = name.charAt(0).toUpperCase() + name.slice(1),
6655
- origName = name,
6656
- i = cssPrefixes.length;
6657
-
6658
- while ( i-- ) {
6659
- name = cssPrefixes[ i ] + capName;
6660
- if ( name in style ) {
6661
- return name;
6662
- }
6663
- }
6664
-
6665
- return origName;
6666
- }
6667
-
6668
- function isHidden( elem, el ) {
6669
- // isHidden might be called from jQuery#filter function;
6670
- // in that case, element will be second argument
6671
- elem = el || elem;
6672
- return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
6673
- }
6674
-
6675
- function showHide( elements, show ) {
6676
- var display, elem, hidden,
6677
- values = [],
6678
- index = 0,
6679
- length = elements.length;
6680
-
6681
- for ( ; index < length; index++ ) {
6682
- elem = elements[ index ];
6683
- if ( !elem.style ) {
6684
- continue;
6685
- }
6686
-
6687
- values[ index ] = jQuery._data( elem, "olddisplay" );
6688
- display = elem.style.display;
6689
- if ( show ) {
6690
- // Reset the inline display of this element to learn if it is
6691
- // being hidden by cascaded rules or not
6692
- if ( !values[ index ] && display === "none" ) {
6693
- elem.style.display = "";
6694
- }
6695
-
6696
- // Set elements which have been overridden with display: none
6697
- // in a stylesheet to whatever the default browser style is
6698
- // for such an element
6699
- if ( elem.style.display === "" && isHidden( elem ) ) {
6700
- values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
6701
- }
6702
- } else {
6703
-
6704
- if ( !values[ index ] ) {
6705
- hidden = isHidden( elem );
6706
-
6707
- if ( display && display !== "none" || !hidden ) {
6708
- jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
6709
- }
6710
- }
6711
- }
6712
- }
6713
-
6714
- // Set the display of most of the elements in a second loop
6715
- // to avoid the constant reflow
6716
- for ( index = 0; index < length; index++ ) {
6717
- elem = elements[ index ];
6718
- if ( !elem.style ) {
6719
- continue;
6720
- }
6721
- if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
6722
- elem.style.display = show ? values[ index ] || "" : "none";
6723
- }
6724
- }
6725
-
6726
- return elements;
6727
- }
6728
-
6729
- jQuery.fn.extend({
6730
- css: function( name, value ) {
6731
- return jQuery.access( this, function( elem, name, value ) {
6732
- var len, styles,
6733
- map = {},
6734
- i = 0;
6735
-
6736
- if ( jQuery.isArray( name ) ) {
6737
- styles = getStyles( elem );
6738
- len = name.length;
6739
-
6740
- for ( ; i < len; i++ ) {
6741
- map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6742
- }
6743
-
6744
- return map;
6745
- }
6746
-
6747
- return value !== undefined ?
6748
- jQuery.style( elem, name, value ) :
6749
- jQuery.css( elem, name );
6750
- }, name, value, arguments.length > 1 );
6751
- },
6752
- show: function() {
6753
- return showHide( this, true );
6754
- },
6755
- hide: function() {
6756
- return showHide( this );
6757
- },
6758
- toggle: function( state ) {
6759
- var bool = typeof state === "boolean";
6760
-
6761
- return this.each(function() {
6762
- if ( bool ? state : isHidden( this ) ) {
6763
- jQuery( this ).show();
6764
- } else {
6765
- jQuery( this ).hide();
6766
- }
6767
- });
6768
- }
6769
- });
6770
-
6771
- jQuery.extend({
6772
- // Add in style property hooks for overriding the default
6773
- // behavior of getting and setting a style property
6774
- cssHooks: {
6775
- opacity: {
6776
- get: function( elem, computed ) {
6777
- if ( computed ) {
6778
- // We should always get a number back from opacity
6779
- var ret = curCSS( elem, "opacity" );
6780
- return ret === "" ? "1" : ret;
6781
- }
6782
- }
6783
- }
6784
- },
6785
-
6786
- // Exclude the following css properties to add px
6787
- cssNumber: {
6788
- "columnCount": true,
6789
- "fillOpacity": true,
6790
- "fontWeight": true,
6791
- "lineHeight": true,
6792
- "opacity": true,
6793
- "orphans": true,
6794
- "widows": true,
6795
- "zIndex": true,
6796
- "zoom": true
6797
- },
6798
-
6799
- // Add in properties whose names you wish to fix before
6800
- // setting or getting the value
6801
- cssProps: {
6802
- // normalize float css property
6803
- "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
6804
- },
6805
-
6806
- // Get and set the style property on a DOM Node
6807
- style: function( elem, name, value, extra ) {
6808
- // Don't set styles on text and comment nodes
6809
- if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6810
- return;
6811
- }
6812
-
6813
- // Make sure that we're working with the right name
6814
- var ret, type, hooks,
6815
- origName = jQuery.camelCase( name ),
6816
- style = elem.style;
6817
-
6818
- name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
6819
-
6820
- // gets hook for the prefixed version
6821
- // followed by the unprefixed version
6822
- hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6823
-
6824
- // Check if we're setting a value
6825
- if ( value !== undefined ) {
6826
- type = typeof value;
6827
-
6828
- // convert relative number strings (+= or -=) to relative numbers. #7345
6829
- if ( type === "string" && (ret = rrelNum.exec( value )) ) {
6830
- value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
6831
- // Fixes bug #9237
6832
- type = "number";
6833
- }
6834
-
6835
- // Make sure that NaN and null values aren't set. See: #7116
6836
- if ( value == null || type === "number" && isNaN( value ) ) {
6837
- return;
6838
- }
6839
-
6840
- // If a number was passed in, add 'px' to the (except for certain CSS properties)
6841
- if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
6842
- value += "px";
6843
- }
6844
-
6845
- // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
6846
- // but it would mean to define eight (for every problematic property) identical functions
6847
- if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
6848
- style[ name ] = "inherit";
6849
- }
6850
-
6851
- // If a hook was provided, use that value, otherwise just set the specified value
6852
- if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
6853
-
6854
- // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
6855
- // Fixes bug #5509
6856
- try {
6857
- style[ name ] = value;
6858
- } catch(e) {}
6859
- }
6860
-
6861
- } else {
6862
- // If a hook was provided get the non-computed value from there
6863
- if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
6864
- return ret;
6865
- }
6866
-
6867
- // Otherwise just get the value from the style object
6868
- return style[ name ];
6869
- }
6870
- },
6871
-
6872
- css: function( elem, name, extra, styles ) {
6873
- var num, val, hooks,
6874
- origName = jQuery.camelCase( name );
6875
-
6876
- // Make sure that we're working with the right name
6877
- name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
6878
-
6879
- // gets hook for the prefixed version
6880
- // followed by the unprefixed version
6881
- hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6882
-
6883
- // If a hook was provided get the computed value from there
6884
- if ( hooks && "get" in hooks ) {
6885
- val = hooks.get( elem, true, extra );
6886
- }
6887
-
6888
- // Otherwise, if a way to get the computed value exists, use that
6889
- if ( val === undefined ) {
6890
- val = curCSS( elem, name, styles );
6891
- }
6892
-
6893
- //convert "normal" to computed value
6894
- if ( val === "normal" && name in cssNormalTransform ) {
6895
- val = cssNormalTransform[ name ];
6896
- }
6897
-
6898
- // Return, converting to number if forced or a qualifier was provided and val looks numeric
6899
- if ( extra === "" || extra ) {
6900
- num = parseFloat( val );
6901
- return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
6902
- }
6903
- return val;
6904
- },
6905
-
6906
- // A method for quickly swapping in/out CSS properties to get correct calculations
6907
- swap: function( elem, options, callback, args ) {
6908
- var ret, name,
6909
- old = {};
6910
-
6911
- // Remember the old values, and insert the new ones
6912
- for ( name in options ) {
6913
- old[ name ] = elem.style[ name ];
6914
- elem.style[ name ] = options[ name ];
6915
- }
6916
-
6917
- ret = callback.apply( elem, args || [] );
6918
-
6919
- // Revert the old values
6920
- for ( name in options ) {
6921
- elem.style[ name ] = old[ name ];
6922
- }
6923
-
6924
- return ret;
6925
- }
6926
- });
6927
-
6928
- // NOTE: we've included the "window" in window.getComputedStyle
6929
- // because jsdom on node.js will break without it.
6930
- if ( window.getComputedStyle ) {
6931
- getStyles = function( elem ) {
6932
- return window.getComputedStyle( elem, null );
6933
- };
6934
-
6935
- curCSS = function( elem, name, _computed ) {
6936
- var width, minWidth, maxWidth,
6937
- computed = _computed || getStyles( elem ),
6938
-
6939
- // getPropertyValue is only needed for .css('filter') in IE9, see #12537
6940
- ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,
6941
- style = elem.style;
6942
-
6943
- if ( computed ) {
6944
-
6945
- if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
6946
- ret = jQuery.style( elem, name );
6947
- }
6948
-
6949
- // A tribute to the "awesome hack by Dean Edwards"
6950
- // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
6951
- // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
6952
- // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
6953
- if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
6954
-
6955
- // Remember the original values
6956
- width = style.width;
6957
- minWidth = style.minWidth;
6958
- maxWidth = style.maxWidth;
6959
-
6960
- // Put in the new values to get a computed value out
6961
- style.minWidth = style.maxWidth = style.width = ret;
6962
- ret = computed.width;
6963
-
6964
- // Revert the changed values
6965
- style.width = width;
6966
- style.minWidth = minWidth;
6967
- style.maxWidth = maxWidth;
6968
- }
6969
- }
6970
-
6971
- return ret;
6972
- };
6973
- } else if ( document.documentElement.currentStyle ) {
6974
- getStyles = function( elem ) {
6975
- return elem.currentStyle;
6976
- };
6977
-
6978
- curCSS = function( elem, name, _computed ) {
6979
- var left, rs, rsLeft,
6980
- computed = _computed || getStyles( elem ),
6981
- ret = computed ? computed[ name ] : undefined,
6982
- style = elem.style;
6983
-
6984
- // Avoid setting ret to empty string here
6985
- // so we don't default to auto
6986
- if ( ret == null && style && style[ name ] ) {
6987
- ret = style[ name ];
6988
- }
6989
-
6990
- // From the awesome hack by Dean Edwards
6991
- // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
6992
-
6993
- // If we're not dealing with a regular pixel number
6994
- // but a number that has a weird ending, we need to convert it to pixels
6995
- // but not position css attributes, as those are proportional to the parent element instead
6996
- // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
6997
- if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
6998
-
6999
- // Remember the original values
7000
- left = style.left;
7001
- rs = elem.runtimeStyle;
7002
- rsLeft = rs && rs.left;
7003
-
7004
- // Put in the new values to get a computed value out
7005
- if ( rsLeft ) {
7006
- rs.left = elem.currentStyle.left;
7007
- }
7008
- style.left = name === "fontSize" ? "1em" : ret;
7009
- ret = style.pixelLeft + "px";
7010
-
7011
- // Revert the changed values
7012
- style.left = left;
7013
- if ( rsLeft ) {
7014
- rs.left = rsLeft;
7015
- }
7016
- }
7017
-
7018
- return ret === "" ? "auto" : ret;
7019
- };
7020
- }
7021
-
7022
- function setPositiveNumber( elem, value, subtract ) {
7023
- var matches = rnumsplit.exec( value );
7024
- return matches ?
7025
- // Guard against undefined "subtract", e.g., when used as in cssHooks
7026
- Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
7027
- value;
7028
- }
7029
-
7030
- function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
7031
- var i = extra === ( isBorderBox ? "border" : "content" ) ?
7032
- // If we already have the right measurement, avoid augmentation
7033
- 4 :
7034
- // Otherwise initialize for horizontal or vertical properties
7035
- name === "width" ? 1 : 0,
7036
-
7037
- val = 0;
7038
-
7039
- for ( ; i < 4; i += 2 ) {
7040
- // both box models exclude margin, so add it if we want it
7041
- if ( extra === "margin" ) {
7042
- val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
7043
- }
7044
-
7045
- if ( isBorderBox ) {
7046
- // border-box includes padding, so remove it if we want content
7047
- if ( extra === "content" ) {
7048
- val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7049
- }
7050
-
7051
- // at this point, extra isn't border nor margin, so remove border
7052
- if ( extra !== "margin" ) {
7053
- val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7054
- }
7055
- } else {
7056
- // at this point, extra isn't content, so add padding
7057
- val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7058
-
7059
- // at this point, extra isn't content nor padding, so add border
7060
- if ( extra !== "padding" ) {
7061
- val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7062
- }
7063
- }
7064
- }
7065
-
7066
- return val;
7067
- }
7068
-
7069
- function getWidthOrHeight( elem, name, extra ) {
7070
-
7071
- // Start with offset property, which is equivalent to the border-box value
7072
- var valueIsBorderBox = true,
7073
- val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
7074
- styles = getStyles( elem ),
7075
- isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
7076
-
7077
- // some non-html elements return undefined for offsetWidth, so check for null/undefined
7078
- // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
7079
- // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
7080
- if ( val <= 0 || val == null ) {
7081
- // Fall back to computed then uncomputed css if necessary
7082
- val = curCSS( elem, name, styles );
7083
- if ( val < 0 || val == null ) {
7084
- val = elem.style[ name ];
7085
- }
7086
-
7087
- // Computed unit is not pixels. Stop here and return.
7088
- if ( rnumnonpx.test(val) ) {
7089
- return val;
7090
- }
7091
-
7092
- // we need the check for style in case a browser which returns unreliable values
7093
- // for getComputedStyle silently falls back to the reliable elem.style
7094
- valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
7095
-
7096
- // Normalize "", auto, and prepare for extra
7097
- val = parseFloat( val ) || 0;
7098
- }
7099
-
7100
- // use the active box-sizing model to add/subtract irrelevant styles
7101
- return ( val +
7102
- augmentWidthOrHeight(
7103
- elem,
7104
- name,
7105
- extra || ( isBorderBox ? "border" : "content" ),
7106
- valueIsBorderBox,
7107
- styles
7108
- )
7109
- ) + "px";
7110
- }
7111
-
7112
- // Try to determine the default display value of an element
7113
- function css_defaultDisplay( nodeName ) {
7114
- var doc = document,
7115
- display = elemdisplay[ nodeName ];
7116
-
7117
- if ( !display ) {
7118
- display = actualDisplay( nodeName, doc );
7119
-
7120
- // If the simple way fails, read from inside an iframe
7121
- if ( display === "none" || !display ) {
7122
- // Use the already-created iframe if possible
7123
- iframe = ( iframe ||
7124
- jQuery("<iframe frameborder='0' width='0' height='0'/>")
7125
- .css( "cssText", "display:block !important" )
7126
- ).appendTo( doc.documentElement );
7127
-
7128
- // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
7129
- doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
7130
- doc.write("<!doctype html><html><body>");
7131
- doc.close();
7132
-
7133
- display = actualDisplay( nodeName, doc );
7134
- iframe.detach();
7135
- }
7136
-
7137
- // Store the correct default display
7138
- elemdisplay[ nodeName ] = display;
7139
- }
7140
-
7141
- return display;
7142
- }
7143
-
7144
- // Called ONLY from within css_defaultDisplay
7145
- function actualDisplay( name, doc ) {
7146
- var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
7147
- display = jQuery.css( elem[0], "display" );
7148
- elem.remove();
7149
- return display;
7150
- }
7151
-
7152
- jQuery.each([ "height", "width" ], function( i, name ) {
7153
- jQuery.cssHooks[ name ] = {
7154
- get: function( elem, computed, extra ) {
7155
- if ( computed ) {
7156
- // certain elements can have dimension info if we invisibly show them
7157
- // however, it must have a current display style that would benefit from this
7158
- return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
7159
- jQuery.swap( elem, cssShow, function() {
7160
- return getWidthOrHeight( elem, name, extra );
7161
- }) :
7162
- getWidthOrHeight( elem, name, extra );
7163
- }
7164
- },
7165
-
7166
- set: function( elem, value, extra ) {
7167
- var styles = extra && getStyles( elem );
7168
- return setPositiveNumber( elem, value, extra ?
7169
- augmentWidthOrHeight(
7170
- elem,
7171
- name,
7172
- extra,
7173
- jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
7174
- styles
7175
- ) : 0
7176
- );
7177
- }
7178
- };
7179
- });
7180
-
7181
- if ( !jQuery.support.opacity ) {
7182
- jQuery.cssHooks.opacity = {
7183
- get: function( elem, computed ) {
7184
- // IE uses filters for opacity
7185
- return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
7186
- ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
7187
- computed ? "1" : "";
7188
- },
7189
-
7190
- set: function( elem, value ) {
7191
- var style = elem.style,
7192
- currentStyle = elem.currentStyle,
7193
- opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
7194
- filter = currentStyle && currentStyle.filter || style.filter || "";
7195
-
7196
- // IE has trouble with opacity if it does not have layout
7197
- // Force it by setting the zoom level
7198
- style.zoom = 1;
7199
-
7200
- // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
7201
- // if value === "", then remove inline opacity #12685
7202
- if ( ( value >= 1 || value === "" ) &&
7203
- jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
7204
- style.removeAttribute ) {
7205
-
7206
- // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
7207
- // if "filter:" is present at all, clearType is disabled, we want to avoid this
7208
- // style.removeAttribute is IE Only, but so apparently is this code path...
7209
- style.removeAttribute( "filter" );
7210
-
7211
- // if there is no filter style applied in a css rule or unset inline opacity, we are done
7212
- if ( value === "" || currentStyle && !currentStyle.filter ) {
7213
- return;
7214
- }
7215
- }
7216
-
7217
- // otherwise, set new filter values
7218
- style.filter = ralpha.test( filter ) ?
7219
- filter.replace( ralpha, opacity ) :
7220
- filter + " " + opacity;
7221
- }
7222
- };
7223
- }
7224
-
7225
- // These hooks cannot be added until DOM ready because the support test
7226
- // for it is not run until after DOM ready
7227
- jQuery(function() {
7228
- if ( !jQuery.support.reliableMarginRight ) {
7229
- jQuery.cssHooks.marginRight = {
7230
- get: function( elem, computed ) {
7231
- if ( computed ) {
7232
- // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
7233
- // Work around by temporarily setting element display to inline-block
7234
- return jQuery.swap( elem, { "display": "inline-block" },
7235
- curCSS, [ elem, "marginRight" ] );
7236
- }
7237
- }
7238
- };
7239
- }
7240
-
7241
- // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
7242
- // getComputedStyle returns percent when specified for top/left/bottom/right
7243
- // rather than make the css module depend on the offset module, we just check for it here
7244
- if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
7245
- jQuery.each( [ "top", "left" ], function( i, prop ) {
7246
- jQuery.cssHooks[ prop ] = {
7247
- get: function( elem, computed ) {
7248
- if ( computed ) {
7249
- computed = curCSS( elem, prop );
7250
- // if curCSS returns percentage, fallback to offset
7251
- return rnumnonpx.test( computed ) ?
7252
- jQuery( elem ).position()[ prop ] + "px" :
7253
- computed;
7254
- }
7255
- }
7256
- };
7257
- });
7258
- }
7259
-
7260
- });
7261
-
7262
- if ( jQuery.expr && jQuery.expr.filters ) {
7263
- jQuery.expr.filters.hidden = function( elem ) {
7264
- // Support: Opera <= 12.12
7265
- // Opera reports offsetWidths and offsetHeights less than zero on some elements
7266
- return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
7267
- (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
7268
- };
7269
-
7270
- jQuery.expr.filters.visible = function( elem ) {
7271
- return !jQuery.expr.filters.hidden( elem );
7272
- };
7273
- }
7274
-
7275
- // These hooks are used by animate to expand properties
7276
- jQuery.each({
7277
- margin: "",
7278
- padding: "",
7279
- border: "Width"
7280
- }, function( prefix, suffix ) {
7281
- jQuery.cssHooks[ prefix + suffix ] = {
7282
- expand: function( value ) {
7283
- var i = 0,
7284
- expanded = {},
7285
-
7286
- // assumes a single number if not a string
7287
- parts = typeof value === "string" ? value.split(" ") : [ value ];
7288
-
7289
- for ( ; i < 4; i++ ) {
7290
- expanded[ prefix + cssExpand[ i ] + suffix ] =
7291
- parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
7292
- }
7293
-
7294
- return expanded;
7295
- }
7296
- };
7297
-
7298
- if ( !rmargin.test( prefix ) ) {
7299
- jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
7300
- }
7301
- });
7302
- var r20 = /%20/g,
7303
- rbracket = /\[\]$/,
7304
- rCRLF = /\r?\n/g,
7305
- rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
7306
- rsubmittable = /^(?:input|select|textarea|keygen)/i;
7307
-
7308
- jQuery.fn.extend({
7309
- serialize: function() {
7310
- return jQuery.param( this.serializeArray() );
7311
- },
7312
- serializeArray: function() {
7313
- return this.map(function(){
7314
- // Can add propHook for "elements" to filter or add form elements
7315
- var elements = jQuery.prop( this, "elements" );
7316
- return elements ? jQuery.makeArray( elements ) : this;
7317
- })
7318
- .filter(function(){
7319
- var type = this.type;
7320
- // Use .is(":disabled") so that fieldset[disabled] works
7321
- return this.name && !jQuery( this ).is( ":disabled" ) &&
7322
- rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
7323
- ( this.checked || !manipulation_rcheckableType.test( type ) );
7324
- })
7325
- .map(function( i, elem ){
7326
- var val = jQuery( this ).val();
7327
-
7328
- return val == null ?
7329
- null :
7330
- jQuery.isArray( val ) ?
7331
- jQuery.map( val, function( val ){
7332
- return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7333
- }) :
7334
- { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7335
- }).get();
7336
- }
7337
- });
7338
-
7339
- //Serialize an array of form elements or a set of
7340
- //key/values into a query string
7341
- jQuery.param = function( a, traditional ) {
7342
- var prefix,
7343
- s = [],
7344
- add = function( key, value ) {
7345
- // If value is a function, invoke it and return its value
7346
- value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
7347
- s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
7348
- };
7349
-
7350
- // Set traditional to true for jQuery <= 1.3.2 behavior.
7351
- if ( traditional === undefined ) {
7352
- traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
7353
- }
7354
-
7355
- // If an array was passed in, assume that it is an array of form elements.
7356
- if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
7357
- // Serialize the form elements
7358
- jQuery.each( a, function() {
7359
- add( this.name, this.value );
7360
- });
7361
-
7362
- } else {
7363
- // If traditional, encode the "old" way (the way 1.3.2 or older
7364
- // did it), otherwise encode params recursively.
7365
- for ( prefix in a ) {
7366
- buildParams( prefix, a[ prefix ], traditional, add );
7367
- }
7368
- }
7369
-
7370
- // Return the resulting serialization
7371
- return s.join( "&" ).replace( r20, "+" );
7372
- };
7373
-
7374
- function buildParams( prefix, obj, traditional, add ) {
7375
- var name;
7376
-
7377
- if ( jQuery.isArray( obj ) ) {
7378
- // Serialize array item.
7379
- jQuery.each( obj, function( i, v ) {
7380
- if ( traditional || rbracket.test( prefix ) ) {
7381
- // Treat each array item as a scalar.
7382
- add( prefix, v );
7383
-
7384
- } else {
7385
- // Item is non-scalar (array or object), encode its numeric index.
7386
- buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
7387
- }
7388
- });
7389
-
7390
- } else if ( !traditional && jQuery.type( obj ) === "object" ) {
7391
- // Serialize object item.
7392
- for ( name in obj ) {
7393
- buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
7394
- }
7395
-
7396
- } else {
7397
- // Serialize scalar item.
7398
- add( prefix, obj );
7399
- }
7400
- }
7401
- jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
7402
- "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
7403
- "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
7404
-
7405
- // Handle event binding
7406
- jQuery.fn[ name ] = function( data, fn ) {
7407
- return arguments.length > 0 ?
7408
- this.on( name, null, data, fn ) :
7409
- this.trigger( name );
7410
- };
7411
- });
7412
-
7413
- jQuery.fn.hover = function( fnOver, fnOut ) {
7414
- return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
7415
- };
7416
- var
7417
- // Document location
7418
- ajaxLocParts,
7419
- ajaxLocation,
7420
- ajax_nonce = jQuery.now(),
7421
-
7422
- ajax_rquery = /\?/,
7423
- rhash = /#.*$/,
7424
- rts = /([?&])_=[^&]*/,
7425
- rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
7426
- // #7653, #8125, #8152: local protocol detection
7427
- rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
7428
- rnoContent = /^(?:GET|HEAD)$/,
7429
- rprotocol = /^\/\//,
7430
- rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
7431
-
7432
- // Keep a copy of the old load method
7433
- _load = jQuery.fn.load,
7434
-
7435
- /* Prefilters
7436
- * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
7437
- * 2) These are called:
7438
- * - BEFORE asking for a transport
7439
- * - AFTER param serialization (s.data is a string if s.processData is true)
7440
- * 3) key is the dataType
7441
- * 4) the catchall symbol "*" can be used
7442
- * 5) execution will start with transport dataType and THEN continue down to "*" if needed
7443
- */
7444
- prefilters = {},
7445
-
7446
- /* Transports bindings
7447
- * 1) key is the dataType
7448
- * 2) the catchall symbol "*" can be used
7449
- * 3) selection will start with transport dataType and THEN go to "*" if needed
7450
- */
7451
- transports = {},
7452
-
7453
- // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
7454
- allTypes = "*/".concat("*");
7455
-
7456
- // #8138, IE may throw an exception when accessing
7457
- // a field from window.location if document.domain has been set
7458
- try {
7459
- ajaxLocation = location.href;
7460
- } catch( e ) {
7461
- // Use the href attribute of an A element
7462
- // since IE will modify it given document.location
7463
- ajaxLocation = document.createElement( "a" );
7464
- ajaxLocation.href = "";
7465
- ajaxLocation = ajaxLocation.href;
7466
- }
7467
-
7468
- // Segment location into parts
7469
- ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
7470
-
7471
- // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
7472
- function addToPrefiltersOrTransports( structure ) {
7473
-
7474
- // dataTypeExpression is optional and defaults to "*"
7475
- return function( dataTypeExpression, func ) {
7476
-
7477
- if ( typeof dataTypeExpression !== "string" ) {
7478
- func = dataTypeExpression;
7479
- dataTypeExpression = "*";
7480
- }
7481
-
7482
- var dataType,
7483
- i = 0,
7484
- dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];
7485
-
7486
- if ( jQuery.isFunction( func ) ) {
7487
- // For each dataType in the dataTypeExpression
7488
- while ( (dataType = dataTypes[i++]) ) {
7489
- // Prepend if requested
7490
- if ( dataType[0] === "+" ) {
7491
- dataType = dataType.slice( 1 ) || "*";
7492
- (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
7493
-
7494
- // Otherwise append
7495
- } else {
7496
- (structure[ dataType ] = structure[ dataType ] || []).push( func );
7497
- }
7498
- }
7499
- }
7500
- };
7501
- }
7502
-
7503
- // Base inspection function for prefilters and transports
7504
- function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
7505
-
7506
- var inspected = {},
7507
- seekingTransport = ( structure === transports );
7508
-
7509
- function inspect( dataType ) {
7510
- var selected;
7511
- inspected[ dataType ] = true;
7512
- jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
7513
- var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
7514
- if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
7515
- options.dataTypes.unshift( dataTypeOrTransport );
7516
- inspect( dataTypeOrTransport );
7517
- return false;
7518
- } else if ( seekingTransport ) {
7519
- return !( selected = dataTypeOrTransport );
7520
- }
7521
- });
7522
- return selected;
7523
- }
7524
-
7525
- return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
7526
- }
7527
-
7528
- // A special extend for ajax options
7529
- // that takes "flat" options (not to be deep extended)
7530
- // Fixes #9887
7531
- function ajaxExtend( target, src ) {
7532
- var deep, key,
7533
- flatOptions = jQuery.ajaxSettings.flatOptions || {};
7534
-
7535
- for ( key in src ) {
7536
- if ( src[ key ] !== undefined ) {
7537
- ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
7538
- }
7539
- }
7540
- if ( deep ) {
7541
- jQuery.extend( true, target, deep );
7542
- }
7543
-
7544
- return target;
7545
- }
7546
-
7547
- jQuery.fn.load = function( url, params, callback ) {
7548
- if ( typeof url !== "string" && _load ) {
7549
- return _load.apply( this, arguments );
7550
- }
7551
-
7552
- var selector, response, type,
7553
- self = this,
7554
- off = url.indexOf(" ");
7555
-
7556
- if ( off >= 0 ) {
7557
- selector = url.slice( off, url.length );
7558
- url = url.slice( 0, off );
7559
- }
7560
-
7561
- // If it's a function
7562
- if ( jQuery.isFunction( params ) ) {
7563
-
7564
- // We assume that it's the callback
7565
- callback = params;
7566
- params = undefined;
7567
-
7568
- // Otherwise, build a param string
7569
- } else if ( params && typeof params === "object" ) {
7570
- type = "POST";
7571
- }
7572
-
7573
- // If we have elements to modify, make the request
7574
- if ( self.length > 0 ) {
7575
- jQuery.ajax({
7576
- url: url,
7577
-
7578
- // if "type" variable is undefined, then "GET" method will be used
7579
- type: type,
7580
- dataType: "html",
7581
- data: params
7582
- }).done(function( responseText ) {
7583
-
7584
- // Save response for use in complete callback
7585
- response = arguments;
7586
-
7587
- self.html( selector ?
7588
-
7589
- // If a selector was specified, locate the right elements in a dummy div
7590
- // Exclude scripts to avoid IE 'Permission Denied' errors
7591
- jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
7592
-
7593
- // Otherwise use the full result
7594
- responseText );
7595
-
7596
- }).complete( callback && function( jqXHR, status ) {
7597
- self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
7598
- });
7599
- }
7600
-
7601
- return this;
7602
- };
7603
-
7604
- // Attach a bunch of functions for handling common AJAX events
7605
- jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
7606
- jQuery.fn[ type ] = function( fn ){
7607
- return this.on( type, fn );
7608
- };
7609
- });
7610
-
7611
- jQuery.each( [ "get", "post" ], function( i, method ) {
7612
- jQuery[ method ] = function( url, data, callback, type ) {
7613
- // shift arguments if data argument was omitted
7614
- if ( jQuery.isFunction( data ) ) {
7615
- type = type || callback;
7616
- callback = data;
7617
- data = undefined;
7618
- }
7619
-
7620
- return jQuery.ajax({
7621
- url: url,
7622
- type: method,
7623
- dataType: type,
7624
- data: data,
7625
- success: callback
7626
- });
7627
- };
7628
- });
7629
-
7630
- jQuery.extend({
7631
-
7632
- // Counter for holding the number of active queries
7633
- active: 0,
7634
-
7635
- // Last-Modified header cache for next request
7636
- lastModified: {},
7637
- etag: {},
7638
-
7639
- ajaxSettings: {
7640
- url: ajaxLocation,
7641
- type: "GET",
7642
- isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
7643
- global: true,
7644
- processData: true,
7645
- async: true,
7646
- contentType: "application/x-www-form-urlencoded; charset=UTF-8",
7647
- /*
7648
- timeout: 0,
7649
- data: null,
7650
- dataType: null,
7651
- username: null,
7652
- password: null,
7653
- cache: null,
7654
- throws: false,
7655
- traditional: false,
7656
- headers: {},
7657
- */
7658
-
7659
- accepts: {
7660
- "*": allTypes,
7661
- text: "text/plain",
7662
- html: "text/html",
7663
- xml: "application/xml, text/xml",
7664
- json: "application/json, text/javascript"
7665
- },
7666
-
7667
- contents: {
7668
- xml: /xml/,
7669
- html: /html/,
7670
- json: /json/
7671
- },
7672
-
7673
- responseFields: {
7674
- xml: "responseXML",
7675
- text: "responseText"
7676
- },
7677
-
7678
- // Data converters
7679
- // Keys separate source (or catchall "*") and destination types with a single space
7680
- converters: {
7681
-
7682
- // Convert anything to text
7683
- "* text": window.String,
7684
-
7685
- // Text to html (true = no transformation)
7686
- "text html": true,
7687
-
7688
- // Evaluate text as a json expression
7689
- "text json": jQuery.parseJSON,
7690
-
7691
- // Parse text as xml
7692
- "text xml": jQuery.parseXML
7693
- },
7694
-
7695
- // For options that shouldn't be deep extended:
7696
- // you can add your own custom options here if
7697
- // and when you create one that shouldn't be
7698
- // deep extended (see ajaxExtend)
7699
- flatOptions: {
7700
- url: true,
7701
- context: true
7702
- }
7703
- },
7704
-
7705
- // Creates a full fledged settings object into target
7706
- // with both ajaxSettings and settings fields.
7707
- // If target is omitted, writes into ajaxSettings.
7708
- ajaxSetup: function( target, settings ) {
7709
- return settings ?
7710
-
7711
- // Building a settings object
7712
- ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
7713
-
7714
- // Extending ajaxSettings
7715
- ajaxExtend( jQuery.ajaxSettings, target );
7716
- },
7717
-
7718
- ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
7719
- ajaxTransport: addToPrefiltersOrTransports( transports ),
7720
-
7721
- // Main method
7722
- ajax: function( url, options ) {
7723
-
7724
- // If url is an object, simulate pre-1.5 signature
7725
- if ( typeof url === "object" ) {
7726
- options = url;
7727
- url = undefined;
7728
- }
7729
-
7730
- // Force options to be an object
7731
- options = options || {};
7732
-
7733
- var // Cross-domain detection vars
7734
- parts,
7735
- // Loop variable
7736
- i,
7737
- // URL without anti-cache param
7738
- cacheURL,
7739
- // Response headers as string
7740
- responseHeadersString,
7741
- // timeout handle
7742
- timeoutTimer,
7743
-
7744
- // To know if global events are to be dispatched
7745
- fireGlobals,
7746
-
7747
- transport,
7748
- // Response headers
7749
- responseHeaders,
7750
- // Create the final options object
7751
- s = jQuery.ajaxSetup( {}, options ),
7752
- // Callbacks context
7753
- callbackContext = s.context || s,
7754
- // Context for global events is callbackContext if it is a DOM node or jQuery collection
7755
- globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
7756
- jQuery( callbackContext ) :
7757
- jQuery.event,
7758
- // Deferreds
7759
- deferred = jQuery.Deferred(),
7760
- completeDeferred = jQuery.Callbacks("once memory"),
7761
- // Status-dependent callbacks
7762
- statusCode = s.statusCode || {},
7763
- // Headers (they are sent all at once)
7764
- requestHeaders = {},
7765
- requestHeadersNames = {},
7766
- // The jqXHR state
7767
- state = 0,
7768
- // Default abort message
7769
- strAbort = "canceled",
7770
- // Fake xhr
7771
- jqXHR = {
7772
- readyState: 0,
7773
-
7774
- // Builds headers hashtable if needed
7775
- getResponseHeader: function( key ) {
7776
- var match;
7777
- if ( state === 2 ) {
7778
- if ( !responseHeaders ) {
7779
- responseHeaders = {};
7780
- while ( (match = rheaders.exec( responseHeadersString )) ) {
7781
- responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
7782
- }
7783
- }
7784
- match = responseHeaders[ key.toLowerCase() ];
7785
- }
7786
- return match == null ? null : match;
7787
- },
7788
-
7789
- // Raw string
7790
- getAllResponseHeaders: function() {
7791
- return state === 2 ? responseHeadersString : null;
7792
- },
7793
-
7794
- // Caches the header
7795
- setRequestHeader: function( name, value ) {
7796
- var lname = name.toLowerCase();
7797
- if ( !state ) {
7798
- name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
7799
- requestHeaders[ name ] = value;
7800
- }
7801
- return this;
7802
- },
7803
-
7804
- // Overrides response content-type header
7805
- overrideMimeType: function( type ) {
7806
- if ( !state ) {
7807
- s.mimeType = type;
7808
- }
7809
- return this;
7810
- },
7811
-
7812
- // Status-dependent callbacks
7813
- statusCode: function( map ) {
7814
- var code;
7815
- if ( map ) {
7816
- if ( state < 2 ) {
7817
- for ( code in map ) {
7818
- // Lazy-add the new callback in a way that preserves old ones
7819
- statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
7820
- }
7821
- } else {
7822
- // Execute the appropriate callbacks
7823
- jqXHR.always( map[ jqXHR.status ] );
7824
- }
7825
- }
7826
- return this;
7827
- },
7828
-
7829
- // Cancel the request
7830
- abort: function( statusText ) {
7831
- var finalText = statusText || strAbort;
7832
- if ( transport ) {
7833
- transport.abort( finalText );
7834
- }
7835
- done( 0, finalText );
7836
- return this;
7837
- }
7838
- };
7839
-
7840
- // Attach deferreds
7841
- deferred.promise( jqXHR ).complete = completeDeferred.add;
7842
- jqXHR.success = jqXHR.done;
7843
- jqXHR.error = jqXHR.fail;
7844
-
7845
- // Remove hash character (#7531: and string promotion)
7846
- // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
7847
- // Handle falsy url in the settings object (#10093: consistency with old signature)
7848
- // We also use the url parameter if available
7849
- s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
7850
-
7851
- // Alias method option to type as per ticket #12004
7852
- s.type = options.method || options.type || s.method || s.type;
7853
-
7854
- // Extract dataTypes list
7855
- s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
7856
-
7857
- // A cross-domain request is in order when we have a protocol:host:port mismatch
7858
- if ( s.crossDomain == null ) {
7859
- parts = rurl.exec( s.url.toLowerCase() );
7860
- s.crossDomain = !!( parts &&
7861
- ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
7862
- ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
7863
- ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
7864
- );
7865
- }
7866
-
7867
- // Convert data if not already a string
7868
- if ( s.data && s.processData && typeof s.data !== "string" ) {
7869
- s.data = jQuery.param( s.data, s.traditional );
7870
- }
7871
-
7872
- // Apply prefilters
7873
- inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
7874
-
7875
- // If request was aborted inside a prefilter, stop there
7876
- if ( state === 2 ) {
7877
- return jqXHR;
7878
- }
7879
-
7880
- // We can fire global events as of now if asked to
7881
- fireGlobals = s.global;
7882
-
7883
- // Watch for a new set of requests
7884
- if ( fireGlobals && jQuery.active++ === 0 ) {
7885
- jQuery.event.trigger("ajaxStart");
7886
- }
7887
-
7888
- // Uppercase the type
7889
- s.type = s.type.toUpperCase();
7890
-
7891
- // Determine if request has content
7892
- s.hasContent = !rnoContent.test( s.type );
7893
-
7894
- // Save the URL in case we're toying with the If-Modified-Since
7895
- // and/or If-None-Match header later on
7896
- cacheURL = s.url;
7897
-
7898
- // More options handling for requests with no content
7899
- if ( !s.hasContent ) {
7900
-
7901
- // If data is available, append data to url
7902
- if ( s.data ) {
7903
- cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
7904
- // #9682: remove data so that it's not used in an eventual retry
7905
- delete s.data;
7906
- }
7907
-
7908
- // Add anti-cache in url if needed
7909
- if ( s.cache === false ) {
7910
- s.url = rts.test( cacheURL ) ?
7911
-
7912
- // If there is already a '_' parameter, set its value
7913
- cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
7914
-
7915
- // Otherwise add one to the end
7916
- cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
7917
- }
7918
- }
7919
-
7920
- // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
7921
- if ( s.ifModified ) {
7922
- if ( jQuery.lastModified[ cacheURL ] ) {
7923
- jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
7924
- }
7925
- if ( jQuery.etag[ cacheURL ] ) {
7926
- jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
7927
- }
7928
- }
7929
-
7930
- // Set the correct header, if data is being sent
7931
- if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
7932
- jqXHR.setRequestHeader( "Content-Type", s.contentType );
7933
- }
7934
-
7935
- // Set the Accepts header for the server, depending on the dataType
7936
- jqXHR.setRequestHeader(
7937
- "Accept",
7938
- s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
7939
- s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
7940
- s.accepts[ "*" ]
7941
- );
7942
-
7943
- // Check for headers option
7944
- for ( i in s.headers ) {
7945
- jqXHR.setRequestHeader( i, s.headers[ i ] );
7946
- }
7947
-
7948
- // Allow custom headers/mimetypes and early abort
7949
- if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
7950
- // Abort if not done already and return
7951
- return jqXHR.abort();
7952
- }
7953
-
7954
- // aborting is no longer a cancellation
7955
- strAbort = "abort";
7956
-
7957
- // Install callbacks on deferreds
7958
- for ( i in { success: 1, error: 1, complete: 1 } ) {
7959
- jqXHR[ i ]( s[ i ] );
7960
- }
7961
-
7962
- // Get transport
7963
- transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
7964
-
7965
- // If no transport, we auto-abort
7966
- if ( !transport ) {
7967
- done( -1, "No Transport" );
7968
- } else {
7969
- jqXHR.readyState = 1;
7970
-
7971
- // Send global event
7972
- if ( fireGlobals ) {
7973
- globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
7974
- }
7975
- // Timeout
7976
- if ( s.async && s.timeout > 0 ) {
7977
- timeoutTimer = setTimeout(function() {
7978
- jqXHR.abort("timeout");
7979
- }, s.timeout );
7980
- }
7981
-
7982
- try {
7983
- state = 1;
7984
- transport.send( requestHeaders, done );
7985
- } catch ( e ) {
7986
- // Propagate exception as error if not done
7987
- if ( state < 2 ) {
7988
- done( -1, e );
7989
- // Simply rethrow otherwise
7990
- } else {
7991
- throw e;
7992
- }
7993
- }
7994
- }
7995
-
7996
- // Callback for when everything is done
7997
- function done( status, nativeStatusText, responses, headers ) {
7998
- var isSuccess, success, error, response, modified,
7999
- statusText = nativeStatusText;
8000
-
8001
- // Called once
8002
- if ( state === 2 ) {
8003
- return;
8004
- }
8005
-
8006
- // State is "done" now
8007
- state = 2;
8008
-
8009
- // Clear timeout if it exists
8010
- if ( timeoutTimer ) {
8011
- clearTimeout( timeoutTimer );
8012
- }
8013
-
8014
- // Dereference transport for early garbage collection
8015
- // (no matter how long the jqXHR object will be used)
8016
- transport = undefined;
8017
-
8018
- // Cache response headers
8019
- responseHeadersString = headers || "";
8020
-
8021
- // Set readyState
8022
- jqXHR.readyState = status > 0 ? 4 : 0;
8023
-
8024
- // Get response data
8025
- if ( responses ) {
8026
- response = ajaxHandleResponses( s, jqXHR, responses );
8027
- }
8028
-
8029
- // If successful, handle type chaining
8030
- if ( status >= 200 && status < 300 || status === 304 ) {
8031
-
8032
- // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8033
- if ( s.ifModified ) {
8034
- modified = jqXHR.getResponseHeader("Last-Modified");
8035
- if ( modified ) {
8036
- jQuery.lastModified[ cacheURL ] = modified;
8037
- }
8038
- modified = jqXHR.getResponseHeader("etag");
8039
- if ( modified ) {
8040
- jQuery.etag[ cacheURL ] = modified;
8041
- }
8042
- }
8043
-
8044
- // if no content
8045
- if ( status === 204 ) {
8046
- isSuccess = true;
8047
- statusText = "nocontent";
8048
-
8049
- // if not modified
8050
- } else if ( status === 304 ) {
8051
- isSuccess = true;
8052
- statusText = "notmodified";
8053
-
8054
- // If we have data, let's convert it
8055
- } else {
8056
- isSuccess = ajaxConvert( s, response );
8057
- statusText = isSuccess.state;
8058
- success = isSuccess.data;
8059
- error = isSuccess.error;
8060
- isSuccess = !error;
8061
- }
8062
- } else {
8063
- // We extract error from statusText
8064
- // then normalize statusText and status for non-aborts
8065
- error = statusText;
8066
- if ( status || !statusText ) {
8067
- statusText = "error";
8068
- if ( status < 0 ) {
8069
- status = 0;
8070
- }
8071
- }
8072
- }
8073
-
8074
- // Set data for the fake xhr object
8075
- jqXHR.status = status;
8076
- jqXHR.statusText = ( nativeStatusText || statusText ) + "";
8077
-
8078
- // Success/Error
8079
- if ( isSuccess ) {
8080
- deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
8081
- } else {
8082
- deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
8083
- }
8084
-
8085
- // Status-dependent callbacks
8086
- jqXHR.statusCode( statusCode );
8087
- statusCode = undefined;
8088
-
8089
- if ( fireGlobals ) {
8090
- globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
8091
- [ jqXHR, s, isSuccess ? success : error ] );
8092
- }
8093
-
8094
- // Complete
8095
- completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
8096
-
8097
- if ( fireGlobals ) {
8098
- globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
8099
- // Handle the global AJAX counter
8100
- if ( !( --jQuery.active ) ) {
8101
- jQuery.event.trigger("ajaxStop");
8102
- }
8103
- }
8104
- }
8105
-
8106
- return jqXHR;
8107
- },
8108
-
8109
- getScript: function( url, callback ) {
8110
- return jQuery.get( url, undefined, callback, "script" );
8111
- },
8112
-
8113
- getJSON: function( url, data, callback ) {
8114
- return jQuery.get( url, data, callback, "json" );
8115
- }
8116
- });
8117
-
8118
- /* Handles responses to an ajax request:
8119
- * - sets all responseXXX fields accordingly
8120
- * - finds the right dataType (mediates between content-type and expected dataType)
8121
- * - returns the corresponding response
8122
- */
8123
- function ajaxHandleResponses( s, jqXHR, responses ) {
8124
- var firstDataType, ct, finalDataType, type,
8125
- contents = s.contents,
8126
- dataTypes = s.dataTypes,
8127
- responseFields = s.responseFields;
8128
-
8129
- // Fill responseXXX fields
8130
- for ( type in responseFields ) {
8131
- if ( type in responses ) {
8132
- jqXHR[ responseFields[type] ] = responses[ type ];
8133
- }
8134
- }
8135
-
8136
- // Remove auto dataType and get content-type in the process
8137
- while( dataTypes[ 0 ] === "*" ) {
8138
- dataTypes.shift();
8139
- if ( ct === undefined ) {
8140
- ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
8141
- }
8142
- }
8143
-
8144
- // Check if we're dealing with a known content-type
8145
- if ( ct ) {
8146
- for ( type in contents ) {
8147
- if ( contents[ type ] && contents[ type ].test( ct ) ) {
8148
- dataTypes.unshift( type );
8149
- break;
8150
- }
8151
- }
8152
- }
8153
-
8154
- // Check to see if we have a response for the expected dataType
8155
- if ( dataTypes[ 0 ] in responses ) {
8156
- finalDataType = dataTypes[ 0 ];
8157
- } else {
8158
- // Try convertible dataTypes
8159
- for ( type in responses ) {
8160
- if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
8161
- finalDataType = type;
8162
- break;
8163
- }
8164
- if ( !firstDataType ) {
8165
- firstDataType = type;
8166
- }
8167
- }
8168
- // Or just use first one
8169
- finalDataType = finalDataType || firstDataType;
8170
- }
8171
-
8172
- // If we found a dataType
8173
- // We add the dataType to the list if needed
8174
- // and return the corresponding response
8175
- if ( finalDataType ) {
8176
- if ( finalDataType !== dataTypes[ 0 ] ) {
8177
- dataTypes.unshift( finalDataType );
8178
- }
8179
- return responses[ finalDataType ];
8180
- }
8181
- }
8182
-
8183
- // Chain conversions given the request and the original response
8184
- function ajaxConvert( s, response ) {
8185
- var conv2, current, conv, tmp,
8186
- converters = {},
8187
- i = 0,
8188
- // Work with a copy of dataTypes in case we need to modify it for conversion
8189
- dataTypes = s.dataTypes.slice(),
8190
- prev = dataTypes[ 0 ];
8191
-
8192
- // Apply the dataFilter if provided
8193
- if ( s.dataFilter ) {
8194
- response = s.dataFilter( response, s.dataType );
8195
- }
8196
-
8197
- // Create converters map with lowercased keys
8198
- if ( dataTypes[ 1 ] ) {
8199
- for ( conv in s.converters ) {
8200
- converters[ conv.toLowerCase() ] = s.converters[ conv ];
8201
- }
8202
- }
8203
-
8204
- // Convert to each sequential dataType, tolerating list modification
8205
- for ( ; (current = dataTypes[++i]); ) {
8206
-
8207
- // There's only work to do if current dataType is non-auto
8208
- if ( current !== "*" ) {
8209
-
8210
- // Convert response if prev dataType is non-auto and differs from current
8211
- if ( prev !== "*" && prev !== current ) {
8212
-
8213
- // Seek a direct converter
8214
- conv = converters[ prev + " " + current ] || converters[ "* " + current ];
8215
-
8216
- // If none found, seek a pair
8217
- if ( !conv ) {
8218
- for ( conv2 in converters ) {
8219
-
8220
- // If conv2 outputs current
8221
- tmp = conv2.split(" ");
8222
- if ( tmp[ 1 ] === current ) {
8223
-
8224
- // If prev can be converted to accepted input
8225
- conv = converters[ prev + " " + tmp[ 0 ] ] ||
8226
- converters[ "* " + tmp[ 0 ] ];
8227
- if ( conv ) {
8228
- // Condense equivalence converters
8229
- if ( conv === true ) {
8230
- conv = converters[ conv2 ];
8231
-
8232
- // Otherwise, insert the intermediate dataType
8233
- } else if ( converters[ conv2 ] !== true ) {
8234
- current = tmp[ 0 ];
8235
- dataTypes.splice( i--, 0, current );
8236
- }
8237
-
8238
- break;
8239
- }
8240
- }
8241
- }
8242
- }
8243
-
8244
- // Apply converter (if not an equivalence)
8245
- if ( conv !== true ) {
8246
-
8247
- // Unless errors are allowed to bubble, catch and return them
8248
- if ( conv && s["throws"] ) {
8249
- response = conv( response );
8250
- } else {
8251
- try {
8252
- response = conv( response );
8253
- } catch ( e ) {
8254
- return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
8255
- }
8256
- }
8257
- }
8258
- }
8259
-
8260
- // Update prev for next iteration
8261
- prev = current;
8262
- }
8263
- }
8264
-
8265
- return { state: "success", data: response };
8266
- }
8267
- // Install script dataType
8268
- jQuery.ajaxSetup({
8269
- accepts: {
8270
- script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
8271
- },
8272
- contents: {
8273
- script: /(?:java|ecma)script/
8274
- },
8275
- converters: {
8276
- "text script": function( text ) {
8277
- jQuery.globalEval( text );
8278
- return text;
8279
- }
8280
- }
8281
- });
8282
-
8283
- // Handle cache's special case and global
8284
- jQuery.ajaxPrefilter( "script", function( s ) {
8285
- if ( s.cache === undefined ) {
8286
- s.cache = false;
8287
- }
8288
- if ( s.crossDomain ) {
8289
- s.type = "GET";
8290
- s.global = false;
8291
- }
8292
- });
8293
-
8294
- // Bind script tag hack transport
8295
- jQuery.ajaxTransport( "script", function(s) {
8296
-
8297
- // This transport only deals with cross domain requests
8298
- if ( s.crossDomain ) {
8299
-
8300
- var script,
8301
- head = document.head || jQuery("head")[0] || document.documentElement;
8302
-
8303
- return {
8304
-
8305
- send: function( _, callback ) {
8306
-
8307
- script = document.createElement("script");
8308
-
8309
- script.async = true;
8310
-
8311
- if ( s.scriptCharset ) {
8312
- script.charset = s.scriptCharset;
8313
- }
8314
-
8315
- script.src = s.url;
8316
-
8317
- // Attach handlers for all browsers
8318
- script.onload = script.onreadystatechange = function( _, isAbort ) {
8319
-
8320
- if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
8321
-
8322
- // Handle memory leak in IE
8323
- script.onload = script.onreadystatechange = null;
8324
-
8325
- // Remove the script
8326
- if ( script.parentNode ) {
8327
- script.parentNode.removeChild( script );
8328
- }
8329
-
8330
- // Dereference the script
8331
- script = null;
8332
-
8333
- // Callback if not abort
8334
- if ( !isAbort ) {
8335
- callback( 200, "success" );
8336
- }
8337
- }
8338
- };
8339
-
8340
- // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
8341
- // Use native DOM manipulation to avoid our domManip AJAX trickery
8342
- head.insertBefore( script, head.firstChild );
8343
- },
8344
-
8345
- abort: function() {
8346
- if ( script ) {
8347
- script.onload( undefined, true );
8348
- }
8349
- }
8350
- };
8351
- }
8352
- });
8353
- var oldCallbacks = [],
8354
- rjsonp = /(=)\?(?=&|$)|\?\?/;
8355
-
8356
- // Default jsonp settings
8357
- jQuery.ajaxSetup({
8358
- jsonp: "callback",
8359
- jsonpCallback: function() {
8360
- var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
8361
- this[ callback ] = true;
8362
- return callback;
8363
- }
8364
- });
8365
-
8366
- // Detect, normalize options and install callbacks for jsonp requests
8367
- jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
8368
-
8369
- var callbackName, overwritten, responseContainer,
8370
- jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
8371
- "url" :
8372
- typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
8373
- );
8374
-
8375
- // Handle iff the expected data type is "jsonp" or we have a parameter to set
8376
- if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
8377
-
8378
- // Get callback name, remembering preexisting value associated with it
8379
- callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
8380
- s.jsonpCallback() :
8381
- s.jsonpCallback;
8382
-
8383
- // Insert callback into url or form data
8384
- if ( jsonProp ) {
8385
- s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
8386
- } else if ( s.jsonp !== false ) {
8387
- s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
8388
- }
8389
-
8390
- // Use data converter to retrieve json after script execution
8391
- s.converters["script json"] = function() {
8392
- if ( !responseContainer ) {
8393
- jQuery.error( callbackName + " was not called" );
8394
- }
8395
- return responseContainer[ 0 ];
8396
- };
8397
-
8398
- // force json dataType
8399
- s.dataTypes[ 0 ] = "json";
8400
-
8401
- // Install callback
8402
- overwritten = window[ callbackName ];
8403
- window[ callbackName ] = function() {
8404
- responseContainer = arguments;
8405
- };
8406
-
8407
- // Clean-up function (fires after converters)
8408
- jqXHR.always(function() {
8409
- // Restore preexisting value
8410
- window[ callbackName ] = overwritten;
8411
-
8412
- // Save back as free
8413
- if ( s[ callbackName ] ) {
8414
- // make sure that re-using the options doesn't screw things around
8415
- s.jsonpCallback = originalSettings.jsonpCallback;
8416
-
8417
- // save the callback name for future use
8418
- oldCallbacks.push( callbackName );
8419
- }
8420
-
8421
- // Call if it was a function and we have a response
8422
- if ( responseContainer && jQuery.isFunction( overwritten ) ) {
8423
- overwritten( responseContainer[ 0 ] );
8424
- }
8425
-
8426
- responseContainer = overwritten = undefined;
8427
- });
8428
-
8429
- // Delegate to script
8430
- return "script";
8431
- }
8432
- });
8433
- var xhrCallbacks, xhrSupported,
8434
- xhrId = 0,
8435
- // #5280: Internet Explorer will keep connections alive if we don't abort on unload
8436
- xhrOnUnloadAbort = window.ActiveXObject && function() {
8437
- // Abort all pending requests
8438
- var key;
8439
- for ( key in xhrCallbacks ) {
8440
- xhrCallbacks[ key ]( undefined, true );
8441
- }
8442
- };
8443
-
8444
- // Functions to create xhrs
8445
- function createStandardXHR() {
8446
- try {
8447
- return new window.XMLHttpRequest();
8448
- } catch( e ) {}
8449
- }
8450
-
8451
- function createActiveXHR() {
8452
- try {
8453
- return new window.ActiveXObject("Microsoft.XMLHTTP");
8454
- } catch( e ) {}
8455
- }
8456
-
8457
- // Create the request object
8458
- // (This is still attached to ajaxSettings for backward compatibility)
8459
- jQuery.ajaxSettings.xhr = window.ActiveXObject ?
8460
- /* Microsoft failed to properly
8461
- * implement the XMLHttpRequest in IE7 (can't request local files),
8462
- * so we use the ActiveXObject when it is available
8463
- * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
8464
- * we need a fallback.
8465
- */
8466
- function() {
8467
- return !this.isLocal && createStandardXHR() || createActiveXHR();
8468
- } :
8469
- // For all other browsers, use the standard XMLHttpRequest object
8470
- createStandardXHR;
8471
-
8472
- // Determine support properties
8473
- xhrSupported = jQuery.ajaxSettings.xhr();
8474
- jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
8475
- xhrSupported = jQuery.support.ajax = !!xhrSupported;
8476
-
8477
- // Create transport if the browser can provide an xhr
8478
- if ( xhrSupported ) {
8479
-
8480
- jQuery.ajaxTransport(function( s ) {
8481
- // Cross domain only allowed if supported through XMLHttpRequest
8482
- if ( !s.crossDomain || jQuery.support.cors ) {
8483
-
8484
- var callback;
8485
-
8486
- return {
8487
- send: function( headers, complete ) {
8488
-
8489
- // Get a new xhr
8490
- var handle, i,
8491
- xhr = s.xhr();
8492
-
8493
- // Open the socket
8494
- // Passing null username, generates a login popup on Opera (#2865)
8495
- if ( s.username ) {
8496
- xhr.open( s.type, s.url, s.async, s.username, s.password );
8497
- } else {
8498
- xhr.open( s.type, s.url, s.async );
8499
- }
8500
-
8501
- // Apply custom fields if provided
8502
- if ( s.xhrFields ) {
8503
- for ( i in s.xhrFields ) {
8504
- xhr[ i ] = s.xhrFields[ i ];
8505
- }
8506
- }
8507
-
8508
- // Override mime type if needed
8509
- if ( s.mimeType && xhr.overrideMimeType ) {
8510
- xhr.overrideMimeType( s.mimeType );
8511
- }
8512
-
8513
- // X-Requested-With header
8514
- // For cross-domain requests, seeing as conditions for a preflight are
8515
- // akin to a jigsaw puzzle, we simply never set it to be sure.
8516
- // (it can always be set on a per-request basis or even using ajaxSetup)
8517
- // For same-domain requests, won't change header if already provided.
8518
- if ( !s.crossDomain && !headers["X-Requested-With"] ) {
8519
- headers["X-Requested-With"] = "XMLHttpRequest";
8520
- }
8521
-
8522
- // Need an extra try/catch for cross domain requests in Firefox 3
8523
- try {
8524
- for ( i in headers ) {
8525
- xhr.setRequestHeader( i, headers[ i ] );
8526
- }
8527
- } catch( err ) {}
8528
-
8529
- // Do send the request
8530
- // This may raise an exception which is actually
8531
- // handled in jQuery.ajax (so no try/catch here)
8532
- xhr.send( ( s.hasContent && s.data ) || null );
8533
-
8534
- // Listener
8535
- callback = function( _, isAbort ) {
8536
- var status, responseHeaders, statusText, responses;
8537
-
8538
- // Firefox throws exceptions when accessing properties
8539
- // of an xhr when a network error occurred
8540
- // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
8541
- try {
8542
-
8543
- // Was never called and is aborted or complete
8544
- if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
8545
-
8546
- // Only called once
8547
- callback = undefined;
8548
-
8549
- // Do not keep as active anymore
8550
- if ( handle ) {
8551
- xhr.onreadystatechange = jQuery.noop;
8552
- if ( xhrOnUnloadAbort ) {
8553
- delete xhrCallbacks[ handle ];
8554
- }
8555
- }
8556
-
8557
- // If it's an abort
8558
- if ( isAbort ) {
8559
- // Abort it manually if needed
8560
- if ( xhr.readyState !== 4 ) {
8561
- xhr.abort();
8562
- }
8563
- } else {
8564
- responses = {};
8565
- status = xhr.status;
8566
- responseHeaders = xhr.getAllResponseHeaders();
8567
-
8568
- // When requesting binary data, IE6-9 will throw an exception
8569
- // on any attempt to access responseText (#11426)
8570
- if ( typeof xhr.responseText === "string" ) {
8571
- responses.text = xhr.responseText;
8572
- }
8573
-
8574
- // Firefox throws an exception when accessing
8575
- // statusText for faulty cross-domain requests
8576
- try {
8577
- statusText = xhr.statusText;
8578
- } catch( e ) {
8579
- // We normalize with Webkit giving an empty statusText
8580
- statusText = "";
8581
- }
8582
-
8583
- // Filter status for non standard behaviors
8584
-
8585
- // If the request is local and we have data: assume a success
8586
- // (success with no data won't get notified, that's the best we
8587
- // can do given current implementations)
8588
- if ( !status && s.isLocal && !s.crossDomain ) {
8589
- status = responses.text ? 200 : 404;
8590
- // IE - #1450: sometimes returns 1223 when it should be 204
8591
- } else if ( status === 1223 ) {
8592
- status = 204;
8593
- }
8594
- }
8595
- }
8596
- } catch( firefoxAccessException ) {
8597
- if ( !isAbort ) {
8598
- complete( -1, firefoxAccessException );
8599
- }
8600
- }
8601
-
8602
- // Call complete if needed
8603
- if ( responses ) {
8604
- complete( status, statusText, responses, responseHeaders );
8605
- }
8606
- };
8607
-
8608
- if ( !s.async ) {
8609
- // if we're in sync mode we fire the callback
8610
- callback();
8611
- } else if ( xhr.readyState === 4 ) {
8612
- // (IE6 & IE7) if it's in cache and has been
8613
- // retrieved directly we need to fire the callback
8614
- setTimeout( callback );
8615
- } else {
8616
- handle = ++xhrId;
8617
- if ( xhrOnUnloadAbort ) {
8618
- // Create the active xhrs callbacks list if needed
8619
- // and attach the unload handler
8620
- if ( !xhrCallbacks ) {
8621
- xhrCallbacks = {};
8622
- jQuery( window ).unload( xhrOnUnloadAbort );
8623
- }
8624
- // Add to list of active xhrs callbacks
8625
- xhrCallbacks[ handle ] = callback;
8626
- }
8627
- xhr.onreadystatechange = callback;
8628
- }
8629
- },
8630
-
8631
- abort: function() {
8632
- if ( callback ) {
8633
- callback( undefined, true );
8634
- }
8635
- }
8636
- };
8637
- }
8638
- });
8639
- }
8640
- var fxNow, timerId,
8641
- rfxtypes = /^(?:toggle|show|hide)$/,
8642
- rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
8643
- rrun = /queueHooks$/,
8644
- animationPrefilters = [ defaultPrefilter ],
8645
- tweeners = {
8646
- "*": [function( prop, value ) {
8647
- var end, unit,
8648
- tween = this.createTween( prop, value ),
8649
- parts = rfxnum.exec( value ),
8650
- target = tween.cur(),
8651
- start = +target || 0,
8652
- scale = 1,
8653
- maxIterations = 20;
8654
-
8655
- if ( parts ) {
8656
- end = +parts[2];
8657
- unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
8658
-
8659
- // We need to compute starting value
8660
- if ( unit !== "px" && start ) {
8661
- // Iteratively approximate from a nonzero starting point
8662
- // Prefer the current property, because this process will be trivial if it uses the same units
8663
- // Fallback to end or a simple constant
8664
- start = jQuery.css( tween.elem, prop, true ) || end || 1;
8665
-
8666
- do {
8667
- // If previous iteration zeroed out, double until we get *something*
8668
- // Use a string for doubling factor so we don't accidentally see scale as unchanged below
8669
- scale = scale || ".5";
8670
-
8671
- // Adjust and apply
8672
- start = start / scale;
8673
- jQuery.style( tween.elem, prop, start + unit );
8674
-
8675
- // Update scale, tolerating zero or NaN from tween.cur()
8676
- // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
8677
- } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
8678
- }
8679
-
8680
- tween.unit = unit;
8681
- tween.start = start;
8682
- // If a +=/-= token was provided, we're doing a relative animation
8683
- tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
8684
- }
8685
- return tween;
8686
- }]
8687
- };
8688
-
8689
- // Animations created synchronously will run synchronously
8690
- function createFxNow() {
8691
- setTimeout(function() {
8692
- fxNow = undefined;
8693
- });
8694
- return ( fxNow = jQuery.now() );
8695
- }
8696
-
8697
- function createTweens( animation, props ) {
8698
- jQuery.each( props, function( prop, value ) {
8699
- var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
8700
- index = 0,
8701
- length = collection.length;
8702
- for ( ; index < length; index++ ) {
8703
- if ( collection[ index ].call( animation, prop, value ) ) {
8704
-
8705
- // we're done with this property
8706
- return;
8707
- }
8708
- }
8709
- });
8710
- }
8711
-
8712
- function Animation( elem, properties, options ) {
8713
- var result,
8714
- stopped,
8715
- index = 0,
8716
- length = animationPrefilters.length,
8717
- deferred = jQuery.Deferred().always( function() {
8718
- // don't match elem in the :animated selector
8719
- delete tick.elem;
8720
- }),
8721
- tick = function() {
8722
- if ( stopped ) {
8723
- return false;
8724
- }
8725
- var currentTime = fxNow || createFxNow(),
8726
- remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
8727
- // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
8728
- temp = remaining / animation.duration || 0,
8729
- percent = 1 - temp,
8730
- index = 0,
8731
- length = animation.tweens.length;
8732
-
8733
- for ( ; index < length ; index++ ) {
8734
- animation.tweens[ index ].run( percent );
8735
- }
8736
-
8737
- deferred.notifyWith( elem, [ animation, percent, remaining ]);
8738
-
8739
- if ( percent < 1 && length ) {
8740
- return remaining;
8741
- } else {
8742
- deferred.resolveWith( elem, [ animation ] );
8743
- return false;
8744
- }
8745
- },
8746
- animation = deferred.promise({
8747
- elem: elem,
8748
- props: jQuery.extend( {}, properties ),
8749
- opts: jQuery.extend( true, { specialEasing: {} }, options ),
8750
- originalProperties: properties,
8751
- originalOptions: options,
8752
- startTime: fxNow || createFxNow(),
8753
- duration: options.duration,
8754
- tweens: [],
8755
- createTween: function( prop, end ) {
8756
- var tween = jQuery.Tween( elem, animation.opts, prop, end,
8757
- animation.opts.specialEasing[ prop ] || animation.opts.easing );
8758
- animation.tweens.push( tween );
8759
- return tween;
8760
- },
8761
- stop: function( gotoEnd ) {
8762
- var index = 0,
8763
- // if we are going to the end, we want to run all the tweens
8764
- // otherwise we skip this part
8765
- length = gotoEnd ? animation.tweens.length : 0;
8766
- if ( stopped ) {
8767
- return this;
8768
- }
8769
- stopped = true;
8770
- for ( ; index < length ; index++ ) {
8771
- animation.tweens[ index ].run( 1 );
8772
- }
8773
-
8774
- // resolve when we played the last frame
8775
- // otherwise, reject
8776
- if ( gotoEnd ) {
8777
- deferred.resolveWith( elem, [ animation, gotoEnd ] );
8778
- } else {
8779
- deferred.rejectWith( elem, [ animation, gotoEnd ] );
8780
- }
8781
- return this;
8782
- }
8783
- }),
8784
- props = animation.props;
8785
-
8786
- propFilter( props, animation.opts.specialEasing );
8787
-
8788
- for ( ; index < length ; index++ ) {
8789
- result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
8790
- if ( result ) {
8791
- return result;
8792
- }
8793
- }
8794
-
8795
- createTweens( animation, props );
8796
-
8797
- if ( jQuery.isFunction( animation.opts.start ) ) {
8798
- animation.opts.start.call( elem, animation );
8799
- }
8800
-
8801
- jQuery.fx.timer(
8802
- jQuery.extend( tick, {
8803
- elem: elem,
8804
- anim: animation,
8805
- queue: animation.opts.queue
8806
- })
8807
- );
8808
-
8809
- // attach callbacks from options
8810
- return animation.progress( animation.opts.progress )
8811
- .done( animation.opts.done, animation.opts.complete )
8812
- .fail( animation.opts.fail )
8813
- .always( animation.opts.always );
8814
- }
8815
-
8816
- function propFilter( props, specialEasing ) {
8817
- var value, name, index, easing, hooks;
8818
-
8819
- // camelCase, specialEasing and expand cssHook pass
8820
- for ( index in props ) {
8821
- name = jQuery.camelCase( index );
8822
- easing = specialEasing[ name ];
8823
- value = props[ index ];
8824
- if ( jQuery.isArray( value ) ) {
8825
- easing = value[ 1 ];
8826
- value = props[ index ] = value[ 0 ];
8827
- }
8828
-
8829
- if ( index !== name ) {
8830
- props[ name ] = value;
8831
- delete props[ index ];
8832
- }
8833
-
8834
- hooks = jQuery.cssHooks[ name ];
8835
- if ( hooks && "expand" in hooks ) {
8836
- value = hooks.expand( value );
8837
- delete props[ name ];
8838
-
8839
- // not quite $.extend, this wont overwrite keys already present.
8840
- // also - reusing 'index' from above because we have the correct "name"
8841
- for ( index in value ) {
8842
- if ( !( index in props ) ) {
8843
- props[ index ] = value[ index ];
8844
- specialEasing[ index ] = easing;
8845
- }
8846
- }
8847
- } else {
8848
- specialEasing[ name ] = easing;
8849
- }
8850
- }
8851
- }
8852
-
8853
- jQuery.Animation = jQuery.extend( Animation, {
8854
-
8855
- tweener: function( props, callback ) {
8856
- if ( jQuery.isFunction( props ) ) {
8857
- callback = props;
8858
- props = [ "*" ];
8859
- } else {
8860
- props = props.split(" ");
8861
- }
8862
-
8863
- var prop,
8864
- index = 0,
8865
- length = props.length;
8866
-
8867
- for ( ; index < length ; index++ ) {
8868
- prop = props[ index ];
8869
- tweeners[ prop ] = tweeners[ prop ] || [];
8870
- tweeners[ prop ].unshift( callback );
8871
- }
8872
- },
8873
-
8874
- prefilter: function( callback, prepend ) {
8875
- if ( prepend ) {
8876
- animationPrefilters.unshift( callback );
8877
- } else {
8878
- animationPrefilters.push( callback );
8879
- }
8880
- }
8881
- });
8882
-
8883
- function defaultPrefilter( elem, props, opts ) {
8884
- /*jshint validthis:true */
8885
- var prop, index, length,
8886
- value, dataShow, toggle,
8887
- tween, hooks, oldfire,
8888
- anim = this,
8889
- style = elem.style,
8890
- orig = {},
8891
- handled = [],
8892
- hidden = elem.nodeType && isHidden( elem );
8893
-
8894
- // handle queue: false promises
8895
- if ( !opts.queue ) {
8896
- hooks = jQuery._queueHooks( elem, "fx" );
8897
- if ( hooks.unqueued == null ) {
8898
- hooks.unqueued = 0;
8899
- oldfire = hooks.empty.fire;
8900
- hooks.empty.fire = function() {
8901
- if ( !hooks.unqueued ) {
8902
- oldfire();
8903
- }
8904
- };
8905
- }
8906
- hooks.unqueued++;
8907
-
8908
- anim.always(function() {
8909
- // doing this makes sure that the complete handler will be called
8910
- // before this completes
8911
- anim.always(function() {
8912
- hooks.unqueued--;
8913
- if ( !jQuery.queue( elem, "fx" ).length ) {
8914
- hooks.empty.fire();
8915
- }
8916
- });
8917
- });
8918
- }
8919
-
8920
- // height/width overflow pass
8921
- if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
8922
- // Make sure that nothing sneaks out
8923
- // Record all 3 overflow attributes because IE does not
8924
- // change the overflow attribute when overflowX and
8925
- // overflowY are set to the same value
8926
- opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
8927
-
8928
- // Set display property to inline-block for height/width
8929
- // animations on inline elements that are having width/height animated
8930
- if ( jQuery.css( elem, "display" ) === "inline" &&
8931
- jQuery.css( elem, "float" ) === "none" ) {
8932
-
8933
- // inline-level elements accept inline-block;
8934
- // block-level elements need to be inline with layout
8935
- if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
8936
- style.display = "inline-block";
8937
-
8938
- } else {
8939
- style.zoom = 1;
8940
- }
8941
- }
8942
- }
8943
-
8944
- if ( opts.overflow ) {
8945
- style.overflow = "hidden";
8946
- if ( !jQuery.support.shrinkWrapBlocks ) {
8947
- anim.always(function() {
8948
- style.overflow = opts.overflow[ 0 ];
8949
- style.overflowX = opts.overflow[ 1 ];
8950
- style.overflowY = opts.overflow[ 2 ];
8951
- });
8952
- }
8953
- }
8954
-
8955
-
8956
- // show/hide pass
8957
- for ( index in props ) {
8958
- value = props[ index ];
8959
- if ( rfxtypes.exec( value ) ) {
8960
- delete props[ index ];
8961
- toggle = toggle || value === "toggle";
8962
- if ( value === ( hidden ? "hide" : "show" ) ) {
8963
- continue;
8964
- }
8965
- handled.push( index );
8966
- }
8967
- }
8968
-
8969
- length = handled.length;
8970
- if ( length ) {
8971
- dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
8972
- if ( "hidden" in dataShow ) {
8973
- hidden = dataShow.hidden;
8974
- }
8975
-
8976
- // store state if its toggle - enables .stop().toggle() to "reverse"
8977
- if ( toggle ) {
8978
- dataShow.hidden = !hidden;
8979
- }
8980
- if ( hidden ) {
8981
- jQuery( elem ).show();
8982
- } else {
8983
- anim.done(function() {
8984
- jQuery( elem ).hide();
8985
- });
8986
- }
8987
- anim.done(function() {
8988
- var prop;
8989
- jQuery._removeData( elem, "fxshow" );
8990
- for ( prop in orig ) {
8991
- jQuery.style( elem, prop, orig[ prop ] );
8992
- }
8993
- });
8994
- for ( index = 0 ; index < length ; index++ ) {
8995
- prop = handled[ index ];
8996
- tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
8997
- orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
8998
-
8999
- if ( !( prop in dataShow ) ) {
9000
- dataShow[ prop ] = tween.start;
9001
- if ( hidden ) {
9002
- tween.end = tween.start;
9003
- tween.start = prop === "width" || prop === "height" ? 1 : 0;
9004
- }
9005
- }
9006
- }
9007
- }
9008
- }
9009
-
9010
- function Tween( elem, options, prop, end, easing ) {
9011
- return new Tween.prototype.init( elem, options, prop, end, easing );
9012
- }
9013
- jQuery.Tween = Tween;
9014
-
9015
- Tween.prototype = {
9016
- constructor: Tween,
9017
- init: function( elem, options, prop, end, easing, unit ) {
9018
- this.elem = elem;
9019
- this.prop = prop;
9020
- this.easing = easing || "swing";
9021
- this.options = options;
9022
- this.start = this.now = this.cur();
9023
- this.end = end;
9024
- this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
9025
- },
9026
- cur: function() {
9027
- var hooks = Tween.propHooks[ this.prop ];
9028
-
9029
- return hooks && hooks.get ?
9030
- hooks.get( this ) :
9031
- Tween.propHooks._default.get( this );
9032
- },
9033
- run: function( percent ) {
9034
- var eased,
9035
- hooks = Tween.propHooks[ this.prop ];
9036
-
9037
- if ( this.options.duration ) {
9038
- this.pos = eased = jQuery.easing[ this.easing ](
9039
- percent, this.options.duration * percent, 0, 1, this.options.duration
9040
- );
9041
- } else {
9042
- this.pos = eased = percent;
9043
- }
9044
- this.now = ( this.end - this.start ) * eased + this.start;
9045
-
9046
- if ( this.options.step ) {
9047
- this.options.step.call( this.elem, this.now, this );
9048
- }
9049
-
9050
- if ( hooks && hooks.set ) {
9051
- hooks.set( this );
9052
- } else {
9053
- Tween.propHooks._default.set( this );
9054
- }
9055
- return this;
9056
- }
9057
- };
9058
-
9059
- Tween.prototype.init.prototype = Tween.prototype;
9060
-
9061
- Tween.propHooks = {
9062
- _default: {
9063
- get: function( tween ) {
9064
- var result;
9065
-
9066
- if ( tween.elem[ tween.prop ] != null &&
9067
- (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
9068
- return tween.elem[ tween.prop ];
9069
- }
9070
-
9071
- // passing an empty string as a 3rd parameter to .css will automatically
9072
- // attempt a parseFloat and fallback to a string if the parse fails
9073
- // so, simple values such as "10px" are parsed to Float.
9074
- // complex values such as "rotate(1rad)" are returned as is.
9075
- result = jQuery.css( tween.elem, tween.prop, "" );
9076
- // Empty strings, null, undefined and "auto" are converted to 0.
9077
- return !result || result === "auto" ? 0 : result;
9078
- },
9079
- set: function( tween ) {
9080
- // use step hook for back compat - use cssHook if its there - use .style if its
9081
- // available and use plain properties where available
9082
- if ( jQuery.fx.step[ tween.prop ] ) {
9083
- jQuery.fx.step[ tween.prop ]( tween );
9084
- } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
9085
- jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
9086
- } else {
9087
- tween.elem[ tween.prop ] = tween.now;
9088
- }
9089
- }
9090
- }
9091
- };
9092
-
9093
- // Remove in 2.0 - this supports IE8's panic based approach
9094
- // to setting things on disconnected nodes
9095
-
9096
- Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
9097
- set: function( tween ) {
9098
- if ( tween.elem.nodeType && tween.elem.parentNode ) {
9099
- tween.elem[ tween.prop ] = tween.now;
9100
- }
9101
- }
9102
- };
9103
-
9104
- jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
9105
- var cssFn = jQuery.fn[ name ];
9106
- jQuery.fn[ name ] = function( speed, easing, callback ) {
9107
- return speed == null || typeof speed === "boolean" ?
9108
- cssFn.apply( this, arguments ) :
9109
- this.animate( genFx( name, true ), speed, easing, callback );
9110
- };
9111
- });
9112
-
9113
- jQuery.fn.extend({
9114
- fadeTo: function( speed, to, easing, callback ) {
9115
-
9116
- // show any hidden elements after setting opacity to 0
9117
- return this.filter( isHidden ).css( "opacity", 0 ).show()
9118
-
9119
- // animate to the value specified
9120
- .end().animate({ opacity: to }, speed, easing, callback );
9121
- },
9122
- animate: function( prop, speed, easing, callback ) {
9123
- var empty = jQuery.isEmptyObject( prop ),
9124
- optall = jQuery.speed( speed, easing, callback ),
9125
- doAnimation = function() {
9126
- // Operate on a copy of prop so per-property easing won't be lost
9127
- var anim = Animation( this, jQuery.extend( {}, prop ), optall );
9128
- doAnimation.finish = function() {
9129
- anim.stop( true );
9130
- };
9131
- // Empty animations, or finishing resolves immediately
9132
- if ( empty || jQuery._data( this, "finish" ) ) {
9133
- anim.stop( true );
9134
- }
9135
- };
9136
- doAnimation.finish = doAnimation;
9137
-
9138
- return empty || optall.queue === false ?
9139
- this.each( doAnimation ) :
9140
- this.queue( optall.queue, doAnimation );
9141
- },
9142
- stop: function( type, clearQueue, gotoEnd ) {
9143
- var stopQueue = function( hooks ) {
9144
- var stop = hooks.stop;
9145
- delete hooks.stop;
9146
- stop( gotoEnd );
9147
- };
9148
-
9149
- if ( typeof type !== "string" ) {
9150
- gotoEnd = clearQueue;
9151
- clearQueue = type;
9152
- type = undefined;
9153
- }
9154
- if ( clearQueue && type !== false ) {
9155
- this.queue( type || "fx", [] );
9156
- }
9157
-
9158
- return this.each(function() {
9159
- var dequeue = true,
9160
- index = type != null && type + "queueHooks",
9161
- timers = jQuery.timers,
9162
- data = jQuery._data( this );
9163
-
9164
- if ( index ) {
9165
- if ( data[ index ] && data[ index ].stop ) {
9166
- stopQueue( data[ index ] );
9167
- }
9168
- } else {
9169
- for ( index in data ) {
9170
- if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
9171
- stopQueue( data[ index ] );
9172
- }
9173
- }
9174
- }
9175
-
9176
- for ( index = timers.length; index--; ) {
9177
- if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
9178
- timers[ index ].anim.stop( gotoEnd );
9179
- dequeue = false;
9180
- timers.splice( index, 1 );
9181
- }
9182
- }
9183
-
9184
- // start the next in the queue if the last step wasn't forced
9185
- // timers currently will call their complete callbacks, which will dequeue
9186
- // but only if they were gotoEnd
9187
- if ( dequeue || !gotoEnd ) {
9188
- jQuery.dequeue( this, type );
9189
- }
9190
- });
9191
- },
9192
- finish: function( type ) {
9193
- if ( type !== false ) {
9194
- type = type || "fx";
9195
- }
9196
- return this.each(function() {
9197
- var index,
9198
- data = jQuery._data( this ),
9199
- queue = data[ type + "queue" ],
9200
- hooks = data[ type + "queueHooks" ],
9201
- timers = jQuery.timers,
9202
- length = queue ? queue.length : 0;
9203
-
9204
- // enable finishing flag on private data
9205
- data.finish = true;
9206
-
9207
- // empty the queue first
9208
- jQuery.queue( this, type, [] );
9209
-
9210
- if ( hooks && hooks.cur && hooks.cur.finish ) {
9211
- hooks.cur.finish.call( this );
9212
- }
9213
-
9214
- // look for any active animations, and finish them
9215
- for ( index = timers.length; index--; ) {
9216
- if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
9217
- timers[ index ].anim.stop( true );
9218
- timers.splice( index, 1 );
9219
- }
9220
- }
9221
-
9222
- // look for any animations in the old queue and finish them
9223
- for ( index = 0; index < length; index++ ) {
9224
- if ( queue[ index ] && queue[ index ].finish ) {
9225
- queue[ index ].finish.call( this );
9226
- }
9227
- }
9228
-
9229
- // turn off finishing flag
9230
- delete data.finish;
9231
- });
9232
- }
9233
- });
9234
-
9235
- // Generate parameters to create a standard animation
9236
- function genFx( type, includeWidth ) {
9237
- var which,
9238
- attrs = { height: type },
9239
- i = 0;
9240
-
9241
- // if we include width, step value is 1 to do all cssExpand values,
9242
- // if we don't include width, step value is 2 to skip over Left and Right
9243
- includeWidth = includeWidth? 1 : 0;
9244
- for( ; i < 4 ; i += 2 - includeWidth ) {
9245
- which = cssExpand[ i ];
9246
- attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
9247
- }
9248
-
9249
- if ( includeWidth ) {
9250
- attrs.opacity = attrs.width = type;
9251
- }
9252
-
9253
- return attrs;
9254
- }
9255
-
9256
- // Generate shortcuts for custom animations
9257
- jQuery.each({
9258
- slideDown: genFx("show"),
9259
- slideUp: genFx("hide"),
9260
- slideToggle: genFx("toggle"),
9261
- fadeIn: { opacity: "show" },
9262
- fadeOut: { opacity: "hide" },
9263
- fadeToggle: { opacity: "toggle" }
9264
- }, function( name, props ) {
9265
- jQuery.fn[ name ] = function( speed, easing, callback ) {
9266
- return this.animate( props, speed, easing, callback );
9267
- };
9268
- });
9269
-
9270
- jQuery.speed = function( speed, easing, fn ) {
9271
- var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
9272
- complete: fn || !fn && easing ||
9273
- jQuery.isFunction( speed ) && speed,
9274
- duration: speed,
9275
- easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
9276
- };
9277
-
9278
- opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
9279
- opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
9280
-
9281
- // normalize opt.queue - true/undefined/null -> "fx"
9282
- if ( opt.queue == null || opt.queue === true ) {
9283
- opt.queue = "fx";
9284
- }
9285
-
9286
- // Queueing
9287
- opt.old = opt.complete;
9288
-
9289
- opt.complete = function() {
9290
- if ( jQuery.isFunction( opt.old ) ) {
9291
- opt.old.call( this );
9292
- }
9293
-
9294
- if ( opt.queue ) {
9295
- jQuery.dequeue( this, opt.queue );
9296
- }
9297
- };
9298
-
9299
- return opt;
9300
- };
9301
-
9302
- jQuery.easing = {
9303
- linear: function( p ) {
9304
- return p;
9305
- },
9306
- swing: function( p ) {
9307
- return 0.5 - Math.cos( p*Math.PI ) / 2;
9308
- }
9309
- };
9310
-
9311
- jQuery.timers = [];
9312
- jQuery.fx = Tween.prototype.init;
9313
- jQuery.fx.tick = function() {
9314
- var timer,
9315
- timers = jQuery.timers,
9316
- i = 0;
9317
-
9318
- fxNow = jQuery.now();
9319
-
9320
- for ( ; i < timers.length; i++ ) {
9321
- timer = timers[ i ];
9322
- // Checks the timer has not already been removed
9323
- if ( !timer() && timers[ i ] === timer ) {
9324
- timers.splice( i--, 1 );
9325
- }
9326
- }
9327
-
9328
- if ( !timers.length ) {
9329
- jQuery.fx.stop();
9330
- }
9331
- fxNow = undefined;
9332
- };
9333
-
9334
- jQuery.fx.timer = function( timer ) {
9335
- if ( timer() && jQuery.timers.push( timer ) ) {
9336
- jQuery.fx.start();
9337
- }
9338
- };
9339
-
9340
- jQuery.fx.interval = 13;
9341
-
9342
- jQuery.fx.start = function() {
9343
- if ( !timerId ) {
9344
- timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
9345
- }
9346
- };
9347
-
9348
- jQuery.fx.stop = function() {
9349
- clearInterval( timerId );
9350
- timerId = null;
9351
- };
9352
-
9353
- jQuery.fx.speeds = {
9354
- slow: 600,
9355
- fast: 200,
9356
- // Default speed
9357
- _default: 400
9358
- };
9359
-
9360
- // Back Compat <1.8 extension point
9361
- jQuery.fx.step = {};
9362
-
9363
- if ( jQuery.expr && jQuery.expr.filters ) {
9364
- jQuery.expr.filters.animated = function( elem ) {
9365
- return jQuery.grep(jQuery.timers, function( fn ) {
9366
- return elem === fn.elem;
9367
- }).length;
9368
- };
9369
- }
9370
- jQuery.fn.offset = function( options ) {
9371
- if ( arguments.length ) {
9372
- return options === undefined ?
9373
- this :
9374
- this.each(function( i ) {
9375
- jQuery.offset.setOffset( this, options, i );
9376
- });
9377
- }
9378
-
9379
- var docElem, win,
9380
- box = { top: 0, left: 0 },
9381
- elem = this[ 0 ],
9382
- doc = elem && elem.ownerDocument;
9383
-
9384
- if ( !doc ) {
9385
- return;
9386
- }
9387
-
9388
- docElem = doc.documentElement;
9389
-
9390
- // Make sure it's not a disconnected DOM node
9391
- if ( !jQuery.contains( docElem, elem ) ) {
9392
- return box;
9393
- }
9394
-
9395
- // If we don't have gBCR, just use 0,0 rather than error
9396
- // BlackBerry 5, iOS 3 (original iPhone)
9397
- if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
9398
- box = elem.getBoundingClientRect();
9399
- }
9400
- win = getWindow( doc );
9401
- return {
9402
- top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
9403
- left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
9404
- };
9405
- };
9406
-
9407
- jQuery.offset = {
9408
-
9409
- setOffset: function( elem, options, i ) {
9410
- var position = jQuery.css( elem, "position" );
9411
-
9412
- // set position first, in-case top/left are set even on static elem
9413
- if ( position === "static" ) {
9414
- elem.style.position = "relative";
9415
- }
9416
-
9417
- var curElem = jQuery( elem ),
9418
- curOffset = curElem.offset(),
9419
- curCSSTop = jQuery.css( elem, "top" ),
9420
- curCSSLeft = jQuery.css( elem, "left" ),
9421
- calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
9422
- props = {}, curPosition = {}, curTop, curLeft;
9423
-
9424
- // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
9425
- if ( calculatePosition ) {
9426
- curPosition = curElem.position();
9427
- curTop = curPosition.top;
9428
- curLeft = curPosition.left;
9429
- } else {
9430
- curTop = parseFloat( curCSSTop ) || 0;
9431
- curLeft = parseFloat( curCSSLeft ) || 0;
9432
- }
9433
-
9434
- if ( jQuery.isFunction( options ) ) {
9435
- options = options.call( elem, i, curOffset );
9436
- }
9437
-
9438
- if ( options.top != null ) {
9439
- props.top = ( options.top - curOffset.top ) + curTop;
9440
- }
9441
- if ( options.left != null ) {
9442
- props.left = ( options.left - curOffset.left ) + curLeft;
9443
- }
9444
-
9445
- if ( "using" in options ) {
9446
- options.using.call( elem, props );
9447
- } else {
9448
- curElem.css( props );
9449
- }
9450
- }
9451
- };
9452
-
9453
-
9454
- jQuery.fn.extend({
9455
-
9456
- position: function() {
9457
- if ( !this[ 0 ] ) {
9458
- return;
9459
- }
9460
-
9461
- var offsetParent, offset,
9462
- parentOffset = { top: 0, left: 0 },
9463
- elem = this[ 0 ];
9464
-
9465
- // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
9466
- if ( jQuery.css( elem, "position" ) === "fixed" ) {
9467
- // we assume that getBoundingClientRect is available when computed position is fixed
9468
- offset = elem.getBoundingClientRect();
9469
- } else {
9470
- // Get *real* offsetParent
9471
- offsetParent = this.offsetParent();
9472
-
9473
- // Get correct offsets
9474
- offset = this.offset();
9475
- if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
9476
- parentOffset = offsetParent.offset();
9477
- }
9478
-
9479
- // Add offsetParent borders
9480
- parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
9481
- parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
9482
- }
9483
-
9484
- // Subtract parent offsets and element margins
9485
- // note: when an element has margin: auto the offsetLeft and marginLeft
9486
- // are the same in Safari causing offset.left to incorrectly be 0
9487
- return {
9488
- top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
9489
- left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
9490
- };
9491
- },
9492
-
9493
- offsetParent: function() {
9494
- return this.map(function() {
9495
- var offsetParent = this.offsetParent || document.documentElement;
9496
- while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
9497
- offsetParent = offsetParent.offsetParent;
9498
- }
9499
- return offsetParent || document.documentElement;
9500
- });
9501
- }
9502
- });
9503
-
9504
-
9505
- // Create scrollLeft and scrollTop methods
9506
- jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
9507
- var top = /Y/.test( prop );
9508
-
9509
- jQuery.fn[ method ] = function( val ) {
9510
- return jQuery.access( this, function( elem, method, val ) {
9511
- var win = getWindow( elem );
9512
-
9513
- if ( val === undefined ) {
9514
- return win ? (prop in win) ? win[ prop ] :
9515
- win.document.documentElement[ method ] :
9516
- elem[ method ];
9517
- }
9518
-
9519
- if ( win ) {
9520
- win.scrollTo(
9521
- !top ? val : jQuery( win ).scrollLeft(),
9522
- top ? val : jQuery( win ).scrollTop()
9523
- );
9524
-
9525
- } else {
9526
- elem[ method ] = val;
9527
- }
9528
- }, method, val, arguments.length, null );
9529
- };
9530
- });
9531
-
9532
- function getWindow( elem ) {
9533
- return jQuery.isWindow( elem ) ?
9534
- elem :
9535
- elem.nodeType === 9 ?
9536
- elem.defaultView || elem.parentWindow :
9537
- false;
9538
- }
9539
- // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
9540
- jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
9541
- jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
9542
- // margin is only for outerHeight, outerWidth
9543
- jQuery.fn[ funcName ] = function( margin, value ) {
9544
- var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
9545
- extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
9546
-
9547
- return jQuery.access( this, function( elem, type, value ) {
9548
- var doc;
9549
-
9550
- if ( jQuery.isWindow( elem ) ) {
9551
- // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
9552
- // isn't a whole lot we can do. See pull request at this URL for discussion:
9553
- // https://github.com/jquery/jquery/pull/764
9554
- return elem.document.documentElement[ "client" + name ];
9555
- }
9556
-
9557
- // Get document width or height
9558
- if ( elem.nodeType === 9 ) {
9559
- doc = elem.documentElement;
9560
-
9561
- // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
9562
- // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
9563
- return Math.max(
9564
- elem.body[ "scroll" + name ], doc[ "scroll" + name ],
9565
- elem.body[ "offset" + name ], doc[ "offset" + name ],
9566
- doc[ "client" + name ]
9567
- );
9568
- }
9569
-
9570
- return value === undefined ?
9571
- // Get width or height on the element, requesting but not forcing parseFloat
9572
- jQuery.css( elem, type, extra ) :
9573
-
9574
- // Set width or height on the element
9575
- jQuery.style( elem, type, value, extra );
9576
- }, type, chainable ? margin : undefined, chainable, null );
9577
- };
9578
- });
9579
- });
9580
- // Limit scope pollution from any deprecated API
9581
- // (function() {
9582
-
9583
- // })();
9584
- // Expose jQuery to the global object
9585
- window.jQuery = window.$ = jQuery;
9586
-
9587
- // Expose jQuery as an AMD module, but only for AMD loaders that
9588
- // understand the issues with loading multiple versions of jQuery
9589
- // in a page that all might call define(). The loader will indicate
9590
- // they have special allowances for multiple jQuery versions by
9591
- // specifying define.amd.jQuery = true. Register as a named module,
9592
- // since jQuery can be concatenated with other files that may use define,
9593
- // but not use a proper concatenation script that understands anonymous
9594
- // AMD modules. A named AMD is safest and most robust way to register.
9595
- // Lowercase jquery is used because AMD module names are derived from
9596
- // file names, and jQuery is normally delivered in a lowercase file name.
9597
- // Do this after creating the global so that if an AMD module wants to call
9598
- // noConflict to hide this version of jQuery, it will work.
9599
- if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
9600
- define( "jquery", [], function () { return jQuery; } );
9601
- }
9602
-
9603
- })( window );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/iGlobal/jquery/jquery.noconflict.js DELETED
@@ -1 +0,0 @@
1
- var jQblvg = jQuery.noConflict();
 
package.xml CHANGED
@@ -1,14 +1,15 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Iglobal_Main</name>
4
- <version>1.1.1</version>
5
  <stability>stable</stability>
6
  <license>OSL</license>
7
  <channel>community</channel>
8
  <extends/>
9
- <summary>Fully Embedded iFrame Checkout and Improvements</summary>
10
  <description>International eCommerce Done Right&#xD;
11
  Thanks for checking out the iGlobal Stores extension for Magento Community Edition! This extension gives you access to the many features of iGlobal Stores services. For more information on this extension and iGlobal's services, please visit http://www.iglobalstores.com/magento&#xD;
 
12
  &#xD;
13
  Improved Global Conversion Rates - Direct international visitors to the iGlobal checkout to keep your conversion rates at their highest&#xD;
14
  &#xD;
@@ -18,7 +19,7 @@ Duty, Tax, VAT? Done. - Calculate customs, duties, taxes and VAT and let your cu
18
  &#xD;
19
  Your Shipping Carriers - Work with the shipping carriers of your choice, at your rates.&#xD;
20
  &#xD;
21
- Direct Shipping to the World- Ship directly from your warehouse to anywhere in the world with iGlobal Stores&amp;apos; easy print and ship technology. We&amp;apos;ll take care of the paperwork&#xD;
22
  &#xD;
23
  Their Currency - Show customers their order totals in their local currency, making the buying decision that much easier&#xD;
24
  &#xD;
@@ -27,16 +28,17 @@ Your Payment Processor or Ours - Use your own payment processor or leverage the
27
  Before You Install&#xD;
28
  The iGlobal Stores extension will have limited use for stores that are not set up with an iGlobal Stores account. In order to accept orders internationally through iGlobal Stores, please contact us at 1-800-942-0721, at www.iglobalstores.com or at info@iglobalstores.com.</description>
29
  <notes>New Features:&#xD;
30
- Fully Embedded Checkout Using iFrame&#xD;
31
- Magento Country Region Support&#xD;
32
- Reconciliation Improvements with Payment Transaction Id&#xD;
33
  Improvements:&#xD;
34
  Faster Speeds&#xD;
35
- iGlobal Stores Updated API Additions</notes>
36
- <authors><author><name>Matt Flamm</name><user>mattflamm</user><email>matt@iglobalstores.com</email></author><author><name>Judd Flamm</name><user>unkuser1</user><email>judd@iglobalstores.com</email></author><author><name>Dustin Dwyer</name><user>unkuser2</user><email>dustin@iglobalstores.com</email></author><author><name>David Meads</name><user>unkuser3</user><email>dave@iglobalstores.com</email></author></authors>
37
- <date>2015-07-08</date>
38
- <time>17:56:39</time>
39
- <contents><target name="mageetc"><dir name="modules"><file name="Iglobal_Stores.xml" hash="56839ad045b6a99f97564de63ebed700"/><file name="Iglobal_Ship.xml" hash="6d40f1c84e29bb7d8b70eadd77a03917"/><file name="Iglobal_Fee.xml" hash="205714b75c3b417343a6b25ecedf35c4"/></dir></target><target name="magecommunity"><dir name="Iglobal"><dir name="Fee"><dir name="Block"><dir name="Sales"><dir name="Order"><file name="Total.php" hash="8ca3334de405b0b7088584f5548bb47e"/></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="406a814f1216d736e8661a32c833a15e"/></dir><dir name="Model"><file name="Fee.php" hash="5a18c1da4f5f091d63051872a9dc0135"/><file name="Observer.php" hash="a9ec09a49108625f592f8ef00bcba842"/><dir name="Sales"><dir name="Order"><dir name="Total"><dir name="Creditmemo"><file name="Fee.php" hash="048c8a97de6d884d3b95e0345c1cb75a"/></dir><dir name="Invoice"><file name="Fee.php" hash="fc98218c9a421b95af9f5f0ca062e1d8"/></dir></dir></dir><dir name="Quote"><dir name="Address"><dir name="Total"><file name="Fee.php" hash="bc925a41535068fb0a94c57183dd2027"/></dir></dir></dir></dir></dir><dir name="etc"><file name="config.xml" hash="c7c42dd266a0cdb0b1c504dd66b920bc"/></dir><dir name="sql"><dir name="fee_setup"><file name="mysql4-install-0.1.0.php" hash="8327866f66c8bff7fcbb0305385a6f93"/></dir></dir></dir><dir name="Ship"><dir name="Block"><file name="Ship.php" hash="a802b4d42e72997ec4ab466dec75b743"/></dir><dir name="Helper"><file name="Data.php" hash="fe9f074c1cb74260fa134efa94eb67c9"/></dir><dir name="Model"><dir name="Carrier"><file name="Excellence.php" hash="1cf0b2e1716d3f726f4e974f02267b53"/></dir></dir><dir name="controllers"><file name="IndexController.php" hash="3355a75caf30f4ff96499da3d8a4102a"/></dir><dir name="etc"><file name="config.xml" hash="adecbc76332ffb4b0f8918d3166c655c"/><file name="system.xml" hash="fea6b2ed9b7fdf5748cb57e53fe1301b"/></dir></dir><dir name="Stores"><dir name="Block"><file name="Ajax.php" hash="5d288c6bc298db3bdc86adcdd036bdd6"/><file name="Cart.php" hash="2fd47fa1ca047bbc75383c2e35dd4bf2"/><file name="Includes.php" hash="8214ef5eae6a83e2909f8ebeee6ea1f7"/><file name="Link.php" hash="25edb29e24e086f0518a7ca4bed59f10"/></dir><dir name="Helper"><file name="Configoptions.php" hash="b129e55b21f845a20d6e7fdb3b532be3"/><file name="Data.php" hash="2d77637b08ac8e7dcb717d8e1571739a"/><file name="Url.php" hash="9ac6f1784835d3c4ac0f81dfe9a2eb1d"/></dir><dir name="Model"><file name="Configoptions.php" hash="56a5c17a3e71079ecf574fd4a0e69011"/><dir name="International"><file name="International.php" hash="b72f00d5bdd6bc2a2b918bb210b5c5b3"/></dir><file name="Observer.php" hash="a399f807657409c06e3463e53666eab3"/><dir name="Payment"><file name="Iglobal.php" hash="9ac8f8d81b8f8d547831ad6db8a1c7fc"/><file name="Iglobalcreditcard.php" hash="f2f5cf4507a128fadc95071951ca2a41"/><file name="Iglobalpaypal.php" hash="3a566289db82b177ce6b52ce205728f6"/></dir><dir name="Resource"><file name="Setup.php" hash="55ef50a78966b6b2bc3db268de5037ce"/></dir><dir name="Rest"><file name="Order.php" hash="7652ce755b605c3cf2ce18d6b1f0d884"/><file name="Region.php" hash="ec4b17694c839236b929e6c537e2e602"/></dir><dir name="Service"><file name="Quote.php" hash="bae0e5a710b9e3aa1427bb78a08fbfd8"/></dir></dir><dir name="controllers"><file name="AjaxController.php" hash="3169062e850efd55749ae8033676bf2d"/><file name="CheckoutController.php" hash="e953271910a1e3ca1469292ec8064e02"/><file name="InternationalController.php" hash="bcb5288ffed067019649cfca31e59356"/><file name="SuccessController.php" hash="6429a3ce3ce1253d3b3ceda13a24f264"/></dir><dir name="etc"><file name="adminhtml.xml" hash="187e2b5c1a92072af9f24ad832cbc371"/><file name="config.xml" hash="d1cbe95a4df7759244f34eb2bef2cfcd"/><file name="system.xml" hash="8f02c3ae7e3060b0006b288a030ce2a9"/></dir><dir name="sql"><dir name="iglobal_stores_setup"><file name="mysql4-install-0.1.0.php" hash="72c543090fe27608e582d22494b65d75"/><file name="mysql4-upgrade-0.1.0-0.1.1.php" hash="51e83dd266d7b232d42f03cac66350df"/><file name="mysql4-upgrade-0.1.1-0.1.2.php" hash="4dc024ad63d7a7ea20697ddef4b60a29"/><file name="mysql4-upgrade-0.1.2-0.1.3.php" hash="51e83dd266d7b232d42f03cac66350df"/><file name="mysql4-upgrade-0.1.3-1.0.0.php" hash="829b7c08d5bce22b5c1750a3d72e21ca"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="iglobal.xml" hash="d49680762997b0480aaaeae331dc4695"/><file name="fee.xml" hash="97d67fc83755f625dfe305748fca65b1"/></dir><dir name="template"><dir name="iglobal"><dir name="checkout"><dir name="cart"><dir name="item"><dir name="configure"><file name="updatecart.phtml" hash="9eaac8c650b6986db7c0a5005966c4ee"/></dir></dir></dir><dir name="onepage"><file name="link.phtml" hash="f0ded88a2ec21ccd130a82a49c4923d2"/></dir></dir><dir name="stores"><file name="cart.phtml" hash="26aad68cbe45247ece12d702f87da59b"/><file name="igcincludes.phtml" hash="3ae102c65bd8a80ebd80267263df69aa"/></dir></dir></dir></dir></dir></dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="iglobal.xml" hash="6df6f5f0aceab891d0cd13061a3b5e55"/><file name="fee.xml" hash="96955d111e2a9014d5dc3d18201ddddf"/></dir><dir name="template"><dir name="iglobal"><dir name="sales"><dir name="order"><dir name="view"><file name="info.phtml" hash="06280040dd9521efcd36c12779648108"/></dir></dir></dir></dir><dir name="fee"><dir name="sales"><dir name="order"><file name="refunded.phtml" hash="f4239d313366d75907a34b3342b35eb1"/><file name="total.phtml" hash="bbb080fb20415086d72719c1f1f613d4"/></dir></dir></dir></dir></dir></dir></dir></target><target name="mage"><dir name="js"><dir name="iGlobal"><file name="ig_welcome_mat_default.css" hash="f095c20844c8ee158b704be69d4dc2bf"/><file name="ig_welcome_mat_default.js" hash="84c466f2ff0142870be6937677cc77b9"/><file name="igc.cs.magento_default_ice.js" hash="45fe3cfd5f55e4a96132fa77c034bc33"/><dir name="jquery"><file name="jquery.js" hash="6903c661e9db496b11e737478528318f"/><file name="jquery.noconflict.js" hash="09bfdd3b964eb2b17b5d6caa1d20a607"/></dir></dir></dir></target></contents>
 
40
  <compatible/>
41
- <dependencies><required><php><min>5.0.0</min><max>7.0.0</max></php></required></dependencies>
42
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Iglobal_Main</name>
4
+ <version>1.2.0</version>
5
  <stability>stable</stability>
6
  <license>OSL</license>
7
  <channel>community</channel>
8
  <extends/>
9
+ <summary>Duties &amp; Fees Integrated into Tax and Improvements</summary>
10
  <description>International eCommerce Done Right&#xD;
11
  Thanks for checking out the iGlobal Stores extension for Magento Community Edition! This extension gives you access to the many features of iGlobal Stores services. For more information on this extension and iGlobal's services, please visit http://www.iglobalstores.com/magento&#xD;
12
+ &#xD;
13
  &#xD;
14
  Improved Global Conversion Rates - Direct international visitors to the iGlobal checkout to keep your conversion rates at their highest&#xD;
15
  &#xD;
19
  &#xD;
20
  Your Shipping Carriers - Work with the shipping carriers of your choice, at your rates.&#xD;
21
  &#xD;
22
+ Direct Shipping to the World- Ship directly from your warehouse to anywhere in the world with iGlobal Stores' easy print and ship technology. We'll take care of the paperwork&#xD;
23
  &#xD;
24
  Their Currency - Show customers their order totals in their local currency, making the buying decision that much easier&#xD;
25
  &#xD;
28
  Before You Install&#xD;
29
  The iGlobal Stores extension will have limited use for stores that are not set up with an iGlobal Stores account. In order to accept orders internationally through iGlobal Stores, please contact us at 1-800-942-0721, at www.iglobalstores.com or at info@iglobalstores.com.</description>
30
  <notes>New Features:&#xD;
31
+ Duty &amp; Fees Integrated into Tax&#xD;
32
+ Order email can be sent from the store&#xD;
33
+ &#xD;
34
  Improvements:&#xD;
35
  Faster Speeds&#xD;
36
+ Country Region Fixes&#xD;
37
+ iGlobal Stores Updated API</notes>
38
+ <authors><author><name>Matt Flamm</name><user>mattflamm</user><email>matt@iglobalstores.com</email></author></authors>
39
+ <date>2015-09-18</date>
40
+ <time>16:58:45</time>
41
+ <contents><target name="mageetc"><dir name="modules"><file name="Iglobal_Stores.xml" hash="56839ad045b6a99f97564de63ebed700"/><file name="Iglobal_Ship.xml" hash="6d40f1c84e29bb7d8b70eadd77a03917"/></dir></target><target name="magecommunity"><dir name="Iglobal"><dir name="Ship"><dir name="Block"><file name="Ship.php" hash="a802b4d42e72997ec4ab466dec75b743"/></dir><dir name="Helper"><file name="Data.php" hash="fe9f074c1cb74260fa134efa94eb67c9"/></dir><dir name="Model"><dir name="Carrier"><file name="Excellence.php" hash="1cf0b2e1716d3f726f4e974f02267b53"/></dir></dir><dir name="controllers"><file name="IndexController.php" hash="3355a75caf30f4ff96499da3d8a4102a"/></dir><dir name="etc"><file name="config.xml" hash="adecbc76332ffb4b0f8918d3166c655c"/><file name="system.xml" hash="fea6b2ed9b7fdf5748cb57e53fe1301b"/></dir></dir><dir name="Stores"><dir name="Block"><file name="Ajax.php" hash="5d288c6bc298db3bdc86adcdd036bdd6"/><file name="Cart.php" hash="2fd47fa1ca047bbc75383c2e35dd4bf2"/><file name="Includes.php" hash="8214ef5eae6a83e2909f8ebeee6ea1f7"/><file name="Link.php" hash="e3fa83ebece58a1c869ac8aa001536ec"/></dir><dir name="Helper"><file name="Configoptions.php" hash="b129e55b21f845a20d6e7fdb3b532be3"/><file name="Data.php" hash="2d77637b08ac8e7dcb717d8e1571739a"/><file name="Url.php" hash="54cfb785649216510e4e78668d2817f2"/></dir><dir name="Model"><file name="Configoptions.php" hash="56a5c17a3e71079ecf574fd4a0e69011"/><dir name="International"><file name="International.php" hash="07d4e7ea4815807789930ff2062c4c7e"/></dir><file name="Observer.php" hash="563b72dc39c27e9f483e8842951adb30"/><file name="Order.php" hash="f02ca892f7f5c8b5cbc4668dbfeb1dda"/><dir name="Payment"><file name="Iglobal.php" hash="9ac8f8d81b8f8d547831ad6db8a1c7fc"/><file name="Iglobalcreditcard.php" hash="f2f5cf4507a128fadc95071951ca2a41"/><file name="Iglobalpaypal.php" hash="3a566289db82b177ce6b52ce205728f6"/></dir><dir name="Resource"><file name="Setup.php" hash="55ef50a78966b6b2bc3db268de5037ce"/></dir><file name="Rest.php" hash="6b208a6c928c686b8ad97a9eb2d29123"/><dir name="Sales"><dir name="Quote"><dir name="Address"><dir name="Total"><file name="Fee.php" hash="433e135f082364766ca14e0f8694e741"/></dir></dir></dir></dir><dir name="Service"><file name="Quote.php" hash="bae0e5a710b9e3aa1427bb78a08fbfd8"/></dir></dir><dir name="controllers"><file name="AjaxController.php" hash="3169062e850efd55749ae8033676bf2d"/><file name="CheckoutController.php" hash="9e95d21cbdce7abac609e109cc39d553"/><file name="SuccessController.php" hash="4e5dbc1bf261cd9e536fb8cc6f4d4b87"/></dir><dir name="etc"><file name="adminhtml.xml" hash="187e2b5c1a92072af9f24ad832cbc371"/><file name="config.xml" hash="4f52d0e71c5566132d6f762d522d3918"/><file name="system.xml" hash="41142f308c4189f5b8cc17ab1730823b"/></dir><dir name="sql"><dir name="iglobal_stores_setup"><file name="mysql4-install-0.1.0.php" hash="72c543090fe27608e582d22494b65d75"/><file name="mysql4-upgrade-0.1.0-0.1.1.php" hash="51e83dd266d7b232d42f03cac66350df"/><file name="mysql4-upgrade-0.1.1-0.1.2.php" hash="4dc024ad63d7a7ea20697ddef4b60a29"/><file name="mysql4-upgrade-0.1.2-0.1.3.php" hash="51e83dd266d7b232d42f03cac66350df"/><file name="mysql4-upgrade-0.1.3-1.0.0.php" hash="829b7c08d5bce22b5c1750a3d72e21ca"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="iglobal.xml" hash="6df6f5f0aceab891d0cd13061a3b5e55"/></dir><dir name="template"><dir name="iglobal"><dir name="sales"><dir name="order"><dir name="view"><file name="info.phtml" hash="06280040dd9521efcd36c12779648108"/></dir></dir></dir></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="iglobal.xml" hash="d49680762997b0480aaaeae331dc4695"/></dir><dir name="template"><dir name="iglobal"><dir name="checkout"><dir name="cart"><dir name="item"><dir name="configure"><file name="updatecart.phtml" hash="9eaac8c650b6986db7c0a5005966c4ee"/></dir></dir></dir><dir name="onepage"><file name="link.phtml" hash="bd5b7d66b63808ea0ca2a2abe8558bbc"/></dir></dir><dir name="stores"><file name="cart.phtml" hash="85e0a8608aee18536007218f2dae5e6c"/><file name="igcincludes.phtml" hash="3ae102c65bd8a80ebd80267263df69aa"/></dir></dir></dir></dir></dir></dir></target></contents>
42
  <compatible/>
43
+ <dependencies><required><php><min>5.0.0</min><max>7.0.7</max></php></required></dependencies>
44
  </package>