Qsolutions_Magemlm - Version 0.1.4

Version Notes

First public release

Download this release

Release Info

Developer Qsolutions Studio
Extension Qsolutions_Magemlm
Version 0.1.4
Comparing to
See all releases


Version 0.1.4

Files changed (63) hide show
  1. app/code/community/Qsolutions/Magemlm/Block/Adminhtml/Commissions.php +25 -0
  2. app/code/community/Qsolutions/Magemlm/Block/Adminhtml/Customer/Edit/Tab/Magemlm.php +87 -0
  3. app/code/community/Qsolutions/Magemlm/Block/Adminhtml/Magemlm/Structure.php +18 -0
  4. app/code/community/Qsolutions/Magemlm/Block/Adminhtml/Unilevel.php +22 -0
  5. app/code/community/Qsolutions/Magemlm/Block/Adminhtml/Unilevel/Edit.php +43 -0
  6. app/code/community/Qsolutions/Magemlm/Block/Adminhtml/Unilevel/Edit/Form.php +55 -0
  7. app/code/community/Qsolutions/Magemlm/Block/Customer/Commissions.php +21 -0
  8. app/code/community/Qsolutions/Magemlm/Block/Customer/Plan.php +21 -0
  9. app/code/community/Qsolutions/Magemlm/Block/Customer/Profile.php +21 -0
  10. app/code/community/Qsolutions/Magemlm/Block/Customer/Structure.php +21 -0
  11. app/code/community/Qsolutions/Magemlm/Block/Customer/Structure/Menu.php +23 -0
  12. app/code/community/Qsolutions/Magemlm/Helper/Data.php +169 -0
  13. app/code/community/Qsolutions/Magemlm/Model/Commissions.php +138 -0
  14. app/code/community/Qsolutions/Magemlm/Model/Customer.php +19 -0
  15. app/code/community/Qsolutions/Magemlm/Model/Observer.php +99 -0
  16. app/code/community/Qsolutions/Magemlm/Model/Referrallink.php +30 -0
  17. app/code/community/Qsolutions/Magemlm/Model/Resource/Commissions.php +21 -0
  18. app/code/community/Qsolutions/Magemlm/Model/Resource/Commissions.php._tmp_uploadphp +20 -0
  19. app/code/community/Qsolutions/Magemlm/Model/Resource/Commissions/Collection.php +22 -0
  20. app/code/community/Qsolutions/Magemlm/Model/Resource/Customer.php +21 -0
  21. app/code/community/Qsolutions/Magemlm/Model/Resource/Customer/Collection.php +21 -0
  22. app/code/community/Qsolutions/Magemlm/Model/Resource/Unilevel.php +20 -0
  23. app/code/community/Qsolutions/Magemlm/Model/Resource/Unilevel/Collection.php +22 -0
  24. app/code/community/Qsolutions/Magemlm/Model/Unilevel.php +19 -0
  25. app/code/community/Qsolutions/Magemlm/controllers/Adminhtml/CommissionController.php +40 -0
  26. app/code/community/Qsolutions/Magemlm/controllers/Adminhtml/CommissionsController.php +67 -0
  27. app/code/community/Qsolutions/Magemlm/controllers/Adminhtml/StructureController.php +42 -0
  28. app/code/community/Qsolutions/Magemlm/controllers/Adminhtml/UnilevelController.php +144 -0
  29. app/code/community/Qsolutions/Magemlm/controllers/CustomerController.php +53 -0
  30. app/code/community/Qsolutions/Magemlm/etc/config.xml +201 -0
  31. app/code/community/Qsolutions/Magemlm/sql/magemlm_setup/mysql4-install-0.1.0.php +16 -0
  32. app/code/community/Qsolutions/Magemlm/sql/magemlm_setup/mysql4-upgrade-0.1.0-0.1.1.php +17 -0
  33. app/code/community/Qsolutions/Magemlm/sql/magemlm_setup/mysql4-upgrade-0.1.1-0.1.2.php +28 -0
  34. app/code/community/Qsolutions/Magemlm/sql/magemlm_setup/mysql4-upgrade-0.1.2-0.1.3.php +27 -0
  35. app/code/community/Qsolutions/Magemlm/sql/magemlm_setup/mysql4-upgrade-0.1.3-0.1.4.php +31 -0
  36. app/design/adminhtml/default/default/layout/magemlm.xml +51 -0
  37. app/design/adminhtml/default/default/template/magemlm/commissions/view.phtml +128 -0
  38. app/design/adminhtml/default/default/template/magemlm/customer.phtml +97 -0
  39. app/design/adminhtml/default/default/template/magemlm/structure.phtml +68 -0
  40. app/design/adminhtml/default/default/template/magemlm/unilevel/edit.phtml +0 -0
  41. app/design/adminhtml/default/default/template/magemlm/unilevel/view.phtml +36 -0
  42. app/design/frontend/base/default/layout/magemlm.xml +70 -0
  43. app/design/frontend/base/default/template/magemlm/commissions.phtml +106 -0
  44. app/design/frontend/base/default/template/magemlm/plan.phtml +21 -0
  45. app/design/frontend/base/default/template/magemlm/profile.phtml +130 -0
  46. app/design/frontend/base/default/template/magemlm/structure.phtml +73 -0
  47. app/design/frontend/base/default/template/magemlm/structure/menu.phtml +32 -0
  48. app/design/frontend/base/default/template/magemlm/structure/page/structure.phtml +28 -0
  49. app/etc/modules/Qsolutions_Magemlm.xml +9 -0
  50. app/locale/pl_PL/Qsolutions_magemlm.csv +84 -0
  51. js/jquery/jquery-1.9.1.js +9690 -0
  52. js/jquery/jquery.jOrgChart.js +237 -0
  53. media/magemlm/female.png +0 -0
  54. media/magemlm/male.png +0 -0
  55. package.xml +18 -0
  56. skin/adminhtml/default/default/images/admin_magemlm_arrow.png +0 -0
  57. skin/adminhtml/default/default/images/admin_magemlm_delete.png +0 -0
  58. skin/adminhtml/default/default/images/admin_magemlm_edit.png +0 -0
  59. skin/adminhtml/default/default/magemlm.css +166 -0
  60. skin/frontend/base/default/css/magemlm.css +172 -0
  61. skin/frontend/base/default/images/magemlm/female.png +0 -0
  62. skin/frontend/base/default/images/magemlm/male.png +0 -0
  63. skin/frontend/base/default/images/magemlm_arrow.png +0 -0
app/code/community/Qsolutions/Magemlm/Block/Adminhtml/Commissions.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Block_Adminhtml_Commissions extends Mage_Adminhtml_Block_Template {
13
+
14
+ protected $_addButtonLabel = 'Create new Unilevel Compensation Plan';
15
+
16
+ /**
17
+ * Constructor. Set template.
18
+ */
19
+ public function __construct() {
20
+ parent::__construct();
21
+ $this->setTemplate('magemlm/commissions/view.phtml');
22
+ }
23
+
24
+ }
25
+
app/code/community/Qsolutions/Magemlm/Block/Adminhtml/Customer/Edit/Tab/Magemlm.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Block_Adminhtml_Customer_Edit_Tab_Magemlm
13
+ extends Mage_Adminhtml_Block_Template
14
+ implements Mage_Adminhtml_Block_Widget_Tab_Interface {
15
+
16
+
17
+ protected $_customer;
18
+
19
+
20
+ public function getCustomer()
21
+ {
22
+ if (!$this->_customer) {
23
+ $this->_customer = Mage::registry('current_customer');
24
+ }
25
+ return $this->_customer;
26
+ }
27
+
28
+
29
+ public function __construct()
30
+ {
31
+ parent::_construct();
32
+ $this->setTemplate('magemlm/customer.phtml');
33
+ }
34
+
35
+
36
+ /**
37
+ * Return Tab label
38
+ *
39
+ * @return string
40
+ */
41
+ public function getTabLabel()
42
+ {
43
+ return $this->__('Customer MLM Profile');
44
+ }
45
+
46
+ /**
47
+ * Return Tab title
48
+ *
49
+ * @return string
50
+ */
51
+ public function getTabTitle()
52
+ {
53
+ return $this->__('Customer MLM Profile');
54
+ }
55
+
56
+ /**
57
+ * Can show tab in tabs
58
+ *
59
+ * @return boolean
60
+ */
61
+ public function canShowTab()
62
+ {
63
+ return true;
64
+ }
65
+
66
+ /**
67
+ * Tab is hidden
68
+ *
69
+ * @return boolean
70
+ */
71
+ public function isHidden()
72
+ {
73
+ return false;
74
+ }
75
+
76
+ /**
77
+ * Defines after which tab, this tab should be rendered
78
+ *
79
+ * @return string
80
+ */
81
+ public function getAfter()
82
+ {
83
+ return 'tags';
84
+ }
85
+
86
+ }
87
+ ?>
app/code/community/Qsolutions/Magemlm/Block/Adminhtml/Magemlm/Structure.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Block_Adminhtml_Magemlm_Structure extends Mage_Adminhtml_Block_Template {
13
+
14
+ public function __construct() {
15
+ parent::__construct();
16
+
17
+ }
18
+ }
app/code/community/Qsolutions/Magemlm/Block/Adminhtml/Unilevel.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Block_Adminhtml_Unilevel extends Mage_Adminhtml_Block_Template {
13
+
14
+ protected $_addButtonLabel = 'Create new Unilevel Compensation Plan';
15
+
16
+ public function __construct() {
17
+ parent::__construct();
18
+ $this->setTemplate('magemlm/unilevel/view.phtml');
19
+ }
20
+
21
+ }
22
+
app/code/community/Qsolutions/Magemlm/Block/Adminhtml/Unilevel/Edit.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * To change this template, choose Tools | Templates
5
+ * and open the template in the editor.
6
+ */
7
+
8
+ class Qsolutions_Magemlm_Block_Adminhtml_Unilevel_Edit extends Mage_Adminhtml_Block_Widget_Form_Container
9
+ {
10
+ public function __construct()
11
+ {
12
+ parent::__construct();
13
+
14
+ $this->_objectId = 'unilevel_id';
15
+ $this->_blockGroup = 'magemlm';
16
+ $this->_controller = 'adminhtml_unilevel';
17
+ $this->_mode = 'edit';
18
+
19
+ $this->_updateButton('save', 'label', Mage::helper('magemlm')->__('Save Commission Level'));
20
+ }
21
+
22
+
23
+ public function getHeaderText()
24
+ {
25
+ if (Mage::registry('unilevel_data') && Mage::registry('unilevel_data')->getId())
26
+ {
27
+ return Mage::helper('magemlm')->__('You are editing commission level: %s' ,Mage::registry('unilevel_data')->getLevelName() );
28
+ } else {
29
+ return Mage::helper('magemlm')->__('New comission level');
30
+ }
31
+ // return '';
32
+ }
33
+
34
+
35
+ protected function _prepareLayout() {
36
+
37
+ if ($this->_blockGroup && $this->_controller && $this->_mode) {
38
+ $this->setChild('form', $this->getLayout()->createBlock($this->_blockGroup . '/' . $this->_controller . '_' . $this->_mode . '_form'));
39
+ }
40
+ return parent::_prepareLayout();
41
+ }
42
+
43
+ }
app/code/community/Qsolutions/Magemlm/Block/Adminhtml/Unilevel/Edit/Form.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Qsolutions_Magemlm_Block_Adminhtml_Unilevel_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
4
+ {
5
+ protected function _prepareForm()
6
+ {
7
+ if (Mage::getSingleton('adminhtml/session')->getUnilevelId())
8
+ {
9
+ $data = Mage::getSingleton('adminhtml/session')->getUnilevelId();
10
+ Mage::getSingleton('adminhtml/session')->getUnilevelId(null);
11
+ }
12
+ elseif (Mage::registry('unilevel_data'))
13
+ {
14
+ $data = Mage::registry('unilevel_data')->getData();
15
+ }
16
+ else
17
+ {
18
+ $data = array();
19
+ }
20
+
21
+ $form = new Varien_Data_Form(array(
22
+ 'id' => 'edit_form',
23
+ 'action' => $this->getUrl('*/*/save', array('id' => $this->getRequest()->getParam('id'))),
24
+ 'method' => 'post',
25
+ 'enctype' => 'multipart/form-data',
26
+ ));
27
+
28
+ $form->setUseContainer(true);
29
+ $this->setForm($form);
30
+
31
+ $fieldset = $form->addFieldset('s', array(
32
+ 'legend' => Mage::helper('magemlm')->__('Commission Level Settings')
33
+ ));
34
+
35
+ $fieldset->addField('level_name', 'text', array(
36
+ 'label' => Mage::helper('magemlm')->__('Level name'),
37
+ 'class' => 'required-entry',
38
+ 'required' => true,
39
+ 'name' => 'level_name',
40
+ 'note' => Mage::helper('magemlm')->__('System name of commission level. For administration purposes'),
41
+ ));
42
+
43
+ $fieldset->addField('level_commission', 'text', array(
44
+ 'label' => Mage::helper('magemlm')->__('Level Commission:'),
45
+ 'class' => 'required-entry validate-zero-or-greater',
46
+ 'required' => true,
47
+ 'name' => 'level_commission',
48
+ 'note' => Mage::helper('magemlm')->__('value in %.'),
49
+ ));
50
+
51
+ $form->setValues($data);
52
+
53
+ return parent::_prepareForm();
54
+ }
55
+ }
app/code/community/Qsolutions/Magemlm/Block/Customer/Commissions.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Block_Customer_Commissions extends Mage_Core_Block_Template {
13
+
14
+ /**
15
+ * Constructor. Set template.
16
+ */
17
+ public function __construct() {
18
+ parent::__construct();
19
+ $this->setTemplate("magemlm/commissions.phtml") ;
20
+ }
21
+ }
app/code/community/Qsolutions/Magemlm/Block/Customer/Plan.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Block_Customer_Plan extends Mage_Core_Block_Template {
13
+
14
+ /**
15
+ * Constructor. Set template.
16
+ */
17
+ public function __construct() {
18
+ parent::__construct();
19
+ $this->setTemplate("magemlm/plan.phtml") ;
20
+ }
21
+ }
app/code/community/Qsolutions/Magemlm/Block/Customer/Profile.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Block_Customer_Profile extends Mage_Core_Block_Template {
13
+
14
+ /**
15
+ * Constructor. Set template.
16
+ */
17
+ public function __construct() {
18
+ parent::__construct();
19
+ $this->setTemplate("magemlm/profile.phtml") ;
20
+ }
21
+ }
app/code/community/Qsolutions/Magemlm/Block/Customer/Structure.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Block_Customer_Structure extends Mage_Core_Block_Template {
13
+
14
+ /**
15
+ * Constructor. Set template.
16
+ */
17
+ public function __construct() {
18
+ parent::__construct();
19
+ $this->setTemplate('magemlm/structure.phtml');
20
+ }
21
+ }
app/code/community/Qsolutions/Magemlm/Block/Customer/Structure/Menu.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Block_Customer_Structure_Menu extends Mage_Core_Block_Template {
13
+
14
+ /**
15
+ * Constructor. Set template.
16
+ */
17
+ public function __construct() {
18
+ parent::__construct();
19
+
20
+ $this->setTemplate('magemlm/structure/menu.phtml');
21
+
22
+ }
23
+ }
app/code/community/Qsolutions/Magemlm/Helper/Data.php ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Helper_Data
13
+ extends Mage_Core_Helper_Abstract {
14
+
15
+
16
+ public $maxDepth = 0;
17
+
18
+
19
+ public function getCustomerName ($customerId) {
20
+ $customerModel = Mage::getModel('customer/customer')->load($customerId);
21
+ return $customerModel->getName();
22
+ }
23
+
24
+
25
+ public function getReferrerName ($customerId) {
26
+ $customer = Mage::getModel('magemlm/customer')->load($customerId , 'customer_id');
27
+ $referrer = $customer->getReferrerId();
28
+ return $this->getCustomerName($referrer);
29
+ }
30
+
31
+
32
+ public function getCustomerGender ($customerId) {
33
+ $customerModel = Mage::getModel('customer/customer')->load($customerId);
34
+ return $customerModel->getGender();
35
+ }
36
+
37
+
38
+ public function getCustomerImage ($custemerId) {
39
+ $customerMlmModel = Mage::getModel('magemlm/customer')->load($custemerId , 'customer_id');
40
+ return $customerMlmModel->getMagemlmImage();
41
+ }
42
+
43
+ public function compensationSum () {
44
+ $sum = 0;
45
+ $magemlmLevels = Mage::getModel('magemlm/unilevel') -> getCollection();
46
+ foreach ($magemlmLevels as $magemlmLevel) {
47
+ $sum += (double)$magemlmLevel->getLevelCommission();
48
+ }
49
+ return $sum;
50
+ }
51
+
52
+
53
+ public function getFirstOrderDate () {
54
+ $orderCollection = Mage::getModel('sales/order')->getCollection()->addAttributeToSort('created_at', 'ASC')->setPageSize(1);
55
+
56
+ if ($orderCollection->count()) {
57
+ foreach ($orderCollection as $order) {
58
+ return date('Y-m' , strtotime($order->getCreatedAt()));
59
+ exit;
60
+ }
61
+ } else {
62
+
63
+ }
64
+ }
65
+
66
+
67
+ public function getCustomerCreatedDate () {
68
+ return date('Y-m' , strtotime( Mage::getSingleton('customer/session')->getCustomer()->getCreatedAt()));
69
+ }
70
+
71
+
72
+ public function countMonths($start, $end) {
73
+ $startParsed = date_parse_from_format('Y-m', $start);
74
+ $startMonth = $startParsed['month'];
75
+ $startYear = $startParsed['year'];
76
+
77
+ $endParsed = date_parse_from_format('Y-m', $end);
78
+ $endMonth = $endParsed['month'];
79
+ $endYear = $endParsed['year'];
80
+
81
+ return ($endYear - $startYear) * 12 + ($endMonth - $startMonth) + 1;
82
+ }
83
+
84
+
85
+ public function getCustomerReferralId ($customerId) {
86
+ $customerMlmModel = Mage::getModel('magemlm/customer')->load($customerId , 'customer_id');
87
+ return $customerMlmModel->getReferrerId();
88
+ }
89
+
90
+
91
+ public function getCustomerLevel($customerId) {
92
+
93
+ Mage::helper('magemlm')->getCustomerReferralId($customerId);
94
+ $level = 0;
95
+
96
+ while (Mage::helper('magemlm')->getCustomerReferralId($customerId) || strpos($customerId , "store") ) {
97
+ $customerId = Mage::helper('magemlm')->getCustomerReferralId($customerId);
98
+
99
+ $pos = strpos($customerId, 'store');
100
+ if ($pos !== false) {
101
+ break ;
102
+ }
103
+ $level++;
104
+ }
105
+ // return customer level in system
106
+ return $level+1;
107
+ }
108
+
109
+ /**
110
+ * Checking if customer exists
111
+ *
112
+ * @return customerID or NULL
113
+ */
114
+ public function customerExists ($customerId) {
115
+ return Mage::getModel ('customer/customer')->load($customerId)->getId();
116
+ }
117
+
118
+
119
+ public function getFrontlineCount ($customerId) {
120
+ $customerMlmModel = Mage::getModel('magemlm/customer')->getCollection()->addFieldToFilter('referrer_id' , array ('eq' => $customerId));
121
+ return $customerMlmModel->count();
122
+ }
123
+
124
+
125
+ public function structureDepth ($customerId , $currentDepth = 1) {
126
+ $depth = 0;
127
+ $customerChilds = $this->_hasChildren($customerId);
128
+ if ($customerChilds) {
129
+ $collection = Mage::getModel('magemlm/customer')->getCollection()->addFieldToFilter('referrer_id', array('eq' => $customerId));
130
+ foreach ($collection as $customer) {
131
+ if (Mage::helper('magemlm')->customerExists($customer->getCustomerId())) {
132
+ $customerChilds = $this->_hasChildren($customer->getCustomerId());
133
+ $depth += $this->structureDepth($customer->getCustomerId() , $currentDepth+1);
134
+ if ($this->maxDepth < $currentDepth) {
135
+ $this->maxDepth = $currentDepth;
136
+ }
137
+ }
138
+ }
139
+ }
140
+ return $depth;
141
+ }
142
+
143
+
144
+ public function structureCount ($customerId) {
145
+ $count = 1;
146
+ $customerChilds = $this->_hasChildren($customerId);
147
+ if ($customerChilds) {
148
+ $collection = Mage::getModel('magemlm/customer')->getCollection()->addFieldToFilter('referrer_id', array('eq' => $customerId));
149
+ foreach ($collection as $customer) {
150
+ if (Mage::helper('magemlm')->customerExists($customer->getCustomerId())) {
151
+ $customerChilds = $this->_hasChildren($customer->getCustomerId());
152
+ $count += $this->structureCount($customer->getCustomerId());
153
+ }
154
+ }
155
+ } else {
156
+ $count = 1;
157
+ }
158
+
159
+ return $count;
160
+ }
161
+
162
+
163
+ protected function _hasChildren ($customerId) {
164
+ $customerMlmModel = Mage::getModel('magemlm/customer')->getCollection()->addFieldToFilter('referrer_id' , array ('eq' => $customerId));
165
+ return ($customerMlmModel->count() > 0 ? true : false);
166
+ }
167
+
168
+
169
+ }
app/code/community/Qsolutions/Magemlm/Model/Commissions.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Model_Commissions extends Mage_Core_Model_Abstract {
13
+
14
+ protected function _construct()
15
+ {
16
+ $this->_init('magemlm/commissions');
17
+ }
18
+
19
+
20
+
21
+ public function calculateCommissions ($customerId , $orderId, $orderSum) {
22
+ // get all commision levels in revert order
23
+ $uniLevelCommision = Mage::getModel('magemlm/unilevel')->getCollection()->setOrder('unilevel_id' , 'desc');
24
+ $customerStructure = Mage::getModel('magemlm/commissions')->getCustomerStructure($customerId); // get array of customers up to store view
25
+ $structureCount = count($customerStructure);
26
+ $commissionStructure = Mage::getModel('magemlm/commissions')->getCommissionStructure();
27
+
28
+ $i = 0 ;
29
+ foreach ($customerStructure as $customer) {
30
+ // check if there is commission for this level
31
+ if (isset($commissionStructure[$i])) {
32
+ $commissionValue = $orderSum * $commissionStructure[$i] / 100; // remeber we save commission levels in %
33
+
34
+ /// set data and save our commission - this is cool :-)
35
+ $commission = Mage::getModel('magemlm/commissions');
36
+ $commission ->setCustomerId($customer)
37
+ ->setOrderId ($orderId)
38
+ ->setCommissionValue ($commissionValue)
39
+ ->setCreatedAt(date('Y-m-d H:i:s'))
40
+ ->setCommissionLevel(Mage::helper('magemlm')->getCustomerLevel($customerId))
41
+ ->save();
42
+ } else {
43
+ break;
44
+ }
45
+ // go to next item
46
+ $i++;
47
+ }
48
+ }
49
+
50
+
51
+ /**
52
+ * getting customer structure
53
+ * @param customerId - customer id
54
+ * @return array of customer id's
55
+ */
56
+ public function getCustomerStructure($customerId) {
57
+
58
+ Mage::helper('magemlm')->getCustomerReferralId($customerId);
59
+ $customerArray = array ();
60
+
61
+ while (Mage::helper('magemlm')->getCustomerReferralId($customerId) || strpos($customerId , "store") ) {
62
+ $customerId = Mage::helper('magemlm')->getCustomerReferralId($customerId);
63
+
64
+ $pos = strpos($customerId, 'store');
65
+ if ($pos !== false) {
66
+ break ;
67
+ }
68
+ $customerArray[] = $customerId;
69
+ }
70
+ return $customerArray;
71
+ }
72
+
73
+
74
+ /**
75
+ * getting commission structure
76
+ * @return array of commission values
77
+ */
78
+ public function getCommissionStructure() {
79
+
80
+ $commissionArray = array ();
81
+ $uniLevelCommision = Mage::getModel ('magemlm/unilevel')->getCollection()->setOrder('unilevel_id' , 'asc');
82
+
83
+ foreach ($uniLevelCommision as $level) {
84
+ $commissionArray[] = $level->getLevelCommission();
85
+ }
86
+
87
+ return $commissionArray;
88
+ }
89
+
90
+
91
+ /**
92
+ * @return double - commission count
93
+ */
94
+ public function getCommissionSummary ($customerId) {
95
+ $resource = Mage::getSingleton('core/resource');
96
+ $readConnection = $resource->getConnection('core_read');
97
+ $query = 'select SUM(commission_value) as sum from magemlm_commissions where customer_id = "'. $customerId . '" ';
98
+ $result = $readConnection->fetchOne($query);
99
+ return $result;
100
+ }
101
+
102
+
103
+ public function calculateCommission ($yearMonth , $paid = 0) {
104
+ $resource = Mage::getSingleton('core/resource');
105
+ $readConnection = $resource->getConnection('core_read');
106
+ $query = ' select magemlm_commissions.customer_id as customer_id,
107
+ magemlm_commissions.created_at as created_at,
108
+ SUM(commission_value) as sum ,
109
+ CONCAT (
110
+ (select value from customer_entity_varchar where customer_entity_varchar.entity_id = magemlm_commissions.customer_id and attribute_id = 1 limit 1) , " " ,
111
+ (select value from customer_entity_varchar where customer_entity_varchar.entity_id = magemlm_commissions.customer_id and attribute_id = 2 limit 1)
112
+ ) as customerName ,
113
+ customer_entity.email as email,
114
+ commission_status
115
+ from magemlm_commissions
116
+ join customer_entity on customer_entity.entity_id = magemlm_commissions.customer_id
117
+ where magemlm_commissions.created_at like "' . $yearMonth . '%"
118
+ and magemlm_commissions.commission_status = "' . $paid . '"
119
+ group by customer_id; ';
120
+ $result = $readConnection->fetchAll($query);
121
+ return $result;
122
+ }
123
+
124
+
125
+ public function payCommissions ($customerIdArray , $yearMonth) {
126
+
127
+ foreach ($customerIdArray as $customerId) {
128
+ $resource = Mage::getSingleton('core/resource');
129
+ $writeConnection = $resource->getConnection('core_read');
130
+ $query = 'update magemlm_commissions
131
+ set magemlm_commissions.commission_status = "1"
132
+ where magemlm_commissions.customer_id = "' . $customerId . '"
133
+ and magemlm_commissions.created_at like "' . $yearMonth . '%"';
134
+ $writeConnection->query($query);
135
+ }
136
+ }
137
+
138
+ }
app/code/community/Qsolutions/Magemlm/Model/Customer.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Model_Customer extends Mage_Core_Model_Abstract {
13
+
14
+ protected function _construct()
15
+ {
16
+ $this->_init('magemlm/customer');
17
+ }
18
+
19
+ }
app/code/community/Qsolutions/Magemlm/Model/Observer.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Model_Observer {
13
+
14
+ public function __construct () {
15
+
16
+ } // public function __construct () {
17
+
18
+ public function getLink(Varien_Event_Observer $observer) {
19
+
20
+ if (isset ($_GET['refId']) ) {
21
+ $cookie = Mage::getSingleton('core/cookie');
22
+ $cookie->set('refId', $_GET['refId'] ,time()+86400,'/');
23
+ }
24
+ } // public function registerPartner($observer) {
25
+
26
+ public function saveCustomerMlmData(Varien_Event_Observer $observer) {
27
+
28
+ $customer = $observer->getEvent()->getCustomer();
29
+ $customerId = $customer->getId();
30
+ $referrerId = Mage::app()->getRequest()->getPost('magemlm_referrer');
31
+
32
+ // load magemlm / customer model
33
+ $customerMagemlm = Mage::getModel('magemlm/customer')->load($customerId , 'customer_id');
34
+
35
+ if(isset($_FILES['magemlm_customer_picture']['name']) and (file_exists($_FILES['magemlm_customer_picture']['tmp_name']))) {
36
+ try {
37
+
38
+ $ext = pathinfo($_FILES['magemlm_customer_picture']['name'], PATHINFO_EXTENSION);
39
+
40
+ $uploader = new Varien_File_Uploader('magemlm_customer_picture');
41
+ $uploader->setAllowedExtensions(array('jpg','jpeg','gif','png')); // or pdf or anything
42
+
43
+ $uploader->setAllowRenameFiles(false);
44
+ $uploader->setFilesDispersion(false);
45
+
46
+ $path = Mage::getBaseDir('media') . DS . 'magemlm' . DS;
47
+
48
+ $fileName = $customer->getId() . '_' . date('Ymdhis') . '.' . $ext;
49
+ $uploader->save($path, $fileName); // save file
50
+
51
+ $customerMagemlm->setCustomerId($customerId);
52
+ $customerMagemlm->setReffererId($referrerId);
53
+ $customerMagemlm->setMagemlmImage($fileName);
54
+ $customerMagemlm->save();
55
+
56
+ } catch(Exception $e) {
57
+ }
58
+ } else {
59
+ $customerMagemlm->setCustomerId($customerId);
60
+ $customerMagemlm->setReferrerId($referrerId);
61
+ $customerMagemlm->save();
62
+ }
63
+ }
64
+
65
+
66
+ public function registerCustomer (Varien_Event_Observer $observer) {
67
+
68
+ $customer = $observer->getEvent()->getCustomer();
69
+ $customerId = $customer->getId();
70
+ $referrerId = Mage::getSingleton('core/cookie')->get('refId');
71
+
72
+ $customerMagemlm = Mage::getModel('magemlm/customer')->load($customerId , 'customer_id');
73
+
74
+ $customerMagemlm->setCustomerId($customerId);
75
+ $customerMagemlm->setReferrerId($referrerId);
76
+ $customerMagemlm->save();
77
+ }
78
+
79
+
80
+
81
+
82
+ public function getCustomer() {
83
+ return Mage::registry('customer');
84
+ } // public function getCustomer() {
85
+
86
+
87
+ // observer function to get Compensation data
88
+ public function saveCompensation(Varien_Event_Observer $observer) {
89
+
90
+ $order = new Mage_Sales_Model_Order();
91
+ $orderId = Mage::getSingleton('checkout/session')->getLastRealOrderId();
92
+ $order->loadByIncrementId($orderId);
93
+
94
+ $orderPriceExldTax = $order->getBaseSubtotal(); // calculate commission for price WITHOUT TAX
95
+ Mage::getModel('magemlm/commissions')->calculateCommissions(Mage::helper('customer')->getCustomer()->getId() , $orderId, $orderPriceExldTax);
96
+
97
+ }
98
+
99
+ }
app/code/community/Qsolutions/Magemlm/Model/Referrallink.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Model_Referrallink extends Mage_Core_Model_Abstract {
13
+
14
+ protected function _construct()
15
+ {
16
+ $this->_init('magemlm/referrallink');
17
+ }
18
+
19
+
20
+ public function link ($customerId) {
21
+ return Mage::getBaseUrl() . '?refId=' . $customerId;
22
+ }
23
+
24
+
25
+ public function setLink ($link) {
26
+ Mage::getSingleton('core/session')->setLink($link);
27
+ }
28
+
29
+
30
+ }
app/code/community/Qsolutions/Magemlm/Model/Resource/Commissions.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Model_Resource_Commissions extends Mage_Core_Model_Resource_Db_Abstract {
13
+
14
+
15
+ protected function _construct()
16
+ {
17
+ $this->_init('magemlm/commissions' , 'commission_id');
18
+ }
19
+ }
20
+
21
+ ?>
app/code/community/Qsolutions/Magemlm/Model/Resource/Commissions.php._tmp_uploadphp ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Model_Resource_Commissions extends Mage_Core_Model_Resource_Db_Abstract {
13
+
14
+ protected function _construct()
15
+ {
16
+ $this->_init('magemlm/commissions' , 'commission_id');
17
+ }
18
+ }
19
+
20
+ ?>
app/code/community/Qsolutions/Magemlm/Model/Resource/Commissions/Collection.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Model_Resource_Commissions_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract {
13
+
14
+ public function _construct()
15
+ {
16
+ parent::_construct();
17
+ $this->_init('magemlm/commissions');
18
+ }
19
+
20
+ }
21
+
22
+ ?>
app/code/community/Qsolutions/Magemlm/Model/Resource/Customer.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Model_Resource_Customer extends Mage_Core_Model_Resource_Db_Abstract {
13
+ //put your code here
14
+
15
+ protected function _construct()
16
+ {
17
+ $this->_init('magemlm/customer' , 'magemlm_id');
18
+ }
19
+ }
20
+
21
+ ?>
app/code/community/Qsolutions/Magemlm/Model/Resource/Customer/Collection.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+ class Qsolutions_Magemlm_Model_Resource_Customer_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract {
12
+
13
+ public function _construct()
14
+ {
15
+ parent::_construct();
16
+ $this->_init('magemlm/customer');
17
+ }
18
+
19
+ }
20
+
21
+ ?>
app/code/community/Qsolutions/Magemlm/Model/Resource/Unilevel.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Model_Resource_Unilevel extends Mage_Core_Model_Resource_Db_Abstract {
13
+
14
+ protected function _construct()
15
+ {
16
+ $this->_init('magemlm/unilevel' , 'unilevel_id');
17
+ }
18
+ }
19
+
20
+ ?>
app/code/community/Qsolutions/Magemlm/Model/Resource/Unilevel/Collection.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Model_Resource_Unilevel_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract {
13
+
14
+ public function _construct()
15
+ {
16
+ parent::_construct();
17
+ $this->_init('magemlm/unilevel');
18
+ }
19
+
20
+ }
21
+
22
+ ?>
app/code/community/Qsolutions/Magemlm/Model/Unilevel.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Model_Unilevel extends Mage_Core_Model_Abstract {
13
+
14
+ protected function _construct()
15
+ {
16
+ $this->_init('magemlm/unilevel');
17
+ }
18
+
19
+ }
app/code/community/Qsolutions/Magemlm/controllers/Adminhtml/CommissionController.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * @category Qsolutions
5
+ * @package Magemlm
6
+ * @copyright Copyright (c) 2013 Qsolutions Studio
7
+ * @author Jakub Winkler
8
+ */
9
+
10
+ class Qsolutions_Magemlm_Adminhtml_CommissionController extends Mage_Adminhtml_Controller_Action {
11
+
12
+
13
+ protected function _prepareLayout()
14
+ {
15
+ return parent::_prepareLayout();
16
+ }
17
+
18
+
19
+ protected function _initAction()
20
+ {
21
+ $this->loadLayout()
22
+ ->_setActiveMenu('multilevel');
23
+ return $this;
24
+ }
25
+
26
+ public function indexAction()
27
+ {
28
+ $this->loadLayout();
29
+
30
+ $this->_initAction()
31
+ ->renderLayout();
32
+ }
33
+
34
+
35
+ protected function _isAllowed()
36
+ {
37
+ return true;
38
+ }
39
+
40
+ }
app/code/community/Qsolutions/Magemlm/controllers/Adminhtml/CommissionsController.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Adminhtml_CommissionsController extends Mage_Adminhtml_Controller_Action {
13
+
14
+
15
+ protected function _prepareLayout()
16
+ {
17
+ return parent::_prepareLayout();
18
+ }
19
+
20
+
21
+ protected function _initAction()
22
+ {
23
+ $this->loadLayout()
24
+ ->_setActiveMenu('multilevel');
25
+ return $this;
26
+ }
27
+
28
+ public function indexAction()
29
+ {
30
+ $this->loadLayout();
31
+ $msg = $this->_getSession()->getMessages(true);
32
+ $this->getLayout()->getMessagesBlock()->addMessages($msg);
33
+ $this->_initLayoutMessages('adminhtml/session')->renderLayout();
34
+ }
35
+
36
+
37
+ protected function _isAllowed()
38
+ {
39
+ return true;
40
+ }
41
+
42
+
43
+ public function payAction () {
44
+
45
+ if ($data = $this->getRequest()->getPost()) {
46
+ try {
47
+ // assign post data
48
+ $customerIds = $data['customerId'];
49
+ $yearMonth = $data['commissionDate'];
50
+ Mage::getModel('magemlm/commissions')->payCommissions($customerIds, $yearMonth);
51
+
52
+ $message = $this->__('Selected commissions were marked as paid');
53
+ Mage::getSingleton('adminhtml/session')->addSuccess($message);
54
+ $this->_redirect('*/*');
55
+
56
+ } catch (Exception $e) {
57
+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
58
+ $this->_initAction()
59
+ ->renderLayout();
60
+ return;
61
+ }
62
+ $this->_redirect('*/*');
63
+ }
64
+
65
+ }
66
+
67
+ }
app/code/community/Qsolutions/Magemlm/controllers/Adminhtml/StructureController.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Adminhtml_StructureController extends Mage_Adminhtml_Controller_Action {
13
+
14
+
15
+ protected function _prepareLayout()
16
+ {
17
+ return parent::_prepareLayout();
18
+ }
19
+
20
+
21
+ protected function _initAction()
22
+ {
23
+ $this->loadLayout()
24
+ ->_setActiveMenu('multilevel');
25
+ return $this;
26
+ }
27
+
28
+ public function indexAction()
29
+ {
30
+ $this->loadLayout();
31
+
32
+ $this->_initAction()
33
+ ->renderLayout();
34
+ }
35
+
36
+
37
+ protected function _isAllowed()
38
+ {
39
+ return true;
40
+ }
41
+
42
+ }
app/code/community/Qsolutions/Magemlm/controllers/Adminhtml/UnilevelController.php ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_Adminhtml_UnilevelController extends Mage_Adminhtml_Controller_Action {
13
+
14
+
15
+ protected function _prepareLayout()
16
+ {
17
+ return parent::_prepareLayout();
18
+ }
19
+
20
+
21
+ protected function _initAction()
22
+ {
23
+ $this->loadLayout()
24
+ ->_setActiveMenu('multilevel');
25
+ return $this;
26
+ }
27
+
28
+ public function indexAction()
29
+ {
30
+ $this->loadLayout();
31
+ $msg = $this->_getSession()->getMessages(true);
32
+ $this->getLayout()->getMessagesBlock()->addMessages($msg);
33
+ $this->_initLayoutMessages('adminhtml/session')->renderLayout();
34
+ }
35
+
36
+ public function editAction()
37
+ {
38
+ $id = $this->getRequest()->getParam('id', null);
39
+ $model = Mage::getModel('magemlm/unilevel');
40
+ if ($id) {
41
+ $model->load((int) $id);
42
+ if ($model->getId()) {
43
+ $data = Mage::getSingleton('adminhtml/session')->getFormData(true);
44
+ if ($data) {
45
+ $model->setData($data)->setId($id);
46
+ }
47
+ } else {
48
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('magemlm')->__('Level does not exists'));
49
+ $this->_redirect('*/*/');
50
+ }
51
+ }
52
+
53
+ Mage::register('unilevel_data', $model);
54
+ $this->loadLayout();
55
+ $this->_initAction()
56
+ ->renderLayout();
57
+ }
58
+
59
+
60
+ protected function _isAllowed()
61
+ {
62
+ return true;
63
+ }
64
+
65
+
66
+ public function deleteAction () {
67
+
68
+ $id = $this->getRequest()->getParam('id');
69
+ try {
70
+ if ($id) {
71
+ $model = Mage::getModel('magemlm/unilevel')->load($id , 'unilevel_id');
72
+ $model->delete();
73
+
74
+ $message = $this->__('Marketing level deleted');
75
+ Mage::getSingleton('adminhtml/session')->addSuccess($message);
76
+ $this->_redirect('*/*/');
77
+ return;
78
+ }
79
+
80
+ } catch (Exception $e) {
81
+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
82
+ if ($model && $model->getId()) {
83
+ $this->_redirect('*/*/edit', array('id' => $model->getId()));
84
+ } else {
85
+ $this->_redirect('*/*/');
86
+ }
87
+ return;
88
+ }
89
+
90
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('magemlm')->__('No data found to delete'));
91
+ $this->_redirect('*/*/');
92
+ }
93
+
94
+
95
+ public function saveAction () {
96
+ if ($data = $this->getRequest()->getPost())
97
+ {
98
+ $model = Mage::getModel('magemlm/unilevel');
99
+ $id = $this->getRequest()->getParam('id');
100
+ if ($id) {
101
+ $model->load($id , 'unilevel_id');
102
+ }
103
+ $model->setData($data);
104
+
105
+
106
+ Mage::getSingleton('adminhtml/session')->setFormData($data);
107
+ try {
108
+ if ($id) {
109
+ $model->setId($id);
110
+ }
111
+ $model->save();
112
+
113
+ if (!$model->getId()) {
114
+ Mage::throwException(Mage::helper('magemlm')->__('Data not found'));
115
+ }
116
+
117
+ $message = $this->__('Data saved');
118
+ Mage::getSingleton('adminhtml/session')->addSuccess($message);
119
+ Mage::getSingleton('adminhtml/session')->setFormData(false);
120
+
121
+ // The following line decides if it is a "save" or "save and continue"
122
+ if ($this->getRequest()->getParam('back')) {
123
+ $this->_redirect('*/*/edit', array('id' => $model->getId()));
124
+ } else {
125
+ $this->_redirect('*/*/');
126
+ }
127
+
128
+ } catch (Exception $e) {
129
+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
130
+ if ($model && $model->getId()) {
131
+ $this->_redirect('*/*/edit', array('id' => $model->getId()));
132
+ } else {
133
+ $this->_redirect('*/*/');
134
+ }
135
+ }
136
+
137
+ return;
138
+ }
139
+ Mage::getSingleton('adminhtml/session')->addError(Mage::helper('magemlm')->__('No data found to save'));
140
+ $this->_redirect('*/*/');
141
+ }
142
+
143
+
144
+ }
app/code/community/Qsolutions/Magemlm/controllers/CustomerController.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Magemlm
5
+ *
6
+ * @category Qsolutions
7
+ * @package Qsolutions_Magemlm
8
+ * @copyright Copyright (c) 2013 Q-Solutions (http://www.qsolutions.com.pl)
9
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
+ */
11
+
12
+ class Qsolutions_Magemlm_CustomerController extends Mage_Core_Controller_Front_Action {
13
+
14
+
15
+ protected function _prepareLayout()
16
+ {
17
+ return parent::_prepareLayout();
18
+ }
19
+
20
+
21
+ protected function _initAction()
22
+ {
23
+ $this->loadLayout();
24
+ return $this;
25
+ }
26
+
27
+ public function indexAction()
28
+ {
29
+ $this->_initAction()
30
+ ->renderLayout();
31
+ }
32
+
33
+ public function viewAction () {
34
+ $this->_initAction()
35
+ ->renderLayout();
36
+ }
37
+
38
+ public function configAction () {
39
+ $this->_initAction()
40
+ ->renderLayout();
41
+ }
42
+
43
+ public function commissionsAction () {
44
+ $this->_initAction()
45
+ ->renderLayout();
46
+ }
47
+
48
+ public function planAction () {
49
+ $this->_initAction()
50
+ ->renderLayout();
51
+ }
52
+
53
+ }
app/code/community/Qsolutions/Magemlm/etc/config.xml ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <config>
2
+ <modules>
3
+ <Qsolutions_Magemlm>
4
+ <version>0.1.4</version>
5
+ </Qsolutions_Magemlm>
6
+ </modules>
7
+
8
+ <global>
9
+ <!-- models -->
10
+ <models>
11
+ <magemlm>
12
+ <class>Qsolutions_Magemlm_Model</class>
13
+ <resourceModel>magemlm_resource</resourceModel>
14
+ </magemlm>
15
+
16
+ <magemlm_resource>
17
+ <class>Qsolutions_Magemlm_Model_Resource</class>
18
+ <entities>
19
+ <customer>
20
+ <table>magemlm_customers</table>
21
+ </customer>
22
+ <unilevel>
23
+ <table>magemlm_unilevel</table>
24
+ </unilevel>
25
+ <commissions>
26
+ <table>magemlm_commissions</table>
27
+ </commissions>
28
+ </entities>
29
+ </magemlm_resource>
30
+ </models>
31
+
32
+ <!-- block -->
33
+ <blocks>
34
+ <magemlm>
35
+ <class>Qsolutions_Magemlm_Block</class>
36
+ </magemlm>
37
+ </blocks>
38
+
39
+ <!-- helper -->
40
+ <helpers>
41
+ <magemlm>
42
+ <class>Qsolutions_Magemlm_Helper</class>
43
+ </magemlm>
44
+ </helpers>
45
+
46
+ <!-- resources -->
47
+ <resources>
48
+ <magemlm_setup>
49
+ <setup>
50
+ <module>Qsolutions_Magemlm</module>
51
+ <class>Mage_Eav_Model_Entity_Setup</class>
52
+ </setup>
53
+ <connection>
54
+ <use>core_setup</use>
55
+ </connection>
56
+ </magemlm_setup>
57
+ </resources>
58
+
59
+ <!-- observers -->
60
+ <events>
61
+ <customer_register_success>
62
+ <observers>
63
+ <magemlm_observer>
64
+ <class>magemlm/observer</class>
65
+ <method>registerCustomer</method>
66
+ </magemlm_observer>
67
+ </observers>
68
+ </customer_register_success>
69
+
70
+ <controller_front_init_before>
71
+ <observers>
72
+ <magemlm_observer>
73
+ <class>magemlm/observer</class>
74
+ <method>getLink</method>
75
+ </magemlm_observer>
76
+ </observers>
77
+ </controller_front_init_before>
78
+
79
+ <adminhtml_customer_save_after>
80
+ <observers>
81
+ <magemlm_observer_save_customer>
82
+ <type>singleton</type>
83
+ <class>Qsolutions_Magemlm_Model_Observer</class>
84
+ <method>saveCustomerMlmData</method>
85
+ </magemlm_observer_save_customer>
86
+ </observers>
87
+ </adminhtml_customer_save_after>
88
+
89
+ <checkout_onepage_controller_success_action>
90
+ <observers>
91
+ <magemlm_observer_compensation_plan>
92
+ <type>singleton</type>
93
+ <class>Qsolutions_Magemlm_Model_Observer</class>
94
+ <method>saveCompensation</method>
95
+ </magemlm_observer_compensation_plan>
96
+ </observers>
97
+ </checkout_onepage_controller_success_action>
98
+
99
+ </events>
100
+ </global>
101
+
102
+ <admin>
103
+ <routers>
104
+ <magemlm>
105
+ <use>admin</use>
106
+ <args>
107
+ <module>Qsolutions_Magemlm</module>
108
+ <frontName>magemlm</frontName>
109
+ </args>
110
+ </magemlm>
111
+ </routers>
112
+
113
+ <layout>
114
+ <updates>
115
+ <magemlm>
116
+ <file>magemlm.xml</file>
117
+ </magemlm>
118
+ </updates>
119
+ </layout>
120
+ </admin>
121
+
122
+ <frontend>
123
+ <!-- controllers -->
124
+ <routers>
125
+ <magemlm>
126
+ <use>standard</use>
127
+ <args>
128
+ <module>Qsolutions_Magemlm</module>
129
+ <frontName>magemlm</frontName>
130
+ </args>
131
+ </magemlm>
132
+ </routers>
133
+
134
+ <!-- layour update -->
135
+ <layout>
136
+ <updates>
137
+ <magemlm>
138
+ <file>magemlm.xml</file>
139
+ </magemlm>
140
+ </updates>
141
+ </layout>
142
+
143
+ <!-- frontend translation -->
144
+ <translate>
145
+ <modules>
146
+ <magemlm>
147
+ <files>
148
+ <default>Qsolutions_magemlm.csv</default>
149
+ </files>
150
+ </magemlm>
151
+ </modules>
152
+ </translate>
153
+ </frontend>
154
+
155
+ <adminhtml>
156
+ <!-- adminhtml translation -->
157
+ <translate>
158
+ <modules>
159
+ <magemlm>
160
+ <files>
161
+ <default>Qsolutions_magemlm.csv</default>
162
+ </files>
163
+ </magemlm>
164
+ </modules>
165
+ </translate>
166
+
167
+ <!-- admin menu -->
168
+ <menu>
169
+ <multilevel module="magemlm">
170
+ <title>Multilevel Settings</title>
171
+ <sort_order>100</sort_order>
172
+ <children>
173
+ <magemlm_unilevel translate="title" module="magemlm">
174
+ <sort_order>1</sort_order>
175
+ <title>Unilevel Commission Plan</title>
176
+ <action>magemlm/adminhtml_unilevel</action>
177
+ </magemlm_unilevel> -->
178
+ <magemlmstructure module="magemlm">
179
+ <sort_order>2</sort_order>
180
+ <action>magemlm/adminhtml_structure</action>
181
+ <title>Show Entire Structure</title>
182
+ </magemlmstructure>
183
+ <magemlm_report module="magemlm">
184
+ <sort_order>3</sort_order>
185
+ <action>magemlm/adminhtml_commissions</action>
186
+ <title>Commission Report</title>
187
+ </magemlm_report>
188
+ </children>
189
+ </multilevel>
190
+ </menu>
191
+ <!-- layout update -->
192
+ <layout>
193
+ <updates>
194
+ <magemlm>
195
+ <file>magemlm.xml</file>
196
+ </magemlm>
197
+ </updates>
198
+ </layout>
199
+
200
+ </adminhtml>
201
+ </config>
app/code/community/Qsolutions/Magemlm/sql/magemlm_setup/mysql4-install-0.1.0.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * @category Qsolutions
5
+ * @package Magemlm
6
+ * @copyright Copyright (c) 2013 Qsolutions Studio
7
+ * @author Jakub Winkler
8
+ */
9
+
10
+ $installer = $this;
11
+ $installer->startSetup();
12
+
13
+ $conn = $installer->getConnection();
14
+ $conn->addColumn($this->getTable('customer_entity'), 'referral_id', 'bigint unsigned not null');
15
+
16
+ $installer->endSetup();
app/code/community/Qsolutions/Magemlm/sql/magemlm_setup/mysql4-upgrade-0.1.0-0.1.1.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * @category Qsolutions
5
+ * @package Magemlm
6
+ * @copyright Copyright (c) 2013 Qsolutions Studio
7
+ * @author Jakub Winkler
8
+ */
9
+
10
+ $installer = $this;
11
+ $installer->startSetup();
12
+
13
+ $conn = $installer->getConnection();
14
+ $conn->addColumn($this->getTable('customer_entity'), 'magemlm_image', 'varchar(255) not null');
15
+
16
+
17
+ $installer->endSetup();
app/code/community/Qsolutions/Magemlm/sql/magemlm_setup/mysql4-upgrade-0.1.1-0.1.2.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * @category Qsolutions
5
+ * @package Magemlm
6
+ * @copyright Copyright (c) 2013 Qsolutions Studio
7
+ * @author Jakub Winkler
8
+ */
9
+
10
+ $installer = $this;
11
+ $installer->startSetup();
12
+
13
+
14
+ $installer->run("
15
+
16
+ DROP TABLE IF EXISTS {$this->getTable('magemlm_customers')};
17
+ CREATE TABLE {$this->getTable('magemlm_customers')} (
18
+ `magemlm_id` int(11) unsigned NOT NULL auto_increment,
19
+ `customer_id` int(11) NOT NULL ,
20
+ `referrer_id` varchar(255) NOT NULL ,
21
+ `magemlm_image` varchar(255) NOT NULL ,
22
+ PRIMARY KEY (`magemlm_id`)
23
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
24
+
25
+ ");
26
+
27
+
28
+ $installer->endSetup();
app/code/community/Qsolutions/Magemlm/sql/magemlm_setup/mysql4-upgrade-0.1.2-0.1.3.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * @category Qsolutions
5
+ * @package Magemlm
6
+ * @copyright Copyright (c) 2013 Qsolutions Studio
7
+ * @author Jakub Winkler
8
+ */
9
+
10
+ $installer = $this;
11
+ $installer->startSetup();
12
+
13
+
14
+ $installer->run("
15
+
16
+ DROP TABLE IF EXISTS {$this->getTable('magemlm_unilevel')};
17
+ CREATE TABLE {$this->getTable('magemlm_unilevel')} (
18
+ `unilevel_id` int(11) unsigned NOT NULL auto_increment,
19
+ `level_name` varchar(255) NOT NULL ,
20
+ `level_commission` varchar(255) NOT NULL ,
21
+ PRIMARY KEY (`unilevel_id`)
22
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
23
+
24
+ ");
25
+
26
+
27
+ $installer->endSetup();
app/code/community/Qsolutions/Magemlm/sql/magemlm_setup/mysql4-upgrade-0.1.3-0.1.4.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * @category Qsolutions
5
+ * @package Magemlm
6
+ * @copyright Copyright (c) 2013 Qsolutions Studio
7
+ * @author Jakub Winkler
8
+ */
9
+
10
+ $installer = $this;
11
+ $installer->startSetup();
12
+
13
+
14
+ $installer->run("
15
+
16
+ DROP TABLE IF EXISTS {$this->getTable('magemlm_commissions')};
17
+ CREATE TABLE {$this->getTable('magemlm_commissions')} (
18
+ `commission_id` int(11) unsigned NOT NULL auto_increment,
19
+ `customer_id` int(11) NOT NULL ,
20
+ `order_id` int(11) NOT NULL ,
21
+ `created_at` datetime NULL,
22
+ `commission_level` int(11),
23
+ `commission_value` decimal(12,4),
24
+ `commission_status` tinyint NOT NULL,
25
+ PRIMARY KEY (`commission_id`)
26
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
27
+
28
+ ");
29
+
30
+
31
+ $installer->endSetup();
app/design/adminhtml/default/default/layout/magemlm.xml ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout version="0.1.0">
3
+
4
+ <default>
5
+ <reference name="head">
6
+ <action method="addJs"><js>jquery/jquery-1.9.1.js</js></action>
7
+ <action method="addJs"><js>jquery/jquery.jOrgChart.js</js></action>
8
+ <action method="addCss"><css>magemlm.css</css></action>
9
+ </reference>
10
+ </default>
11
+
12
+ <adminhtml_customer_edit>
13
+ <reference name="customer_edit_tabs">
14
+ <action method="addTab">
15
+ <name>customer_edit_tab_magemlm</name>
16
+ <block>magemlm/adminhtml_customer_edit_tab_magemlm</block>
17
+ </action>
18
+ </reference>
19
+ </adminhtml_customer_edit>
20
+
21
+ <magemlm_adminhtml_structure_index>
22
+ <reference name="content">
23
+ <block type="magemlm/adminhtml_magemlm_structure" name="structure">
24
+ <action method="setTemplate">
25
+ <template>magemlm/structure.phtml</template>
26
+ </action>
27
+ </block>
28
+ </reference>
29
+ </magemlm_adminhtml_structure_index>
30
+
31
+ <magemlm_adminhtml_unilevel_index>
32
+ <reference name="content">
33
+ <block type="magemlm/adminhtml_unilevel" name="unilevel" as="unilevel" />
34
+ </reference>
35
+ </magemlm_adminhtml_unilevel_index>
36
+
37
+
38
+ <magemlm_adminhtml_unilevel_edit>
39
+ <reference name="content">
40
+ <block type="magemlm/adminhtml_unilevel_edit" name="unilevel.edit" as="unilevel.edit" />
41
+ </reference>
42
+ </magemlm_adminhtml_unilevel_edit>
43
+
44
+
45
+ <magemlm_adminhtml_commissions_index>
46
+ <reference name="content">
47
+ <block type="magemlm/adminhtml_commissions" name="commissions.view" as="commissions.view" />
48
+ </reference>
49
+ </magemlm_adminhtml_commissions_index>
50
+
51
+ </layout>
app/design/adminhtml/default/default/template/magemlm/commissions/view.phtml ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $controller = Mage::app()->getRequest()->getControllerName(); // get controller name - we do it so changes in config.xml wont reflect extension integrity
4
+ $action = Mage::app()->getRequest()->getActionName(); // same here - action
5
+ $router = Mage::app()->getRequest()->getRouteName(); // same here - router
6
+ $currentMonth = Mage::app()->getRequest()->getParam('month'); // get request month for option selecting
7
+ $firstOrderDate = Mage::helper('magemlm')->getFirstOrderDate(); // get first order ever created date
8
+ $monthCount = Mage::helper('magemlm')->countMonths($firstOrderDate, date('Y-m')); // count months - for reporting purposes
9
+ $dateUrl = Mage::helper("adminhtml") -> getUrl($router . DS . $controller . DS . $action); // get come controller action
10
+
11
+ // set current month, if not selected
12
+ if ($currentMonth == '') $currentMonth = date('Y-m');
13
+
14
+ $commissionsPaid = Mage::getModel('magemlm/commissions')->calculateCommission($currentMonth , 1);
15
+ $commissionsUnpaid = Mage::getModel('magemlm/commissions')->calculateCommission($currentMonth , 0);
16
+
17
+ ?>
18
+
19
+
20
+ <script>
21
+ function processPayment () {
22
+ var checkedCount = 0;
23
+ $$('.customerId').each(function(element){
24
+ if( $(element).checked )
25
+ {
26
+ checkedCount++;
27
+ }
28
+ });
29
+
30
+ if (checkedCount > 0) {
31
+ paymentForm.submit();
32
+ return true;
33
+ } else {
34
+ alert("Please select at least 1 customer");
35
+ return false;
36
+ }
37
+ };
38
+ </script>
39
+
40
+ <!-- commission month selector -->
41
+ <div style="float: right; width: 300px; text-align: right;"><?php echo $this->__('Select date for commission report:') ?>
42
+ <select onChange="setLocation(this.value);">
43
+ <?php for ($i = 0; $i < $monthCount ; $i++) : ?>
44
+ <?php
45
+ $time = strtotime($firstOrderDate);
46
+ $date = date("Y-m", strtotime("$i month", $time));
47
+ ?>
48
+ <option value="<?php echo $dateUrl . "month" . DS . $date ?>" <?php echo ($date == $currentMonth) ? 'selected' : '' ?>>
49
+ <?php echo $date ?>
50
+ </option>
51
+ <?php endfor ; ?>
52
+ </select>
53
+ </div>
54
+
55
+
56
+ <h3 class="icon-head head-sales-order"><?php echo $this->__('Commission report:')?> <?php echo $currentMonth; ?></h3>
57
+ <hr />
58
+
59
+ <p class="switcher"><label for="store_switcher"><?php echo $this->__('Unpaid Commissions for selected date:'); ?> <strong><?php echo $currentMonth ?></strong></label> </p>
60
+
61
+ <form id="payment_form" method="post" action="<?php echo $this->getUrl('*/*/pay')?>">
62
+ <input type="hidden" name="form_key" value="<?php echo Mage::getSingleton('core/session')->getFormKey(); ?>" />
63
+ <input type="hidden" name="commissionDate" value="<?php echo $currentMonth; ?>" />
64
+
65
+ <div class="grid" id="productListgrid" style="margin-top: -10px; margin-bottom: 20px; ">
66
+ <table cellspacing="0" id="gridProduct_table" class="data">
67
+ <colgroup>
68
+ <col width="1">
69
+ <col width="150">
70
+ <col width="150">
71
+ <col width="200">
72
+ </colgroup><thead>
73
+ <tr class="headings">
74
+ <th>&nbsp;</th>
75
+ <th class="no-link"><span class="no-br"><?php echo $this->__('Customer');?></span></th>
76
+ <th class="no-link"><span class="no-br"><?php echo $this->__('Customer email');?></span></th>
77
+ <th class="no-link a-right"><span class="no-br"><?php echo $this->__('Commission Value') ?></span></th>
78
+ </tr>
79
+ </thead>
80
+ <tbody id="tbodyList">
81
+ <?php $i = 1; foreach ($commissionsUnpaid as $commissionData) : ?>
82
+ <tr <?php echo ($i % 2 == 0 ? 'class="even"' : '') ?>>
83
+ <td><input type="checkbox" name="customerId[]" class="customerId" value="<?php echo $commissionData['customer_id']?>" ></td>
84
+ <td><?php echo $commissionData['customerName'] ?></td>
85
+ <td><?php echo $commissionData['email'] ?></td>
86
+ <td class="a-right"><?php echo Mage::helper('core')->currency($commissionData['sum'], true, false) ?></td>
87
+ </tr>
88
+ <?php $i++; ?>
89
+ <?php endforeach; ?>
90
+ </tbody>
91
+ </table>
92
+ </form>
93
+
94
+ <div style="text-align: right">
95
+ <button id="markPaid" onClick="return processPayment(); "><span><?php echo $this->__('Mark selected commissions as paid')?> </span></button>
96
+ </div>
97
+ </div>
98
+
99
+ <p class="switcher"><label for="store_switcher"><?php echo $this->__('Paid Commissions for selected date:')?> <strong><?php echo $currentMonth ?></strong></label> </p>
100
+ <div class="grid" id="productListgrid" style="margin-top: -10px;">
101
+ <table cellspacing="0" id="gridProduct_table" class="data">
102
+ <colgroup><col width="150">
103
+ <col width="150">
104
+ <col width="200">
105
+ </colgroup><thead>
106
+ <tr class="headings">
107
+ <th class="no-link"><span class="no-br"><?php echo $this->__('Customer');?></span></th>
108
+ <th class="no-link"><span class="no-br"><?php echo $this->__('Customer email');?></span></th>
109
+ <th class="no-link a-right"><span class="no-br"><?php echo $this->__('Commission Value') ?></span></th>
110
+ </tr>
111
+ </thead>
112
+ <tbody id="tbodyList">
113
+ <?php $i = 1; foreach ($commissionsPaid as $commissionData) : ?>
114
+ <tr <?php echo ($i % 2 == 0 ? 'class="even"' : '') ?>>
115
+ <td><?php echo $commissionData['customerName'] ?></td>
116
+ <td><?php echo $commissionData['email'] ?></td>
117
+ <td class="a-right"><?php echo Mage::helper('core')->currency($commissionData['sum'], true, false) ?></td>
118
+ </tr>
119
+ <?php $i++; ?>
120
+ <?php endforeach; ?>
121
+ </tbody>
122
+ </table>
123
+ </div>
124
+
125
+
126
+ <script type="text/javascript">
127
+ paymentForm = new varienForm('payment_form', '');
128
+ </script>
app/design/adminhtml/default/default/template/magemlm/customer.phtml ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $stores = Mage::getModel('core/store') -> getCollection() -> toOptionHash();
3
+ $customerId = $this->getCustomer()->getId();
4
+ $referralId = $this->getCustomer()->getReferralId();
5
+ $customerCollection = Mage::getModel('customer/customer')->getCollection()
6
+ ->addAttributeToSelect('*')
7
+ ->addFieldToFilter('entity_id', array('neq' => $customerId));
8
+
9
+ $customerReferrer = Mage::getModel('magemlm/customer')->load($customerId , 'customer_id');
10
+ $referrerId = $customerReferrer->getReferrerId();
11
+
12
+ ?>
13
+
14
+ <div id="customer_info_tabs_customer_edit_tab_action_content" class="box-left">
15
+ <div class="entry-edit">
16
+ <div class="entry-edit-head">
17
+ <h4 class="icon-head head-edit-form fieldset-legend"><?php echo $this->__('Refferal') ?></h4>
18
+ </div>
19
+ <div id="group_fields4" class="fieldset fieldset-wide">
20
+ <div class="hor-scroll">
21
+ <table class="form-list" cellspacing="0">
22
+ <tbody>
23
+ <tr>
24
+ <td>
25
+ <?php echo $this->__('Refferal Person:') ?>
26
+ <p class="note">
27
+ <span><?php echo $this->__('Store views are displayed first.') ?></span>
28
+ </p>
29
+ </td>
30
+ <td class="value">
31
+ <select class="select" name="magemlm_referrer">
32
+ <?php foreach ($stores as $key => $store) : ?>
33
+ <option value="store_<?php echo $key ?>" <?php (($referrerId == $customerId) ? 'selected' : '' )?>><?php echo $this->__('-- direct cooworker: ') ?><?php echo $store ?></option>
34
+ <?php endforeach ; ?>
35
+ <?php foreach ($customerCollection as $customer) : ?>
36
+ <option value="<?php echo $customer->getId(); ?>" <?php echo (($referrerId == $customer->getId()) ? 'selected' : ''); ?>><?php echo $customer->getName() ?></option>
37
+ <?php endforeach; ?>
38
+ </select>
39
+ <p class="note">
40
+ <span><?php echo $this->__('Please be very carefull when changing refferal.') ?></span>
41
+ </p>
42
+ </td>
43
+ </tr>
44
+ </tbody>
45
+ </table>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ </div>
50
+
51
+
52
+ <div class="box-right">
53
+ <div class="entry-edit">
54
+ <div class="entry-edit-head">
55
+ <h4 class="icon-head head-account"><?php echo $this->__('Customer Image') ?></h4>
56
+ <?php $customerMagemlm = Mage::getModel('magemlm/customer')->load($customerId, 'customer_id'); ?>
57
+ <?php
58
+ $image = $customerMagemlm->getMagemlmImage();
59
+
60
+ if ($image == '') {
61
+ $gender = $this->getCustomer()->getGender();
62
+ if ($gender == '124') {
63
+ $genderImg = Mage::getBaseUrl('media') . DS . 'magemlm' . DS . 'female.png';
64
+ } else if ($gender == '123' ) {
65
+ $genderImg = Mage::getBaseUrl('media') . DS . 'magemlm' . DS . 'male.png';
66
+ } else {
67
+
68
+ }
69
+ $image = $genderImg;
70
+ } else {
71
+ $image = Mage::getBaseUrl('media') . DS . 'magemlm' . DS . $customerMagemlm->getMagemlmImage();
72
+ }
73
+ ?>
74
+ </div>
75
+ <div class="fieldset">
76
+ <div class="hor-scroll">
77
+ <table class="form-list" cellspacing="0" width="100%">
78
+ <tbody>
79
+ <tr>
80
+ <td class="value">
81
+ <?php echo $this->__('Image:') ?><br />
82
+ <img src="<?php echo $image; ?>" width="80%"/>
83
+ <div class="clear"></div>
84
+ <input type="file" title="File" name="magemlm_customer_picture">
85
+ <p class="form-list note">
86
+ <span><?php echo $this->__('Uploading new image will replace the current image.') ?></span>
87
+ </p>
88
+ </td>
89
+ </tr>
90
+ </tbody>
91
+ </table>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ </div>
96
+
97
+ <div class="clear"></div>
app/design/adminhtml/default/default/template/magemlm/structure.phtml ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php $stores = Mage::getModel('core/store') -> getCollection() -> toOptionHash(); ?>
2
+
3
+ <script>
4
+ jQuery(document).ready(function() {
5
+ jQuery("#org").jOrgChart({
6
+ chartElement : '#chart',
7
+ dragAndDrop : false
8
+ });
9
+ });
10
+ </script>
11
+
12
+ <?php
13
+
14
+ function displayStructure($referralId) {
15
+ $collection = Mage::getModel('magemlm/customer')->getCollection()->addFieldToFilter('referrer_id', array('eq' => $referralId));
16
+
17
+ if ($collection -> count() > 0) {
18
+ echo '<ul>';
19
+ foreach ($collection as $customer) {
20
+
21
+ if (Mage::helper('magemlm')->customerExists($customer->getCustomerId())) {
22
+ echo '<li id="' . $customer->getCustomerId() . '">';
23
+ $image = Mage::helper('magemlm')->getCustomerImage($customer->getCustomerId());
24
+
25
+ if ($image == '' ) {
26
+ $customerModel = Mage::getModel('customer/customer')->load($customer->getCustomerId());
27
+ $gender = $customerModel->getGender();
28
+ // var_dump($gender);
29
+
30
+ if ($gender == '124') {
31
+ $genderImg = Mage::getBaseUrl('media') . DS . 'magemlm' . DS . 'female.png';
32
+ } else if ($gender == '123' ) {
33
+ $genderImg = Mage::getBaseUrl('media') . DS . 'magemlm' . DS . 'male.png';
34
+ } else {
35
+
36
+ }
37
+ $image = $genderImg;
38
+ } else {
39
+ $image = Mage::getBaseUrl('media') . DS . 'magemlm' . DS . $image;
40
+ }
41
+
42
+ echo '<div class="magemlm_name">' . Mage::helper('magemlm')->getCustomerName($customer->getCustomerId()) . '</div>';
43
+ echo '<img src="' . $image . '" height="80px" class="node_img" /><br /> ';
44
+
45
+ displayStructure($customer -> getCustomerId());
46
+ echo '</li>';
47
+ }
48
+ }
49
+ echo '</ul>';
50
+ }
51
+ }
52
+ ?>
53
+
54
+ <ul id="org" style="display:none;">
55
+ <li>
56
+ <?php echo Mage::app() -> getStore() -> getName(); ?>
57
+ <?php displayStructure('store_1'); ?>
58
+ </li>
59
+ </ul>
60
+
61
+ <div id="chart" class="orgChart"></div>
62
+
63
+ <script>
64
+ jQuery(document).ready(function() {
65
+ jQuery('#list-html').text(jQuery('#org').html());
66
+ });
67
+
68
+ </script>
app/design/adminhtml/default/default/template/magemlm/unilevel/edit.phtml ADDED
File without changes
app/design/adminhtml/default/default/template/magemlm/unilevel/view.phtml ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $magemlmLevels = Mage::getModel('magemlm/unilevel') -> getCollection();
3
+ $editUrl = Mage::helper("adminhtml") -> getUrl("*/*/edit");
4
+ $deleteUrl = Mage::helper("adminhtml") -> getUrl("*/*/delete");
5
+ $sum = Mage::helper('magemlm')->compensationSum() ;
6
+ ?>
7
+
8
+ <div class="content-header">
9
+ <h3 class="icon-head head-sales-order"><?php echo $this -> __('Commissions levels'); ?><i> (<?php echo $this->__('sum'); ?> = <?php echo $sum ?>%)</i></h3>
10
+ <p class="magemlm-buttons">
11
+ <button style="" class="scalable add" type="button" title="Save Account" id="id_5e2f7c269e1d3bbc886158b7d0906c2b" onClick="window.location = '<?php echo $editUrl; ?>'">
12
+ <span><?php echo $this->__('Add commission level') ?></span>
13
+ </button>
14
+ </p>
15
+ </div>
16
+
17
+
18
+ <?php $i = 0;?>
19
+ <?php foreach ($magemlmLevels as $magemlmLevel) : ?>
20
+ <?php if ($i >= 1) : ?>
21
+ <div style="background-image: url('<?php echo $this->getSkinUrl('images/admin_magemlm_arrow.png'); ?>'); margin-left: <?php echo (($i-1) * 95); ?>px; width: 95px; heighT: 80px; float: left; margin-top: -15px;"></div>
22
+ <?php endif ; ?>
23
+ <div style="clear: right; width: 600px; height: 95px; margin-left: <?php echo ($i * 95); $i++ ?>px;">
24
+ <button class="magemlm-admin-edit" onClick="window.location = '<?php echo $editUrl; ?>id/<?php echo $magemlmLevel->getId()?>/'";></button>
25
+ <button class="magemlm-admin-delete" onClick="window.location = '<?php echo $deleteUrl; ?>id/<?php echo $magemlmLevel->getId()?>/'";></button>
26
+
27
+ <div class="entry-edit" style="width: 396px; float: left;">
28
+ <div class="entry-edit-head">
29
+ <h4 class="icon-head head-edit-form fieldset-legend"><?php echo $this -> __('Level name: ') . $magemlmLevel -> getLevelName(); ?></h4>
30
+ </div>
31
+ <div class="fieldset" style="height: 32px; padding-top: 14px;">
32
+ <p class="magemlm-level"><?php echo $this->__('Value: ') ?> <?php echo $magemlmLevel -> getLevelCommission(); ?>%</p>
33
+ </div>
34
+ </div>
35
+ </div>
36
+ <?php endforeach ; ?>
app/design/frontend/base/default/layout/magemlm.xml ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout version="0.1.0">
3
+
4
+ <default>
5
+ <reference name="head">
6
+ <action method="addJs"><js>jquery/jquery-1.9.1.js</js></action>
7
+ <action method="addJs"><js>jquery/jquery.jOrgChart.js</js></action>
8
+ <action method="addCss"><css>css/magemlm.css</css></action>
9
+ </reference>
10
+ </default>
11
+
12
+ <customer_account>
13
+ <reference name="customer_account_navigation">
14
+ <action method="addLink" translate="label" module="magemlm">
15
+ <name>magemlm_structure</name>
16
+ <path>magemlm/customer/view</path>
17
+ <label>My Structure</label>
18
+ </action>
19
+ <action method="addLink" translate="label" module="magemlm">
20
+ <name>magemlm_settings</name>
21
+ <path>magemlm/customer/config</path>
22
+ <label>My MLM Profile</label>
23
+ </action>
24
+ <action method="addLink" translate="label" module="magemlm">
25
+ <name>magemlm_commissions</name>
26
+ <path>magemlm/customer/commissions</path>
27
+ <label>My Commissions</label>
28
+ </action>
29
+ <action method="addLink" translate="label" module="magemlm">
30
+ <name>magemlm_compensation_plan</name>
31
+ <path>magemlm/customer/plan</path>
32
+ <label>Unilevel Compensation Plan</label>
33
+ </action>
34
+ </reference>
35
+ </customer_account>
36
+
37
+ <magemlm_customer_view>
38
+ <update handle="customer_account"/>
39
+ <reference name="content">
40
+ <block type="magemlm/customer_structure" name="view.magemlm.structure" as="magemlm.structure" />
41
+ <!-- <block type="magemlm/customer_structure_menu" name="magemlm.structure.menu" as="structure.menu" /> --><!-- disable menu -->
42
+ </reference>
43
+
44
+ <!-- <reference name="root">
45
+ <action method="setTemplate"><template>magemlm/structure/page/structure.phtml</template></action>
46
+ </reference> -->
47
+ </magemlm_customer_view>
48
+
49
+ <magemlm_customer_config>
50
+ <update handle="customer_account"/>
51
+ <reference name="content">
52
+ <block type="magemlm/customer_profile" name="view.magemlm.profile" />
53
+ </reference>
54
+ </magemlm_customer_config>
55
+
56
+ <magemlm_customer_commissions>
57
+ <update handle="customer_account"/>
58
+ <reference name="content">
59
+ <block type="magemlm/customer_commissions" name="view.magemlm.commissions" />
60
+ </reference>
61
+ </magemlm_customer_commissions>
62
+
63
+ <magemlm_customer_plan>
64
+ <update handle="customer_account"/>
65
+ <reference name="content">
66
+ <block type="magemlm/customer_plan" name="view.magemlm.plan" />
67
+ </reference>
68
+ </magemlm_customer_plan>
69
+
70
+ </layout>
app/design/frontend/base/default/template/magemlm/commissions.phtml ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php /*
2
+ * Profile template for frontend
3
+ *
4
+ */
5
+
6
+ // customer createdAt date is important for filtering
7
+ $customerCreatedAt = Mage::helper('magemlm')->getCustomerCreatedDate();
8
+ $monthCount = Mage::helper('magemlm')->countMonths($customerCreatedAt, date('Y-m'));
9
+ $customerLevel = Mage::helper('magemlm')->getCustomerLevel(Mage::helper('customer')->getCustomer()->getId());
10
+
11
+ $controller = Mage::app()->getRequest()->getControllerName();
12
+ $action = Mage::app()->getRequest()->getActionName();
13
+ $router = Mage::app()->getRequest()->getRouteName();
14
+ $currentMonth = Mage::app()->getRequest()->getParam('month'); // get request month for option selecting
15
+
16
+ // set current month, if not selected
17
+ if ($currentMonth == '') $currentMonth = date('Y-m');
18
+ $customerCommissions = Mage::getModel('magemlm/commissions')->getCollection()
19
+ ->addFieldToFilter('customer_id' , array ('eq' => Mage::helper('customer')->getCustomer()->getId() ))
20
+ ->addFieldToFilter('created_at' , array ('like' => $currentMonth . '%' ));
21
+
22
+ ?>
23
+
24
+
25
+ <div class="page-title">
26
+ <h1><?php echo $this -> __('My Commissions:'); ?></h1>
27
+ </div>
28
+
29
+
30
+ <div class="pager">
31
+ <p class="amount">
32
+ <strong><?php echo $this->__('Current month:'); ?> <?php echo ($currentMonth != '') ? $currentMonth : date ('Y-m'); ?></strong>
33
+ </p>
34
+
35
+ <div class="limiter">
36
+ <label><?php echo $this->__('Show commission for date: '); ?></label>
37
+ <select onChange="setLocation(this.value);">
38
+ <?php for ($i = 0; $i < $monthCount ; $i++) : ?>
39
+ <?php
40
+ $time = strtotime($customerCreatedAt);
41
+ $date = date("Y-m", strtotime("$i month", $time));
42
+ ?>
43
+ <option value="<?php echo Mage::getBaseUrl() . $router . DS . $controller . DS . $action . DS . "month" . DS . $date ?>" <?php echo ($date == $currentMonth) ? 'selected' : '' ?>>
44
+ <?php echo $date ?>
45
+ </option>
46
+ <?php endfor ; ?>
47
+ </select>
48
+ </div>
49
+ </div>
50
+
51
+ <table id="my-orders-table" class="data-table">
52
+ <colgroup>
53
+ <col width="1">
54
+ <col width="1">
55
+ <col width="1">
56
+ <col width="1">
57
+ <col width="1">
58
+ </colgroup>
59
+ <thead>
60
+ <tr class="first last">
61
+ <th><?php echo $this->__('Order Date') ?> </th>
62
+ <th><?php echo $this->__('Order Id') ?></th>
63
+ <th><?php echo $this->__('Commission level')?></th>
64
+ <th><?php echo $this->__('Commission value')?></th>
65
+ <th><?php echo $this->__('Commission status') ?></th>
66
+ </tr>
67
+ </thead>
68
+
69
+ <?php if ($customerCommissions->count() == 0) : ?>
70
+ <tbody>
71
+ <tr>
72
+ <td colspan="5" align="center">
73
+ <?php echo $this->__('There are no commissions for this month') ?>
74
+ </td>
75
+ </tr>
76
+ </tbody>
77
+ <?php else : ?>
78
+ <tbody>
79
+ <?php $commissionTotal = 0; ?>
80
+ <?php $i = 1; foreach ($customerCommissions as $commission) : ?>
81
+ <tr <?php echo ($i % 2 == 0 ? '' : 'class="even"') ?> >
82
+ <td><?php echo date('Y-m-d' , strtotime($commission->getCreatedAt())) ?> </td>
83
+ <td><?php echo $commission->getOrderId();?> </td>
84
+ <td><?php echo ((int)$commission->getCommissionLevel() - (int)$customerLevel) ; ?> </td>
85
+ <td><?php echo Mage::helper('core')->currency($commission->getCommissionValue(), true, false) ; $commissionTotal += $commission->getCommissionValue(); ?> </td>
86
+ <td><?php
87
+ if ($commission->getCommissionStatus()) {
88
+ echo 'Paid';
89
+ } else {
90
+ echo 'Not paid';
91
+ }?>
92
+ </td>
93
+ </tr>
94
+ <?php $i++; ?>
95
+ <?php endforeach ; ?>
96
+ </tbody>
97
+ <?php endif; ?>
98
+ <tfoot>
99
+ <tr class="subtotal first">
100
+ <td colspan="4" class="a-right"><strong><?php echo $this->__('Commission total') ?> </strong></td>
101
+ <td class="last a-right">
102
+ <span class="a-right"><strong><?php echo Mage::helper('core')->currency($commissionTotal, true, false) ;?></strong></span>
103
+ </td>
104
+ </tfoot>
105
+ </table>
106
+
app/design/frontend/base/default/template/magemlm/plan.phtml ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php /*
2
+ * Profile template for frontend
3
+ *
4
+ */
5
+ ?>
6
+
7
+ <div class="page-title">
8
+ <h1><?php echo $this->__('Unilevel Compensation Plan:'); ?></h1>
9
+ </div>
10
+
11
+ <?php $magemlmLevels = Mage::getModel('magemlm/unilevel') -> getCollection(); ?>
12
+ <?php $i = 0;?>
13
+
14
+ <?php foreach ($magemlmLevels as $magemlmLevel) : ?>
15
+
16
+ <div class="fieldset">
17
+ <h2 class="legend"><?php echo $magemlmLevel -> getLevelName(); ?></h2>
18
+ <p><strong> <?php echo $this->__('Commission Value') ?> <?php echo $magemlmLevel -> getLevelCommission(); ?>%</strong></p>
19
+ </div>
20
+
21
+ <?php endforeach ; ?>
app/design/frontend/base/default/template/magemlm/profile.phtml ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php /*
2
+ * Profile template for frontend
3
+ *
4
+ */
5
+ $totalCommission = Mage::getModel('magemlm/commissions')->getCommissionSummary($customerId);
6
+ $customerCreatedAt = Mage::helper('magemlm')->getCustomerCreatedDate();
7
+ $monthCount = Mage::helper('magemlm')->countMonths($customerCreatedAt, date('Y-m'));
8
+ $customerId = Mage::helper('customer')->getCustomer()->getId();
9
+ $totalCommission = Mage::getModel('magemlm/commissions')->getCommissionSummary($customerId);
10
+
11
+ ?>
12
+ <div class="page-title">
13
+ <h1><?php echo $this->__('My MLM profile'); ?></h1>
14
+ </div>
15
+
16
+
17
+ <div class="fieldset magemlm-full">
18
+ <h2 class="legend"><?php echo $this->__('Referral Link') ?></h2>
19
+ <p>
20
+ <a href="<?php echo Mage::getModel('magemlm/referrallink')->link($customerId); ?>">
21
+ <?php echo Mage::getModel('magemlm/referrallink')->link($customerId); ?>
22
+ </a>
23
+ </p>
24
+ </div>
25
+
26
+
27
+ <div class="fieldset magemlm-left" style="clear: both;">
28
+ <h2 class="legend"><?php echo $this->__('Structure Data') ?></h2>
29
+ <table id="my-orders-table" class="data-table">
30
+ <colgroup>
31
+ <col width="120">
32
+ <col width="1">
33
+ </colgroup>
34
+ <thead>
35
+ <tr class="first last">
36
+ <th><?php echo $this->__('Data')?></th>
37
+ <th><?php echo $this->__('Value')?></th>
38
+ </tr>
39
+ </thead>
40
+ <tbody>
41
+ <tr class="first odd">
42
+ <td><?php echo $this->__('Frontline: '); ?></td>
43
+ <td><span class="nobr"><?php echo Mage::helper('magemlm')->getFrontlineCount($customerId) ?> </span></td>
44
+ </tr>
45
+ <tr class="even">
46
+ <td><?php echo $this->__('Structure Depth: '); ?></td>
47
+ <?php
48
+ $depthMdl = Mage::helper('magemlm');
49
+ $depthMdl->structureDepth($customerId);
50
+ $depth = $depthMdl->maxDepth;
51
+ ?>
52
+ <td><span class="nobr"><?php echo $depth ?></span></td>
53
+ </tr>
54
+ <tr class="first last odd">
55
+ <td><?php echo $this->__('Structure Count: '); ?></td>
56
+ <td><span class="nobr"><?php echo Mage::helper('magemlm')->structureCount($customerId) ?></span></td>
57
+ </tr>
58
+ </tbody>
59
+ </table>
60
+ </div>
61
+
62
+
63
+
64
+
65
+ <div class="fieldset magemlm-right">
66
+ <h2 class="legend"><?php echo $this->__('Your picture') ?></h2>
67
+ <?php $customerMagemlm = Mage::getModel('magemlm/customer')->load($customerId, 'customer_id'); ?>
68
+ <?php $image = Mage::getBaseUrl('media') . DS . 'magemlm' . DS . $customerMagemlm->getMagemlmImage(); ?>
69
+
70
+ <p align="center">
71
+ <img src="<?php echo $image; ?>" width="95%"/>
72
+ </p>
73
+ <p align="center">
74
+ <?php echo $this->__('Your image is uploaded by MLM central') ?>
75
+ </p>
76
+ </div>
77
+
78
+
79
+ <div class="fieldset magemlm-left">
80
+ <h2 class="legend"><?php echo $this->__('Commission Data') ?></h2>
81
+ <table id="my-orders-table" class="data-table">
82
+ <colgroup>
83
+ <col width="120">
84
+ <col width="1">
85
+ </colgroup>
86
+ <thead>
87
+ <tr class="first last">
88
+ <th><?php echo $this->__('Type')?></th>
89
+ <th><?php echo $this->__('Value')?></th>
90
+ </tr>
91
+ </thead>
92
+ <tbody>
93
+ <tr class="first odd">
94
+ <td><?php echo $this->__('Total earnings: '); ?></td>
95
+ <td><span class="nobr"><?php echo Mage::helper('core')->currency($totalCommission, true, false) ?> </span></td>
96
+ </tr>
97
+ <tr class="even">
98
+ <td><?php echo $this->__('Average monthly earnings: '); ?></td>
99
+ <td><span class="nobr"><?php echo Mage::helper('core')->currency($totalCommission/$monthCount, true, false) ?> </span></td>
100
+ </tr>
101
+ </tbody>
102
+ </table>
103
+ </div>
104
+
105
+
106
+ <div class="fieldset magemlm-left">
107
+ <h2 class="legend"><?php echo $this->__('Personal Info') ?></h2>
108
+ <table id="my-orders-table" class="data-table">
109
+ <colgroup>
110
+ <col width="120">
111
+ <col width="1">
112
+ </colgroup>
113
+ <thead>
114
+ <tr class="first last">
115
+ <th><?php echo $this->__('Type')?></th>
116
+ <th><?php echo $this->__('Value')?></th>
117
+ </tr>
118
+ </thead>
119
+ <tbody>
120
+ <tr class="first odd">
121
+ <td><?php echo $this->__('Account created at: '); ?></td>
122
+ <td><span class="nobr"><?php echo date('Y-m-d' , strtotime($customerCreatedAt)); ?> </span></td>
123
+ </tr>
124
+ <tr class="even">
125
+ <td><?php echo $this->__('Referrer name: '); ?></td>
126
+ <td><span class="nobr"><?php echo Mage::helper('magemlm')->getReferrerName($customerId) ; ?> </span></td>
127
+ </tr>
128
+ </tbody>
129
+ </table>
130
+ </div>
app/design/frontend/base/default/template/magemlm/structure.phtml ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php /*
2
+ * Structure template for frontend
3
+ *
4
+ */
5
+ ?>
6
+ <div class="page-title">
7
+ <h1><?php echo $this->__('My structure'); ?></h1>
8
+ </div>
9
+
10
+ <?php
11
+
12
+ function displayStructure($referralId) {
13
+ $collection = Mage::getModel('magemlm/customer')->getCollection()->addFieldToFilter('referrer_id', array('eq' => $referralId));
14
+
15
+ if ($collection -> count() > 0) {
16
+ echo '<ul>';
17
+ foreach ($collection as $customer) {
18
+ if (Mage::helper('magemlm')->customerExists($customer->getCustomerId())) {
19
+
20
+ echo '<li id="' . $customer->getCustomerId() . '">';
21
+ $image = Mage::helper('magemlm')->getCustomerImage($customer->getCustomerId());
22
+
23
+ if ($image == '' ) {
24
+ $customerModel = Mage::getModel('customer/customer')->load($customer->getCustomerId());
25
+ $gender = $customerModel->getGender();
26
+ // var_dump($gender);
27
+
28
+ if ($gender == '124') {
29
+ $genderImg = Mage::getBaseUrl('media') . DS . 'magemlm' . DS . 'female.png';
30
+ } else if ($gender == '123' ) {
31
+ $genderImg = Mage::getBaseUrl('media') . DS . 'magemlm' . DS . 'male.png';
32
+ } else {
33
+
34
+ }
35
+ $image = $genderImg;
36
+ } else {
37
+ $image = Mage::getBaseUrl('media') . DS . 'magemlm' . DS . $image;
38
+ }
39
+
40
+ echo '<div class="magemlm_name">' . Mage::helper('magemlm')->getCustomerName($customer->getCustomerId()) . '</div>';
41
+ echo '<img src="' . $image . '" height="80px" class="node_img" /><br /> ';
42
+
43
+ displayStructure($customer -> getCustomerId());
44
+ echo '</li>';
45
+ }
46
+ }
47
+ echo '</ul>';
48
+ }
49
+ }
50
+ ?>
51
+
52
+ <ul id="org" style="display:none;">
53
+ <li id="<?php echo Mage::helper('customer')->getCustomer()->getId(); ?>">
54
+ <?php echo '<div class="magemlm_name">' . Mage::helper('customer')->getCustomer()->getName() . '</div>'; ?>
55
+ <?php echo '<img src="' . Mage::getBaseUrl('media') . DS . 'magemlm' . DS . Mage::helper('magemlm')->getCustomerImage(Mage::helper('customer')->getCustomer()->getId()) . '" width="60px" class="node_img" /><br /> '; '</div>'; ?>
56
+ <?php displayStructure(Mage::helper('customer')->getCustomer()->getId()); ?>
57
+ </li>
58
+ </ul>
59
+
60
+ <div id="chart" class="orgChart" style="overflow: scroll;"></div>
61
+
62
+
63
+ <script>
64
+
65
+ jQuery(document).ready(function() {
66
+ jQuery("#org").jOrgChart({
67
+ chartElement : '#chart',
68
+ dragAndDrop : true
69
+ });
70
+ });
71
+
72
+
73
+ </script>
app/design/frontend/base/default/template/magemlm/structure/menu.phtml ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div id="magemlm_menu">
2
+ <ul>
3
+ <!-- <li>Menu 1</li>
4
+ <li>Menu 2</li>
5
+ <li>Menu 3</li>
6
+ <li>Menu 4</li> -->
7
+ </ul>
8
+ </div>
9
+
10
+ <script>
11
+ jQuery("#chart").bind("contextmenu", function(event) {
12
+ var className = (jQuery(event.target).attr('class'));
13
+
14
+ if (className == "node") {
15
+ var id = (jQuery(event.target).attr('id'));
16
+ } else if (className == "node_img") {
17
+ var id = jQuery(event.target).parent().attr('id');
18
+ }
19
+
20
+ jQuery("#magemlm_menu").css({
21
+ top : event.pageY-15,
22
+ left : event.pageX-15
23
+ }).fadeIn(250);
24
+
25
+ return false;
26
+ });
27
+
28
+
29
+ jQuery("#magemlm_menu").mouseleave(function(){
30
+ jQuery(this).fadeOut(250);
31
+ });
32
+ </script>
app/design/frontend/base/default/template/magemlm/structure/page/structure.phtml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $this->getLang() ?>" lang="<?php echo $this->getLang() ?>">
3
+ <head>
4
+ <?php echo $this->getChildHtml('head') ?>
5
+ </head>
6
+ <body<?php echo $this->getBodyClass()?' class="'.$this->getBodyClass().'"':'' ?>>
7
+ <?php echo $this->getChildHtml('after_body_start') ?>
8
+ <div class="wrapper">
9
+ <?php echo $this->getChildHtml('global_notices') ?>
10
+ <div class="page">
11
+
12
+ <div class="col2-left-layout magemlm-structure-body">
13
+ <div class="main magemlm-structure-body">
14
+ <div style="float: left;"><?php echo $this->getChildHtml('left') ?></div>
15
+ <div class="col-main" style="margin-left: 20px; float: left;">
16
+ <?php echo $this->getChildHtml('global_messages') ?>
17
+ <?php echo $this->getChildHtml('content') ?>
18
+ </div>
19
+
20
+ </div>
21
+ </div>
22
+ <?php echo $this->getChildHtml('footer') ?>
23
+ <?php echo $this->getChildHtml('before_body_end') ?>
24
+ </div>
25
+ </div>
26
+ <?php echo $this->getAbsoluteFooter() ?>
27
+ </body>
28
+ </html>
app/etc/modules/Qsolutions_Magemlm.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Qsolutions_Magemlm>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ </Qsolutions_Magemlm>
8
+ </modules>
9
+ </config>
app/locale/pl_PL/Qsolutions_magemlm.csv ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "Show structure for store view:","Pokaż strukturę dla widoku sklepu:"
2
+ "Customer MLM Profile","Profil MLM klienta"
3
+ "-- direct cooworker: ","-- bezpośredni współpracownik: "
4
+ "Refferal Person:","Osoba rekomendująca"
5
+ "Refferal","Rekomendacja"
6
+ "Please be very carefull when changing refferal.","Proszę uważać przy zmianie osoby rekomendującej"
7
+ "Customer Image","Zdjęcie klienta"
8
+ "Image:","Zdjęcie:"
9
+ "Uploading new image will replace the current image.","Zgranie nowego zdjęcia zastąpi obecne"
10
+ "Uploading new image will replace the current one.","Zgranie nowego zdjęcia zastąpi obecne"
11
+ "Store views are displayed first.","Widoki sklepów są wypisywane w pierwszej kolejności"
12
+ "Show structure","Wyświetl strukturę"
13
+ "Multilevel Settings","Ustawienia MLM"
14
+ "Multilevel Marketing Settings","Ustawienia multilevel marketingu"
15
+ "My structure","Moja struktura"
16
+ "My Structure","Moja Struktura"
17
+ "My MLM profile","Mój profil MLM"
18
+ "My MLM Profile","Mój Profil MLM"
19
+ "Referral Link","Link referencyjny"
20
+ "You are editing commission level: %s","Edytujesz poziom prowizji: %s"
21
+ "New comission level","Nowy poziom prowizji"
22
+ "Save Commission Level","Zapisz poziom prowizji"
23
+ "Commission Level Settings","Ustawienia poziomu prowizji"
24
+ "Level name",'Nazwa poziomu"
25
+ "System name of commission level. For administration purposes","Nazwa systemowa poziomu prowizyjnego. Dla potrzeb administracyjnych"
26
+ "Level Commission:","Wartość prowizji:"
27
+ "value in %.","wartość prowizji w %."
28
+ "Unilevel payment plan","Plan prowizyjny"
29
+ "Configuration","Konfiguracja"
30
+ "Commissions levels","Poziomy prowizjyne"
31
+ "sum","suma"
32
+ "Level name: ","Nazwa poziomu: "
33
+ "Value: ","Prowizja: "
34
+ "Delete","Usuń"
35
+ "Back","Wróć"
36
+ "Commission Report","Raport prowizyjny"
37
+ "My Commissions:","Moje prowizje"
38
+ "Current month:","Obecny miesiąc:"
39
+ "Order Date","Data zamówienia"
40
+ "Order Id","Identyfikator zamówienia"
41
+ "Commission level","Poziom prowizyjny"
42
+ "Commission value","Wartość prowizji"
43
+ "Status","Stan"
44
+ "Unilevel Compensation Plan:","Schemat wypłaty prowizji"
45
+ "Unilevel Commission Plan","Podstawowy Plan Prowizyjny"
46
+ "Frontline: ","Pierwsza linia"
47
+ "Structure Depth: ","Głębokość struktury"
48
+ "Structure Total: ","Ilość osób w strukturze"
49
+ "Structure Count:","Osób w strukturze"
50
+ "Selected commissions were marked as paid","Prowizje zostały oznaczone jako zapłacone"
51
+ "Select date for commission report:","Wybierz datę dla raportu prowizyjnego"
52
+ "Commission report:","Raport prowizyjny"
53
+ "Unpaid Commissions for selected date:","Niewypłacone prowizje dla daty:"
54
+ "Customer","Klient"
55
+ "Customer email","Adres email klienta"
56
+ "Commission Value","Wartość prowizji"
57
+ "Mark selected commissions as paid","Oznacz prowizje jako zapłacone"
58
+ "Paid Commissions for selected date:","Wypłacone prowizje dla daty:"
59
+ "Marketing level deleted","Usunięto poziom prowizyjny"
60
+ "No data found to delete","Nie znaleziono danych do usunięcia"
61
+ "No data found to save","Nie znaleziono danych do zapisu"
62
+ "Data not found","Nie znaleziono informacji"
63
+ "Data saved","Zapisano dane"
64
+ "Multilevel Customer Data","Profil MLM klienta"
65
+ "Show Entire Structure","Pokaż całą strukturę"
66
+ "Commission total","Wartość prowizji"
67
+ "Commission status","Stan prowizji"
68
+ "There are no commissions for this month","W danym miesiącu nie ma prowizji"
69
+ "Paid","Wypłacono"
70
+ "Not paid","Nie wypłacono"
71
+ "Commission Value","Wielkość prowizji"
72
+ "My MLM profile","Mój profil MLM"
73
+ "Structure Data","Twoja struktura"
74
+ "Data","Dane"
75
+ "Value","Wartość"
76
+ "Your picture","Twoje zdjęcie"
77
+ "Your image is uploaded by MLM central","Twoje zdjęcie dodawane jest przez centralę"
78
+ "Commission Data","Wynagrodzenia"
79
+ "Type","Rodzaj"
80
+ "Total earnings: ","Całkowity przychód"
81
+ "Average monthly earnings: ","Średni miesięczny zarobek"
82
+ "Personal Info","Informacje osobiste"
83
+ "Account created at: ","Konto stworzone zostało: "
84
+ "Referrer name: ","Osoba rekomendująca"
js/jquery/jquery-1.9.1.js ADDED
@@ -0,0 +1,9690 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jQuery JavaScript Library v1.9.1
3
+ * http://jquery.com/
4
+ *
5
+ * Includes Sizzle.js
6
+ * http://sizzlejs.com/
7
+ *
8
+ * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors
9
+ * Released under the MIT license
10
+ * http://jquery.org/license
11
+ *
12
+ * Date: 2013-2-4
13
+ */
14
+ (function( window, undefined ) {
15
+
16
+ // Can't do this because several apps including ASP.NET trace
17
+ // the stack via arguments.caller.callee and Firefox dies if
18
+ // you try to trace through "use strict" call chains. (#13335)
19
+ // Support: Firefox 18+
20
+ //"use strict";
21
+ var
22
+ // The deferred used on DOM ready
23
+ readyList,
24
+
25
+ // A central reference to the root jQuery(document)
26
+ rootjQuery,
27
+
28
+ // Support: IE<9
29
+ // For `typeof node.method` instead of `node.method !== undefined`
30
+ core_strundefined = typeof undefined,
31
+
32
+ // Use the correct document accordingly with window argument (sandbox)
33
+ document = window.document,
34
+ location = window.location,
35
+
36
+ // Map over jQuery in case of overwrite
37
+ _jQuery = window.jQuery,
38
+
39
+ // Map over the $ in case of overwrite
40
+ _$ = window.$,
41
+
42
+ // [[Class]] -> type pairs
43
+ class2type = {},
44
+
45
+ // List of deleted data cache ids, so we can reuse them
46
+ core_deletedIds = [],
47
+
48
+ core_version = "1.9.1",
49
+
50
+ // Save a reference to some core methods
51
+ core_concat = core_deletedIds.concat,
52
+ core_push = core_deletedIds.push,
53
+ core_slice = core_deletedIds.slice,
54
+ core_indexOf = core_deletedIds.indexOf,
55
+ core_toString = class2type.toString,
56
+ core_hasOwn = class2type.hasOwnProperty,
57
+ core_trim = core_version.trim,
58
+
59
+ // Define a local copy of jQuery
60
+ jQuery = function( selector, context ) {
61
+ // The jQuery object is actually just the init constructor 'enhanced'
62
+ return new jQuery.fn.init( selector, context, rootjQuery );
63
+ },
64
+
65
+ // Used for matching numbers
66
+ core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
67
+
68
+ // Used for splitting on whitespace
69
+ core_rnotwhite = /\S+/g,
70
+
71
+ // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
72
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
73
+
74
+ // A simple way to check for HTML strings
75
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
76
+ // Strict HTML recognition (#11290: must start with <)
77
+ rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,
78
+
79
+ // Match a standalone tag
80
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
81
+
82
+ // JSON RegExp
83
+ rvalidchars = /^[\],:{}\s]*$/,
84
+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
85
+ rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
86
+ rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,
87
+
88
+ // Matches dashed string for camelizing
89
+ rmsPrefix = /^-ms-/,
90
+ rdashAlpha = /-([\da-z])/gi,
91
+
92
+ // Used by jQuery.camelCase as callback to replace()
93
+ fcamelCase = function( all, letter ) {
94
+ return letter.toUpperCase();
95
+ },
96
+
97
+ // The ready event handler
98
+ completed = function( event ) {
99
+
100
+ // readyState === "complete" is good enough for us to call the dom ready in oldIE
101
+ if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
102
+ detach();
103
+ jQuery.ready();
104
+ }
105
+ },
106
+ // Clean-up method for dom ready events
107
+ detach = function() {
108
+ if ( document.addEventListener ) {
109
+ document.removeEventListener( "DOMContentLoaded", completed, false );
110
+ window.removeEventListener( "load", completed, false );
111
+
112
+ } else {
113
+ document.detachEvent( "onreadystatechange", completed );
114
+ window.detachEvent( "onload", completed );
115
+ }
116
+ };
117
+
118
+ jQuery.fn = jQuery.prototype = {
119
+ // The current version of jQuery being used
120
+ jquery: core_version,
121
+
122
+ constructor: jQuery,
123
+ init: function( selector, context, rootjQuery ) {
124
+ var match, elem;
125
+
126
+ // HANDLE: $(""), $(null), $(undefined), $(false)
127
+ if ( !selector ) {
128
+ return this;
129
+ }
130
+
131
+ // Handle HTML strings
132
+ if ( typeof selector === "string" ) {
133
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
134
+ // Assume that strings that start and end with <> are HTML and skip the regex check
135
+ match = [ null, selector, null ];
136
+
137
+ } else {
138
+ match = rquickExpr.exec( selector );
139
+ }
140
+
141
+ // Match html or make sure no context is specified for #id
142
+ if ( match && (match[1] || !context) ) {
143
+
144
+ // HANDLE: $(html) -> $(array)
145
+ if ( match[1] ) {
146
+ context = context instanceof jQuery ? context[0] : context;
147
+
148
+ // scripts is true for back-compat
149
+ jQuery.merge( this, jQuery.parseHTML(
150
+ match[1],
151
+ context && context.nodeType ? context.ownerDocument || context : document,
152
+ true
153
+ ) );
154
+
155
+ // HANDLE: $(html, props)
156
+ if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
157
+ for ( match in context ) {
158
+ // Properties of context are called as methods if possible
159
+ if ( jQuery.isFunction( this[ match ] ) ) {
160
+ this[ match ]( context[ match ] );
161
+
162
+ // ...and otherwise set as attributes
163
+ } else {
164
+ this.attr( match, context[ match ] );
165
+ }
166
+ }
167
+ }
168
+
169
+ return this;
170
+
171
+ // HANDLE: $(#id)
172
+ } else {
173
+ elem = document.getElementById( match[2] );
174
+
175
+ // Check parentNode to catch when Blackberry 4.6 returns
176
+ // nodes that are no longer in the document #6963
177
+ if ( elem && elem.parentNode ) {
178
+ // Handle the case where IE and Opera return items
179
+ // by name instead of ID
180
+ if ( elem.id !== match[2] ) {
181
+ return rootjQuery.find( selector );
182
+ }
183
+
184
+ // Otherwise, we inject the element directly into the jQuery object
185
+ this.length = 1;
186
+ this[0] = elem;
187
+ }
188
+
189
+ this.context = document;
190
+ this.selector = selector;
191
+ return this;
192
+ }
193
+
194
+ // HANDLE: $(expr, $(...))
195
+ } else if ( !context || context.jquery ) {
196
+ return ( context || rootjQuery ).find( selector );
197
+
198
+ // HANDLE: $(expr, context)
199
+ // (which is just equivalent to: $(context).find(expr)
200
+ } else {
201
+ return this.constructor( context ).find( selector );
202
+ }
203
+
204
+ // HANDLE: $(DOMElement)
205
+ } else if ( selector.nodeType ) {
206
+ this.context = this[0] = selector;
207
+ this.length = 1;
208
+ return this;
209
+
210
+ // HANDLE: $(function)
211
+ // Shortcut for document ready
212
+ } else if ( jQuery.isFunction( selector ) ) {
213
+ return rootjQuery.ready( selector );
214
+ }
215
+
216
+ if ( selector.selector !== undefined ) {
217
+ this.selector = selector.selector;
218
+ this.context = selector.context;
219
+ }
220
+
221
+ return jQuery.makeArray( selector, this );
222
+ },
223
+
224
+ // Start with an empty selector
225
+ selector: "",
226
+
227
+ // The default length of a jQuery object is 0
228
+ length: 0,
229
+
230
+ // The number of elements contained in the matched element set
231
+ size: function() {
232
+ return this.length;
233
+ },
234
+
235
+ toArray: function() {
236
+ return core_slice.call( this );
237
+ },
238
+
239
+ // Get the Nth element in the matched element set OR
240
+ // Get the whole matched element set as a clean array
241
+ get: function( num ) {
242
+ return num == null ?
243
+
244
+ // Return a 'clean' array
245
+ this.toArray() :
246
+
247
+ // Return just the object
248
+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
249
+ },
250
+
251
+ // Take an array of elements and push it onto the stack
252
+ // (returning the new matched element set)
253
+ pushStack: function( elems ) {
254
+
255
+ // Build a new jQuery matched element set
256
+ var ret = jQuery.merge( this.constructor(), elems );
257
+
258
+ // Add the old object onto the stack (as a reference)
259
+ ret.prevObject = this;
260
+ ret.context = this.context;
261
+
262
+ // Return the newly-formed element set
263
+ return ret;
264
+ },
265
+
266
+ // Execute a callback for every element in the matched set.
267
+ // (You can seed the arguments with an array of args, but this is
268
+ // only used internally.)
269
+ each: function( callback, args ) {
270
+ return jQuery.each( this, callback, args );
271
+ },
272
+
273
+ ready: function( fn ) {
274
+ // Add the callback
275
+ jQuery.ready.promise().done( fn );
276
+
277
+ return this;
278
+ },
279
+
280
+ slice: function() {
281
+ return this.pushStack( core_slice.apply( this, arguments ) );
282
+ },
283
+
284
+ first: function() {
285
+ return this.eq( 0 );
286
+ },
287
+
288
+ last: function() {
289
+ return this.eq( -1 );
290
+ },
291
+
292
+ eq: function( i ) {
293
+ var len = this.length,
294
+ j = +i + ( i < 0 ? len : 0 );
295
+ return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
296
+ },
297
+
298
+ map: function( callback ) {
299
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
300
+ return callback.call( elem, i, elem );
301
+ }));
302
+ },
303
+
304
+ end: function() {
305
+ return this.prevObject || this.constructor(null);
306
+ },
307
+
308
+ // For internal use only.
309
+ // Behaves like an Array's method, not like a jQuery method.
310
+ push: core_push,
311
+ sort: [].sort,
312
+ splice: [].splice
313
+ };
314
+
315
+ // Give the init function the jQuery prototype for later instantiation
316
+ jQuery.fn.init.prototype = jQuery.fn;
317
+
318
+ jQuery.extend = jQuery.fn.extend = function() {
319
+ var src, copyIsArray, copy, name, options, clone,
320
+ target = arguments[0] || {},
321
+ i = 1,
322
+ length = arguments.length,
323
+ deep = false;
324
+
325
+ // Handle a deep copy situation
326
+ if ( typeof target === "boolean" ) {
327
+ deep = target;
328
+ target = arguments[1] || {};
329
+ // skip the boolean and the target
330
+ i = 2;
331
+ }
332
+
333
+ // Handle case when target is a string or something (possible in deep copy)
334
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
335
+ target = {};
336
+ }
337
+
338
+ // extend jQuery itself if only one argument is passed
339
+ if ( length === i ) {
340
+ target = this;
341
+ --i;
342
+ }
343
+
344
+ for ( ; i < length; i++ ) {
345
+ // Only deal with non-null/undefined values
346
+ if ( (options = arguments[ i ]) != null ) {
347
+ // Extend the base object
348
+ for ( name in options ) {
349
+ src = target[ name ];
350
+ copy = options[ name ];
351
+
352
+ // Prevent never-ending loop
353
+ if ( target === copy ) {
354
+ continue;
355
+ }
356
+
357
+ // Recurse if we're merging plain objects or arrays
358
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
359
+ if ( copyIsArray ) {
360
+ copyIsArray = false;
361
+ clone = src && jQuery.isArray(src) ? src : [];
362
+
363
+ } else {
364
+ clone = src && jQuery.isPlainObject(src) ? src : {};
365
+ }
366
+
367
+ // Never move original objects, clone them
368
+ target[ name ] = jQuery.extend( deep, clone, copy );
369
+
370
+ // Don't bring in undefined values
371
+ } else if ( copy !== undefined ) {
372
+ target[ name ] = copy;
373
+ }
374
+ }
375
+ }
376
+ }
377
+
378
+ // Return the modified object
379
+ return target;
380
+ };
381
+
382
+ jQuery.extend({
383
+ noConflict: function( deep ) {
384
+ if ( window.$ === jQuery ) {
385
+ window.$ = _$;
386
+ }
387
+
388
+ if ( deep && window.jQuery === jQuery ) {
389
+ window.jQuery = _jQuery;
390
+ }
391
+
392
+ return jQuery;
393
+ },
394
+
395
+ // Is the DOM ready to be used? Set to true once it occurs.
396
+ isReady: false,
397
+
398
+ // A counter to track how many items to wait for before
399
+ // the ready event fires. See #6781
400
+ readyWait: 1,
401
+
402
+ // Hold (or release) the ready event
403
+ holdReady: function( hold ) {
404
+ if ( hold ) {
405
+ jQuery.readyWait++;
406
+ } else {
407
+ jQuery.ready( true );
408
+ }
409
+ },
410
+
411
+ // Handle when the DOM is ready
412
+ ready: function( wait ) {
413
+
414
+ // Abort if there are pending holds or we're already ready
415
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
416
+ return;
417
+ }
418
+
419
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
420
+ if ( !document.body ) {
421
+ return setTimeout( jQuery.ready );
422
+ }
423
+
424
+ // Remember that the DOM is ready
425
+ jQuery.isReady = true;
426
+
427
+ // If a normal DOM Ready event fired, decrement, and wait if need be
428
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
429
+ return;
430
+ }
431
+
432
+ // If there are functions bound, to execute
433
+ readyList.resolveWith( document, [ jQuery ] );
434
+
435
+ // Trigger any bound ready events
436
+ if ( jQuery.fn.trigger ) {
437
+ jQuery( document ).trigger("ready").off("ready");
438
+ }
439
+ },
440
+
441
+ // See test/unit/core.js for details concerning isFunction.
442
+ // Since version 1.3, DOM methods and functions like alert
443
+ // aren't supported. They return false on IE (#2968).
444
+ isFunction: function( obj ) {
445
+ return jQuery.type(obj) === "function";
446
+ },
447
+
448
+ isArray: Array.isArray || function( obj ) {
449
+ return jQuery.type(obj) === "array";
450
+ },
451
+
452
+ isWindow: function( obj ) {
453
+ return obj != null && obj == obj.window;
454
+ },
455
+
456
+ isNumeric: function( obj ) {
457
+ return !isNaN( parseFloat(obj) ) && isFinite( obj );
458
+ },
459
+
460
+ type: function( obj ) {
461
+ if ( obj == null ) {
462
+ return String( obj );
463
+ }
464
+ return typeof obj === "object" || typeof obj === "function" ?
465
+ class2type[ core_toString.call(obj) ] || "object" :
466
+ typeof obj;
467
+ },
468
+
469
+ isPlainObject: function( obj ) {
470
+ // Must be an Object.
471
+ // Because of IE, we also have to check the presence of the constructor property.
472
+ // Make sure that DOM nodes and window objects don't pass through, as well
473
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
474
+ return false;
475
+ }
476
+
477
+ try {
478
+ // Not own constructor property must be Object
479
+ if ( obj.constructor &&
480
+ !core_hasOwn.call(obj, "constructor") &&
481
+ !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
482
+ return false;
483
+ }
484
+ } catch ( e ) {
485
+ // IE8,9 Will throw exceptions on certain host objects #9897
486
+ return false;
487
+ }
488
+
489
+ // Own properties are enumerated firstly, so to speed up,
490
+ // if last one is own, then all properties are own.
491
+
492
+ var key;
493
+ for ( key in obj ) {}
494
+
495
+ return key === undefined || core_hasOwn.call( obj, key );
496
+ },
497
+
498
+ isEmptyObject: function( obj ) {
499
+ var name;
500
+ for ( name in obj ) {
501
+ return false;
502
+ }
503
+ return true;
504
+ },
505
+
506
+ error: function( msg ) {
507
+ throw new Error( msg );
508
+ },
509
+
510
+ // data: string of html
511
+ // context (optional): If specified, the fragment will be created in this context, defaults to document
512
+ // keepScripts (optional): If true, will include scripts passed in the html string
513
+ parseHTML: function( data, context, keepScripts ) {
514
+ if ( !data || typeof data !== "string" ) {
515
+ return null;
516
+ }
517
+ if ( typeof context === "boolean" ) {
518
+ keepScripts = context;
519
+ context = false;
520
+ }
521
+ context = context || document;
522
+
523
+ var parsed = rsingleTag.exec( data ),
524
+ scripts = !keepScripts && [];
525
+
526
+ // Single tag
527
+ if ( parsed ) {
528
+ return [ context.createElement( parsed[1] ) ];
529
+ }
530
+
531
+ parsed = jQuery.buildFragment( [ data ], context, scripts );
532
+ if ( scripts ) {
533
+ jQuery( scripts ).remove();
534
+ }
535
+ return jQuery.merge( [], parsed.childNodes );
536
+ },
537
+
538
+ parseJSON: function( data ) {
539
+ // Attempt to parse using the native JSON parser first
540
+ if ( window.JSON && window.JSON.parse ) {
541
+ return window.JSON.parse( data );
542
+ }
543
+
544
+ if ( data === null ) {
545
+ return data;
546
+ }
547
+
548
+ if ( typeof data === "string" ) {
549
+
550
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
551
+ data = jQuery.trim( data );
552
+
553
+ if ( data ) {
554
+ // Make sure the incoming data is actual JSON
555
+ // Logic borrowed from http://json.org/json2.js
556
+ if ( rvalidchars.test( data.replace( rvalidescape, "@" )
557
+ .replace( rvalidtokens, "]" )
558
+ .replace( rvalidbraces, "")) ) {
559
+
560
+ return ( new Function( "return " + data ) )();
561
+ }
562
+ }
563
+ }
564
+
565
+ jQuery.error( "Invalid JSON: " + data );
566
+ },
567
+
568
+ // Cross-browser xml parsing
569
+ parseXML: function( data ) {
570
+ var xml, tmp;
571
+ if ( !data || typeof data !== "string" ) {
572
+ return null;
573
+ }
574
+ try {
575
+ if ( window.DOMParser ) { // Standard
576
+ tmp = new DOMParser();
577
+ xml = tmp.parseFromString( data , "text/xml" );
578
+ } else { // IE
579
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
580
+ xml.async = "false";
581
+ xml.loadXML( data );
582
+ }
583
+ } catch( e ) {
584
+ xml = undefined;
585
+ }
586
+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
587
+ jQuery.error( "Invalid XML: " + data );
588
+ }
589
+ return xml;
590
+ },
591
+
592
+ noop: function() {},
593
+
594
+ // Evaluates a script in a global context
595
+ // Workarounds based on findings by Jim Driscoll
596
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
597
+ globalEval: function( data ) {
598
+ if ( data && jQuery.trim( data ) ) {
599
+ // We use execScript on Internet Explorer
600
+ // We use an anonymous function so that context is window
601
+ // rather than jQuery in Firefox
602
+ ( window.execScript || function( data ) {
603
+ window[ "eval" ].call( window, data );
604
+ } )( data );
605
+ }
606
+ },
607
+
608
+ // Convert dashed to camelCase; used by the css and data modules
609
+ // Microsoft forgot to hump their vendor prefix (#9572)
610
+ camelCase: function( string ) {
611
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
612
+ },
613
+
614
+ nodeName: function( elem, name ) {
615
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
616
+ },
617
+
618
+ // args is for internal usage only
619
+ each: function( obj, callback, args ) {
620
+ var value,
621
+ i = 0,
622
+ length = obj.length,
623
+ isArray = isArraylike( obj );
624
+
625
+ if ( args ) {
626
+ if ( isArray ) {
627
+ for ( ; i < length; i++ ) {
628
+ value = callback.apply( obj[ i ], args );
629
+
630
+ if ( value === false ) {
631
+ break;
632
+ }
633
+ }
634
+ } else {
635
+ for ( i in obj ) {
636
+ value = callback.apply( obj[ i ], args );
637
+
638
+ if ( value === false ) {
639
+ break;
640
+ }
641
+ }
642
+ }
643
+
644
+ // A special, fast, case for the most common use of each
645
+ } else {
646
+ if ( isArray ) {
647
+ for ( ; i < length; i++ ) {
648
+ value = callback.call( obj[ i ], i, obj[ i ] );
649
+
650
+ if ( value === false ) {
651
+ break;
652
+ }
653
+ }
654
+ } else {
655
+ for ( i in obj ) {
656
+ value = callback.call( obj[ i ], i, obj[ i ] );
657
+
658
+ if ( value === false ) {
659
+ break;
660
+ }
661
+ }
662
+ }
663
+ }
664
+
665
+ return obj;
666
+ },
667
+
668
+ // Use native String.trim function wherever possible
669
+ trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
670
+ function( text ) {
671
+ return text == null ?
672
+ "" :
673
+ core_trim.call( text );
674
+ } :
675
+
676
+ // Otherwise use our own trimming functionality
677
+ function( text ) {
678
+ return text == null ?
679
+ "" :
680
+ ( text + "" ).replace( rtrim, "" );
681
+ },
682
+
683
+ // results is for internal usage only
684
+ makeArray: function( arr, results ) {
685
+ var ret = results || [];
686
+
687
+ if ( arr != null ) {
688
+ if ( isArraylike( Object(arr) ) ) {
689
+ jQuery.merge( ret,
690
+ typeof arr === "string" ?
691
+ [ arr ] : arr
692
+ );
693
+ } else {
694
+ core_push.call( ret, arr );
695
+ }
696
+ }
697
+
698
+ return ret;
699
+ },
700
+
701
+ inArray: function( elem, arr, i ) {
702
+ var len;
703
+
704
+ if ( arr ) {
705
+ if ( core_indexOf ) {
706
+ return core_indexOf.call( arr, elem, i );
707
+ }
708
+
709
+ len = arr.length;
710
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
711
+
712
+ for ( ; i < len; i++ ) {
713
+ // Skip accessing in sparse arrays
714
+ if ( i in arr && arr[ i ] === elem ) {
715
+ return i;
716
+ }
717
+ }
718
+ }
719
+
720
+ return -1;
721
+ },
722
+
723
+ merge: function( first, second ) {
724
+ var l = second.length,
725
+ i = first.length,
726
+ j = 0;
727
+
728
+ if ( typeof l === "number" ) {
729
+ for ( ; j < l; j++ ) {
730
+ first[ i++ ] = second[ j ];
731
+ }
732
+ } else {
733
+ while ( second[j] !== undefined ) {
734
+ first[ i++ ] = second[ j++ ];
735
+ }
736
+ }
737
+
738
+ first.length = i;
739
+
740
+ return first;
741
+ },
742
+
743
+ grep: function( elems, callback, inv ) {
744
+ var retVal,
745
+ ret = [],
746
+ i = 0,
747
+ length = elems.length;
748
+ inv = !!inv;
749
+
750
+ // Go through the array, only saving the items
751
+ // that pass the validator function
752
+ for ( ; i < length; i++ ) {
753
+ retVal = !!callback( elems[ i ], i );
754
+ if ( inv !== retVal ) {
755
+ ret.push( elems[ i ] );
756
+ }
757
+ }
758
+
759
+ return ret;
760
+ },
761
+
762
+ // arg is for internal usage only
763
+ map: function( elems, callback, arg ) {
764
+ var value,
765
+ i = 0,
766
+ length = elems.length,
767
+ isArray = isArraylike( elems ),
768
+ ret = [];
769
+
770
+ // Go through the array, translating each of the items to their
771
+ if ( isArray ) {
772
+ for ( ; i < length; i++ ) {
773
+ value = callback( elems[ i ], i, arg );
774
+
775
+ if ( value != null ) {
776
+ ret[ ret.length ] = value;
777
+ }
778
+ }
779
+
780
+ // Go through every key on the object,
781
+ } else {
782
+ for ( i in elems ) {
783
+ value = callback( elems[ i ], i, arg );
784
+
785
+ if ( value != null ) {
786
+ ret[ ret.length ] = value;
787
+ }
788
+ }
789
+ }
790
+
791
+ // Flatten any nested arrays
792
+ return core_concat.apply( [], ret );
793
+ },
794
+
795
+ // A global GUID counter for objects
796
+ guid: 1,
797
+
798
+ // Bind a function to a context, optionally partially applying any
799
+ // arguments.
800
+ proxy: function( fn, context ) {
801
+ var args, proxy, tmp;
802
+
803
+ if ( typeof context === "string" ) {
804
+ tmp = fn[ context ];
805
+ context = fn;
806
+ fn = tmp;
807
+ }
808
+
809
+ // Quick check to determine if target is callable, in the spec
810
+ // this throws a TypeError, but we will just return undefined.
811
+ if ( !jQuery.isFunction( fn ) ) {
812
+ return undefined;
813
+ }
814
+
815
+ // Simulated bind
816
+ args = core_slice.call( arguments, 2 );
817
+ proxy = function() {
818
+ return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
819
+ };
820
+
821
+ // Set the guid of unique handler to the same of original handler, so it can be removed
822
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
823
+
824
+ return proxy;
825
+ },
826
+
827
+ // Multifunctional method to get and set values of a collection
828
+ // The value/s can optionally be executed if it's a function
829
+ access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
830
+ var i = 0,
831
+ length = elems.length,
832
+ bulk = key == null;
833
+
834
+ // Sets many values
835
+ if ( jQuery.type( key ) === "object" ) {
836
+ chainable = true;
837
+ for ( i in key ) {
838
+ jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
839
+ }
840
+
841
+ // Sets one value
842
+ } else if ( value !== undefined ) {
843
+ chainable = true;
844
+
845
+ if ( !jQuery.isFunction( value ) ) {
846
+ raw = true;
847
+ }
848
+
849
+ if ( bulk ) {
850
+ // Bulk operations run against the entire set
851
+ if ( raw ) {
852
+ fn.call( elems, value );
853
+ fn = null;
854
+
855
+ // ...except when executing function values
856
+ } else {
857
+ bulk = fn;
858
+ fn = function( elem, key, value ) {
859
+ return bulk.call( jQuery( elem ), value );
860
+ };
861
+ }
862
+ }
863
+
864
+ if ( fn ) {
865
+ for ( ; i < length; i++ ) {
866
+ fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
867
+ }
868
+ }
869
+ }
870
+
871
+ return chainable ?
872
+ elems :
873
+
874
+ // Gets
875
+ bulk ?
876
+ fn.call( elems ) :
877
+ length ? fn( elems[0], key ) : emptyGet;
878
+ },
879
+
880
+ now: function() {
881
+ return ( new Date() ).getTime();
882
+ }
883
+ });
884
+
885
+ jQuery.ready.promise = function( obj ) {
886
+ if ( !readyList ) {
887
+
888
+ readyList = jQuery.Deferred();
889
+
890
+ // Catch cases where $(document).ready() is called after the browser event has already occurred.
891
+ // we once tried to use readyState "interactive" here, but it caused issues like the one
892
+ // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
893
+ if ( document.readyState === "complete" ) {
894
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
895
+ setTimeout( jQuery.ready );
896
+
897
+ // Standards-based browsers support DOMContentLoaded
898
+ } else if ( document.addEventListener ) {
899
+ // Use the handy event callback
900
+ document.addEventListener( "DOMContentLoaded", completed, false );
901
+
902
+ // A fallback to window.onload, that will always work
903
+ window.addEventListener( "load", completed, false );
904
+
905
+ // If IE event model is used
906
+ } else {
907
+ // Ensure firing before onload, maybe late but safe also for iframes
908
+ document.attachEvent( "onreadystatechange", completed );
909
+
910
+ // A fallback to window.onload, that will always work
911
+ window.attachEvent( "onload", completed );
912
+
913
+ // If IE and not a frame
914
+ // continually check to see if the document is ready
915
+ var top = false;
916
+
917
+ try {
918
+ top = window.frameElement == null && document.documentElement;
919
+ } catch(e) {}
920
+
921
+ if ( top && top.doScroll ) {
922
+ (function doScrollCheck() {
923
+ if ( !jQuery.isReady ) {
924
+
925
+ try {
926
+ // Use the trick by Diego Perini
927
+ // http://javascript.nwbox.com/IEContentLoaded/
928
+ top.doScroll("left");
929
+ } catch(e) {
930
+ return setTimeout( doScrollCheck, 50 );
931
+ }
932
+
933
+ // detach all dom ready events
934
+ detach();
935
+
936
+ // and execute any waiting functions
937
+ jQuery.ready();
938
+ }
939
+ })();
940
+ }
941
+ }
942
+ }
943
+ return readyList.promise( obj );
944
+ };
945
+
946
+ // Populate the class2type map
947
+ jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
948
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
949
+ });
950
+
951
+ function isArraylike( obj ) {
952
+ var length = obj.length,
953
+ type = jQuery.type( obj );
954
+
955
+ if ( jQuery.isWindow( obj ) ) {
956
+ return false;
957
+ }
958
+
959
+ if ( obj.nodeType === 1 && length ) {
960
+ return true;
961
+ }
962
+
963
+ return type === "array" || type !== "function" &&
964
+ ( length === 0 ||
965
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj );
966
+ }
967
+
968
+ // All jQuery objects should point back to these
969
+ rootjQuery = jQuery(document);
970
+ // String to Object options format cache
971
+ var optionsCache = {};
972
+
973
+ // Convert String-formatted options into Object-formatted ones and store in cache
974
+ function createOptions( options ) {
975
+ var object = optionsCache[ options ] = {};
976
+ jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
977
+ object[ flag ] = true;
978
+ });
979
+ return object;
980
+ }
981
+
982
+ /*
983
+ * Create a callback list using the following parameters:
984
+ *
985
+ * options: an optional list of space-separated options that will change how
986
+ * the callback list behaves or a more traditional option object
987
+ *
988
+ * By default a callback list will act like an event callback list and can be
989
+ * "fired" multiple times.
990
+ *
991
+ * Possible options:
992
+ *
993
+ * once: will ensure the callback list can only be fired once (like a Deferred)
994
+ *
995
+ * memory: will keep track of previous values and will call any callback added
996
+ * after the list has been fired right away with the latest "memorized"
997
+ * values (like a Deferred)
998
+ *
999
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
1000
+ *
1001
+ * stopOnFalse: interrupt callings when a callback returns false
1002
+ *
1003
+ */
1004
+ jQuery.Callbacks = function( options ) {
1005
+
1006
+ // Convert options from String-formatted to Object-formatted if needed
1007
+ // (we check in cache first)
1008
+ options = typeof options === "string" ?
1009
+ ( optionsCache[ options ] || createOptions( options ) ) :
1010
+ jQuery.extend( {}, options );
1011
+
1012
+ var // Flag to know if list is currently firing
1013
+ firing,
1014
+ // Last fire value (for non-forgettable lists)
1015
+ memory,
1016
+ // Flag to know if list was already fired
1017
+ fired,
1018
+ // End of the loop when firing
1019
+ firingLength,
1020
+ // Index of currently firing callback (modified by remove if needed)
1021
+ firingIndex,
1022
+ // First callback to fire (used internally by add and fireWith)
1023
+ firingStart,
1024
+ // Actual callback list
1025
+ list = [],
1026
+ // Stack of fire calls for repeatable lists
1027
+ stack = !options.once && [],
1028
+ // Fire callbacks
1029
+ fire = function( data ) {
1030
+ memory = options.memory && data;
1031
+ fired = true;
1032
+ firingIndex = firingStart || 0;
1033
+ firingStart = 0;
1034
+ firingLength = list.length;
1035
+ firing = true;
1036
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
1037
+ if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
1038
+ memory = false; // To prevent further calls using add
1039
+ break;
1040
+ }
1041
+ }
1042
+ firing = false;
1043
+ if ( list ) {
1044
+ if ( stack ) {
1045
+ if ( stack.length ) {
1046
+ fire( stack.shift() );
1047
+ }
1048
+ } else if ( memory ) {
1049
+ list = [];
1050
+ } else {
1051
+ self.disable();
1052
+ }
1053
+ }
1054
+ },
1055
+ // Actual Callbacks object
1056
+ self = {
1057
+ // Add a callback or a collection of callbacks to the list
1058
+ add: function() {
1059
+ if ( list ) {
1060
+ // First, we save the current length
1061
+ var start = list.length;
1062
+ (function add( args ) {
1063
+ jQuery.each( args, function( _, arg ) {
1064
+ var type = jQuery.type( arg );
1065
+ if ( type === "function" ) {
1066
+ if ( !options.unique || !self.has( arg ) ) {
1067
+ list.push( arg );
1068
+ }
1069
+ } else if ( arg && arg.length && type !== "string" ) {
1070
+ // Inspect recursively
1071
+ add( arg );
1072
+ }
1073
+ });
1074
+ })( arguments );
1075
+ // Do we need to add the callbacks to the
1076
+ // current firing batch?
1077
+ if ( firing ) {
1078
+ firingLength = list.length;
1079
+ // With memory, if we're not firing then
1080
+ // we should call right away
1081
+ } else if ( memory ) {
1082
+ firingStart = start;
1083
+ fire( memory );
1084
+ }
1085
+ }
1086
+ return this;
1087
+ },
1088
+ // Remove a callback from the list
1089
+ remove: function() {
1090
+ if ( list ) {
1091
+ jQuery.each( arguments, function( _, arg ) {
1092
+ var index;
1093
+ while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
1094
+ list.splice( index, 1 );
1095
+ // Handle firing indexes
1096
+ if ( firing ) {
1097
+ if ( index <= firingLength ) {
1098
+ firingLength--;
1099
+ }
1100
+ if ( index <= firingIndex ) {
1101
+ firingIndex--;
1102
+ }
1103
+ }
1104
+ }
1105
+ });
1106
+ }
1107
+ return this;
1108
+ },
1109
+ // Check if a given callback is in the list.
1110
+ // If no argument is given, return whether or not list has callbacks attached.
1111
+ has: function( fn ) {
1112
+ return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
1113
+ },
1114
+ // Remove all callbacks from the list
1115
+ empty: function() {
1116
+ list = [];
1117
+ return this;
1118
+ },
1119
+ // Have the list do nothing anymore
1120
+ disable: function() {
1121
+ list = stack = memory = undefined;
1122
+ return this;
1123
+ },
1124
+ // Is it disabled?
1125
+ disabled: function() {
1126
+ return !list;
1127
+ },
1128
+ // Lock the list in its current state
1129
+ lock: function() {
1130
+ stack = undefined;
1131
+ if ( !memory ) {
1132
+ self.disable();
1133
+ }
1134
+ return this;
1135
+ },
1136
+ // Is it locked?
1137
+ locked: function() {
1138
+ return !stack;
1139
+ },
1140
+ // Call all callbacks with the given context and arguments
1141
+ fireWith: function( context, args ) {
1142
+ args = args || [];
1143
+ args = [ context, args.slice ? args.slice() : args ];
1144
+ if ( list && ( !fired || stack ) ) {
1145
+ if ( firing ) {
1146
+ stack.push( args );
1147
+ } else {
1148
+ fire( args );
1149
+ }
1150
+ }
1151
+ return this;
1152
+ },
1153
+ // Call all the callbacks with the given arguments
1154
+ fire: function() {
1155
+ self.fireWith( this, arguments );
1156
+ return this;
1157
+ },
1158
+ // To know if the callbacks have already been called at least once
1159
+ fired: function() {
1160
+ return !!fired;
1161
+ }
1162
+ };
1163
+
1164
+ return self;
1165
+ };
1166
+ jQuery.extend({
1167
+
1168
+ Deferred: function( func ) {
1169
+ var tuples = [
1170
+ // action, add listener, listener list, final state
1171
+ [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
1172
+ [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
1173
+ [ "notify", "progress", jQuery.Callbacks("memory") ]
1174
+ ],
1175
+ state = "pending",
1176
+ promise = {
1177
+ state: function() {
1178
+ return state;
1179
+ },
1180
+ always: function() {
1181
+ deferred.done( arguments ).fail( arguments );
1182
+ return this;
1183
+ },
1184
+ then: function( /* fnDone, fnFail, fnProgress */ ) {
1185
+ var fns = arguments;
1186
+ return jQuery.Deferred(function( newDefer ) {
1187
+ jQuery.each( tuples, function( i, tuple ) {
1188
+ var action = tuple[ 0 ],
1189
+ fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
1190
+ // deferred[ done | fail | progress ] for forwarding actions to newDefer
1191
+ deferred[ tuple[1] ](function() {
1192
+ var returned = fn && fn.apply( this, arguments );
1193
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
1194
+ returned.promise()
1195
+ .done( newDefer.resolve )
1196
+ .fail( newDefer.reject )
1197
+ .progress( newDefer.notify );
1198
+ } else {
1199
+ newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
1200
+ }
1201
+ });
1202
+ });
1203
+ fns = null;
1204
+ }).promise();
1205
+ },
1206
+ // Get a promise for this deferred
1207
+ // If obj is provided, the promise aspect is added to the object
1208
+ promise: function( obj ) {
1209
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
1210
+ }
1211
+ },
1212
+ deferred = {};
1213
+
1214
+ // Keep pipe for back-compat
1215
+ promise.pipe = promise.then;
1216
+
1217
+ // Add list-specific methods
1218
+ jQuery.each( tuples, function( i, tuple ) {
1219
+ var list = tuple[ 2 ],
1220
+ stateString = tuple[ 3 ];
1221
+
1222
+ // promise[ done | fail | progress ] = list.add
1223
+ promise[ tuple[1] ] = list.add;
1224
+
1225
+ // Handle state
1226
+ if ( stateString ) {
1227
+ list.add(function() {
1228
+ // state = [ resolved | rejected ]
1229
+ state = stateString;
1230
+
1231
+ // [ reject_list | resolve_list ].disable; progress_list.lock
1232
+ }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
1233
+ }
1234
+
1235
+ // deferred[ resolve | reject | notify ]
1236
+ deferred[ tuple[0] ] = function() {
1237
+ deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
1238
+ return this;
1239
+ };
1240
+ deferred[ tuple[0] + "With" ] = list.fireWith;
1241
+ });
1242
+
1243
+ // Make the deferred a promise
1244
+ promise.promise( deferred );
1245
+
1246
+ // Call given func if any
1247
+ if ( func ) {
1248
+ func.call( deferred, deferred );
1249
+ }
1250
+
1251
+ // All done!
1252
+ return deferred;
1253
+ },
1254
+
1255
+ // Deferred helper
1256
+ when: function( subordinate /* , ..., subordinateN */ ) {
1257
+ var i = 0,
1258
+ resolveValues = core_slice.call( arguments ),
1259
+ length = resolveValues.length,
1260
+
1261
+ // the count of uncompleted subordinates
1262
+ remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
1263
+
1264
+ // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
1265
+ deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
1266
+
1267
+ // Update function for both resolve and progress values
1268
+ updateFunc = function( i, contexts, values ) {
1269
+ return function( value ) {
1270
+ contexts[ i ] = this;
1271
+ values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
1272
+ if( values === progressValues ) {
1273
+ deferred.notifyWith( contexts, values );
1274
+ } else if ( !( --remaining ) ) {
1275
+ deferred.resolveWith( contexts, values );
1276
+ }
1277
+ };
1278
+ },
1279
+
1280
+ progressValues, progressContexts, resolveContexts;
1281
+
1282
+ // add listeners to Deferred subordinates; treat others as resolved
1283
+ if ( length > 1 ) {
1284
+ progressValues = new Array( length );
1285
+ progressContexts = new Array( length );
1286
+ resolveContexts = new Array( length );
1287
+ for ( ; i < length; i++ ) {
1288
+ if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
1289
+ resolveValues[ i ].promise()
1290
+ .done( updateFunc( i, resolveContexts, resolveValues ) )
1291
+ .fail( deferred.reject )
1292
+ .progress( updateFunc( i, progressContexts, progressValues ) );
1293
+ } else {
1294
+ --remaining;
1295
+ }
1296
+ }
1297
+ }
1298
+
1299
+ // if we're not waiting on anything, resolve the master
1300
+ if ( !remaining ) {
1301
+ deferred.resolveWith( resolveContexts, resolveValues );
1302
+ }
1303
+
1304
+ return deferred.promise();
1305
+ }
1306
+ });
1307
+ jQuery.support = (function() {
1308
+
1309
+ var support, all, a,
1310
+ input, select, fragment,
1311
+ opt, eventName, isSupported, i,
1312
+ div = document.createElement("div");
1313
+
1314
+ // Setup
1315
+ div.setAttribute( "className", "t" );
1316
+ div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
1317
+
1318
+ // Support tests won't run in some limited or non-browser environments
1319
+ all = div.getElementsByTagName("*");
1320
+ a = div.getElementsByTagName("a")[ 0 ];
1321
+ if ( !all || !a || !all.length ) {
1322
+ return {};
1323
+ }
1324
+
1325
+ // First batch of tests
1326
+ select = document.createElement("select");
1327
+ opt = select.appendChild( document.createElement("option") );
1328
+ input = div.getElementsByTagName("input")[ 0 ];
1329
+
1330
+ a.style.cssText = "top:1px;float:left;opacity:.5";
1331
+ support = {
1332
+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
1333
+ getSetAttribute: div.className !== "t",
1334
+
1335
+ // IE strips leading whitespace when .innerHTML is used
1336
+ leadingWhitespace: div.firstChild.nodeType === 3,
1337
+
1338
+ // Make sure that tbody elements aren't automatically inserted
1339
+ // IE will insert them into empty tables
1340
+ tbody: !div.getElementsByTagName("tbody").length,
1341
+
1342
+ // Make sure that link elements get serialized correctly by innerHTML
1343
+ // This requires a wrapper element in IE
1344
+ htmlSerialize: !!div.getElementsByTagName("link").length,
1345
+
1346
+ // Get the style information from getAttribute
1347
+ // (IE uses .cssText instead)
1348
+ style: /top/.test( a.getAttribute("style") ),
1349
+
1350
+ // Make sure that URLs aren't manipulated
1351
+ // (IE normalizes it by default)
1352
+ hrefNormalized: a.getAttribute("href") === "/a",
1353
+
1354
+ // Make sure that element opacity exists
1355
+ // (IE uses filter instead)
1356
+ // Use a regex to work around a WebKit issue. See #5145
1357
+ opacity: /^0.5/.test( a.style.opacity ),
1358
+
1359
+ // Verify style float existence
1360
+ // (IE uses styleFloat instead of cssFloat)
1361
+ cssFloat: !!a.style.cssFloat,
1362
+
1363
+ // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
1364
+ checkOn: !!input.value,
1365
+
1366
+ // Make sure that a selected-by-default option has a working selected property.
1367
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
1368
+ optSelected: opt.selected,
1369
+
1370
+ // Tests for enctype support on a form (#6743)
1371
+ enctype: !!document.createElement("form").enctype,
1372
+
1373
+ // Makes sure cloning an html5 element does not cause problems
1374
+ // Where outerHTML is undefined, this still works
1375
+ html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
1376
+
1377
+ // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
1378
+ boxModel: document.compatMode === "CSS1Compat",
1379
+
1380
+ // Will be defined later
1381
+ deleteExpando: true,
1382
+ noCloneEvent: true,
1383
+ inlineBlockNeedsLayout: false,
1384
+ shrinkWrapBlocks: false,
1385
+ reliableMarginRight: true,
1386
+ boxSizingReliable: true,
1387
+ pixelPosition: false
1388
+ };
1389
+
1390
+ // Make sure checked status is properly cloned
1391
+ input.checked = true;
1392
+ support.noCloneChecked = input.cloneNode( true ).checked;
1393
+
1394
+ // Make sure that the options inside disabled selects aren't marked as disabled
1395
+ // (WebKit marks them as disabled)
1396
+ select.disabled = true;
1397
+ support.optDisabled = !opt.disabled;
1398
+
1399
+ // Support: IE<9
1400
+ try {
1401
+ delete div.test;
1402
+ } catch( e ) {
1403
+ support.deleteExpando = false;
1404
+ }
1405
+
1406
+ // Check if we can trust getAttribute("value")
1407
+ input = document.createElement("input");
1408
+ input.setAttribute( "value", "" );
1409
+ support.input = input.getAttribute( "value" ) === "";
1410
+
1411
+ // Check if an input maintains its value after becoming a radio
1412
+ input.value = "t";
1413
+ input.setAttribute( "type", "radio" );
1414
+ support.radioValue = input.value === "t";
1415
+
1416
+ // #11217 - WebKit loses check when the name is after the checked attribute
1417
+ input.setAttribute( "checked", "t" );
1418
+ input.setAttribute( "name", "t" );
1419
+
1420
+ fragment = document.createDocumentFragment();
1421
+ fragment.appendChild( input );
1422
+
1423
+ // Check if a disconnected checkbox will retain its checked
1424
+ // value of true after appended to the DOM (IE6/7)
1425
+ support.appendChecked = input.checked;
1426
+
1427
+ // WebKit doesn't clone checked state correctly in fragments
1428
+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
1429
+
1430
+ // Support: IE<9
1431
+ // Opera does not clone events (and typeof div.attachEvent === undefined).
1432
+ // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
1433
+ if ( div.attachEvent ) {
1434
+ div.attachEvent( "onclick", function() {
1435
+ support.noCloneEvent = false;
1436
+ });
1437
+
1438
+ div.cloneNode( true ).click();
1439
+ }
1440
+
1441
+ // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)
1442
+ // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php
1443
+ for ( i in {
1444
+ submit: true,
1445
+ change: true,
1446
+ focusin: true
1447
+ }) {
1448
+ div.setAttribute( eventName = "on" + i, "t" );
1449
+
1450
+ support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false;
1451
+ }
1452
+
1453
+ div.style.backgroundClip = "content-box";
1454
+ div.cloneNode( true ).style.backgroundClip = "";
1455
+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
1456
+
1457
+ // Run tests that need a body at doc ready
1458
+ jQuery(function() {
1459
+ var container, marginDiv, tds,
1460
+ divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
1461
+ body = document.getElementsByTagName("body")[0];
1462
+
1463
+ if ( !body ) {
1464
+ // Return for frameset docs that don't have a body
1465
+ return;
1466
+ }
1467
+
1468
+ container = document.createElement("div");
1469
+ container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
1470
+
1471
+ body.appendChild( container ).appendChild( div );
1472
+
1473
+ // Support: IE8
1474
+ // Check if table cells still have offsetWidth/Height when they are set
1475
+ // to display:none and there are still other visible table cells in a
1476
+ // table row; if so, offsetWidth/Height are not reliable for use when
1477
+ // determining if an element has been hidden directly using
1478
+ // display:none (it is still safe to use offsets if a parent element is
1479
+ // hidden; don safety goggles and see bug #4512 for more information).
1480
+ div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
1481
+ tds = div.getElementsByTagName("td");
1482
+ tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
1483
+ isSupported = ( tds[ 0 ].offsetHeight === 0 );
1484
+
1485
+ tds[ 0 ].style.display = "";
1486
+ tds[ 1 ].style.display = "none";
1487
+
1488
+ // Support: IE8
1489
+ // Check if empty table cells still have offsetWidth/Height
1490
+ support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
1491
+
1492
+ // Check box-sizing and margin behavior
1493
+ div.innerHTML = "";
1494
+ 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%;";
1495
+ support.boxSizing = ( div.offsetWidth === 4 );
1496
+ support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
1497
+
1498
+ // Use window.getComputedStyle because jsdom on node.js will break without it.
1499
+ if ( window.getComputedStyle ) {
1500
+ support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
1501
+ support.boxSizingReliable = ( window.getComputedStyle( div, null ) || {
1502
+ width: "4px"
1503
+ } ).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({
3134
+ elem: cur,
3135
+ handlers: matches
3136
+ });
3137
+ }
3138
+ }
3139
+ }
3140
+ }
3141
+
3142
+ // Add the remaining (directly-bound) handlers
3143
+ if ( delegateCount < handlers.length ) {
3144
+ handlerQueue.push({
3145
+ elem: this,
3146
+ handlers: handlers.slice( delegateCount )
3147
+ });
3148
+ }
3149
+
3150
+ return handlerQueue;
3151
+ },
3152
+
3153
+ fix: function( event ) {
3154
+ if ( event[ jQuery.expando ] ) {
3155
+ return event;
3156
+ }
3157
+
3158
+ // Create a writable copy of the event object and normalize some properties
3159
+ var i, prop, copy,
3160
+ type = event.type,
3161
+ originalEvent = event,
3162
+ fixHook = this.fixHooks[ type ];
3163
+
3164
+ if ( !fixHook ) {
3165
+ this.fixHooks[ type ] = fixHook =
3166
+ rmouseEvent.test( type ) ? this.mouseHooks :
3167
+ rkeyEvent.test( type ) ? this.keyHooks :
3168
+ {};
3169
+ }
3170
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
3171
+
3172
+ event = new jQuery.Event( originalEvent );
3173
+
3174
+ i = copy.length;
3175
+ while ( i-- ) {
3176
+ prop = copy[ i ];
3177
+ event[ prop ] = originalEvent[ prop ];
3178
+ }
3179
+
3180
+ // Support: IE<9
3181
+ // Fix target property (#1925)
3182
+ if ( !event.target ) {
3183
+ event.target = originalEvent.srcElement || document;
3184
+ }
3185
+
3186
+ // Support: Chrome 23+, Safari?
3187
+ // Target should not be a text node (#504, #13143)
3188
+ if ( event.target.nodeType === 3 ) {
3189
+ event.target = event.target.parentNode;
3190
+ }
3191
+
3192
+ // Support: IE<9
3193
+ // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
3194
+ event.metaKey = !!event.metaKey;
3195
+
3196
+ return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
3197
+ },
3198
+
3199
+ // Includes some event props shared by KeyEvent and MouseEvent
3200
+ props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
3201
+
3202
+ fixHooks: {},
3203
+
3204
+ keyHooks: {
3205
+ props: "char charCode key keyCode".split(" "),
3206
+ filter: function( event, original ) {
3207
+
3208
+ // Add which for key events
3209
+ if ( event.which == null ) {
3210
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
3211
+ }
3212
+
3213
+ return event;
3214
+ }
3215
+ },
3216
+
3217
+ mouseHooks: {
3218
+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
3219
+ filter: function( event, original ) {
3220
+ var body, eventDoc, doc,
3221
+ button = original.button,
3222
+ fromElement = original.fromElement;
3223
+
3224
+ // Calculate pageX/Y if missing and clientX/Y available
3225
+ if ( event.pageX == null && original.clientX != null ) {
3226
+ eventDoc = event.target.ownerDocument || document;
3227
+ doc = eventDoc.documentElement;
3228
+ body = eventDoc.body;
3229
+
3230
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
3231
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
3232
+ }
3233
+
3234
+ // Add relatedTarget, if necessary
3235
+ if ( !event.relatedTarget && fromElement ) {
3236
+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
3237
+ }
3238
+
3239
+ // Add which for click: 1 === left; 2 === middle; 3 === right
3240
+ // Note: button is not normalized, so don't use it
3241
+ if ( !event.which && button !== undefined ) {
3242
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
3243
+ }
3244
+
3245
+ return event;
3246
+ }
3247
+ },
3248
+
3249
+ special: {
3250
+ load: {
3251
+ // Prevent triggered image.load events from bubbling to window.load
3252
+ noBubble: true
3253
+ },
3254
+ click: {
3255
+ // For checkbox, fire native event so checked state will be right
3256
+ trigger: function() {
3257
+ if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
3258
+ this.click();
3259
+ return false;
3260
+ }
3261
+ }
3262
+ },
3263
+ focus: {
3264
+ // Fire native event if possible so blur/focus sequence is correct
3265
+ trigger: function() {
3266
+ if ( this !== document.activeElement && this.focus ) {
3267
+ try {
3268
+ this.focus();
3269
+ return false;
3270
+ } catch ( e ) {
3271
+ // Support: IE<9
3272
+ // If we error on focus to hidden element (#1486, #12518),
3273
+ // let .trigger() run the handlers
3274
+ }
3275
+ }
3276
+ },
3277
+ delegateType: "focusin"
3278
+ },
3279
+ blur: {
3280
+ trigger: function() {
3281
+ if ( this === document.activeElement && this.blur ) {
3282
+ this.blur();
3283
+ return false;
3284
+ }
3285
+ },
3286
+ delegateType: "focusout"
3287
+ },
3288
+
3289
+ beforeunload: {
3290
+ postDispatch: function( event ) {
3291
+
3292
+ // Even when returnValue equals to undefined Firefox will still show alert
3293
+ if ( event.result !== undefined ) {
3294
+ event.originalEvent.returnValue = event.result;
3295
+ }
3296
+ }
3297
+ }
3298
+ },
3299
+
3300
+ simulate: function( type, elem, event, bubble ) {
3301
+ // Piggyback on a donor event to simulate a different one.
3302
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
3303
+ // simulated event prevents default then we do the same on the donor.
3304
+ var e = jQuery.extend(
3305
+ new jQuery.Event(),
3306
+ event,
3307
+ {
3308
+ type: type,
3309
+ isSimulated: true,
3310
+ originalEvent: {}
3311
+ }
3312
+ );
3313
+ if ( bubble ) {
3314
+ jQuery.event.trigger( e, null, elem );
3315
+ } else {
3316
+ jQuery.event.dispatch.call( elem, e );
3317
+ }
3318
+ if ( e.isDefaultPrevented() ) {
3319
+ event.preventDefault();
3320
+ }
3321
+ }
3322
+ };
3323
+
3324
+ jQuery.removeEvent = document.removeEventListener ?
3325
+ function( elem, type, handle ) {
3326
+ if ( elem.removeEventListener ) {
3327
+ elem.removeEventListener( type, handle, false );
3328
+ }
3329
+ } :
3330
+ function( elem, type, handle ) {
3331
+ var name = "on" + type;
3332
+
3333
+ if ( elem.detachEvent ) {
3334
+
3335
+ // #8545, #7054, preventing memory leaks for custom events in IE6-8
3336
+ // detachEvent needed property on element, by name of that event, to properly expose it to GC
3337
+ if ( typeof elem[ name ] === core_strundefined ) {
3338
+ elem[ name ] = null;
3339
+ }
3340
+
3341
+ elem.detachEvent( name, handle );
3342
+ }
3343
+ };
3344
+
3345
+ jQuery.Event = function( src, props ) {
3346
+ // Allow instantiation without the 'new' keyword
3347
+ if ( !(this instanceof jQuery.Event) ) {
3348
+ return new jQuery.Event( src, props );
3349
+ }
3350
+
3351
+ // Event object
3352
+ if ( src && src.type ) {
3353
+ this.originalEvent = src;
3354
+ this.type = src.type;
3355
+
3356
+ // Events bubbling up the document may have been marked as prevented
3357
+ // by a handler lower down the tree; reflect the correct value.
3358
+ this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
3359
+ src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
3360
+
3361
+ // Event type
3362
+ } else {
3363
+ this.type = src;
3364
+ }
3365
+
3366
+ // Put explicitly provided properties onto the event object
3367
+ if ( props ) {
3368
+ jQuery.extend( this, props );
3369
+ }
3370
+
3371
+ // Create a timestamp if incoming event doesn't have one
3372
+ this.timeStamp = src && src.timeStamp || jQuery.now();
3373
+
3374
+ // Mark it as fixed
3375
+ this[ jQuery.expando ] = true;
3376
+ };
3377
+
3378
+ // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
3379
+ // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
3380
+ jQuery.Event.prototype = {
3381
+ isDefaultPrevented: returnFalse,
3382
+ isPropagationStopped: returnFalse,
3383
+ isImmediatePropagationStopped: returnFalse,
3384
+
3385
+ preventDefault: function() {
3386
+ var e = this.originalEvent;
3387
+
3388
+ this.isDefaultPrevented = returnTrue;
3389
+ if ( !e ) {
3390
+ return;
3391
+ }
3392
+
3393
+ // If preventDefault exists, run it on the original event
3394
+ if ( e.preventDefault ) {
3395
+ e.preventDefault();
3396
+
3397
+ // Support: IE
3398
+ // Otherwise set the returnValue property of the original event to false
3399
+ } else {
3400
+ e.returnValue = false;
3401
+ }
3402
+ },
3403
+ stopPropagation: function() {
3404
+ var e = this.originalEvent;
3405
+
3406
+ this.isPropagationStopped = returnTrue;
3407
+ if ( !e ) {
3408
+ return;
3409
+ }
3410
+ // If stopPropagation exists, run it on the original event
3411
+ if ( e.stopPropagation ) {
3412
+ e.stopPropagation();
3413
+ }
3414
+
3415
+ // Support: IE
3416
+ // Set the cancelBubble property of the original event to true
3417
+ e.cancelBubble = true;
3418
+ },
3419
+ stopImmediatePropagation: function() {
3420
+ this.isImmediatePropagationStopped = returnTrue;
3421
+ this.stopPropagation();
3422
+ }
3423
+ };
3424
+
3425
+ // Create mouseenter/leave events using mouseover/out and event-time checks
3426
+ jQuery.each({
3427
+ mouseenter: "mouseover",
3428
+ mouseleave: "mouseout"
3429
+ }, function( orig, fix ) {
3430
+ jQuery.event.special[ orig ] = {
3431
+ delegateType: fix,
3432
+ bindType: fix,
3433
+
3434
+ handle: function( event ) {
3435
+ var ret,
3436
+ target = this,
3437
+ related = event.relatedTarget,
3438
+ handleObj = event.handleObj;
3439
+
3440
+ // For mousenter/leave call the handler if related is outside the target.
3441
+ // NB: No relatedTarget if the mouse left/entered the browser window
3442
+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
3443
+ event.type = handleObj.origType;
3444
+ ret = handleObj.handler.apply( this, arguments );
3445
+ event.type = fix;
3446
+ }
3447
+ return ret;
3448
+ }
3449
+ };
3450
+ });
3451
+
3452
+ // IE submit delegation
3453
+ if ( !jQuery.support.submitBubbles ) {
3454
+
3455
+ jQuery.event.special.submit = {
3456
+ setup: function() {
3457
+ // Only need this for delegated form submit events
3458
+ if ( jQuery.nodeName( this, "form" ) ) {
3459
+ return false;
3460
+ }
3461
+
3462
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
3463
+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
3464
+ // Node name check avoids a VML-related crash in IE (#9807)
3465
+ var elem = e.target,
3466
+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
3467
+ if ( form && !jQuery._data( form, "submitBubbles" ) ) {
3468
+ jQuery.event.add( form, "submit._submit", function( event ) {
3469
+ event._submit_bubble = true;
3470
+ });
3471
+ jQuery._data( form, "submitBubbles", true );
3472
+ }
3473
+ });
3474
+ // return undefined since we don't need an event listener
3475
+ },
3476
+
3477
+ postDispatch: function( event ) {
3478
+ // If form was submitted by the user, bubble the event up the tree
3479
+ if ( event._submit_bubble ) {
3480
+ delete event._submit_bubble;
3481
+ if ( this.parentNode && !event.isTrigger ) {
3482
+ jQuery.event.simulate( "submit", this.parentNode, event, true );
3483
+ }
3484
+ }
3485
+ },
3486
+
3487
+ teardown: function() {
3488
+ // Only need this for delegated form submit events
3489
+ if ( jQuery.nodeName( this, "form" ) ) {
3490
+ return false;
3491
+ }
3492
+
3493
+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
3494
+ jQuery.event.remove( this, "._submit" );
3495
+ }
3496
+ };
3497
+ }
3498
+
3499
+ // IE change delegation and checkbox/radio fix
3500
+ if ( !jQuery.support.changeBubbles ) {
3501
+
3502
+ jQuery.event.special.change = {
3503
+
3504
+ setup: function() {
3505
+
3506
+ if ( rformElems.test( this.nodeName ) ) {
3507
+ // IE doesn't fire change on a check/radio until blur; trigger it on click
3508
+ // after a propertychange. Eat the blur-change in special.change.handle.
3509
+ // This still fires onchange a second time for check/radio after blur.
3510
+ if ( this.type === "checkbox" || this.type === "radio" ) {
3511
+ jQuery.event.add( this, "propertychange._change", function( event ) {
3512
+ if ( event.originalEvent.propertyName === "checked" ) {
3513
+ this._just_changed = true;
3514
+ }
3515
+ });
3516
+ jQuery.event.add( this, "click._change", function( event ) {
3517
+ if ( this._just_changed && !event.isTrigger ) {
3518
+ this._just_changed = false;
3519
+ }
3520
+ // Allow triggered, simulated change events (#11500)
3521
+ jQuery.event.simulate( "change", this, event, true );
3522
+ });
3523
+ }
3524
+ return false;
3525
+ }
3526
+ // Delegated event; lazy-add a change handler on descendant inputs
3527
+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
3528
+ var elem = e.target;
3529
+
3530
+ if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
3531
+ jQuery.event.add( elem, "change._change", function( event ) {
3532
+ if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
3533
+ jQuery.event.simulate( "change", this.parentNode, event, true );
3534
+ }
3535
+ });
3536
+ jQuery._data( elem, "changeBubbles", true );
3537
+ }
3538
+ });
3539
+ },
3540
+
3541
+ handle: function( event ) {
3542
+ var elem = event.target;
3543
+
3544
+ // Swallow native change events from checkbox/radio, we already triggered them above
3545
+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
3546
+ return event.handleObj.handler.apply( this, arguments );
3547
+ }
3548
+ },
3549
+
3550
+ teardown: function() {
3551
+ jQuery.event.remove( this, "._change" );
3552
+
3553
+ return !rformElems.test( this.nodeName );
3554
+ }
3555
+ };
3556
+ }
3557
+
3558
+ // Create "bubbling" focus and blur events
3559
+ if ( !jQuery.support.focusinBubbles ) {
3560
+ jQuery.each({
3561
+ focus: "focusin",
3562
+ blur: "focusout"
3563
+ }, function( orig, fix ) {
3564
+
3565
+ // Attach a single capturing handler while someone wants focusin/focusout
3566
+ var attaches = 0,
3567
+ handler = function( event ) {
3568
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
3569
+ };
3570
+
3571
+ jQuery.event.special[ fix ] = {
3572
+ setup: function() {
3573
+ if ( attaches++ === 0 ) {
3574
+ document.addEventListener( orig, handler, true );
3575
+ }
3576
+ },
3577
+ teardown: function() {
3578
+ if ( --attaches === 0 ) {
3579
+ document.removeEventListener( orig, handler, true );
3580
+ }
3581
+ }
3582
+ };
3583
+ });
3584
+ }
3585
+
3586
+ jQuery.fn.extend({
3587
+
3588
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
3589
+ var type, origFn;
3590
+
3591
+ // Types can be a map of types/handlers
3592
+ if ( typeof types === "object" ) {
3593
+ // ( types-Object, selector, data )
3594
+ if ( typeof selector !== "string" ) {
3595
+ // ( types-Object, data )
3596
+ data = data || selector;
3597
+ selector = undefined;
3598
+ }
3599
+ for ( type in types ) {
3600
+ this.on( type, selector, data, types[ type ], one );
3601
+ }
3602
+ return this;
3603
+ }
3604
+
3605
+ if ( data == null && fn == null ) {
3606
+ // ( types, fn )
3607
+ fn = selector;
3608
+ data = selector = undefined;
3609
+ } else if ( fn == null ) {
3610
+ if ( typeof selector === "string" ) {
3611
+ // ( types, selector, fn )
3612
+ fn = data;
3613
+ data = undefined;
3614
+ } else {
3615
+ // ( types, data, fn )
3616
+ fn = data;
3617
+ data = selector;
3618
+ selector = undefined;
3619
+ }
3620
+ }
3621
+ if ( fn === false ) {
3622
+ fn = returnFalse;
3623
+ } else if ( !fn ) {
3624
+ return this;
3625
+ }
3626
+
3627
+ if ( one === 1 ) {
3628
+ origFn = fn;
3629
+ fn = function( event ) {
3630
+ // Can use an empty set, since event contains the info
3631
+ jQuery().off( event );
3632
+ return origFn.apply( this, arguments );
3633
+ };
3634
+ // Use same guid so caller can remove using origFn
3635
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
3636
+ }
3637
+ return this.each( function() {
3638
+ jQuery.event.add( this, types, fn, data, selector );
3639
+ });
3640
+ },
3641
+ one: function( types, selector, data, fn ) {
3642
+ return this.on( types, selector, data, fn, 1 );
3643
+ },
3644
+ off: function( types, selector, fn ) {
3645
+ var handleObj, type;
3646
+ if ( types && types.preventDefault && types.handleObj ) {
3647
+ // ( event ) dispatched jQuery.Event
3648
+ handleObj = types.handleObj;
3649
+ jQuery( types.delegateTarget ).off(
3650
+ handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
3651
+ handleObj.selector,
3652
+ handleObj.handler
3653
+ );
3654
+ return this;
3655
+ }
3656
+ if ( typeof types === "object" ) {
3657
+ // ( types-object [, selector] )
3658
+ for ( type in types ) {
3659
+ this.off( type, selector, types[ type ] );
3660
+ }
3661
+ return this;
3662
+ }
3663
+ if ( selector === false || typeof selector === "function" ) {
3664
+ // ( types [, fn] )
3665
+ fn = selector;
3666
+ selector = undefined;
3667
+ }
3668
+ if ( fn === false ) {
3669
+ fn = returnFalse;
3670
+ }
3671
+ return this.each(function() {
3672
+ jQuery.event.remove( this, types, fn, selector );
3673
+ });
3674
+ },
3675
+
3676
+ bind: function( types, data, fn ) {
3677
+ return this.on( types, null, data, fn );
3678
+ },
3679
+ unbind: function( types, fn ) {
3680
+ return this.off( types, null, fn );
3681
+ },
3682
+
3683
+ delegate: function( selector, types, data, fn ) {
3684
+ return this.on( types, selector, data, fn );
3685
+ },
3686
+ undelegate: function( selector, types, fn ) {
3687
+ // ( namespace ) or ( selector, types [, fn] )
3688
+ return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
3689
+ },
3690
+
3691
+ trigger: function( type, data ) {
3692
+ return this.each(function() {
3693
+ jQuery.event.trigger( type, data, this );
3694
+ });
3695
+ },
3696
+ triggerHandler: function( type, data ) {
3697
+ var elem = this[0];
3698
+ if ( elem ) {
3699
+ return jQuery.event.trigger( type, data, elem, true );
3700
+ }
3701
+ }
3702
+ });
3703
+ /*!
3704
+ * Sizzle CSS Selector Engine
3705
+ * Copyright 2012 jQuery Foundation and other contributors
3706
+ * Released under the MIT license
3707
+ * http://sizzlejs.com/
3708
+ */
3709
+ (function( window, undefined ) {
3710
+
3711
+ var i,
3712
+ cachedruns,
3713
+ Expr,
3714
+ getText,
3715
+ isXML,
3716
+ compile,
3717
+ hasDuplicate,
3718
+ outermostContext,
3719
+
3720
+ // Local document vars
3721
+ setDocument,
3722
+ document,
3723
+ docElem,
3724
+ documentIsXML,
3725
+ rbuggyQSA,
3726
+ rbuggyMatches,
3727
+ matches,
3728
+ contains,
3729
+ sortOrder,
3730
+
3731
+ // Instance-specific data
3732
+ expando = "sizzle" + -(new Date()),
3733
+ preferredDoc = window.document,
3734
+ support = {},
3735
+ dirruns = 0,
3736
+ done = 0,
3737
+ classCache = createCache(),
3738
+ tokenCache = createCache(),
3739
+ compilerCache = createCache(),
3740
+
3741
+ // General-purpose constants
3742
+ strundefined = typeof undefined,
3743
+ MAX_NEGATIVE = 1 << 31,
3744
+
3745
+ // Array methods
3746
+ arr = [],
3747
+ pop = arr.pop,
3748
+ push = arr.push,
3749
+ slice = arr.slice,
3750
+ // Use a stripped-down indexOf if we can't use a native one
3751
+ indexOf = arr.indexOf || function( elem ) {
3752
+ var i = 0,
3753
+ len = this.length;
3754
+ for ( ; i < len; i++ ) {
3755
+ if ( this[i] === elem ) {
3756
+ return i;
3757
+ }
3758
+ }
3759
+ return -1;
3760
+ },
3761
+
3762
+
3763
+ // Regular expressions
3764
+
3765
+ // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
3766
+ whitespace = "[\\x20\\t\\r\\n\\f]",
3767
+ // http://www.w3.org/TR/css3-syntax/#characters
3768
+ characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
3769
+
3770
+ // Loosely modeled on CSS identifier characters
3771
+ // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
3772
+ // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
3773
+ identifier = characterEncoding.replace( "w", "w#" ),
3774
+
3775
+ // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
3776
+ operators = "([*^$|!~]?=)",
3777
+ attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
3778
+ "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
3779
+
3780
+ // Prefer arguments quoted,
3781
+ // then not containing pseudos/brackets,
3782
+ // then attribute selectors/non-parenthetical expressions,
3783
+ // then anything else
3784
+ // These preferences are here to reduce the number of selectors
3785
+ // needing tokenize in the PSEUDO preFilter
3786
+ pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
3787
+
3788
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
3789
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
3790
+
3791
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
3792
+ rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),
3793
+ rpseudo = new RegExp( pseudos ),
3794
+ ridentifier = new RegExp( "^" + identifier + "$" ),
3795
+
3796
+ matchExpr = {
3797
+ "ID": new RegExp( "^#(" + characterEncoding + ")" ),
3798
+ "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
3799
+ "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),
3800
+ "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
3801
+ "ATTR": new RegExp( "^" + attributes ),
3802
+ "PSEUDO": new RegExp( "^" + pseudos ),
3803
+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
3804
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
3805
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
3806
+ // For use in libraries implementing .is()
3807
+ // We use this for POS matching in `select`
3808
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
3809
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
3810
+ },
3811
+
3812
+ rsibling = /[\x20\t\r\n\f]*[+~]/,
3813
+
3814
+ rnative = /^[^{]+\{\s*\[native code/,
3815
+
3816
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
3817
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
3818
+
3819
+ rinputs = /^(?:input|select|textarea|button)$/i,
3820
+ rheader = /^h\d$/i,
3821
+
3822
+ rescape = /'|\\/g,
3823
+ rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
3824
+
3825
+ // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
3826
+ runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,
3827
+ funescape = function( _, escaped ) {
3828
+ var high = "0x" + escaped - 0x10000;
3829
+ // NaN means non-codepoint
3830
+ return high !== high ?
3831
+ escaped :
3832
+ // BMP codepoint
3833
+ high < 0 ?
3834
+ String.fromCharCode( high + 0x10000 ) :
3835
+ // Supplemental Plane codepoint (surrogate pair)
3836
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
3837
+ };
3838
+
3839
+ // Use a stripped-down slice if we can't use a native one
3840
+ try {
3841
+ slice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType;
3842
+ } catch ( e ) {
3843
+ slice = function( i ) {
3844
+ var elem,
3845
+ results = [];
3846
+ while ( (elem = this[i++]) ) {
3847
+ results.push( elem );
3848
+ }
3849
+ return results;
3850
+ };
3851
+ }
3852
+
3853
+ /**
3854
+ * For feature detection
3855
+ * @param {Function} fn The function to test for native support
3856
+ */
3857
+ function isNative( fn ) {
3858
+ return rnative.test( fn + "" );
3859
+ }
3860
+
3861
+ /**
3862
+ * Create key-value caches of limited size
3863
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
3864
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
3865
+ * deleting the oldest entry
3866
+ */
3867
+ function createCache() {
3868
+ var cache,
3869
+ keys = [];
3870
+
3871
+ return (cache = function( key, value ) {
3872
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
3873
+ if ( keys.push( key += " " ) > Expr.cacheLength ) {
3874
+ // Only keep the most recent entries
3875
+ delete cache[ keys.shift() ];
3876
+ }
3877
+ return (cache[ key ] = value);
3878
+ });
3879
+ }
3880
+
3881
+ /**
3882
+ * Mark a function for special use by Sizzle
3883
+ * @param {Function} fn The function to mark
3884
+ */
3885
+ function markFunction( fn ) {
3886
+ fn[ expando ] = true;
3887
+ return fn;
3888
+ }
3889
+
3890
+ /**
3891
+ * Support testing using an element
3892
+ * @param {Function} fn Passed the created div and expects a boolean result
3893
+ */
3894
+ function assert( fn ) {
3895
+ var div = document.createElement("div");
3896
+
3897
+ try {
3898
+ return fn( div );
3899
+ } catch (e) {
3900
+ return false;
3901
+ } finally {
3902
+ // release memory in IE
3903
+ div = null;
3904
+ }
3905
+ }
3906
+
3907
+ function Sizzle( selector, context, results, seed ) {
3908
+ var match, elem, m, nodeType,
3909
+ // QSA vars
3910
+ i, groups, old, nid, newContext, newSelector;
3911
+
3912
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
3913
+ setDocument( context );
3914
+ }
3915
+
3916
+ context = context || document;
3917
+ results = results || [];
3918
+
3919
+ if ( !selector || typeof selector !== "string" ) {
3920
+ return results;
3921
+ }
3922
+
3923
+ if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
3924
+ return [];
3925
+ }
3926
+
3927
+ if ( !documentIsXML && !seed ) {
3928
+
3929
+ // Shortcuts
3930
+ if ( (match = rquickExpr.exec( selector )) ) {
3931
+ // Speed-up: Sizzle("#ID")
3932
+ if ( (m = match[1]) ) {
3933
+ if ( nodeType === 9 ) {
3934
+ elem = context.getElementById( m );
3935
+ // Check parentNode to catch when Blackberry 4.6 returns
3936
+ // nodes that are no longer in the document #6963
3937
+ if ( elem && elem.parentNode ) {
3938
+ // Handle the case where IE, Opera, and Webkit return items
3939
+ // by name instead of ID
3940
+ if ( elem.id === m ) {
3941
+ results.push( elem );
3942
+ return results;
3943
+ }
3944
+ } else {
3945
+ return results;
3946
+ }
3947
+ } else {
3948
+ // Context is not a document
3949
+ if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
3950
+ contains( context, elem ) && elem.id === m ) {
3951
+ results.push( elem );
3952
+ return results;
3953
+ }
3954
+ }
3955
+
3956
+ // Speed-up: Sizzle("TAG")
3957
+ } else if ( match[2] ) {
3958
+ push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );
3959
+ return results;
3960
+
3961
+ // Speed-up: Sizzle(".CLASS")
3962
+ } else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) {
3963
+ push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );
3964
+ return results;
3965
+ }
3966
+ }
3967
+
3968
+ // QSA path
3969
+ if ( support.qsa && !rbuggyQSA.test(selector) ) {
3970
+ old = true;
3971
+ nid = expando;
3972
+ newContext = context;
3973
+ newSelector = nodeType === 9 && selector;
3974
+
3975
+ // qSA works strangely on Element-rooted queries
3976
+ // We can work around this by specifying an extra ID on the root
3977
+ // and working up from there (Thanks to Andrew Dupont for the technique)
3978
+ // IE 8 doesn't work on object elements
3979
+ if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
3980
+ groups = tokenize( selector );
3981
+
3982
+ if ( (old = context.getAttribute("id")) ) {
3983
+ nid = old.replace( rescape, "\\$&" );
3984
+ } else {
3985
+ context.setAttribute( "id", nid );
3986
+ }
3987
+ nid = "[id='" + nid + "'] ";
3988
+
3989
+ i = groups.length;
3990
+ while ( i-- ) {
3991
+ groups[i] = nid + toSelector( groups[i] );
3992
+ }
3993
+ newContext = rsibling.test( selector ) && context.parentNode || context;
3994
+ newSelector = groups.join(",");
3995
+ }
3996
+
3997
+ if ( newSelector ) {
3998
+ try {
3999
+ push.apply( results, slice.call( newContext.querySelectorAll(
4000
+ newSelector
4001
+ ), 0 ) );
4002
+ return results;
4003
+ } catch(qsaError) {
4004
+ } finally {
4005
+ if ( !old ) {
4006
+ context.removeAttribute("id");
4007
+ }
4008
+ }
4009
+ }
4010
+ }
4011
+ }
4012
+
4013
+ // All others
4014
+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
4015
+ }
4016
+
4017
+ /**
4018
+ * Detect xml
4019
+ * @param {Element|Object} elem An element or a document
4020
+ */
4021
+ isXML = Sizzle.isXML = function( elem ) {
4022
+ // documentElement is verified for cases where it doesn't yet exist
4023
+ // (such as loading iframes in IE - #4833)
4024
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
4025
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
4026
+ };
4027
+
4028
+ /**
4029
+ * Sets document-related variables once based on the current document
4030
+ * @param {Element|Object} [doc] An element or document object to use to set the document
4031
+ * @returns {Object} Returns the current document
4032
+ */
4033
+ setDocument = Sizzle.setDocument = function( node ) {
4034
+ var doc = node ? node.ownerDocument || node : preferredDoc;
4035
+
4036
+ // If no document and documentElement is available, return
4037
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
4038
+ return document;
4039
+ }
4040
+
4041
+ // Set our document
4042
+ document = doc;
4043
+ docElem = doc.documentElement;
4044
+
4045
+ // Support tests
4046
+ documentIsXML = isXML( doc );
4047
+
4048
+ // Check if getElementsByTagName("*") returns only elements
4049
+ support.tagNameNoComments = assert(function( div ) {
4050
+ div.appendChild( doc.createComment("") );
4051
+ return !div.getElementsByTagName("*").length;
4052
+ });
4053
+
4054
+ // Check if attributes should be retrieved by attribute nodes
4055
+ support.attributes = assert(function( div ) {
4056
+ div.innerHTML = "<select></select>";
4057
+ var type = typeof div.lastChild.getAttribute("multiple");
4058
+ // IE8 returns a string for some attributes even when not present
4059
+ return type !== "boolean" && type !== "string";
4060
+ });
4061
+
4062
+ // Check if getElementsByClassName can be trusted
4063
+ support.getByClassName = assert(function( div ) {
4064
+ // Opera can't find a second classname (in 9.6)
4065
+ div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";
4066
+ if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {
4067
+ return false;
4068
+ }
4069
+
4070
+ // Safari 3.2 caches class attributes and doesn't catch changes
4071
+ div.lastChild.className = "e";
4072
+ return div.getElementsByClassName("e").length === 2;
4073
+ });
4074
+
4075
+ // Check if getElementById returns elements by name
4076
+ // Check if getElementsByName privileges form controls or returns elements by ID
4077
+ support.getByName = assert(function( div ) {
4078
+ // Inject content
4079
+ div.id = expando + 0;
4080
+ div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
4081
+ docElem.insertBefore( div, docElem.firstChild );
4082
+
4083
+ // Test
4084
+ var pass = doc.getElementsByName &&
4085
+ // buggy browsers will return fewer than the correct 2
4086
+ doc.getElementsByName( expando ).length === 2 +
4087
+ // buggy browsers will return more than the correct 0
4088
+ doc.getElementsByName( expando + 0 ).length;
4089
+ support.getIdNotName = !doc.getElementById( expando );
4090
+
4091
+ // Cleanup
4092
+ docElem.removeChild( div );
4093
+
4094
+ return pass;
4095
+ });
4096
+
4097
+ // IE6/7 return modified attributes
4098
+ Expr.attrHandle = assert(function( div ) {
4099
+ div.innerHTML = "<a href='#'></a>";
4100
+ return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
4101
+ div.firstChild.getAttribute("href") === "#";
4102
+ }) ?
4103
+ {} :
4104
+ {
4105
+ "href": function( elem ) {
4106
+ return elem.getAttribute( "href", 2 );
4107
+ },
4108
+ "type": function( elem ) {
4109
+ return elem.getAttribute("type");
4110
+ }
4111
+ };
4112
+
4113
+ // ID find and filter
4114
+ if ( support.getIdNotName ) {
4115
+ Expr.find["ID"] = function( id, context ) {
4116
+ if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
4117
+ var m = context.getElementById( id );
4118
+ // Check parentNode to catch when Blackberry 4.6 returns
4119
+ // nodes that are no longer in the document #6963
4120
+ return m && m.parentNode ? [m] : [];
4121
+ }
4122
+ };
4123
+ Expr.filter["ID"] = function( id ) {
4124
+ var attrId = id.replace( runescape, funescape );
4125
+ return function( elem ) {
4126
+ return elem.getAttribute("id") === attrId;
4127
+ };
4128
+ };
4129
+ } else {
4130
+ Expr.find["ID"] = function( id, context ) {
4131
+ if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
4132
+ var m = context.getElementById( id );
4133
+
4134
+ return m ?
4135
+ m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
4136
+ [m] :
4137
+ undefined :
4138
+ [];
4139
+ }
4140
+ };
4141
+ Expr.filter["ID"] = function( id ) {
4142
+ var attrId = id.replace( runescape, funescape );
4143
+ return function( elem ) {
4144
+ var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
4145
+ return node && node.value === attrId;
4146
+ };
4147
+ };
4148
+ }
4149
+
4150
+ // Tag
4151
+ Expr.find["TAG"] = support.tagNameNoComments ?
4152
+ function( tag, context ) {
4153
+ if ( typeof context.getElementsByTagName !== strundefined ) {
4154
+ return context.getElementsByTagName( tag );
4155
+ }
4156
+ } :
4157
+ function( tag, context ) {
4158
+ var elem,
4159
+ tmp = [],
4160
+ i = 0,
4161
+ results = context.getElementsByTagName( tag );
4162
+
4163
+ // Filter out possible comments
4164
+ if ( tag === "*" ) {
4165
+ while ( (elem = results[i++]) ) {
4166
+ if ( elem.nodeType === 1 ) {
4167
+ tmp.push( elem );
4168
+ }
4169
+ }
4170
+
4171
+ return tmp;
4172
+ }
4173
+ return results;
4174
+ };
4175
+
4176
+ // Name
4177
+ Expr.find["NAME"] = support.getByName && function( tag, context ) {
4178
+ if ( typeof context.getElementsByName !== strundefined ) {
4179
+ return context.getElementsByName( name );
4180
+ }
4181
+ };
4182
+
4183
+ // Class
4184
+ Expr.find["CLASS"] = support.getByClassName && function( className, context ) {
4185
+ if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) {
4186
+ return context.getElementsByClassName( className );
4187
+ }
4188
+ };
4189
+
4190
+ // QSA and matchesSelector support
4191
+
4192
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
4193
+ rbuggyMatches = [];
4194
+
4195
+ // qSa(:focus) reports false when true (Chrome 21),
4196
+ // no need to also add to buggyMatches since matches checks buggyQSA
4197
+ // A support test would require too much code (would include document ready)
4198
+ rbuggyQSA = [ ":focus" ];
4199
+
4200
+ if ( (support.qsa = isNative(doc.querySelectorAll)) ) {
4201
+ // Build QSA regex
4202
+ // Regex strategy adopted from Diego Perini
4203
+ assert(function( div ) {
4204
+ // Select is set to empty string on purpose
4205
+ // This is to test IE's treatment of not explictly
4206
+ // setting a boolean content attribute,
4207
+ // since its presence should be enough
4208
+ // http://bugs.jquery.com/ticket/12359
4209
+ div.innerHTML = "<select><option selected=''></option></select>";
4210
+
4211
+ // IE8 - Some boolean attributes are not treated correctly
4212
+ if ( !div.querySelectorAll("[selected]").length ) {
4213
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );
4214
+ }
4215
+
4216
+ // Webkit/Opera - :checked should return selected option elements
4217
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
4218
+ // IE8 throws error here and will not see later tests
4219
+ if ( !div.querySelectorAll(":checked").length ) {
4220
+ rbuggyQSA.push(":checked");
4221
+ }
4222
+ });
4223
+
4224
+ assert(function( div ) {
4225
+
4226
+ // Opera 10-12/IE8 - ^= $= *= and empty values
4227
+ // Should not select anything
4228
+ div.innerHTML = "<input type='hidden' i=''/>";
4229
+ if ( div.querySelectorAll("[i^='']").length ) {
4230
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );
4231
+ }
4232
+
4233
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
4234
+ // IE8 throws error here and will not see later tests
4235
+ if ( !div.querySelectorAll(":enabled").length ) {
4236
+ rbuggyQSA.push( ":enabled", ":disabled" );
4237
+ }
4238
+
4239
+ // Opera 10-11 does not throw on post-comma invalid pseudos
4240
+ div.querySelectorAll("*,:x");
4241
+ rbuggyQSA.push(",.*:");
4242
+ });
4243
+ }
4244
+
4245
+ if ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector ||
4246
+ docElem.mozMatchesSelector ||
4247
+ docElem.webkitMatchesSelector ||
4248
+ docElem.oMatchesSelector ||
4249
+ docElem.msMatchesSelector) )) ) {
4250
+
4251
+ assert(function( div ) {
4252
+ // Check to see if it's possible to do matchesSelector
4253
+ // on a disconnected node (IE 9)
4254
+ support.disconnectedMatch = matches.call( div, "div" );
4255
+
4256
+ // This should fail with an exception
4257
+ // Gecko does not error, returns false instead
4258
+ matches.call( div, "[s!='']:x" );
4259
+ rbuggyMatches.push( "!=", pseudos );
4260
+ });
4261
+ }
4262
+
4263
+ rbuggyQSA = new RegExp( rbuggyQSA.join("|") );
4264
+ rbuggyMatches = new RegExp( rbuggyMatches.join("|") );
4265
+
4266
+ // Element contains another
4267
+ // Purposefully does not implement inclusive descendent
4268
+ // As in, an element does not contain itself
4269
+ contains = isNative(docElem.contains) || docElem.compareDocumentPosition ?
4270
+ function( a, b ) {
4271
+ var adown = a.nodeType === 9 ? a.documentElement : a,
4272
+ bup = b && b.parentNode;
4273
+ return a === bup || !!( bup && bup.nodeType === 1 && (
4274
+ adown.contains ?
4275
+ adown.contains( bup ) :
4276
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
4277
+ ));
4278
+ } :
4279
+ function( a, b ) {
4280
+ if ( b ) {
4281
+ while ( (b = b.parentNode) ) {
4282
+ if ( b === a ) {
4283
+ return true;
4284
+ }
4285
+ }
4286
+ }
4287
+ return false;
4288
+ };
4289
+
4290
+ // Document order sorting
4291
+ sortOrder = docElem.compareDocumentPosition ?
4292
+ function( a, b ) {
4293
+ var compare;
4294
+
4295
+ if ( a === b ) {
4296
+ hasDuplicate = true;
4297
+ return 0;
4298
+ }
4299
+
4300
+ if ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) {
4301
+ if ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) {
4302
+ if ( a === doc || contains( preferredDoc, a ) ) {
4303
+ return -1;
4304
+ }
4305
+ if ( b === doc || contains( preferredDoc, b ) ) {
4306
+ return 1;
4307
+ }
4308
+ return 0;
4309
+ }
4310
+ return compare & 4 ? -1 : 1;
4311
+ }
4312
+
4313
+ return a.compareDocumentPosition ? -1 : 1;
4314
+ } :
4315
+ function( a, b ) {
4316
+ var cur,
4317
+ i = 0,
4318
+ aup = a.parentNode,
4319
+ bup = b.parentNode,
4320
+ ap = [ a ],
4321
+ bp = [ b ];
4322
+
4323
+ // Exit early if the nodes are identical
4324
+ if ( a === b ) {
4325
+ hasDuplicate = true;
4326
+ return 0;
4327
+
4328
+ // Parentless nodes are either documents or disconnected
4329
+ } else if ( !aup || !bup ) {
4330
+ return a === doc ? -1 :
4331
+ b === doc ? 1 :
4332
+ aup ? -1 :
4333
+ bup ? 1 :
4334
+ 0;
4335
+
4336
+ // If the nodes are siblings, we can do a quick check
4337
+ } else if ( aup === bup ) {
4338
+ return siblingCheck( a, b );
4339
+ }
4340
+
4341
+ // Otherwise we need full lists of their ancestors for comparison
4342
+ cur = a;
4343
+ while ( (cur = cur.parentNode) ) {
4344
+ ap.unshift( cur );
4345
+ }
4346
+ cur = b;
4347
+ while ( (cur = cur.parentNode) ) {
4348
+ bp.unshift( cur );
4349
+ }
4350
+
4351
+ // Walk down the tree looking for a discrepancy
4352
+ while ( ap[i] === bp[i] ) {
4353
+ i++;
4354
+ }
4355
+
4356
+ return i ?
4357
+ // Do a sibling check if the nodes have a common ancestor
4358
+ siblingCheck( ap[i], bp[i] ) :
4359
+
4360
+ // Otherwise nodes in our document sort first
4361
+ ap[i] === preferredDoc ? -1 :
4362
+ bp[i] === preferredDoc ? 1 :
4363
+ 0;
4364
+ };
4365
+
4366
+ // Always assume the presence of duplicates if sort doesn't
4367
+ // pass them to our comparison function (as in Google Chrome).
4368
+ hasDuplicate = false;
4369
+ [0, 0].sort( sortOrder );
4370
+ support.detectDuplicates = hasDuplicate;
4371
+
4372
+ return document;
4373
+ };
4374
+
4375
+ Sizzle.matches = function( expr, elements ) {
4376
+ return Sizzle( expr, null, null, elements );
4377
+ };
4378
+
4379
+ Sizzle.matchesSelector = function( elem, expr ) {
4380
+ // Set document vars if needed
4381
+ if ( ( elem.ownerDocument || elem ) !== document ) {
4382
+ setDocument( elem );
4383
+ }
4384
+
4385
+ // Make sure that attribute selectors are quoted
4386
+ expr = expr.replace( rattributeQuotes, "='$1']" );
4387
+
4388
+ // rbuggyQSA always contains :focus, so no need for an existence check
4389
+ if ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) {
4390
+ try {
4391
+ var ret = matches.call( elem, expr );
4392
+
4393
+ // IE 9's matchesSelector returns false on disconnected nodes
4394
+ if ( ret || support.disconnectedMatch ||
4395
+ // As well, disconnected nodes are said to be in a document
4396
+ // fragment in IE 9
4397
+ elem.document && elem.document.nodeType !== 11 ) {
4398
+ return ret;
4399
+ }
4400
+ } catch(e) {}
4401
+ }
4402
+
4403
+ return Sizzle( expr, document, null, [elem] ).length > 0;
4404
+ };
4405
+
4406
+ Sizzle.contains = function( context, elem ) {
4407
+ // Set document vars if needed
4408
+ if ( ( context.ownerDocument || context ) !== document ) {
4409
+ setDocument( context );
4410
+ }
4411
+ return contains( context, elem );
4412
+ };
4413
+
4414
+ Sizzle.attr = function( elem, name ) {
4415
+ var val;
4416
+
4417
+ // Set document vars if needed
4418
+ if ( ( elem.ownerDocument || elem ) !== document ) {
4419
+ setDocument( elem );
4420
+ }
4421
+
4422
+ if ( !documentIsXML ) {
4423
+ name = name.toLowerCase();
4424
+ }
4425
+ if ( (val = Expr.attrHandle[ name ]) ) {
4426
+ return val( elem );
4427
+ }
4428
+ if ( documentIsXML || support.attributes ) {
4429
+ return elem.getAttribute( name );
4430
+ }
4431
+ return ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ?
4432
+ name :
4433
+ val && val.specified ? val.value : null;
4434
+ };
4435
+
4436
+ Sizzle.error = function( msg ) {
4437
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
4438
+ };
4439
+
4440
+ // Document sorting and removing duplicates
4441
+ Sizzle.uniqueSort = function( results ) {
4442
+ var elem,
4443
+ duplicates = [],
4444
+ i = 1,
4445
+ j = 0;
4446
+
4447
+ // Unless we *know* we can detect duplicates, assume their presence
4448
+ hasDuplicate = !support.detectDuplicates;
4449
+ results.sort( sortOrder );
4450
+
4451
+ if ( hasDuplicate ) {
4452
+ for ( ; (elem = results[i]); i++ ) {
4453
+ if ( elem === results[ i - 1 ] ) {
4454
+ j = duplicates.push( i );
4455
+ }
4456
+ }
4457
+ while ( j-- ) {
4458
+ results.splice( duplicates[ j ], 1 );
4459
+ }
4460
+ }
4461
+
4462
+ return results;
4463
+ };
4464
+
4465
+ function siblingCheck( a, b ) {
4466
+ var cur = b && a,
4467
+ diff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE );
4468
+
4469
+ // Use IE sourceIndex if available on both nodes
4470
+ if ( diff ) {
4471
+ return diff;
4472
+ }
4473
+
4474
+ // Check if b follows a
4475
+ if ( cur ) {
4476
+ while ( (cur = cur.nextSibling) ) {
4477
+ if ( cur === b ) {
4478
+ return -1;
4479
+ }
4480
+ }
4481
+ }
4482
+
4483
+ return a ? 1 : -1;
4484
+ }
4485
+
4486
+ // Returns a function to use in pseudos for input types
4487
+ function createInputPseudo( type ) {
4488
+ return function( elem ) {
4489
+ var name = elem.nodeName.toLowerCase();
4490
+ return name === "input" && elem.type === type;
4491
+ };
4492
+ }
4493
+
4494
+ // Returns a function to use in pseudos for buttons
4495
+ function createButtonPseudo( type ) {
4496
+ return function( elem ) {
4497
+ var name = elem.nodeName.toLowerCase();
4498
+ return (name === "input" || name === "button") && elem.type === type;
4499
+ };
4500
+ }
4501
+
4502
+ // Returns a function to use in pseudos for positionals
4503
+ function createPositionalPseudo( fn ) {
4504
+ return markFunction(function( argument ) {
4505
+ argument = +argument;
4506
+ return markFunction(function( seed, matches ) {
4507
+ var j,
4508
+ matchIndexes = fn( [], seed.length, argument ),
4509
+ i = matchIndexes.length;
4510
+
4511
+ // Match elements found at the specified indexes
4512
+ while ( i-- ) {
4513
+ if ( seed[ (j = matchIndexes[i]) ] ) {
4514
+ seed[j] = !(matches[j] = seed[j]);
4515
+ }
4516
+ }
4517
+ });
4518
+ });
4519
+ }
4520
+
4521
+ /**
4522
+ * Utility function for retrieving the text value of an array of DOM nodes
4523
+ * @param {Array|Element} elem
4524
+ */
4525
+ getText = Sizzle.getText = function( elem ) {
4526
+ var node,
4527
+ ret = "",
4528
+ i = 0,
4529
+ nodeType = elem.nodeType;
4530
+
4531
+ if ( !nodeType ) {
4532
+ // If no nodeType, this is expected to be an array
4533
+ for ( ; (node = elem[i]); i++ ) {
4534
+ // Do not traverse comment nodes
4535
+ ret += getText( node );
4536
+ }
4537
+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
4538
+ // Use textContent for elements
4539
+ // innerText usage removed for consistency of new lines (see #11153)
4540
+ if ( typeof elem.textContent === "string" ) {
4541
+ return elem.textContent;
4542
+ } else {
4543
+ // Traverse its children
4544
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
4545
+ ret += getText( elem );
4546
+ }
4547
+ }
4548
+ } else if ( nodeType === 3 || nodeType === 4 ) {
4549
+ return elem.nodeValue;
4550
+ }
4551
+ // Do not include comment or processing instruction nodes
4552
+
4553
+ return ret;
4554
+ };
4555
+
4556
+ Expr = Sizzle.selectors = {
4557
+
4558
+ // Can be adjusted by the user
4559
+ cacheLength: 50,
4560
+
4561
+ createPseudo: markFunction,
4562
+
4563
+ match: matchExpr,
4564
+
4565
+ find: {},
4566
+
4567
+ relative: {
4568
+ ">": {
4569
+ dir: "parentNode",
4570
+ first: true
4571
+ },
4572
+ " ": {
4573
+ dir: "parentNode"
4574
+ },
4575
+ "+": {
4576
+ dir: "previousSibling",
4577
+ first: true
4578
+ },
4579
+ "~": {
4580
+ dir: "previousSibling"
4581
+ }
4582
+ },
4583
+
4584
+ preFilter: {
4585
+ "ATTR": function( match ) {
4586
+ match[1] = match[1].replace( runescape, funescape );
4587
+
4588
+ // Move the given value to match[3] whether quoted or unquoted
4589
+ match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
4590
+
4591
+ if ( match[2] === "~=" ) {
4592
+ match[3] = " " + match[3] + " ";
4593
+ }
4594
+
4595
+ return match.slice( 0, 4 );
4596
+ },
4597
+
4598
+ "CHILD": function( match ) {
4599
+ /* matches from matchExpr["CHILD"]
4600
+ 1 type (only|nth|...)
4601
+ 2 what (child|of-type)
4602
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
4603
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
4604
+ 5 sign of xn-component
4605
+ 6 x of xn-component
4606
+ 7 sign of y-component
4607
+ 8 y of y-component
4608
+ */
4609
+ match[1] = match[1].toLowerCase();
4610
+
4611
+ if ( match[1].slice( 0, 3 ) === "nth" ) {
4612
+ // nth-* requires argument
4613
+ if ( !match[3] ) {
4614
+ Sizzle.error( match[0] );
4615
+ }
4616
+
4617
+ // numeric x and y parameters for Expr.filter.CHILD
4618
+ // remember that false/true cast respectively to 0/1
4619
+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
4620
+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
4621
+
4622
+ // other types prohibit arguments
4623
+ } else if ( match[3] ) {
4624
+ Sizzle.error( match[0] );
4625
+ }
4626
+
4627
+ return match;
4628
+ },
4629
+
4630
+ "PSEUDO": function( match ) {
4631
+ var excess,
4632
+ unquoted = !match[5] && match[2];
4633
+
4634
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
4635
+ return null;
4636
+ }
4637
+
4638
+ // Accept quoted arguments as-is
4639
+ if ( match[4] ) {
4640
+ match[2] = match[4];
4641
+
4642
+ // Strip excess characters from unquoted arguments
4643
+ } else if ( unquoted && rpseudo.test( unquoted ) &&
4644
+ // Get excess from tokenize (recursively)
4645
+ (excess = tokenize( unquoted, true )) &&
4646
+ // advance to the next closing parenthesis
4647
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
4648
+
4649
+ // excess is a negative index
4650
+ match[0] = match[0].slice( 0, excess );
4651
+ match[2] = unquoted.slice( 0, excess );
4652
+ }
4653
+
4654
+ // Return only captures needed by the pseudo filter method (type and argument)
4655
+ return match.slice( 0, 3 );
4656
+ }
4657
+ },
4658
+
4659
+ filter: {
4660
+
4661
+ "TAG": function( nodeName ) {
4662
+ if ( nodeName === "*" ) {
4663
+ return function() {
4664
+ return true;
4665
+ };
4666
+ }
4667
+
4668
+ nodeName = nodeName.replace( runescape, funescape ).toLowerCase();
4669
+ return function( elem ) {
4670
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
4671
+ };
4672
+ },
4673
+
4674
+ "CLASS": function( className ) {
4675
+ var pattern = classCache[ className + " " ];
4676
+
4677
+ return pattern ||
4678
+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
4679
+ classCache( className, function( elem ) {
4680
+ return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
4681
+ });
4682
+ },
4683
+
4684
+ "ATTR": function( name, operator, check ) {
4685
+ return function( elem ) {
4686
+ var result = Sizzle.attr( elem, name );
4687
+
4688
+ if ( result == null ) {
4689
+ return operator === "!=";
4690
+ }
4691
+ if ( !operator ) {
4692
+ return true;
4693
+ }
4694
+
4695
+ result += "";
4696
+
4697
+ return operator === "=" ? result === check :
4698
+ operator === "!=" ? result !== check :
4699
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
4700
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
4701
+ operator === "$=" ? check && result.slice( -check.length ) === check :
4702
+ operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
4703
+ operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
4704
+ false;
4705
+ };
4706
+ },
4707
+
4708
+ "CHILD": function( type, what, argument, first, last ) {
4709
+ var simple = type.slice( 0, 3 ) !== "nth",
4710
+ forward = type.slice( -4 ) !== "last",
4711
+ ofType = what === "of-type";
4712
+
4713
+ return first === 1 && last === 0 ?
4714
+
4715
+ // Shortcut for :nth-*(n)
4716
+ function( elem ) {
4717
+ return !!elem.parentNode;
4718
+ } :
4719
+
4720
+ function( elem, context, xml ) {
4721
+ var cache, outerCache, node, diff, nodeIndex, start,
4722
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
4723
+ parent = elem.parentNode,
4724
+ name = ofType && elem.nodeName.toLowerCase(),
4725
+ useCache = !xml && !ofType;
4726
+
4727
+ if ( parent ) {
4728
+
4729
+ // :(first|last|only)-(child|of-type)
4730
+ if ( simple ) {
4731
+ while ( dir ) {
4732
+ node = elem;
4733
+ while ( (node = node[ dir ]) ) {
4734
+ if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
4735
+ return false;
4736
+ }
4737
+ }
4738
+ // Reverse direction for :only-* (if we haven't yet done so)
4739
+ start = dir = type === "only" && !start && "nextSibling";
4740
+ }
4741
+ return true;
4742
+ }
4743
+
4744
+ start = [ forward ? parent.firstChild : parent.lastChild ];
4745
+
4746
+ // non-xml :nth-child(...) stores cache data on `parent`
4747
+ if ( forward && useCache ) {
4748
+ // Seek `elem` from a previously-cached index
4749
+ outerCache = parent[ expando ] || (parent[ expando ] = {});
4750
+ cache = outerCache[ type ] || [];
4751
+ nodeIndex = cache[0] === dirruns && cache[1];
4752
+ diff = cache[0] === dirruns && cache[2];
4753
+ node = nodeIndex && parent.childNodes[ nodeIndex ];
4754
+
4755
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
4756
+
4757
+ // Fallback to seeking `elem` from the start
4758
+ (diff = nodeIndex = 0) || start.pop()) ) {
4759
+
4760
+ // When found, cache indexes on `parent` and break
4761
+ if ( node.nodeType === 1 && ++diff && node === elem ) {
4762
+ outerCache[ type ] = [ dirruns, nodeIndex, diff ];
4763
+ break;
4764
+ }
4765
+ }
4766
+
4767
+ // Use previously-cached element index if available
4768
+ } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
4769
+ diff = cache[1];
4770
+
4771
+ // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
4772
+ } else {
4773
+ // Use the same loop as above to seek `elem` from the start
4774
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
4775
+ (diff = nodeIndex = 0) || start.pop()) ) {
4776
+
4777
+ if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
4778
+ // Cache the index of each encountered element
4779
+ if ( useCache ) {
4780
+ (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
4781
+ }
4782
+
4783
+ if ( node === elem ) {
4784
+ break;
4785
+ }
4786
+ }
4787
+ }
4788
+ }
4789
+
4790
+ // Incorporate the offset, then check against cycle size
4791
+ diff -= last;
4792
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
4793
+ }
4794
+ };
4795
+ },
4796
+
4797
+ "PSEUDO": function( pseudo, argument ) {
4798
+ // pseudo-class names are case-insensitive
4799
+ // http://www.w3.org/TR/selectors/#pseudo-classes
4800
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
4801
+ // Remember that setFilters inherits from pseudos
4802
+ var args,
4803
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
4804
+ Sizzle.error( "unsupported pseudo: " + pseudo );
4805
+
4806
+ // The user may use createPseudo to indicate that
4807
+ // arguments are needed to create the filter function
4808
+ // just as Sizzle does
4809
+ if ( fn[ expando ] ) {
4810
+ return fn( argument );
4811
+ }
4812
+
4813
+ // But maintain support for old signatures
4814
+ if ( fn.length > 1 ) {
4815
+ args = [ pseudo, pseudo, "", argument ];
4816
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
4817
+ markFunction(function( seed, matches ) {
4818
+ var idx,
4819
+ matched = fn( seed, argument ),
4820
+ i = matched.length;
4821
+ while ( i-- ) {
4822
+ idx = indexOf.call( seed, matched[i] );
4823
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
4824
+ }
4825
+ }) :
4826
+ function( elem ) {
4827
+ return fn( elem, 0, args );
4828
+ };
4829
+ }
4830
+
4831
+ return fn;
4832
+ }
4833
+ },
4834
+
4835
+ pseudos: {
4836
+ // Potentially complex pseudos
4837
+ "not": markFunction(function( selector ) {
4838
+ // Trim the selector passed to compile
4839
+ // to avoid treating leading and trailing
4840
+ // spaces as combinators
4841
+ var input = [],
4842
+ results = [],
4843
+ matcher = compile( selector.replace( rtrim, "$1" ) );
4844
+
4845
+ return matcher[ expando ] ?
4846
+ markFunction(function( seed, matches, context, xml ) {
4847
+ var elem,
4848
+ unmatched = matcher( seed, null, xml, [] ),
4849
+ i = seed.length;
4850
+
4851
+ // Match elements unmatched by `matcher`
4852
+ while ( i-- ) {
4853
+ if ( (elem = unmatched[i]) ) {
4854
+ seed[i] = !(matches[i] = elem);
4855
+ }
4856
+ }
4857
+ }) :
4858
+ function( elem, context, xml ) {
4859
+ input[0] = elem;
4860
+ matcher( input, null, xml, results );
4861
+ return !results.pop();
4862
+ };
4863
+ }),
4864
+
4865
+ "has": markFunction(function( selector ) {
4866
+ return function( elem ) {
4867
+ return Sizzle( selector, elem ).length > 0;
4868
+ };
4869
+ }),
4870
+
4871
+ "contains": markFunction(function( text ) {
4872
+ return function( elem ) {
4873
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
4874
+ };
4875
+ }),
4876
+
4877
+ // "Whether an element is represented by a :lang() selector
4878
+ // is based solely on the element's language value
4879
+ // being equal to the identifier C,
4880
+ // or beginning with the identifier C immediately followed by "-".
4881
+ // The matching of C against the element's language value is performed case-insensitively.
4882
+ // The identifier C does not have to be a valid language name."
4883
+ // http://www.w3.org/TR/selectors/#lang-pseudo
4884
+ "lang": markFunction( function( lang ) {
4885
+ // lang value must be a valid identifider
4886
+ if ( !ridentifier.test(lang || "") ) {
4887
+ Sizzle.error( "unsupported lang: " + lang );
4888
+ }
4889
+ lang = lang.replace( runescape, funescape ).toLowerCase();
4890
+ return function( elem ) {
4891
+ var elemLang;
4892
+ do {
4893
+ if ( (elemLang = documentIsXML ?
4894
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang") :
4895
+ elem.lang) ) {
4896
+
4897
+ elemLang = elemLang.toLowerCase();
4898
+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
4899
+ }
4900
+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
4901
+ return false;
4902
+ };
4903
+ }),
4904
+
4905
+ // Miscellaneous
4906
+ "target": function( elem ) {
4907
+ var hash = window.location && window.location.hash;
4908
+ return hash && hash.slice( 1 ) === elem.id;
4909
+ },
4910
+
4911
+ "root": function( elem ) {
4912
+ return elem === docElem;
4913
+ },
4914
+
4915
+ "focus": function( elem ) {
4916
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
4917
+ },
4918
+
4919
+ // Boolean properties
4920
+ "enabled": function( elem ) {
4921
+ return elem.disabled === false;
4922
+ },
4923
+
4924
+ "disabled": function( elem ) {
4925
+ return elem.disabled === true;
4926
+ },
4927
+
4928
+ "checked": function( elem ) {
4929
+ // In CSS3, :checked should return both checked and selected elements
4930
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
4931
+ var nodeName = elem.nodeName.toLowerCase();
4932
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
4933
+ },
4934
+
4935
+ "selected": function( elem ) {
4936
+ // Accessing this property makes selected-by-default
4937
+ // options in Safari work properly
4938
+ if ( elem.parentNode ) {
4939
+ elem.parentNode.selectedIndex;
4940
+ }
4941
+
4942
+ return elem.selected === true;
4943
+ },
4944
+
4945
+ // Contents
4946
+ "empty": function( elem ) {
4947
+ // http://www.w3.org/TR/selectors/#empty-pseudo
4948
+ // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
4949
+ // not comment, processing instructions, or others
4950
+ // Thanks to Diego Perini for the nodeName shortcut
4951
+ // Greater than "@" means alpha characters (specifically not starting with "#" or "?")
4952
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
4953
+ if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
4954
+ return false;
4955
+ }
4956
+ }
4957
+ return true;
4958
+ },
4959
+
4960
+ "parent": function( elem ) {
4961
+ return !Expr.pseudos["empty"]( elem );
4962
+ },
4963
+
4964
+ // Element/input types
4965
+ "header": function( elem ) {
4966
+ return rheader.test( elem.nodeName );
4967
+ },
4968
+
4969
+ "input": function( elem ) {
4970
+ return rinputs.test( elem.nodeName );
4971
+ },
4972
+
4973
+ "button": function( elem ) {
4974
+ var name = elem.nodeName.toLowerCase();
4975
+ return name === "input" && elem.type === "button" || name === "button";
4976
+ },
4977
+
4978
+ "text": function( elem ) {
4979
+ var attr;
4980
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
4981
+ // use getAttribute instead to test this case
4982
+ return elem.nodeName.toLowerCase() === "input" &&
4983
+ elem.type === "text" &&
4984
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
4985
+ },
4986
+
4987
+ // Position-in-collection
4988
+ "first": createPositionalPseudo(function() {
4989
+ return [ 0 ];
4990
+ }),
4991
+
4992
+ "last": createPositionalPseudo(function( matchIndexes, length ) {
4993
+ return [ length - 1 ];
4994
+ }),
4995
+
4996
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
4997
+ return [ argument < 0 ? argument + length : argument ];
4998
+ }),
4999
+
5000
+ "even": createPositionalPseudo(function( matchIndexes, length ) {
5001
+ var i = 0;
5002
+ for ( ; i < length; i += 2 ) {
5003
+ matchIndexes.push( i );
5004
+ }
5005
+ return matchIndexes;
5006
+ }),
5007
+
5008
+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
5009
+ var i = 1;
5010
+ for ( ; i < length; i += 2 ) {
5011
+ matchIndexes.push( i );
5012
+ }
5013
+ return matchIndexes;
5014
+ }),
5015
+
5016
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
5017
+ var i = argument < 0 ? argument + length : argument;
5018
+ for ( ; --i >= 0; ) {
5019
+ matchIndexes.push( i );
5020
+ }
5021
+ return matchIndexes;
5022
+ }),
5023
+
5024
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
5025
+ var i = argument < 0 ? argument + length : argument;
5026
+ for ( ; ++i < length; ) {
5027
+ matchIndexes.push( i );
5028
+ }
5029
+ return matchIndexes;
5030
+ })
5031
+ }
5032
+ };
5033
+
5034
+ // Add button/input type pseudos
5035
+ for ( i in {
5036
+ radio: true,
5037
+ checkbox: true,
5038
+ file: true,
5039
+ password: true,
5040
+ image: true
5041
+ } ) {
5042
+ Expr.pseudos[ i ] = createInputPseudo( i );
5043
+ }
5044
+ for ( i in {
5045
+ submit: true,
5046
+ reset: true
5047
+ } ) {
5048
+ Expr.pseudos[ i ] = createButtonPseudo( i );
5049
+ }
5050
+
5051
+ function tokenize( selector, parseOnly ) {
5052
+ var matched, match, tokens, type,
5053
+ soFar, groups, preFilters,
5054
+ cached = tokenCache[ selector + " " ];
5055
+
5056
+ if ( cached ) {
5057
+ return parseOnly ? 0 : cached.slice( 0 );
5058
+ }
5059
+
5060
+ soFar = selector;
5061
+ groups = [];
5062
+ preFilters = Expr.preFilter;
5063
+
5064
+ while ( soFar ) {
5065
+
5066
+ // Comma and first run
5067
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
5068
+ if ( match ) {
5069
+ // Don't consume trailing commas as valid
5070
+ soFar = soFar.slice( match[0].length ) || soFar;
5071
+ }
5072
+ groups.push( tokens = [] );
5073
+ }
5074
+
5075
+ matched = false;
5076
+
5077
+ // Combinators
5078
+ if ( (match = rcombinators.exec( soFar )) ) {
5079
+ matched = match.shift();
5080
+ tokens.push( {
5081
+ value: matched,
5082
+ // Cast descendant combinators to space
5083
+ type: match[0].replace( rtrim, " " )
5084
+ } );
5085
+ soFar = soFar.slice( matched.length );
5086
+ }
5087
+
5088
+ // Filters
5089
+ for ( type in Expr.filter ) {
5090
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
5091
+ (match = preFilters[ type ]( match ))) ) {
5092
+ matched = match.shift();
5093
+ tokens.push( {
5094
+ value: matched,
5095
+ type: type,
5096
+ matches: match
5097
+ } );
5098
+ soFar = soFar.slice( matched.length );
5099
+ }
5100
+ }
5101
+
5102
+ if ( !matched ) {
5103
+ break;
5104
+ }
5105
+ }
5106
+
5107
+ // Return the length of the invalid excess
5108
+ // if we're just parsing
5109
+ // Otherwise, throw an error or return tokens
5110
+ return parseOnly ?
5111
+ soFar.length :
5112
+ soFar ?
5113
+ Sizzle.error( selector ) :
5114
+ // Cache the tokens
5115
+ tokenCache( selector, groups ).slice( 0 );
5116
+ }
5117
+
5118
+ function toSelector( tokens ) {
5119
+ var i = 0,
5120
+ len = tokens.length,
5121
+ selector = "";
5122
+ for ( ; i < len; i++ ) {
5123
+ selector += tokens[i].value;
5124
+ }
5125
+ return selector;
5126
+ }
5127
+
5128
+ function addCombinator( matcher, combinator, base ) {
5129
+ var dir = combinator.dir,
5130
+ checkNonElements = base && dir === "parentNode",
5131
+ doneName = done++;
5132
+
5133
+ return combinator.first ?
5134
+ // Check against closest ancestor/preceding element
5135
+ function( elem, context, xml ) {
5136
+ while ( (elem = elem[ dir ]) ) {
5137
+ if ( elem.nodeType === 1 || checkNonElements ) {
5138
+ return matcher( elem, context, xml );
5139
+ }
5140
+ }
5141
+ } :
5142
+
5143
+ // Check against all ancestor/preceding elements
5144
+ function( elem, context, xml ) {
5145
+ var data, cache, outerCache,
5146
+ dirkey = dirruns + " " + doneName;
5147
+
5148
+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
5149
+ if ( xml ) {
5150
+ while ( (elem = elem[ dir ]) ) {
5151
+ if ( elem.nodeType === 1 || checkNonElements ) {
5152
+ if ( matcher( elem, context, xml ) ) {
5153
+ return true;
5154
+ }
5155
+ }
5156
+ }
5157
+ } else {
5158
+ while ( (elem = elem[ dir ]) ) {
5159
+ if ( elem.nodeType === 1 || checkNonElements ) {
5160
+ outerCache = elem[ expando ] || (elem[ expando ] = {});
5161
+ if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
5162
+ if ( (data = cache[1]) === true || data === cachedruns ) {
5163
+ return data === true;
5164
+ }
5165
+ } else {
5166
+ cache = outerCache[ dir ] = [ dirkey ];
5167
+ cache[1] = matcher( elem, context, xml ) || cachedruns;
5168
+ if ( cache[1] === true ) {
5169
+ return true;
5170
+ }
5171
+ }
5172
+ }
5173
+ }
5174
+ }
5175
+ };
5176
+ }
5177
+
5178
+ function elementMatcher( matchers ) {
5179
+ return matchers.length > 1 ?
5180
+ function( elem, context, xml ) {
5181
+ var i = matchers.length;
5182
+ while ( i-- ) {
5183
+ if ( !matchers[i]( elem, context, xml ) ) {
5184
+ return false;
5185
+ }
5186
+ }
5187
+ return true;
5188
+ } :
5189
+ matchers[0];
5190
+ }
5191
+
5192
+ function condense( unmatched, map, filter, context, xml ) {
5193
+ var elem,
5194
+ newUnmatched = [],
5195
+ i = 0,
5196
+ len = unmatched.length,
5197
+ mapped = map != null;
5198
+
5199
+ for ( ; i < len; i++ ) {
5200
+ if ( (elem = unmatched[i]) ) {
5201
+ if ( !filter || filter( elem, context, xml ) ) {
5202
+ newUnmatched.push( elem );
5203
+ if ( mapped ) {
5204
+ map.push( i );
5205
+ }
5206
+ }
5207
+ }
5208
+ }
5209
+
5210
+ return newUnmatched;
5211
+ }
5212
+
5213
+ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
5214
+ if ( postFilter && !postFilter[ expando ] ) {
5215
+ postFilter = setMatcher( postFilter );
5216
+ }
5217
+ if ( postFinder && !postFinder[ expando ] ) {
5218
+ postFinder = setMatcher( postFinder, postSelector );
5219
+ }
5220
+ return markFunction(function( seed, results, context, xml ) {
5221
+ var temp, i, elem,
5222
+ preMap = [],
5223
+ postMap = [],
5224
+ preexisting = results.length,
5225
+
5226
+ // Get initial elements from seed or context
5227
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
5228
+
5229
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
5230
+ matcherIn = preFilter && ( seed || !selector ) ?
5231
+ condense( elems, preMap, preFilter, context, xml ) :
5232
+ elems,
5233
+
5234
+ matcherOut = matcher ?
5235
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
5236
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
5237
+
5238
+ // ...intermediate processing is necessary
5239
+ [] :
5240
+
5241
+ // ...otherwise use results directly
5242
+ results :
5243
+ matcherIn;
5244
+
5245
+ // Find primary matches
5246
+ if ( matcher ) {
5247
+ matcher( matcherIn, matcherOut, context, xml );
5248
+ }
5249
+
5250
+ // Apply postFilter
5251
+ if ( postFilter ) {
5252
+ temp = condense( matcherOut, postMap );
5253
+ postFilter( temp, [], context, xml );
5254
+
5255
+ // Un-match failing elements by moving them back to matcherIn
5256
+ i = temp.length;
5257
+ while ( i-- ) {
5258
+ if ( (elem = temp[i]) ) {
5259
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
5260
+ }
5261
+ }
5262
+ }
5263
+
5264
+ if ( seed ) {
5265
+ if ( postFinder || preFilter ) {
5266
+ if ( postFinder ) {
5267
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
5268
+ temp = [];
5269
+ i = matcherOut.length;
5270
+ while ( i-- ) {
5271
+ if ( (elem = matcherOut[i]) ) {
5272
+ // Restore matcherIn since elem is not yet a final match
5273
+ temp.push( (matcherIn[i] = elem) );
5274
+ }
5275
+ }
5276
+ postFinder( null, (matcherOut = []), temp, xml );
5277
+ }
5278
+
5279
+ // Move matched elements from seed to results to keep them synchronized
5280
+ i = matcherOut.length;
5281
+ while ( i-- ) {
5282
+ if ( (elem = matcherOut[i]) &&
5283
+ (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
5284
+
5285
+ seed[temp] = !(results[temp] = elem);
5286
+ }
5287
+ }
5288
+ }
5289
+
5290
+ // Add elements to results, through postFinder if defined
5291
+ } else {
5292
+ matcherOut = condense(
5293
+ matcherOut === results ?
5294
+ matcherOut.splice( preexisting, matcherOut.length ) :
5295
+ matcherOut
5296
+ );
5297
+ if ( postFinder ) {
5298
+ postFinder( null, results, matcherOut, xml );
5299
+ } else {
5300
+ push.apply( results, matcherOut );
5301
+ }
5302
+ }
5303
+ });
5304
+ }
5305
+
5306
+ function matcherFromTokens( tokens ) {
5307
+ var checkContext, matcher, j,
5308
+ len = tokens.length,
5309
+ leadingRelative = Expr.relative[ tokens[0].type ],
5310
+ implicitRelative = leadingRelative || Expr.relative[" "],
5311
+ i = leadingRelative ? 1 : 0,
5312
+
5313
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
5314
+ matchContext = addCombinator( function( elem ) {
5315
+ return elem === checkContext;
5316
+ }, implicitRelative, true ),
5317
+ matchAnyContext = addCombinator( function( elem ) {
5318
+ return indexOf.call( checkContext, elem ) > -1;
5319
+ }, implicitRelative, true ),
5320
+ matchers = [ function( elem, context, xml ) {
5321
+ return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
5322
+ (checkContext = context).nodeType ?
5323
+ matchContext( elem, context, xml ) :
5324
+ matchAnyContext( elem, context, xml ) );
5325
+ } ];
5326
+
5327
+ for ( ; i < len; i++ ) {
5328
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
5329
+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
5330
+ } else {
5331
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
5332
+
5333
+ // Return special upon seeing a positional matcher
5334
+ if ( matcher[ expando ] ) {
5335
+ // Find the next relative operator (if any) for proper handling
5336
+ j = ++i;
5337
+ for ( ; j < len; j++ ) {
5338
+ if ( Expr.relative[ tokens[j].type ] ) {
5339
+ break;
5340
+ }
5341
+ }
5342
+ return setMatcher(
5343
+ i > 1 && elementMatcher( matchers ),
5344
+ i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ),
5345
+ matcher,
5346
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
5347
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
5348
+ j < len && toSelector( tokens )
5349
+ );
5350
+ }
5351
+ matchers.push( matcher );
5352
+ }
5353
+ }
5354
+
5355
+ return elementMatcher( matchers );
5356
+ }
5357
+
5358
+ function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
5359
+ // A counter to specify which element is currently being matched
5360
+ var matcherCachedRuns = 0,
5361
+ bySet = setMatchers.length > 0,
5362
+ byElement = elementMatchers.length > 0,
5363
+ superMatcher = function( seed, context, xml, results, expandContext ) {
5364
+ var elem, j, matcher,
5365
+ setMatched = [],
5366
+ matchedCount = 0,
5367
+ i = "0",
5368
+ unmatched = seed && [],
5369
+ outermost = expandContext != null,
5370
+ contextBackup = outermostContext,
5371
+ // We must always have either seed elements or context
5372
+ elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
5373
+ // Use integer dirruns iff this is the outermost matcher
5374
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);
5375
+
5376
+ if ( outermost ) {
5377
+ outermostContext = context !== document && context;
5378
+ cachedruns = matcherCachedRuns;
5379
+ }
5380
+
5381
+ // Add elements passing elementMatchers directly to results
5382
+ // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
5383
+ for ( ; (elem = elems[i]) != null; i++ ) {
5384
+ if ( byElement && elem ) {
5385
+ j = 0;
5386
+ while ( (matcher = elementMatchers[j++]) ) {
5387
+ if ( matcher( elem, context, xml ) ) {
5388
+ results.push( elem );
5389
+ break;
5390
+ }
5391
+ }
5392
+ if ( outermost ) {
5393
+ dirruns = dirrunsUnique;
5394
+ cachedruns = ++matcherCachedRuns;
5395
+ }
5396
+ }
5397
+
5398
+ // Track unmatched elements for set filters
5399
+ if ( bySet ) {
5400
+ // They will have gone through all possible matchers
5401
+ if ( (elem = !matcher && elem) ) {
5402
+ matchedCount--;
5403
+ }
5404
+
5405
+ // Lengthen the array for every element, matched or not
5406
+ if ( seed ) {
5407
+ unmatched.push( elem );
5408
+ }
5409
+ }
5410
+ }
5411
+
5412
+ // Apply set filters to unmatched elements
5413
+ matchedCount += i;
5414
+ if ( bySet && i !== matchedCount ) {
5415
+ j = 0;
5416
+ while ( (matcher = setMatchers[j++]) ) {
5417
+ matcher( unmatched, setMatched, context, xml );
5418
+ }
5419
+
5420
+ if ( seed ) {
5421
+ // Reintegrate element matches to eliminate the need for sorting
5422
+ if ( matchedCount > 0 ) {
5423
+ while ( i-- ) {
5424
+ if ( !(unmatched[i] || setMatched[i]) ) {
5425
+ setMatched[i] = pop.call( results );
5426
+ }
5427
+ }
5428
+ }
5429
+
5430
+ // Discard index placeholder values to get only actual matches
5431
+ setMatched = condense( setMatched );
5432
+ }
5433
+
5434
+ // Add matches to results
5435
+ push.apply( results, setMatched );
5436
+
5437
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
5438
+ if ( outermost && !seed && setMatched.length > 0 &&
5439
+ ( matchedCount + setMatchers.length ) > 1 ) {
5440
+
5441
+ Sizzle.uniqueSort( results );
5442
+ }
5443
+ }
5444
+
5445
+ // Override manipulation of globals by nested matchers
5446
+ if ( outermost ) {
5447
+ dirruns = dirrunsUnique;
5448
+ outermostContext = contextBackup;
5449
+ }
5450
+
5451
+ return unmatched;
5452
+ };
5453
+
5454
+ return bySet ?
5455
+ markFunction( superMatcher ) :
5456
+ superMatcher;
5457
+ }
5458
+
5459
+ compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
5460
+ var i,
5461
+ setMatchers = [],
5462
+ elementMatchers = [],
5463
+ cached = compilerCache[ selector + " " ];
5464
+
5465
+ if ( !cached ) {
5466
+ // Generate a function of recursive functions that can be used to check each element
5467
+ if ( !group ) {
5468
+ group = tokenize( selector );
5469
+ }
5470
+ i = group.length;
5471
+ while ( i-- ) {
5472
+ cached = matcherFromTokens( group[i] );
5473
+ if ( cached[ expando ] ) {
5474
+ setMatchers.push( cached );
5475
+ } else {
5476
+ elementMatchers.push( cached );
5477
+ }
5478
+ }
5479
+
5480
+ // Cache the compiled function
5481
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
5482
+ }
5483
+ return cached;
5484
+ };
5485
+
5486
+ function multipleContexts( selector, contexts, results ) {
5487
+ var i = 0,
5488
+ len = contexts.length;
5489
+ for ( ; i < len; i++ ) {
5490
+ Sizzle( selector, contexts[i], results );
5491
+ }
5492
+ return results;
5493
+ }
5494
+
5495
+ function select( selector, context, results, seed ) {
5496
+ var i, tokens, token, type, find,
5497
+ match = tokenize( selector );
5498
+
5499
+ if ( !seed ) {
5500
+ // Try to minimize operations if there is only one group
5501
+ if ( match.length === 1 ) {
5502
+
5503
+ // Take a shortcut and set the context if the root selector is an ID
5504
+ tokens = match[0] = match[0].slice( 0 );
5505
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
5506
+ context.nodeType === 9 && !documentIsXML &&
5507
+ Expr.relative[ tokens[1].type ] ) {
5508
+
5509
+ context = Expr.find["ID"]( token.matches[0].replace( runescape, funescape ), context )[0];
5510
+ if ( !context ) {
5511
+ return results;
5512
+ }
5513
+
5514
+ selector = selector.slice( tokens.shift().value.length );
5515
+ }
5516
+
5517
+ // Fetch a seed set for right-to-left matching
5518
+ i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
5519
+ while ( i-- ) {
5520
+ token = tokens[i];
5521
+
5522
+ // Abort if we hit a combinator
5523
+ if ( Expr.relative[ (type = token.type) ] ) {
5524
+ break;
5525
+ }
5526
+ if ( (find = Expr.find[ type ]) ) {
5527
+ // Search, expanding context for leading sibling combinators
5528
+ if ( (seed = find(
5529
+ token.matches[0].replace( runescape, funescape ),
5530
+ rsibling.test( tokens[0].type ) && context.parentNode || context
5531
+ )) ) {
5532
+
5533
+ // If seed is empty or no tokens remain, we can return early
5534
+ tokens.splice( i, 1 );
5535
+ selector = seed.length && toSelector( tokens );
5536
+ if ( !selector ) {
5537
+ push.apply( results, slice.call( seed, 0 ) );
5538
+ return results;
5539
+ }
5540
+
5541
+ break;
5542
+ }
5543
+ }
5544
+ }
5545
+ }
5546
+ }
5547
+
5548
+ // Compile and execute a filtering function
5549
+ // Provide `match` to avoid retokenization if we modified the selector above
5550
+ compile( selector, match )(
5551
+ seed,
5552
+ context,
5553
+ documentIsXML,
5554
+ results,
5555
+ rsibling.test( selector )
5556
+ );
5557
+ return results;
5558
+ }
5559
+
5560
+ // Deprecated
5561
+ Expr.pseudos["nth"] = Expr.pseudos["eq"];
5562
+
5563
+ // Easy API for creating new setFilters
5564
+ function setFilters() {}
5565
+ Expr.filters = setFilters.prototype = Expr.pseudos;
5566
+ Expr.setFilters = new setFilters();
5567
+
5568
+ // Initialize with the default document
5569
+ setDocument();
5570
+
5571
+ // Override sizzle attribute retrieval
5572
+ Sizzle.attr = jQuery.attr;
5573
+ jQuery.find = Sizzle;
5574
+ jQuery.expr = Sizzle.selectors;
5575
+ jQuery.expr[":"] = jQuery.expr.pseudos;
5576
+ jQuery.unique = Sizzle.uniqueSort;
5577
+ jQuery.text = Sizzle.getText;
5578
+ jQuery.isXMLDoc = Sizzle.isXML;
5579
+ jQuery.contains = Sizzle.contains;
5580
+
5581
+
5582
+ })( window );
5583
+ var runtil = /Until$/,
5584
+ rparentsprev = /^(?:parents|prev(?:Until|All))/,
5585
+ isSimple = /^.[^:#\[\.,]*$/,
5586
+ rneedsContext = jQuery.expr.match.needsContext,
5587
+ // methods guaranteed to produce a unique set when starting from a unique set
5588
+ guaranteedUnique = {
5589
+ children: true,
5590
+ contents: true,
5591
+ next: true,
5592
+ prev: true
5593
+ };
5594
+
5595
+ jQuery.fn.extend({
5596
+ find: function( selector ) {
5597
+ var i, ret, self,
5598
+ len = this.length;
5599
+
5600
+ if ( typeof selector !== "string" ) {
5601
+ self = this;
5602
+ return this.pushStack( jQuery( selector ).filter(function() {
5603
+ for ( i = 0; i < len; i++ ) {
5604
+ if ( jQuery.contains( self[ i ], this ) ) {
5605
+ return true;
5606
+ }
5607
+ }
5608
+ }) );
5609
+ }
5610
+
5611
+ ret = [];
5612
+ for ( i = 0; i < len; i++ ) {
5613
+ jQuery.find( selector, this[ i ], ret );
5614
+ }
5615
+
5616
+ // Needed because $( selector, context ) becomes $( context ).find( selector )
5617
+ ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
5618
+ ret.selector = ( this.selector ? this.selector + " " : "" ) + selector;
5619
+ return ret;
5620
+ },
5621
+
5622
+ has: function( target ) {
5623
+ var i,
5624
+ targets = jQuery( target, this ),
5625
+ len = targets.length;
5626
+
5627
+ return this.filter(function() {
5628
+ for ( i = 0; i < len; i++ ) {
5629
+ if ( jQuery.contains( this, targets[i] ) ) {
5630
+ return true;
5631
+ }
5632
+ }
5633
+ });
5634
+ },
5635
+
5636
+ not: function( selector ) {
5637
+ return this.pushStack( winnow(this, selector, false) );
5638
+ },
5639
+
5640
+ filter: function( selector ) {
5641
+ return this.pushStack( winnow(this, selector, true) );
5642
+ },
5643
+
5644
+ is: function( selector ) {
5645
+ return !!selector && (
5646
+ typeof selector === "string" ?
5647
+ // If this is a positional/relative selector, check membership in the returned set
5648
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
5649
+ rneedsContext.test( selector ) ?
5650
+ jQuery( selector, this.context ).index( this[0] ) >= 0 :
5651
+ jQuery.filter( selector, this ).length > 0 :
5652
+ this.filter( selector ).length > 0 );
5653
+ },
5654
+
5655
+ closest: function( selectors, context ) {
5656
+ var cur,
5657
+ i = 0,
5658
+ l = this.length,
5659
+ ret = [],
5660
+ pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
5661
+ jQuery( selectors, context || this.context ) :
5662
+ 0;
5663
+
5664
+ for ( ; i < l; i++ ) {
5665
+ cur = this[i];
5666
+
5667
+ while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
5668
+ if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
5669
+ ret.push( cur );
5670
+ break;
5671
+ }
5672
+ cur = cur.parentNode;
5673
+ }
5674
+ }
5675
+
5676
+ return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );
5677
+ },
5678
+
5679
+ // Determine the position of an element within
5680
+ // the matched set of elements
5681
+ index: function( elem ) {
5682
+
5683
+ // No argument, return index in parent
5684
+ if ( !elem ) {
5685
+ return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
5686
+ }
5687
+
5688
+ // index in selector
5689
+ if ( typeof elem === "string" ) {
5690
+ return jQuery.inArray( this[0], jQuery( elem ) );
5691
+ }
5692
+
5693
+ // Locate the position of the desired element
5694
+ return jQuery.inArray(
5695
+ // If it receives a jQuery object, the first element is used
5696
+ elem.jquery ? elem[0] : elem, this );
5697
+ },
5698
+
5699
+ add: function( selector, context ) {
5700
+ var set = typeof selector === "string" ?
5701
+ jQuery( selector, context ) :
5702
+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
5703
+ all = jQuery.merge( this.get(), set );
5704
+
5705
+ return this.pushStack( jQuery.unique(all) );
5706
+ },
5707
+
5708
+ addBack: function( selector ) {
5709
+ return this.add( selector == null ?
5710
+ this.prevObject : this.prevObject.filter(selector)
5711
+ );
5712
+ }
5713
+ });
5714
+
5715
+ jQuery.fn.andSelf = jQuery.fn.addBack;
5716
+
5717
+ function sibling( cur, dir ) {
5718
+ do {
5719
+ cur = cur[ dir ];
5720
+ } while ( cur && cur.nodeType !== 1 );
5721
+
5722
+ return cur;
5723
+ }
5724
+
5725
+ jQuery.each({
5726
+ parent: function( elem ) {
5727
+ var parent = elem.parentNode;
5728
+ return parent && parent.nodeType !== 11 ? parent : null;
5729
+ },
5730
+ parents: function( elem ) {
5731
+ return jQuery.dir( elem, "parentNode" );
5732
+ },
5733
+ parentsUntil: function( elem, i, until ) {
5734
+ return jQuery.dir( elem, "parentNode", until );
5735
+ },
5736
+ next: function( elem ) {
5737
+ return sibling( elem, "nextSibling" );
5738
+ },
5739
+ prev: function( elem ) {
5740
+ return sibling( elem, "previousSibling" );
5741
+ },
5742
+ nextAll: function( elem ) {
5743
+ return jQuery.dir( elem, "nextSibling" );
5744
+ },
5745
+ prevAll: function( elem ) {
5746
+ return jQuery.dir( elem, "previousSibling" );
5747
+ },
5748
+ nextUntil: function( elem, i, until ) {
5749
+ return jQuery.dir( elem, "nextSibling", until );
5750
+ },
5751
+ prevUntil: function( elem, i, until ) {
5752
+ return jQuery.dir( elem, "previousSibling", until );
5753
+ },
5754
+ siblings: function( elem ) {
5755
+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
5756
+ },
5757
+ children: function( elem ) {
5758
+ return jQuery.sibling( elem.firstChild );
5759
+ },
5760
+ contents: function( elem ) {
5761
+ return jQuery.nodeName( elem, "iframe" ) ?
5762
+ elem.contentDocument || elem.contentWindow.document :
5763
+ jQuery.merge( [], elem.childNodes );
5764
+ }
5765
+ }, function( name, fn ) {
5766
+ jQuery.fn[ name ] = function( until, selector ) {
5767
+ var ret = jQuery.map( this, fn, until );
5768
+
5769
+ if ( !runtil.test( name ) ) {
5770
+ selector = until;
5771
+ }
5772
+
5773
+ if ( selector && typeof selector === "string" ) {
5774
+ ret = jQuery.filter( selector, ret );
5775
+ }
5776
+
5777
+ ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
5778
+
5779
+ if ( this.length > 1 && rparentsprev.test( name ) ) {
5780
+ ret = ret.reverse();
5781
+ }
5782
+
5783
+ return this.pushStack( ret );
5784
+ };
5785
+ });
5786
+
5787
+ jQuery.extend({
5788
+ filter: function( expr, elems, not ) {
5789
+ if ( not ) {
5790
+ expr = ":not(" + expr + ")";
5791
+ }
5792
+
5793
+ return elems.length === 1 ?
5794
+ jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
5795
+ jQuery.find.matches(expr, elems);
5796
+ },
5797
+
5798
+ dir: function( elem, dir, until ) {
5799
+ var matched = [],
5800
+ cur = elem[ dir ];
5801
+
5802
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
5803
+ if ( cur.nodeType === 1 ) {
5804
+ matched.push( cur );
5805
+ }
5806
+ cur = cur[dir];
5807
+ }
5808
+ return matched;
5809
+ },
5810
+
5811
+ sibling: function( n, elem ) {
5812
+ var r = [];
5813
+
5814
+ for ( ; n; n = n.nextSibling ) {
5815
+ if ( n.nodeType === 1 && n !== elem ) {
5816
+ r.push( n );
5817
+ }
5818
+ }
5819
+
5820
+ return r;
5821
+ }
5822
+ });
5823
+
5824
+ // Implement the identical functionality for filter and not
5825
+ function winnow( elements, qualifier, keep ) {
5826
+
5827
+ // Can't pass null or undefined to indexOf in Firefox 4
5828
+ // Set to 0 to skip string check
5829
+ qualifier = qualifier || 0;
5830
+
5831
+ if ( jQuery.isFunction( qualifier ) ) {
5832
+ return jQuery.grep(elements, function( elem, i ) {
5833
+ var retVal = !!qualifier.call( elem, i, elem );
5834
+ return retVal === keep;
5835
+ });
5836
+
5837
+ } else if ( qualifier.nodeType ) {
5838
+ return jQuery.grep(elements, function( elem ) {
5839
+ return ( elem === qualifier ) === keep;
5840
+ });
5841
+
5842
+ } else if ( typeof qualifier === "string" ) {
5843
+ var filtered = jQuery.grep(elements, function( elem ) {
5844
+ return elem.nodeType === 1;
5845
+ });
5846
+
5847
+ if ( isSimple.test( qualifier ) ) {
5848
+ return jQuery.filter(qualifier, filtered, !keep);
5849
+ } else {
5850
+ qualifier = jQuery.filter( qualifier, filtered );
5851
+ }
5852
+ }
5853
+
5854
+ return jQuery.grep(elements, function( elem ) {
5855
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
5856
+ });
5857
+ }
5858
+ function createSafeFragment( document ) {
5859
+ var list = nodeNames.split( "|" ),
5860
+ safeFrag = document.createDocumentFragment();
5861
+
5862
+ if ( safeFrag.createElement ) {
5863
+ while ( list.length ) {
5864
+ safeFrag.createElement(
5865
+ list.pop()
5866
+ );
5867
+ }
5868
+ }
5869
+ return safeFrag;
5870
+ }
5871
+
5872
+ var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
5873
+ "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
5874
+ rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
5875
+ rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
5876
+ rleadingWhitespace = /^\s+/,
5877
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
5878
+ rtagName = /<([\w:]+)/,
5879
+ rtbody = /<tbody/i,
5880
+ rhtml = /<|&#?\w+;/,
5881
+ rnoInnerhtml = /<(?:script|style|link)/i,
5882
+ manipulation_rcheckableType = /^(?:checkbox|radio)$/i,
5883
+ // checked="checked" or checked
5884
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5885
+ rscriptType = /^$|\/(?:java|ecma)script/i,
5886
+ rscriptTypeMasked = /^true\/(.*)/,
5887
+ rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
5888
+
5889
+ // We have to close these tags to support XHTML (#13200)
5890
+ wrapMap = {
5891
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
5892
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
5893
+ area: [ 1, "<map>", "</map>" ],
5894
+ param: [ 1, "<object>", "</object>" ],
5895
+ thead: [ 1, "<table>", "</table>" ],
5896
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
5897
+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
5898
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
5899
+
5900
+ // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
5901
+ // unless wrapped in a div with non-breaking characters in front of it.
5902
+ _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
5903
+ },
5904
+ safeFragment = createSafeFragment( document ),
5905
+ fragmentDiv = safeFragment.appendChild( document.createElement("div") );
5906
+
5907
+ wrapMap.optgroup = wrapMap.option;
5908
+ wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
5909
+ wrapMap.th = wrapMap.td;
5910
+
5911
+ jQuery.fn.extend({
5912
+ text: function( value ) {
5913
+ return jQuery.access( this, function( value ) {
5914
+ return value === undefined ?
5915
+ jQuery.text( this ) :
5916
+ this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
5917
+ }, null, value, arguments.length );
5918
+ },
5919
+
5920
+ wrapAll: function( html ) {
5921
+ if ( jQuery.isFunction( html ) ) {
5922
+ return this.each(function(i) {
5923
+ jQuery(this).wrapAll( html.call(this, i) );
5924
+ });
5925
+ }
5926
+
5927
+ if ( this[0] ) {
5928
+ // The elements to wrap the target around
5929
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
5930
+
5931
+ if ( this[0].parentNode ) {
5932
+ wrap.insertBefore( this[0] );
5933
+ }
5934
+
5935
+ wrap.map(function() {
5936
+ var elem = this;
5937
+
5938
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
5939
+ elem = elem.firstChild;
5940
+ }
5941
+
5942
+ return elem;
5943
+ }).append( this );
5944
+ }
5945
+
5946
+ return this;
5947
+ },
5948
+
5949
+ wrapInner: function( html ) {
5950
+ if ( jQuery.isFunction( html ) ) {
5951
+ return this.each(function(i) {
5952
+ jQuery(this).wrapInner( html.call(this, i) );
5953
+ });
5954
+ }
5955
+
5956
+ return this.each(function() {
5957
+ var self = jQuery( this ),
5958
+ contents = self.contents();
5959
+
5960
+ if ( contents.length ) {
5961
+ contents.wrapAll( html );
5962
+
5963
+ } else {
5964
+ self.append( html );
5965
+ }
5966
+ });
5967
+ },
5968
+
5969
+ wrap: function( html ) {
5970
+ var isFunction = jQuery.isFunction( html );
5971
+
5972
+ return this.each(function(i) {
5973
+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
5974
+ });
5975
+ },
5976
+
5977
+ unwrap: function() {
5978
+ return this.parent().each(function() {
5979
+ if ( !jQuery.nodeName( this, "body" ) ) {
5980
+ jQuery( this ).replaceWith( this.childNodes );
5981
+ }
5982
+ }).end();
5983
+ },
5984
+
5985
+ append: function() {
5986
+ return this.domManip(arguments, true, function( elem ) {
5987
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5988
+ this.appendChild( elem );
5989
+ }
5990
+ });
5991
+ },
5992
+
5993
+ prepend: function() {
5994
+ return this.domManip(arguments, true, function( elem ) {
5995
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5996
+ this.insertBefore( elem, this.firstChild );
5997
+ }
5998
+ });
5999
+ },
6000
+
6001
+ before: function() {
6002
+ return this.domManip( arguments, false, function( elem ) {
6003
+ if ( this.parentNode ) {
6004
+ this.parentNode.insertBefore( elem, this );
6005
+ }
6006
+ });
6007
+ },
6008
+
6009
+ after: function() {
6010
+ return this.domManip( arguments, false, function( elem ) {
6011
+ if ( this.parentNode ) {
6012
+ this.parentNode.insertBefore( elem, this.nextSibling );
6013
+ }
6014
+ });
6015
+ },
6016
+
6017
+ // keepData is for internal use only--do not document
6018
+ remove: function( selector, keepData ) {
6019
+ var elem,
6020
+ i = 0;
6021
+
6022
+ for ( ; (elem = this[i]) != null; i++ ) {
6023
+ if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) {
6024
+ if ( !keepData && elem.nodeType === 1 ) {
6025
+ jQuery.cleanData( getAll( elem ) );
6026
+ }
6027
+
6028
+ if ( elem.parentNode ) {
6029
+ if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
6030
+ setGlobalEval( getAll( elem, "script" ) );
6031
+ }
6032
+ elem.parentNode.removeChild( elem );
6033
+ }
6034
+ }
6035
+ }
6036
+
6037
+ return this;
6038
+ },
6039
+
6040
+ empty: function() {
6041
+ var elem,
6042
+ i = 0;
6043
+
6044
+ for ( ; (elem = this[i]) != null; i++ ) {
6045
+ // Remove element nodes and prevent memory leaks
6046
+ if ( elem.nodeType === 1 ) {
6047
+ jQuery.cleanData( getAll( elem, false ) );
6048
+ }
6049
+
6050
+ // Remove any remaining nodes
6051
+ while ( elem.firstChild ) {
6052
+ elem.removeChild( elem.firstChild );
6053
+ }
6054
+
6055
+ // If this is a select, ensure that it displays empty (#12336)
6056
+ // Support: IE<9
6057
+ if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
6058
+ elem.options.length = 0;
6059
+ }
6060
+ }
6061
+
6062
+ return this;
6063
+ },
6064
+
6065
+ clone: function( dataAndEvents, deepDataAndEvents ) {
6066
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
6067
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
6068
+
6069
+ return this.map( function () {
6070
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
6071
+ });
6072
+ },
6073
+
6074
+ html: function( value ) {
6075
+ return jQuery.access( this, function( value ) {
6076
+ var elem = this[0] || {},
6077
+ i = 0,
6078
+ l = this.length;
6079
+
6080
+ if ( value === undefined ) {
6081
+ return elem.nodeType === 1 ?
6082
+ elem.innerHTML.replace( rinlinejQuery, "" ) :
6083
+ undefined;
6084
+ }
6085
+
6086
+ // See if we can take a shortcut and just use innerHTML
6087
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
6088
+ ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
6089
+ ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
6090
+ !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
6091
+
6092
+ value = value.replace( rxhtmlTag, "<$1></$2>" );
6093
+
6094
+ try {
6095
+ for (; i < l; i++ ) {
6096
+ // Remove element nodes and prevent memory leaks
6097
+ elem = this[i] || {};
6098
+ if ( elem.nodeType === 1 ) {
6099
+ jQuery.cleanData( getAll( elem, false ) );
6100
+ elem.innerHTML = value;
6101
+ }
6102
+ }
6103
+
6104
+ elem = 0;
6105
+
6106
+ // If using innerHTML throws an exception, use the fallback method
6107
+ } catch(e) {}
6108
+ }
6109
+
6110
+ if ( elem ) {
6111
+ this.empty().append( value );
6112
+ }
6113
+ }, null, value, arguments.length );
6114
+ },
6115
+
6116
+ replaceWith: function( value ) {
6117
+ var isFunc = jQuery.isFunction( value );
6118
+
6119
+ // Make sure that the elements are removed from the DOM before they are inserted
6120
+ // this can help fix replacing a parent with child elements
6121
+ if ( !isFunc && typeof value !== "string" ) {
6122
+ value = jQuery( value ).not( this ).detach();
6123
+ }
6124
+
6125
+ return this.domManip( [ value ], true, function( elem ) {
6126
+ var next = this.nextSibling,
6127
+ parent = this.parentNode;
6128
+
6129
+ if ( parent ) {
6130
+ jQuery( this ).remove();
6131
+ parent.insertBefore( elem, next );
6132
+ }
6133
+ });
6134
+ },
6135
+
6136
+ detach: function( selector ) {
6137
+ return this.remove( selector, true );
6138
+ },
6139
+
6140
+ domManip: function( args, table, callback ) {
6141
+
6142
+ // Flatten any nested arrays
6143
+ args = core_concat.apply( [], args );
6144
+
6145
+ var first, node, hasScripts,
6146
+ scripts, doc, fragment,
6147
+ i = 0,
6148
+ l = this.length,
6149
+ set = this,
6150
+ iNoClone = l - 1,
6151
+ value = args[0],
6152
+ isFunction = jQuery.isFunction( value );
6153
+
6154
+ // We can't cloneNode fragments that contain checked, in WebKit
6155
+ if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {
6156
+ return this.each(function( index ) {
6157
+ var self = set.eq( index );
6158
+ if ( isFunction ) {
6159
+ args[0] = value.call( this, index, table ? self.html() : undefined );
6160
+ }
6161
+ self.domManip( args, table, callback );
6162
+ });
6163
+ }
6164
+
6165
+ if ( l ) {
6166
+ fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
6167
+ first = fragment.firstChild;
6168
+
6169
+ if ( fragment.childNodes.length === 1 ) {
6170
+ fragment = first;
6171
+ }
6172
+
6173
+ if ( first ) {
6174
+ table = table && jQuery.nodeName( first, "tr" );
6175
+ scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
6176
+ hasScripts = scripts.length;
6177
+
6178
+ // Use the original fragment for the last item instead of the first because it can end up
6179
+ // being emptied incorrectly in certain situations (#8070).
6180
+ for ( ; i < l; i++ ) {
6181
+ node = fragment;
6182
+
6183
+ if ( i !== iNoClone ) {
6184
+ node = jQuery.clone( node, true, true );
6185
+
6186
+ // Keep references to cloned scripts for later restoration
6187
+ if ( hasScripts ) {
6188
+ jQuery.merge( scripts, getAll( node, "script" ) );
6189
+ }
6190
+ }
6191
+
6192
+ callback.call(
6193
+ table && jQuery.nodeName( this[i], "table" ) ?
6194
+ findOrAppend( this[i], "tbody" ) :
6195
+ this[i],
6196
+ node,
6197
+ i
6198
+ );
6199
+ }
6200
+
6201
+ if ( hasScripts ) {
6202
+ doc = scripts[ scripts.length - 1 ].ownerDocument;
6203
+
6204
+ // Reenable scripts
6205
+ jQuery.map( scripts, restoreScript );
6206
+
6207
+ // Evaluate executable scripts on first document insertion
6208
+ for ( i = 0; i < hasScripts; i++ ) {
6209
+ node = scripts[ i ];
6210
+ if ( rscriptType.test( node.type || "" ) &&
6211
+ !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
6212
+
6213
+ if ( node.src ) {
6214
+ // Hope ajax is available...
6215
+ jQuery.ajax({
6216
+ url: node.src,
6217
+ type: "GET",
6218
+ dataType: "script",
6219
+ async: false,
6220
+ global: false,
6221
+ "throws": true
6222
+ });
6223
+ } else {
6224
+ jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
6225
+ }
6226
+ }
6227
+ }
6228
+ }
6229
+
6230
+ // Fix #11809: Avoid leaking memory
6231
+ fragment = first = null;
6232
+ }
6233
+ }
6234
+
6235
+ return this;
6236
+ }
6237
+ });
6238
+
6239
+ function findOrAppend( elem, tag ) {
6240
+ return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
6241
+ }
6242
+
6243
+ // Replace/restore the type attribute of script elements for safe DOM manipulation
6244
+ function disableScript( elem ) {
6245
+ var attr = elem.getAttributeNode("type");
6246
+ elem.type = ( attr && attr.specified ) + "/" + elem.type;
6247
+ return elem;
6248
+ }
6249
+ function restoreScript( elem ) {
6250
+ var match = rscriptTypeMasked.exec( elem.type );
6251
+ if ( match ) {
6252
+ elem.type = match[1];
6253
+ } else {
6254
+ elem.removeAttribute("type");
6255
+ }
6256
+ return elem;
6257
+ }
6258
+
6259
+ // Mark scripts as having already been evaluated
6260
+ function setGlobalEval( elems, refElements ) {
6261
+ var elem,
6262
+ i = 0;
6263
+ for ( ; (elem = elems[i]) != null; i++ ) {
6264
+ jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
6265
+ }
6266
+ }
6267
+
6268
+ function cloneCopyEvent( src, dest ) {
6269
+
6270
+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
6271
+ return;
6272
+ }
6273
+
6274
+ var type, i, l,
6275
+ oldData = jQuery._data( src ),
6276
+ curData = jQuery._data( dest, oldData ),
6277
+ events = oldData.events;
6278
+
6279
+ if ( events ) {
6280
+ delete curData.handle;
6281
+ curData.events = {};
6282
+
6283
+ for ( type in events ) {
6284
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
6285
+ jQuery.event.add( dest, type, events[ type ][ i ] );
6286
+ }
6287
+ }
6288
+ }
6289
+
6290
+ // make the cloned public data object a copy from the original
6291
+ if ( curData.data ) {
6292
+ curData.data = jQuery.extend( {}, curData.data );
6293
+ }
6294
+ }
6295
+
6296
+ function fixCloneNodeIssues( src, dest ) {
6297
+ var nodeName, e, data;
6298
+
6299
+ // We do not need to do anything for non-Elements
6300
+ if ( dest.nodeType !== 1 ) {
6301
+ return;
6302
+ }
6303
+
6304
+ nodeName = dest.nodeName.toLowerCase();
6305
+
6306
+ // IE6-8 copies events bound via attachEvent when using cloneNode.
6307
+ if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {
6308
+ data = jQuery._data( dest );
6309
+
6310
+ for ( e in data.events ) {
6311
+ jQuery.removeEvent( dest, e, data.handle );
6312
+ }
6313
+
6314
+ // Event data gets referenced instead of copied if the expando gets copied too
6315
+ dest.removeAttribute( jQuery.expando );
6316
+ }
6317
+
6318
+ // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
6319
+ if ( nodeName === "script" && dest.text !== src.text ) {
6320
+ disableScript( dest ).text = src.text;
6321
+ restoreScript( dest );
6322
+
6323
+ // IE6-10 improperly clones children of object elements using classid.
6324
+ // IE10 throws NoModificationAllowedError if parent is null, #12132.
6325
+ } else if ( nodeName === "object" ) {
6326
+ if ( dest.parentNode ) {
6327
+ dest.outerHTML = src.outerHTML;
6328
+ }
6329
+
6330
+ // This path appears unavoidable for IE9. When cloning an object
6331
+ // element in IE9, the outerHTML strategy above is not sufficient.
6332
+ // If the src has innerHTML and the destination does not,
6333
+ // copy the src.innerHTML into the dest.innerHTML. #10324
6334
+ if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
6335
+ dest.innerHTML = src.innerHTML;
6336
+ }
6337
+
6338
+ } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) {
6339
+ // IE6-8 fails to persist the checked state of a cloned checkbox
6340
+ // or radio button. Worse, IE6-7 fail to give the cloned element
6341
+ // a checked appearance if the defaultChecked value isn't also set
6342
+
6343
+ dest.defaultChecked = dest.checked = src.checked;
6344
+
6345
+ // IE6-7 get confused and end up setting the value of a cloned
6346
+ // checkbox/radio button to an empty string instead of "on"
6347
+ if ( dest.value !== src.value ) {
6348
+ dest.value = src.value;
6349
+ }
6350
+
6351
+ // IE6-8 fails to return the selected option to the default selected
6352
+ // state when cloning options
6353
+ } else if ( nodeName === "option" ) {
6354
+ dest.defaultSelected = dest.selected = src.defaultSelected;
6355
+
6356
+ // IE6-8 fails to set the defaultValue to the correct value when
6357
+ // cloning other types of input fields
6358
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
6359
+ dest.defaultValue = src.defaultValue;
6360
+ }
6361
+ }
6362
+
6363
+ jQuery.each({
6364
+ appendTo: "append",
6365
+ prependTo: "prepend",
6366
+ insertBefore: "before",
6367
+ insertAfter: "after",
6368
+ replaceAll: "replaceWith"
6369
+ }, function( name, original ) {
6370
+ jQuery.fn[ name ] = function( selector ) {
6371
+ var elems,
6372
+ i = 0,
6373
+ ret = [],
6374
+ insert = jQuery( selector ),
6375
+ last = insert.length - 1;
6376
+
6377
+ for ( ; i <= last; i++ ) {
6378
+ elems = i === last ? this : this.clone(true);
6379
+ jQuery( insert[i] )[ original ]( elems );
6380
+
6381
+ // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
6382
+ core_push.apply( ret, elems.get() );
6383
+ }
6384
+
6385
+ return this.pushStack( ret );
6386
+ };
6387
+ });
6388
+
6389
+ function getAll( context, tag ) {
6390
+ var elems, elem,
6391
+ i = 0,
6392
+ found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) :
6393
+ typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) :
6394
+ undefined;
6395
+
6396
+ if ( !found ) {
6397
+ for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
6398
+ if ( !tag || jQuery.nodeName( elem, tag ) ) {
6399
+ found.push( elem );
6400
+ } else {
6401
+ jQuery.merge( found, getAll( elem, tag ) );
6402
+ }
6403
+ }
6404
+ }
6405
+
6406
+ return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
6407
+ jQuery.merge( [ context ], found ) :
6408
+ found;
6409
+ }
6410
+
6411
+ // Used in buildFragment, fixes the defaultChecked property
6412
+ function fixDefaultChecked( elem ) {
6413
+ if ( manipulation_rcheckableType.test( elem.type ) ) {
6414
+ elem.defaultChecked = elem.checked;
6415
+ }
6416
+ }
6417
+
6418
+ jQuery.extend({
6419
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
6420
+ var destElements, node, clone, i, srcElements,
6421
+ inPage = jQuery.contains( elem.ownerDocument, elem );
6422
+
6423
+ if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
6424
+ clone = elem.cloneNode( true );
6425
+
6426
+ // IE<=8 does not properly clone detached, unknown element nodes
6427
+ } else {
6428
+ fragmentDiv.innerHTML = elem.outerHTML;
6429
+ fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
6430
+ }
6431
+
6432
+ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
6433
+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
6434
+
6435
+ // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
6436
+ destElements = getAll( clone );
6437
+ srcElements = getAll( elem );
6438
+
6439
+ // Fix all IE cloning issues
6440
+ for ( i = 0; (node = srcElements[i]) != null; ++i ) {
6441
+ // Ensure that the destination node is not null; Fixes #9587
6442
+ if ( destElements[i] ) {
6443
+ fixCloneNodeIssues( node, destElements[i] );
6444
+ }
6445
+ }
6446
+ }
6447
+
6448
+ // Copy the events from the original to the clone
6449
+ if ( dataAndEvents ) {
6450
+ if ( deepDataAndEvents ) {
6451
+ srcElements = srcElements || getAll( elem );
6452
+ destElements = destElements || getAll( clone );
6453
+
6454
+ for ( i = 0; (node = srcElements[i]) != null; i++ ) {
6455
+ cloneCopyEvent( node, destElements[i] );
6456
+ }
6457
+ } else {
6458
+ cloneCopyEvent( elem, clone );
6459
+ }
6460
+ }
6461
+
6462
+ // Preserve script evaluation history
6463
+ destElements = getAll( clone, "script" );
6464
+ if ( destElements.length > 0 ) {
6465
+ setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
6466
+ }
6467
+
6468
+ destElements = srcElements = node = null;
6469
+
6470
+ // Return the cloned set
6471
+ return clone;
6472
+ },
6473
+
6474
+ buildFragment: function( elems, context, scripts, selection ) {
6475
+ var j, elem, contains,
6476
+ tmp, tag, tbody, wrap,
6477
+ l = elems.length,
6478
+
6479
+ // Ensure a safe fragment
6480
+ safe = createSafeFragment( context ),
6481
+
6482
+ nodes = [],
6483
+ i = 0;
6484
+
6485
+ for ( ; i < l; i++ ) {
6486
+ elem = elems[ i ];
6487
+
6488
+ if ( elem || elem === 0 ) {
6489
+
6490
+ // Add nodes directly
6491
+ if ( jQuery.type( elem ) === "object" ) {
6492
+ jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
6493
+
6494
+ // Convert non-html into a text node
6495
+ } else if ( !rhtml.test( elem ) ) {
6496
+ nodes.push( context.createTextNode( elem ) );
6497
+
6498
+ // Convert html into DOM nodes
6499
+ } else {
6500
+ tmp = tmp || safe.appendChild( context.createElement("div") );
6501
+
6502
+ // Deserialize a standard representation
6503
+ tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
6504
+ wrap = wrapMap[ tag ] || wrapMap._default;
6505
+
6506
+ tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
6507
+
6508
+ // Descend through wrappers to the right content
6509
+ j = wrap[0];
6510
+ while ( j-- ) {
6511
+ tmp = tmp.lastChild;
6512
+ }
6513
+
6514
+ // Manually add leading whitespace removed by IE
6515
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
6516
+ nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
6517
+ }
6518
+
6519
+ // Remove IE's autoinserted <tbody> from table fragments
6520
+ if ( !jQuery.support.tbody ) {
6521
+
6522
+ // String was a <table>, *may* have spurious <tbody>
6523
+ elem = tag === "table" && !rtbody.test( elem ) ?
6524
+ tmp.firstChild :
6525
+
6526
+ // String was a bare <thead> or <tfoot>
6527
+ wrap[1] === "<table>" && !rtbody.test( elem ) ?
6528
+ tmp :
6529
+ 0;
6530
+
6531
+ j = elem && elem.childNodes.length;
6532
+ while ( j-- ) {
6533
+ if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
6534
+ elem.removeChild( tbody );
6535
+ }
6536
+ }
6537
+ }
6538
+
6539
+ jQuery.merge( nodes, tmp.childNodes );
6540
+
6541
+ // Fix #12392 for WebKit and IE > 9
6542
+ tmp.textContent = "";
6543
+
6544
+ // Fix #12392 for oldIE
6545
+ while ( tmp.firstChild ) {
6546
+ tmp.removeChild( tmp.firstChild );
6547
+ }
6548
+
6549
+ // Remember the top-level container for proper cleanup
6550
+ tmp = safe.lastChild;
6551
+ }
6552
+ }
6553
+ }
6554
+
6555
+ // Fix #11356: Clear elements from fragment
6556
+ if ( tmp ) {
6557
+ safe.removeChild( tmp );
6558
+ }
6559
+
6560
+ // Reset defaultChecked for any radios and checkboxes
6561
+ // about to be appended to the DOM in IE 6/7 (#8060)
6562
+ if ( !jQuery.support.appendChecked ) {
6563
+ jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
6564
+ }
6565
+
6566
+ i = 0;
6567
+ while ( (elem = nodes[ i++ ]) ) {
6568
+
6569
+ // #4087 - If origin and destination elements are the same, and this is
6570
+ // that element, do not do anything
6571
+ if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
6572
+ continue;
6573
+ }
6574
+
6575
+ contains = jQuery.contains( elem.ownerDocument, elem );
6576
+
6577
+ // Append to fragment
6578
+ tmp = getAll( safe.appendChild( elem ), "script" );
6579
+
6580
+ // Preserve script evaluation history
6581
+ if ( contains ) {
6582
+ setGlobalEval( tmp );
6583
+ }
6584
+
6585
+ // Capture executables
6586
+ if ( scripts ) {
6587
+ j = 0;
6588
+ while ( (elem = tmp[ j++ ]) ) {
6589
+ if ( rscriptType.test( elem.type || "" ) ) {
6590
+ scripts.push( elem );
6591
+ }
6592
+ }
6593
+ }
6594
+ }
6595
+
6596
+ tmp = null;
6597
+
6598
+ return safe;
6599
+ },
6600
+
6601
+ cleanData: function( elems, /* internal */ acceptData ) {
6602
+ var elem, type, id, data,
6603
+ i = 0,
6604
+ internalKey = jQuery.expando,
6605
+ cache = jQuery.cache,
6606
+ deleteExpando = jQuery.support.deleteExpando,
6607
+ special = jQuery.event.special;
6608
+
6609
+ for ( ; (elem = elems[i]) != null; i++ ) {
6610
+
6611
+ if ( acceptData || jQuery.acceptData( elem ) ) {
6612
+
6613
+ id = elem[ internalKey ];
6614
+ data = id && cache[ id ];
6615
+
6616
+ if ( data ) {
6617
+ if ( data.events ) {
6618
+ for ( type in data.events ) {
6619
+ if ( special[ type ] ) {
6620
+ jQuery.event.remove( elem, type );
6621
+
6622
+ // This is a shortcut to avoid jQuery.event.remove's overhead
6623
+ } else {
6624
+ jQuery.removeEvent( elem, type, data.handle );
6625
+ }
6626
+ }
6627
+ }
6628
+
6629
+ // Remove cache only if it was not already removed by jQuery.event.remove
6630
+ if ( cache[ id ] ) {
6631
+
6632
+ delete cache[ id ];
6633
+
6634
+ // IE does not allow us to delete expando properties from nodes,
6635
+ // nor does it have a removeAttribute function on Document nodes;
6636
+ // we must handle all of these cases
6637
+ if ( deleteExpando ) {
6638
+ delete elem[ internalKey ];
6639
+
6640
+ } else if ( typeof elem.removeAttribute !== core_strundefined ) {
6641
+ elem.removeAttribute( internalKey );
6642
+
6643
+ } else {
6644
+ elem[ internalKey ] = null;
6645
+ }
6646
+
6647
+ core_deletedIds.push( id );
6648
+ }
6649
+ }
6650
+ }
6651
+ }
6652
+ }
6653
+ });
6654
+ var iframe, getStyles, curCSS,
6655
+ ralpha = /alpha\([^)]*\)/i,
6656
+ ropacity = /opacity\s*=\s*([^)]*)/,
6657
+ rposition = /^(top|right|bottom|left)$/,
6658
+ // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
6659
+ // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6660
+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6661
+ rmargin = /^margin/,
6662
+ rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
6663
+ rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
6664
+ rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ),
6665
+ elemdisplay = {
6666
+ BODY: "block"
6667
+ },
6668
+
6669
+ cssShow = {
6670
+ position: "absolute",
6671
+ visibility: "hidden",
6672
+ display: "block"
6673
+ },
6674
+ cssNormalTransform = {
6675
+ letterSpacing: 0,
6676
+ fontWeight: 400
6677
+ },
6678
+
6679
+ cssExpand = [ "Top", "Right", "Bottom", "Left" ],
6680
+ cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
6681
+
6682
+ // return a css property mapped to a potentially vendor prefixed property
6683
+ function vendorPropName( style, name ) {
6684
+
6685
+ // shortcut for names that are not vendor prefixed
6686
+ if ( name in style ) {
6687
+ return name;
6688
+ }
6689
+
6690
+ // check for vendor prefixed names
6691
+ var capName = name.charAt(0).toUpperCase() + name.slice(1),
6692
+ origName = name,
6693
+ i = cssPrefixes.length;
6694
+
6695
+ while ( i-- ) {
6696
+ name = cssPrefixes[ i ] + capName;
6697
+ if ( name in style ) {
6698
+ return name;
6699
+ }
6700
+ }
6701
+
6702
+ return origName;
6703
+ }
6704
+
6705
+ function isHidden( elem, el ) {
6706
+ // isHidden might be called from jQuery#filter function;
6707
+ // in that case, element will be second argument
6708
+ elem = el || elem;
6709
+ return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
6710
+ }
6711
+
6712
+ function showHide( elements, show ) {
6713
+ var display, elem, hidden,
6714
+ values = [],
6715
+ index = 0,
6716
+ length = elements.length;
6717
+
6718
+ for ( ; index < length; index++ ) {
6719
+ elem = elements[ index ];
6720
+ if ( !elem.style ) {
6721
+ continue;
6722
+ }
6723
+
6724
+ values[ index ] = jQuery._data( elem, "olddisplay" );
6725
+ display = elem.style.display;
6726
+ if ( show ) {
6727
+ // Reset the inline display of this element to learn if it is
6728
+ // being hidden by cascaded rules or not
6729
+ if ( !values[ index ] && display === "none" ) {
6730
+ elem.style.display = "";
6731
+ }
6732
+
6733
+ // Set elements which have been overridden with display: none
6734
+ // in a stylesheet to whatever the default browser style is
6735
+ // for such an element
6736
+ if ( elem.style.display === "" && isHidden( elem ) ) {
6737
+ values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
6738
+ }
6739
+ } else {
6740
+
6741
+ if ( !values[ index ] ) {
6742
+ hidden = isHidden( elem );
6743
+
6744
+ if ( display && display !== "none" || !hidden ) {
6745
+ jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
6746
+ }
6747
+ }
6748
+ }
6749
+ }
6750
+
6751
+ // Set the display of most of the elements in a second loop
6752
+ // to avoid the constant reflow
6753
+ for ( index = 0; index < length; index++ ) {
6754
+ elem = elements[ index ];
6755
+ if ( !elem.style ) {
6756
+ continue;
6757
+ }
6758
+ if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
6759
+ elem.style.display = show ? values[ index ] || "" : "none";
6760
+ }
6761
+ }
6762
+
6763
+ return elements;
6764
+ }
6765
+
6766
+ jQuery.fn.extend({
6767
+ css: function( name, value ) {
6768
+ return jQuery.access( this, function( elem, name, value ) {
6769
+ var len, styles,
6770
+ map = {},
6771
+ i = 0;
6772
+
6773
+ if ( jQuery.isArray( name ) ) {
6774
+ styles = getStyles( elem );
6775
+ len = name.length;
6776
+
6777
+ for ( ; i < len; i++ ) {
6778
+ map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6779
+ }
6780
+
6781
+ return map;
6782
+ }
6783
+
6784
+ return value !== undefined ?
6785
+ jQuery.style( elem, name, value ) :
6786
+ jQuery.css( elem, name );
6787
+ }, name, value, arguments.length > 1 );
6788
+ },
6789
+ show: function() {
6790
+ return showHide( this, true );
6791
+ },
6792
+ hide: function() {
6793
+ return showHide( this );
6794
+ },
6795
+ toggle: function( state ) {
6796
+ var bool = typeof state === "boolean";
6797
+
6798
+ return this.each(function() {
6799
+ if ( bool ? state : isHidden( this ) ) {
6800
+ jQuery( this ).show();
6801
+ } else {
6802
+ jQuery( this ).hide();
6803
+ }
6804
+ });
6805
+ }
6806
+ });
6807
+
6808
+ jQuery.extend({
6809
+ // Add in style property hooks for overriding the default
6810
+ // behavior of getting and setting a style property
6811
+ cssHooks: {
6812
+ opacity: {
6813
+ get: function( elem, computed ) {
6814
+ if ( computed ) {
6815
+ // We should always get a number back from opacity
6816
+ var ret = curCSS( elem, "opacity" );
6817
+ return ret === "" ? "1" : ret;
6818
+ }
6819
+ }
6820
+ }
6821
+ },
6822
+
6823
+ // Exclude the following css properties to add px
6824
+ cssNumber: {
6825
+ "columnCount": true,
6826
+ "fillOpacity": true,
6827
+ "fontWeight": true,
6828
+ "lineHeight": true,
6829
+ "opacity": true,
6830
+ "orphans": true,
6831
+ "widows": true,
6832
+ "zIndex": true,
6833
+ "zoom": true
6834
+ },
6835
+
6836
+ // Add in properties whose names you wish to fix before
6837
+ // setting or getting the value
6838
+ cssProps: {
6839
+ // normalize float css property
6840
+ "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
6841
+ },
6842
+
6843
+ // Get and set the style property on a DOM Node
6844
+ style: function( elem, name, value, extra ) {
6845
+ // Don't set styles on text and comment nodes
6846
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6847
+ return;
6848
+ }
6849
+
6850
+ // Make sure that we're working with the right name
6851
+ var ret, type, hooks,
6852
+ origName = jQuery.camelCase( name ),
6853
+ style = elem.style;
6854
+
6855
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
6856
+
6857
+ // gets hook for the prefixed version
6858
+ // followed by the unprefixed version
6859
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6860
+
6861
+ // Check if we're setting a value
6862
+ if ( value !== undefined ) {
6863
+ type = typeof value;
6864
+
6865
+ // convert relative number strings (+= or -=) to relative numbers. #7345
6866
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
6867
+ value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
6868
+ // Fixes bug #9237
6869
+ type = "number";
6870
+ }
6871
+
6872
+ // Make sure that NaN and null values aren't set. See: #7116
6873
+ if ( value == null || type === "number" && isNaN( value ) ) {
6874
+ return;
6875
+ }
6876
+
6877
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
6878
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
6879
+ value += "px";
6880
+ }
6881
+
6882
+ // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
6883
+ // but it would mean to define eight (for every problematic property) identical functions
6884
+ if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
6885
+ style[ name ] = "inherit";
6886
+ }
6887
+
6888
+ // If a hook was provided, use that value, otherwise just set the specified value
6889
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
6890
+
6891
+ // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
6892
+ // Fixes bug #5509
6893
+ try {
6894
+ style[ name ] = value;
6895
+ } catch(e) {}
6896
+ }
6897
+
6898
+ } else {
6899
+ // If a hook was provided get the non-computed value from there
6900
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
6901
+ return ret;
6902
+ }
6903
+
6904
+ // Otherwise just get the value from the style object
6905
+ return style[ name ];
6906
+ }
6907
+ },
6908
+
6909
+ css: function( elem, name, extra, styles ) {
6910
+ var num, val, hooks,
6911
+ origName = jQuery.camelCase( name );
6912
+
6913
+ // Make sure that we're working with the right name
6914
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
6915
+
6916
+ // gets hook for the prefixed version
6917
+ // followed by the unprefixed version
6918
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6919
+
6920
+ // If a hook was provided get the computed value from there
6921
+ if ( hooks && "get" in hooks ) {
6922
+ val = hooks.get( elem, true, extra );
6923
+ }
6924
+
6925
+ // Otherwise, if a way to get the computed value exists, use that
6926
+ if ( val === undefined ) {
6927
+ val = curCSS( elem, name, styles );
6928
+ }
6929
+
6930
+ //convert "normal" to computed value
6931
+ if ( val === "normal" && name in cssNormalTransform ) {
6932
+ val = cssNormalTransform[ name ];
6933
+ }
6934
+
6935
+ // Return, converting to number if forced or a qualifier was provided and val looks numeric
6936
+ if ( extra === "" || extra ) {
6937
+ num = parseFloat( val );
6938
+ return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
6939
+ }
6940
+ return val;
6941
+ },
6942
+
6943
+ // A method for quickly swapping in/out CSS properties to get correct calculations
6944
+ swap: function( elem, options, callback, args ) {
6945
+ var ret, name,
6946
+ old = {};
6947
+
6948
+ // Remember the old values, and insert the new ones
6949
+ for ( name in options ) {
6950
+ old[ name ] = elem.style[ name ];
6951
+ elem.style[ name ] = options[ name ];
6952
+ }
6953
+
6954
+ ret = callback.apply( elem, args || [] );
6955
+
6956
+ // Revert the old values
6957
+ for ( name in options ) {
6958
+ elem.style[ name ] = old[ name ];
6959
+ }
6960
+
6961
+ return ret;
6962
+ }
6963
+ });
6964
+
6965
+ // NOTE: we've included the "window" in window.getComputedStyle
6966
+ // because jsdom on node.js will break without it.
6967
+ if ( window.getComputedStyle ) {
6968
+ getStyles = function( elem ) {
6969
+ return window.getComputedStyle( elem, null );
6970
+ };
6971
+
6972
+ curCSS = function( elem, name, _computed ) {
6973
+ var width, minWidth, maxWidth,
6974
+ computed = _computed || getStyles( elem ),
6975
+
6976
+ // getPropertyValue is only needed for .css('filter') in IE9, see #12537
6977
+ ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,
6978
+ style = elem.style;
6979
+
6980
+ if ( computed ) {
6981
+
6982
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
6983
+ ret = jQuery.style( elem, name );
6984
+ }
6985
+
6986
+ // A tribute to the "awesome hack by Dean Edwards"
6987
+ // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
6988
+ // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
6989
+ // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
6990
+ if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
6991
+
6992
+ // Remember the original values
6993
+ width = style.width;
6994
+ minWidth = style.minWidth;
6995
+ maxWidth = style.maxWidth;
6996
+
6997
+ // Put in the new values to get a computed value out
6998
+ style.minWidth = style.maxWidth = style.width = ret;
6999
+ ret = computed.width;
7000
+
7001
+ // Revert the changed values
7002
+ style.width = width;
7003
+ style.minWidth = minWidth;
7004
+ style.maxWidth = maxWidth;
7005
+ }
7006
+ }
7007
+
7008
+ return ret;
7009
+ };
7010
+ } else if ( document.documentElement.currentStyle ) {
7011
+ getStyles = function( elem ) {
7012
+ return elem.currentStyle;
7013
+ };
7014
+
7015
+ curCSS = function( elem, name, _computed ) {
7016
+ var left, rs, rsLeft,
7017
+ computed = _computed || getStyles( elem ),
7018
+ ret = computed ? computed[ name ] : undefined,
7019
+ style = elem.style;
7020
+
7021
+ // Avoid setting ret to empty string here
7022
+ // so we don't default to auto
7023
+ if ( ret == null && style && style[ name ] ) {
7024
+ ret = style[ name ];
7025
+ }
7026
+
7027
+ // From the awesome hack by Dean Edwards
7028
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
7029
+
7030
+ // If we're not dealing with a regular pixel number
7031
+ // but a number that has a weird ending, we need to convert it to pixels
7032
+ // but not position css attributes, as those are proportional to the parent element instead
7033
+ // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
7034
+ if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
7035
+
7036
+ // Remember the original values
7037
+ left = style.left;
7038
+ rs = elem.runtimeStyle;
7039
+ rsLeft = rs && rs.left;
7040
+
7041
+ // Put in the new values to get a computed value out
7042
+ if ( rsLeft ) {
7043
+ rs.left = elem.currentStyle.left;
7044
+ }
7045
+ style.left = name === "fontSize" ? "1em" : ret;
7046
+ ret = style.pixelLeft + "px";
7047
+
7048
+ // Revert the changed values
7049
+ style.left = left;
7050
+ if ( rsLeft ) {
7051
+ rs.left = rsLeft;
7052
+ }
7053
+ }
7054
+
7055
+ return ret === "" ? "auto" : ret;
7056
+ };
7057
+ }
7058
+
7059
+ function setPositiveNumber( elem, value, subtract ) {
7060
+ var matches = rnumsplit.exec( value );
7061
+ return matches ?
7062
+ // Guard against undefined "subtract", e.g., when used as in cssHooks
7063
+ Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
7064
+ value;
7065
+ }
7066
+
7067
+ function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
7068
+ var i = extra === ( isBorderBox ? "border" : "content" ) ?
7069
+ // If we already have the right measurement, avoid augmentation
7070
+ 4 :
7071
+ // Otherwise initialize for horizontal or vertical properties
7072
+ name === "width" ? 1 : 0,
7073
+
7074
+ val = 0;
7075
+
7076
+ for ( ; i < 4; i += 2 ) {
7077
+ // both box models exclude margin, so add it if we want it
7078
+ if ( extra === "margin" ) {
7079
+ val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
7080
+ }
7081
+
7082
+ if ( isBorderBox ) {
7083
+ // border-box includes padding, so remove it if we want content
7084
+ if ( extra === "content" ) {
7085
+ val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7086
+ }
7087
+
7088
+ // at this point, extra isn't border nor margin, so remove border
7089
+ if ( extra !== "margin" ) {
7090
+ val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7091
+ }
7092
+ } else {
7093
+ // at this point, extra isn't content, so add padding
7094
+ val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7095
+
7096
+ // at this point, extra isn't content nor padding, so add border
7097
+ if ( extra !== "padding" ) {
7098
+ val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7099
+ }
7100
+ }
7101
+ }
7102
+
7103
+ return val;
7104
+ }
7105
+
7106
+ function getWidthOrHeight( elem, name, extra ) {
7107
+
7108
+ // Start with offset property, which is equivalent to the border-box value
7109
+ var valueIsBorderBox = true,
7110
+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
7111
+ styles = getStyles( elem ),
7112
+ isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
7113
+
7114
+ // some non-html elements return undefined for offsetWidth, so check for null/undefined
7115
+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
7116
+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
7117
+ if ( val <= 0 || val == null ) {
7118
+ // Fall back to computed then uncomputed css if necessary
7119
+ val = curCSS( elem, name, styles );
7120
+ if ( val < 0 || val == null ) {
7121
+ val = elem.style[ name ];
7122
+ }
7123
+
7124
+ // Computed unit is not pixels. Stop here and return.
7125
+ if ( rnumnonpx.test(val) ) {
7126
+ return val;
7127
+ }
7128
+
7129
+ // we need the check for style in case a browser which returns unreliable values
7130
+ // for getComputedStyle silently falls back to the reliable elem.style
7131
+ valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
7132
+
7133
+ // Normalize "", auto, and prepare for extra
7134
+ val = parseFloat( val ) || 0;
7135
+ }
7136
+
7137
+ // use the active box-sizing model to add/subtract irrelevant styles
7138
+ return ( val +
7139
+ augmentWidthOrHeight(
7140
+ elem,
7141
+ name,
7142
+ extra || ( isBorderBox ? "border" : "content" ),
7143
+ valueIsBorderBox,
7144
+ styles
7145
+ )
7146
+ ) + "px";
7147
+ }
7148
+
7149
+ // Try to determine the default display value of an element
7150
+ function css_defaultDisplay( nodeName ) {
7151
+ var doc = document,
7152
+ display = elemdisplay[ nodeName ];
7153
+
7154
+ if ( !display ) {
7155
+ display = actualDisplay( nodeName, doc );
7156
+
7157
+ // If the simple way fails, read from inside an iframe
7158
+ if ( display === "none" || !display ) {
7159
+ // Use the already-created iframe if possible
7160
+ iframe = ( iframe ||
7161
+ jQuery("<iframe frameborder='0' width='0' height='0'/>")
7162
+ .css( "cssText", "display:block !important" )
7163
+ ).appendTo( doc.documentElement );
7164
+
7165
+ // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
7166
+ doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
7167
+ doc.write("<!doctype html><html><body>");
7168
+ doc.close();
7169
+
7170
+ display = actualDisplay( nodeName, doc );
7171
+ iframe.detach();
7172
+ }
7173
+
7174
+ // Store the correct default display
7175
+ elemdisplay[ nodeName ] = display;
7176
+ }
7177
+
7178
+ return display;
7179
+ }
7180
+
7181
+ // Called ONLY from within css_defaultDisplay
7182
+ function actualDisplay( name, doc ) {
7183
+ var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
7184
+ display = jQuery.css( elem[0], "display" );
7185
+ elem.remove();
7186
+ return display;
7187
+ }
7188
+
7189
+ jQuery.each([ "height", "width" ], function( i, name ) {
7190
+ jQuery.cssHooks[ name ] = {
7191
+ get: function( elem, computed, extra ) {
7192
+ if ( computed ) {
7193
+ // certain elements can have dimension info if we invisibly show them
7194
+ // however, it must have a current display style that would benefit from this
7195
+ return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
7196
+ jQuery.swap( elem, cssShow, function() {
7197
+ return getWidthOrHeight( elem, name, extra );
7198
+ }) :
7199
+ getWidthOrHeight( elem, name, extra );
7200
+ }
7201
+ },
7202
+
7203
+ set: function( elem, value, extra ) {
7204
+ var styles = extra && getStyles( elem );
7205
+ return setPositiveNumber( elem, value, extra ?
7206
+ augmentWidthOrHeight(
7207
+ elem,
7208
+ name,
7209
+ extra,
7210
+ jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
7211
+ styles
7212
+ ) : 0
7213
+ );
7214
+ }
7215
+ };
7216
+ });
7217
+
7218
+ if ( !jQuery.support.opacity ) {
7219
+ jQuery.cssHooks.opacity = {
7220
+ get: function( elem, computed ) {
7221
+ // IE uses filters for opacity
7222
+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
7223
+ ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
7224
+ computed ? "1" : "";
7225
+ },
7226
+
7227
+ set: function( elem, value ) {
7228
+ var style = elem.style,
7229
+ currentStyle = elem.currentStyle,
7230
+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
7231
+ filter = currentStyle && currentStyle.filter || style.filter || "";
7232
+
7233
+ // IE has trouble with opacity if it does not have layout
7234
+ // Force it by setting the zoom level
7235
+ style.zoom = 1;
7236
+
7237
+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
7238
+ // if value === "", then remove inline opacity #12685
7239
+ if ( ( value >= 1 || value === "" ) &&
7240
+ jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
7241
+ style.removeAttribute ) {
7242
+
7243
+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
7244
+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
7245
+ // style.removeAttribute is IE Only, but so apparently is this code path...
7246
+ style.removeAttribute( "filter" );
7247
+
7248
+ // if there is no filter style applied in a css rule or unset inline opacity, we are done
7249
+ if ( value === "" || currentStyle && !currentStyle.filter ) {
7250
+ return;
7251
+ }
7252
+ }
7253
+
7254
+ // otherwise, set new filter values
7255
+ style.filter = ralpha.test( filter ) ?
7256
+ filter.replace( ralpha, opacity ) :
7257
+ filter + " " + opacity;
7258
+ }
7259
+ };
7260
+ }
7261
+
7262
+ // These hooks cannot be added until DOM ready because the support test
7263
+ // for it is not run until after DOM ready
7264
+ jQuery(function() {
7265
+ if ( !jQuery.support.reliableMarginRight ) {
7266
+ jQuery.cssHooks.marginRight = {
7267
+ get: function( elem, computed ) {
7268
+ if ( computed ) {
7269
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
7270
+ // Work around by temporarily setting element display to inline-block
7271
+ return jQuery.swap( elem, {
7272
+ "display": "inline-block"
7273
+ },
7274
+ curCSS, [ elem, "marginRight" ] );
7275
+ }
7276
+ }
7277
+ };
7278
+ }
7279
+
7280
+ // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
7281
+ // getComputedStyle returns percent when specified for top/left/bottom/right
7282
+ // rather than make the css module depend on the offset module, we just check for it here
7283
+ if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
7284
+ jQuery.each( [ "top", "left" ], function( i, prop ) {
7285
+ jQuery.cssHooks[ prop ] = {
7286
+ get: function( elem, computed ) {
7287
+ if ( computed ) {
7288
+ computed = curCSS( elem, prop );
7289
+ // if curCSS returns percentage, fallback to offset
7290
+ return rnumnonpx.test( computed ) ?
7291
+ jQuery( elem ).position()[ prop ] + "px" :
7292
+ computed;
7293
+ }
7294
+ }
7295
+ };
7296
+ });
7297
+ }
7298
+
7299
+ });
7300
+
7301
+ if ( jQuery.expr && jQuery.expr.filters ) {
7302
+ jQuery.expr.filters.hidden = function( elem ) {
7303
+ // Support: Opera <= 12.12
7304
+ // Opera reports offsetWidths and offsetHeights less than zero on some elements
7305
+ return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
7306
+ (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
7307
+ };
7308
+
7309
+ jQuery.expr.filters.visible = function( elem ) {
7310
+ return !jQuery.expr.filters.hidden( elem );
7311
+ };
7312
+ }
7313
+
7314
+ // These hooks are used by animate to expand properties
7315
+ jQuery.each({
7316
+ margin: "",
7317
+ padding: "",
7318
+ border: "Width"
7319
+ }, function( prefix, suffix ) {
7320
+ jQuery.cssHooks[ prefix + suffix ] = {
7321
+ expand: function( value ) {
7322
+ var i = 0,
7323
+ expanded = {},
7324
+
7325
+ // assumes a single number if not a string
7326
+ parts = typeof value === "string" ? value.split(" ") : [ value ];
7327
+
7328
+ for ( ; i < 4; i++ ) {
7329
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
7330
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
7331
+ }
7332
+
7333
+ return expanded;
7334
+ }
7335
+ };
7336
+
7337
+ if ( !rmargin.test( prefix ) ) {
7338
+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
7339
+ }
7340
+ });
7341
+ var r20 = /%20/g,
7342
+ rbracket = /\[\]$/,
7343
+ rCRLF = /\r?\n/g,
7344
+ rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
7345
+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
7346
+
7347
+ jQuery.fn.extend({
7348
+ serialize: function() {
7349
+ return jQuery.param( this.serializeArray() );
7350
+ },
7351
+ serializeArray: function() {
7352
+ return this.map(function(){
7353
+ // Can add propHook for "elements" to filter or add form elements
7354
+ var elements = jQuery.prop( this, "elements" );
7355
+ return elements ? jQuery.makeArray( elements ) : this;
7356
+ })
7357
+ .filter(function(){
7358
+ var type = this.type;
7359
+ // Use .is(":disabled") so that fieldset[disabled] works
7360
+ return this.name && !jQuery( this ).is( ":disabled" ) &&
7361
+ rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
7362
+ ( this.checked || !manipulation_rcheckableType.test( type ) );
7363
+ })
7364
+ .map(function( i, elem ){
7365
+ var val = jQuery( this ).val();
7366
+
7367
+ return val == null ?
7368
+ null :
7369
+ jQuery.isArray( val ) ?
7370
+ jQuery.map( val, function( val ){
7371
+ return {
7372
+ name: elem.name,
7373
+ value: val.replace( rCRLF, "\r\n" )
7374
+ };
7375
+ }) :
7376
+ {
7377
+ name: elem.name,
7378
+ value: val.replace( rCRLF, "\r\n" )
7379
+ };
7380
+ }).get();
7381
+ }
7382
+ });
7383
+
7384
+ //Serialize an array of form elements or a set of
7385
+ //key/values into a query string
7386
+ jQuery.param = function( a, traditional ) {
7387
+ var prefix,
7388
+ s = [],
7389
+ add = function( key, value ) {
7390
+ // If value is a function, invoke it and return its value
7391
+ value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
7392
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
7393
+ };
7394
+
7395
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
7396
+ if ( traditional === undefined ) {
7397
+ traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
7398
+ }
7399
+
7400
+ // If an array was passed in, assume that it is an array of form elements.
7401
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
7402
+ // Serialize the form elements
7403
+ jQuery.each( a, function() {
7404
+ add( this.name, this.value );
7405
+ });
7406
+
7407
+ } else {
7408
+ // If traditional, encode the "old" way (the way 1.3.2 or older
7409
+ // did it), otherwise encode params recursively.
7410
+ for ( prefix in a ) {
7411
+ buildParams( prefix, a[ prefix ], traditional, add );
7412
+ }
7413
+ }
7414
+
7415
+ // Return the resulting serialization
7416
+ return s.join( "&" ).replace( r20, "+" );
7417
+ };
7418
+
7419
+ function buildParams( prefix, obj, traditional, add ) {
7420
+ var name;
7421
+
7422
+ if ( jQuery.isArray( obj ) ) {
7423
+ // Serialize array item.
7424
+ jQuery.each( obj, function( i, v ) {
7425
+ if ( traditional || rbracket.test( prefix ) ) {
7426
+ // Treat each array item as a scalar.
7427
+ add( prefix, v );
7428
+
7429
+ } else {
7430
+ // Item is non-scalar (array or object), encode its numeric index.
7431
+ buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
7432
+ }
7433
+ });
7434
+
7435
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
7436
+ // Serialize object item.
7437
+ for ( name in obj ) {
7438
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
7439
+ }
7440
+
7441
+ } else {
7442
+ // Serialize scalar item.
7443
+ add( prefix, obj );
7444
+ }
7445
+ }
7446
+ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
7447
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
7448
+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
7449
+
7450
+ // Handle event binding
7451
+ jQuery.fn[ name ] = function( data, fn ) {
7452
+ return arguments.length > 0 ?
7453
+ this.on( name, null, data, fn ) :
7454
+ this.trigger( name );
7455
+ };
7456
+ });
7457
+
7458
+ jQuery.fn.hover = function( fnOver, fnOut ) {
7459
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
7460
+ };
7461
+ var
7462
+ // Document location
7463
+ ajaxLocParts,
7464
+ ajaxLocation,
7465
+ ajax_nonce = jQuery.now(),
7466
+
7467
+ ajax_rquery = /\?/,
7468
+ rhash = /#.*$/,
7469
+ rts = /([?&])_=[^&]*/,
7470
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
7471
+ // #7653, #8125, #8152: local protocol detection
7472
+ rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
7473
+ rnoContent = /^(?:GET|HEAD)$/,
7474
+ rprotocol = /^\/\//,
7475
+ rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
7476
+
7477
+ // Keep a copy of the old load method
7478
+ _load = jQuery.fn.load,
7479
+
7480
+ /* Prefilters
7481
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
7482
+ * 2) These are called:
7483
+ * - BEFORE asking for a transport
7484
+ * - AFTER param serialization (s.data is a string if s.processData is true)
7485
+ * 3) key is the dataType
7486
+ * 4) the catchall symbol "*" can be used
7487
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
7488
+ */
7489
+ prefilters = {},
7490
+
7491
+ /* Transports bindings
7492
+ * 1) key is the dataType
7493
+ * 2) the catchall symbol "*" can be used
7494
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
7495
+ */
7496
+ transports = {},
7497
+
7498
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
7499
+ allTypes = "*/".concat("*");
7500
+
7501
+ // #8138, IE may throw an exception when accessing
7502
+ // a field from window.location if document.domain has been set
7503
+ try {
7504
+ ajaxLocation = location.href;
7505
+ } catch( e ) {
7506
+ // Use the href attribute of an A element
7507
+ // since IE will modify it given document.location
7508
+ ajaxLocation = document.createElement( "a" );
7509
+ ajaxLocation.href = "";
7510
+ ajaxLocation = ajaxLocation.href;
7511
+ }
7512
+
7513
+ // Segment location into parts
7514
+ ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
7515
+
7516
+ // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
7517
+ function addToPrefiltersOrTransports( structure ) {
7518
+
7519
+ // dataTypeExpression is optional and defaults to "*"
7520
+ return function( dataTypeExpression, func ) {
7521
+
7522
+ if ( typeof dataTypeExpression !== "string" ) {
7523
+ func = dataTypeExpression;
7524
+ dataTypeExpression = "*";
7525
+ }
7526
+
7527
+ var dataType,
7528
+ i = 0,
7529
+ dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];
7530
+
7531
+ if ( jQuery.isFunction( func ) ) {
7532
+ // For each dataType in the dataTypeExpression
7533
+ while ( (dataType = dataTypes[i++]) ) {
7534
+ // Prepend if requested
7535
+ if ( dataType[0] === "+" ) {
7536
+ dataType = dataType.slice( 1 ) || "*";
7537
+ (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
7538
+
7539
+ // Otherwise append
7540
+ } else {
7541
+ (structure[ dataType ] = structure[ dataType ] || []).push( func );
7542
+ }
7543
+ }
7544
+ }
7545
+ };
7546
+ }
7547
+
7548
+ // Base inspection function for prefilters and transports
7549
+ function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
7550
+
7551
+ var inspected = {},
7552
+ seekingTransport = ( structure === transports );
7553
+
7554
+ function inspect( dataType ) {
7555
+ var selected;
7556
+ inspected[ dataType ] = true;
7557
+ jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
7558
+ var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
7559
+ if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
7560
+ options.dataTypes.unshift( dataTypeOrTransport );
7561
+ inspect( dataTypeOrTransport );
7562
+ return false;
7563
+ } else if ( seekingTransport ) {
7564
+ return !( selected = dataTypeOrTransport );
7565
+ }
7566
+ });
7567
+ return selected;
7568
+ }
7569
+
7570
+ return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
7571
+ }
7572
+
7573
+ // A special extend for ajax options
7574
+ // that takes "flat" options (not to be deep extended)
7575
+ // Fixes #9887
7576
+ function ajaxExtend( target, src ) {
7577
+ var deep, key,
7578
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
7579
+
7580
+ for ( key in src ) {
7581
+ if ( src[ key ] !== undefined ) {
7582
+ ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
7583
+ }
7584
+ }
7585
+ if ( deep ) {
7586
+ jQuery.extend( true, target, deep );
7587
+ }
7588
+
7589
+ return target;
7590
+ }
7591
+
7592
+ jQuery.fn.load = function( url, params, callback ) {
7593
+ if ( typeof url !== "string" && _load ) {
7594
+ return _load.apply( this, arguments );
7595
+ }
7596
+
7597
+ var selector, response, type,
7598
+ self = this,
7599
+ off = url.indexOf(" ");
7600
+
7601
+ if ( off >= 0 ) {
7602
+ selector = url.slice( off, url.length );
7603
+ url = url.slice( 0, off );
7604
+ }
7605
+
7606
+ // If it's a function
7607
+ if ( jQuery.isFunction( params ) ) {
7608
+
7609
+ // We assume that it's the callback
7610
+ callback = params;
7611
+ params = undefined;
7612
+
7613
+ // Otherwise, build a param string
7614
+ } else if ( params && typeof params === "object" ) {
7615
+ type = "POST";
7616
+ }
7617
+
7618
+ // If we have elements to modify, make the request
7619
+ if ( self.length > 0 ) {
7620
+ jQuery.ajax({
7621
+ url: url,
7622
+
7623
+ // if "type" variable is undefined, then "GET" method will be used
7624
+ type: type,
7625
+ dataType: "html",
7626
+ data: params
7627
+ }).done(function( responseText ) {
7628
+
7629
+ // Save response for use in complete callback
7630
+ response = arguments;
7631
+
7632
+ self.html( selector ?
7633
+
7634
+ // If a selector was specified, locate the right elements in a dummy div
7635
+ // Exclude scripts to avoid IE 'Permission Denied' errors
7636
+ jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
7637
+
7638
+ // Otherwise use the full result
7639
+ responseText );
7640
+
7641
+ }).complete( callback && function( jqXHR, status ) {
7642
+ self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
7643
+ });
7644
+ }
7645
+
7646
+ return this;
7647
+ };
7648
+
7649
+ // Attach a bunch of functions for handling common AJAX events
7650
+ jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
7651
+ jQuery.fn[ type ] = function( fn ){
7652
+ return this.on( type, fn );
7653
+ };
7654
+ });
7655
+
7656
+ jQuery.each( [ "get", "post" ], function( i, method ) {
7657
+ jQuery[ method ] = function( url, data, callback, type ) {
7658
+ // shift arguments if data argument was omitted
7659
+ if ( jQuery.isFunction( data ) ) {
7660
+ type = type || callback;
7661
+ callback = data;
7662
+ data = undefined;
7663
+ }
7664
+
7665
+ return jQuery.ajax({
7666
+ url: url,
7667
+ type: method,
7668
+ dataType: type,
7669
+ data: data,
7670
+ success: callback
7671
+ });
7672
+ };
7673
+ });
7674
+
7675
+ jQuery.extend({
7676
+
7677
+ // Counter for holding the number of active queries
7678
+ active: 0,
7679
+
7680
+ // Last-Modified header cache for next request
7681
+ lastModified: {},
7682
+ etag: {},
7683
+
7684
+ ajaxSettings: {
7685
+ url: ajaxLocation,
7686
+ type: "GET",
7687
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
7688
+ global: true,
7689
+ processData: true,
7690
+ async: true,
7691
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
7692
+ /*
7693
+ timeout: 0,
7694
+ data: null,
7695
+ dataType: null,
7696
+ username: null,
7697
+ password: null,
7698
+ cache: null,
7699
+ throws: false,
7700
+ traditional: false,
7701
+ headers: {},
7702
+ */
7703
+
7704
+ accepts: {
7705
+ "*": allTypes,
7706
+ text: "text/plain",
7707
+ html: "text/html",
7708
+ xml: "application/xml, text/xml",
7709
+ json: "application/json, text/javascript"
7710
+ },
7711
+
7712
+ contents: {
7713
+ xml: /xml/,
7714
+ html: /html/,
7715
+ json: /json/
7716
+ },
7717
+
7718
+ responseFields: {
7719
+ xml: "responseXML",
7720
+ text: "responseText"
7721
+ },
7722
+
7723
+ // Data converters
7724
+ // Keys separate source (or catchall "*") and destination types with a single space
7725
+ converters: {
7726
+
7727
+ // Convert anything to text
7728
+ "* text": window.String,
7729
+
7730
+ // Text to html (true = no transformation)
7731
+ "text html": true,
7732
+
7733
+ // Evaluate text as a json expression
7734
+ "text json": jQuery.parseJSON,
7735
+
7736
+ // Parse text as xml
7737
+ "text xml": jQuery.parseXML
7738
+ },
7739
+
7740
+ // For options that shouldn't be deep extended:
7741
+ // you can add your own custom options here if
7742
+ // and when you create one that shouldn't be
7743
+ // deep extended (see ajaxExtend)
7744
+ flatOptions: {
7745
+ url: true,
7746
+ context: true
7747
+ }
7748
+ },
7749
+
7750
+ // Creates a full fledged settings object into target
7751
+ // with both ajaxSettings and settings fields.
7752
+ // If target is omitted, writes into ajaxSettings.
7753
+ ajaxSetup: function( target, settings ) {
7754
+ return settings ?
7755
+
7756
+ // Building a settings object
7757
+ ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
7758
+
7759
+ // Extending ajaxSettings
7760
+ ajaxExtend( jQuery.ajaxSettings, target );
7761
+ },
7762
+
7763
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
7764
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
7765
+
7766
+ // Main method
7767
+ ajax: function( url, options ) {
7768
+
7769
+ // If url is an object, simulate pre-1.5 signature
7770
+ if ( typeof url === "object" ) {
7771
+ options = url;
7772
+ url = undefined;
7773
+ }
7774
+
7775
+ // Force options to be an object
7776
+ options = options || {};
7777
+
7778
+ var // Cross-domain detection vars
7779
+ parts,
7780
+ // Loop variable
7781
+ i,
7782
+ // URL without anti-cache param
7783
+ cacheURL,
7784
+ // Response headers as string
7785
+ responseHeadersString,
7786
+ // timeout handle
7787
+ timeoutTimer,
7788
+
7789
+ // To know if global events are to be dispatched
7790
+ fireGlobals,
7791
+
7792
+ transport,
7793
+ // Response headers
7794
+ responseHeaders,
7795
+ // Create the final options object
7796
+ s = jQuery.ajaxSetup( {}, options ),
7797
+ // Callbacks context
7798
+ callbackContext = s.context || s,
7799
+ // Context for global events is callbackContext if it is a DOM node or jQuery collection
7800
+ globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
7801
+ jQuery( callbackContext ) :
7802
+ jQuery.event,
7803
+ // Deferreds
7804
+ deferred = jQuery.Deferred(),
7805
+ completeDeferred = jQuery.Callbacks("once memory"),
7806
+ // Status-dependent callbacks
7807
+ statusCode = s.statusCode || {},
7808
+ // Headers (they are sent all at once)
7809
+ requestHeaders = {},
7810
+ requestHeadersNames = {},
7811
+ // The jqXHR state
7812
+ state = 0,
7813
+ // Default abort message
7814
+ strAbort = "canceled",
7815
+ // Fake xhr
7816
+ jqXHR = {
7817
+ readyState: 0,
7818
+
7819
+ // Builds headers hashtable if needed
7820
+ getResponseHeader: function( key ) {
7821
+ var match;
7822
+ if ( state === 2 ) {
7823
+ if ( !responseHeaders ) {
7824
+ responseHeaders = {};
7825
+ while ( (match = rheaders.exec( responseHeadersString )) ) {
7826
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
7827
+ }
7828
+ }
7829
+ match = responseHeaders[ key.toLowerCase() ];
7830
+ }
7831
+ return match == null ? null : match;
7832
+ },
7833
+
7834
+ // Raw string
7835
+ getAllResponseHeaders: function() {
7836
+ return state === 2 ? responseHeadersString : null;
7837
+ },
7838
+
7839
+ // Caches the header
7840
+ setRequestHeader: function( name, value ) {
7841
+ var lname = name.toLowerCase();
7842
+ if ( !state ) {
7843
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
7844
+ requestHeaders[ name ] = value;
7845
+ }
7846
+ return this;
7847
+ },
7848
+
7849
+ // Overrides response content-type header
7850
+ overrideMimeType: function( type ) {
7851
+ if ( !state ) {
7852
+ s.mimeType = type;
7853
+ }
7854
+ return this;
7855
+ },
7856
+
7857
+ // Status-dependent callbacks
7858
+ statusCode: function( map ) {
7859
+ var code;
7860
+ if ( map ) {
7861
+ if ( state < 2 ) {
7862
+ for ( code in map ) {
7863
+ // Lazy-add the new callback in a way that preserves old ones
7864
+ statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
7865
+ }
7866
+ } else {
7867
+ // Execute the appropriate callbacks
7868
+ jqXHR.always( map[ jqXHR.status ] );
7869
+ }
7870
+ }
7871
+ return this;
7872
+ },
7873
+
7874
+ // Cancel the request
7875
+ abort: function( statusText ) {
7876
+ var finalText = statusText || strAbort;
7877
+ if ( transport ) {
7878
+ transport.abort( finalText );
7879
+ }
7880
+ done( 0, finalText );
7881
+ return this;
7882
+ }
7883
+ };
7884
+
7885
+ // Attach deferreds
7886
+ deferred.promise( jqXHR ).complete = completeDeferred.add;
7887
+ jqXHR.success = jqXHR.done;
7888
+ jqXHR.error = jqXHR.fail;
7889
+
7890
+ // Remove hash character (#7531: and string promotion)
7891
+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
7892
+ // Handle falsy url in the settings object (#10093: consistency with old signature)
7893
+ // We also use the url parameter if available
7894
+ s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
7895
+
7896
+ // Alias method option to type as per ticket #12004
7897
+ s.type = options.method || options.type || s.method || s.type;
7898
+
7899
+ // Extract dataTypes list
7900
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
7901
+
7902
+ // A cross-domain request is in order when we have a protocol:host:port mismatch
7903
+ if ( s.crossDomain == null ) {
7904
+ parts = rurl.exec( s.url.toLowerCase() );
7905
+ s.crossDomain = !!( parts &&
7906
+ ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
7907
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
7908
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
7909
+ );
7910
+ }
7911
+
7912
+ // Convert data if not already a string
7913
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
7914
+ s.data = jQuery.param( s.data, s.traditional );
7915
+ }
7916
+
7917
+ // Apply prefilters
7918
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
7919
+
7920
+ // If request was aborted inside a prefilter, stop there
7921
+ if ( state === 2 ) {
7922
+ return jqXHR;
7923
+ }
7924
+
7925
+ // We can fire global events as of now if asked to
7926
+ fireGlobals = s.global;
7927
+
7928
+ // Watch for a new set of requests
7929
+ if ( fireGlobals && jQuery.active++ === 0 ) {
7930
+ jQuery.event.trigger("ajaxStart");
7931
+ }
7932
+
7933
+ // Uppercase the type
7934
+ s.type = s.type.toUpperCase();
7935
+
7936
+ // Determine if request has content
7937
+ s.hasContent = !rnoContent.test( s.type );
7938
+
7939
+ // Save the URL in case we're toying with the If-Modified-Since
7940
+ // and/or If-None-Match header later on
7941
+ cacheURL = s.url;
7942
+
7943
+ // More options handling for requests with no content
7944
+ if ( !s.hasContent ) {
7945
+
7946
+ // If data is available, append data to url
7947
+ if ( s.data ) {
7948
+ cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
7949
+ // #9682: remove data so that it's not used in an eventual retry
7950
+ delete s.data;
7951
+ }
7952
+
7953
+ // Add anti-cache in url if needed
7954
+ if ( s.cache === false ) {
7955
+ s.url = rts.test( cacheURL ) ?
7956
+
7957
+ // If there is already a '_' parameter, set its value
7958
+ cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
7959
+
7960
+ // Otherwise add one to the end
7961
+ cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
7962
+ }
7963
+ }
7964
+
7965
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
7966
+ if ( s.ifModified ) {
7967
+ if ( jQuery.lastModified[ cacheURL ] ) {
7968
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
7969
+ }
7970
+ if ( jQuery.etag[ cacheURL ] ) {
7971
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
7972
+ }
7973
+ }
7974
+
7975
+ // Set the correct header, if data is being sent
7976
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
7977
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
7978
+ }
7979
+
7980
+ // Set the Accepts header for the server, depending on the dataType
7981
+ jqXHR.setRequestHeader(
7982
+ "Accept",
7983
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
7984
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
7985
+ s.accepts[ "*" ]
7986
+ );
7987
+
7988
+ // Check for headers option
7989
+ for ( i in s.headers ) {
7990
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
7991
+ }
7992
+
7993
+ // Allow custom headers/mimetypes and early abort
7994
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
7995
+ // Abort if not done already and return
7996
+ return jqXHR.abort();
7997
+ }
7998
+
7999
+ // aborting is no longer a cancellation
8000
+ strAbort = "abort";
8001
+
8002
+ // Install callbacks on deferreds
8003
+ for ( i in {
8004
+ success: 1,
8005
+ error: 1,
8006
+ complete: 1
8007
+ } ) {
8008
+ jqXHR[ i ]( s[ i ] );
8009
+ }
8010
+
8011
+ // Get transport
8012
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
8013
+
8014
+ // If no transport, we auto-abort
8015
+ if ( !transport ) {
8016
+ done( -1, "No Transport" );
8017
+ } else {
8018
+ jqXHR.readyState = 1;
8019
+
8020
+ // Send global event
8021
+ if ( fireGlobals ) {
8022
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
8023
+ }
8024
+ // Timeout
8025
+ if ( s.async && s.timeout > 0 ) {
8026
+ timeoutTimer = setTimeout(function() {
8027
+ jqXHR.abort("timeout");
8028
+ }, s.timeout );
8029
+ }
8030
+
8031
+ try {
8032
+ state = 1;
8033
+ transport.send( requestHeaders, done );
8034
+ } catch ( e ) {
8035
+ // Propagate exception as error if not done
8036
+ if ( state < 2 ) {
8037
+ done( -1, e );
8038
+ // Simply rethrow otherwise
8039
+ } else {
8040
+ throw e;
8041
+ }
8042
+ }
8043
+ }
8044
+
8045
+ // Callback for when everything is done
8046
+ function done( status, nativeStatusText, responses, headers ) {
8047
+ var isSuccess, success, error, response, modified,
8048
+ statusText = nativeStatusText;
8049
+
8050
+ // Called once
8051
+ if ( state === 2 ) {
8052
+ return;
8053
+ }
8054
+
8055
+ // State is "done" now
8056
+ state = 2;
8057
+
8058
+ // Clear timeout if it exists
8059
+ if ( timeoutTimer ) {
8060
+ clearTimeout( timeoutTimer );
8061
+ }
8062
+
8063
+ // Dereference transport for early garbage collection
8064
+ // (no matter how long the jqXHR object will be used)
8065
+ transport = undefined;
8066
+
8067
+ // Cache response headers
8068
+ responseHeadersString = headers || "";
8069
+
8070
+ // Set readyState
8071
+ jqXHR.readyState = status > 0 ? 4 : 0;
8072
+
8073
+ // Get response data
8074
+ if ( responses ) {
8075
+ response = ajaxHandleResponses( s, jqXHR, responses );
8076
+ }
8077
+
8078
+ // If successful, handle type chaining
8079
+ if ( status >= 200 && status < 300 || status === 304 ) {
8080
+
8081
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8082
+ if ( s.ifModified ) {
8083
+ modified = jqXHR.getResponseHeader("Last-Modified");
8084
+ if ( modified ) {
8085
+ jQuery.lastModified[ cacheURL ] = modified;
8086
+ }
8087
+ modified = jqXHR.getResponseHeader("etag");
8088
+ if ( modified ) {
8089
+ jQuery.etag[ cacheURL ] = modified;
8090
+ }
8091
+ }
8092
+
8093
+ // if no content
8094
+ if ( status === 204 ) {
8095
+ isSuccess = true;
8096
+ statusText = "nocontent";
8097
+
8098
+ // if not modified
8099
+ } else if ( status === 304 ) {
8100
+ isSuccess = true;
8101
+ statusText = "notmodified";
8102
+
8103
+ // If we have data, let's convert it
8104
+ } else {
8105
+ isSuccess = ajaxConvert( s, response );
8106
+ statusText = isSuccess.state;
8107
+ success = isSuccess.data;
8108
+ error = isSuccess.error;
8109
+ isSuccess = !error;
8110
+ }
8111
+ } else {
8112
+ // We extract error from statusText
8113
+ // then normalize statusText and status for non-aborts
8114
+ error = statusText;
8115
+ if ( status || !statusText ) {
8116
+ statusText = "error";
8117
+ if ( status < 0 ) {
8118
+ status = 0;
8119
+ }
8120
+ }
8121
+ }
8122
+
8123
+ // Set data for the fake xhr object
8124
+ jqXHR.status = status;
8125
+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
8126
+
8127
+ // Success/Error
8128
+ if ( isSuccess ) {
8129
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
8130
+ } else {
8131
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
8132
+ }
8133
+
8134
+ // Status-dependent callbacks
8135
+ jqXHR.statusCode( statusCode );
8136
+ statusCode = undefined;
8137
+
8138
+ if ( fireGlobals ) {
8139
+ globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
8140
+ [ jqXHR, s, isSuccess ? success : error ] );
8141
+ }
8142
+
8143
+ // Complete
8144
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
8145
+
8146
+ if ( fireGlobals ) {
8147
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
8148
+ // Handle the global AJAX counter
8149
+ if ( !( --jQuery.active ) ) {
8150
+ jQuery.event.trigger("ajaxStop");
8151
+ }
8152
+ }
8153
+ }
8154
+
8155
+ return jqXHR;
8156
+ },
8157
+
8158
+ getScript: function( url, callback ) {
8159
+ return jQuery.get( url, undefined, callback, "script" );
8160
+ },
8161
+
8162
+ getJSON: function( url, data, callback ) {
8163
+ return jQuery.get( url, data, callback, "json" );
8164
+ }
8165
+ });
8166
+
8167
+ /* Handles responses to an ajax request:
8168
+ * - sets all responseXXX fields accordingly
8169
+ * - finds the right dataType (mediates between content-type and expected dataType)
8170
+ * - returns the corresponding response
8171
+ */
8172
+ function ajaxHandleResponses( s, jqXHR, responses ) {
8173
+ var firstDataType, ct, finalDataType, type,
8174
+ contents = s.contents,
8175
+ dataTypes = s.dataTypes,
8176
+ responseFields = s.responseFields;
8177
+
8178
+ // Fill responseXXX fields
8179
+ for ( type in responseFields ) {
8180
+ if ( type in responses ) {
8181
+ jqXHR[ responseFields[type] ] = responses[ type ];
8182
+ }
8183
+ }
8184
+
8185
+ // Remove auto dataType and get content-type in the process
8186
+ while( dataTypes[ 0 ] === "*" ) {
8187
+ dataTypes.shift();
8188
+ if ( ct === undefined ) {
8189
+ ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
8190
+ }
8191
+ }
8192
+
8193
+ // Check if we're dealing with a known content-type
8194
+ if ( ct ) {
8195
+ for ( type in contents ) {
8196
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
8197
+ dataTypes.unshift( type );
8198
+ break;
8199
+ }
8200
+ }
8201
+ }
8202
+
8203
+ // Check to see if we have a response for the expected dataType
8204
+ if ( dataTypes[ 0 ] in responses ) {
8205
+ finalDataType = dataTypes[ 0 ];
8206
+ } else {
8207
+ // Try convertible dataTypes
8208
+ for ( type in responses ) {
8209
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
8210
+ finalDataType = type;
8211
+ break;
8212
+ }
8213
+ if ( !firstDataType ) {
8214
+ firstDataType = type;
8215
+ }
8216
+ }
8217
+ // Or just use first one
8218
+ finalDataType = finalDataType || firstDataType;
8219
+ }
8220
+
8221
+ // If we found a dataType
8222
+ // We add the dataType to the list if needed
8223
+ // and return the corresponding response
8224
+ if ( finalDataType ) {
8225
+ if ( finalDataType !== dataTypes[ 0 ] ) {
8226
+ dataTypes.unshift( finalDataType );
8227
+ }
8228
+ return responses[ finalDataType ];
8229
+ }
8230
+ }
8231
+
8232
+ // Chain conversions given the request and the original response
8233
+ function ajaxConvert( s, response ) {
8234
+ var conv2, current, conv, tmp,
8235
+ converters = {},
8236
+ i = 0,
8237
+ // Work with a copy of dataTypes in case we need to modify it for conversion
8238
+ dataTypes = s.dataTypes.slice(),
8239
+ prev = dataTypes[ 0 ];
8240
+
8241
+ // Apply the dataFilter if provided
8242
+ if ( s.dataFilter ) {
8243
+ response = s.dataFilter( response, s.dataType );
8244
+ }
8245
+
8246
+ // Create converters map with lowercased keys
8247
+ if ( dataTypes[ 1 ] ) {
8248
+ for ( conv in s.converters ) {
8249
+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
8250
+ }
8251
+ }
8252
+
8253
+ // Convert to each sequential dataType, tolerating list modification
8254
+ for ( ; (current = dataTypes[++i]); ) {
8255
+
8256
+ // There's only work to do if current dataType is non-auto
8257
+ if ( current !== "*" ) {
8258
+
8259
+ // Convert response if prev dataType is non-auto and differs from current
8260
+ if ( prev !== "*" && prev !== current ) {
8261
+
8262
+ // Seek a direct converter
8263
+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
8264
+
8265
+ // If none found, seek a pair
8266
+ if ( !conv ) {
8267
+ for ( conv2 in converters ) {
8268
+
8269
+ // If conv2 outputs current
8270
+ tmp = conv2.split(" ");
8271
+ if ( tmp[ 1 ] === current ) {
8272
+
8273
+ // If prev can be converted to accepted input
8274
+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
8275
+ converters[ "* " + tmp[ 0 ] ];
8276
+ if ( conv ) {
8277
+ // Condense equivalence converters
8278
+ if ( conv === true ) {
8279
+ conv = converters[ conv2 ];
8280
+
8281
+ // Otherwise, insert the intermediate dataType
8282
+ } else if ( converters[ conv2 ] !== true ) {
8283
+ current = tmp[ 0 ];
8284
+ dataTypes.splice( i--, 0, current );
8285
+ }
8286
+
8287
+ break;
8288
+ }
8289
+ }
8290
+ }
8291
+ }
8292
+
8293
+ // Apply converter (if not an equivalence)
8294
+ if ( conv !== true ) {
8295
+
8296
+ // Unless errors are allowed to bubble, catch and return them
8297
+ if ( conv && s["throws"] ) {
8298
+ response = conv( response );
8299
+ } else {
8300
+ try {
8301
+ response = conv( response );
8302
+ } catch ( e ) {
8303
+ return {
8304
+ state: "parsererror",
8305
+ error: conv ? e : "No conversion from " + prev + " to " + current
8306
+ };
8307
+ }
8308
+ }
8309
+ }
8310
+ }
8311
+
8312
+ // Update prev for next iteration
8313
+ prev = current;
8314
+ }
8315
+ }
8316
+
8317
+ return {
8318
+ state: "success",
8319
+ data: response
8320
+ };
8321
+ }
8322
+ // Install script dataType
8323
+ jQuery.ajaxSetup({
8324
+ accepts: {
8325
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
8326
+ },
8327
+ contents: {
8328
+ script: /(?:java|ecma)script/
8329
+ },
8330
+ converters: {
8331
+ "text script": function( text ) {
8332
+ jQuery.globalEval( text );
8333
+ return text;
8334
+ }
8335
+ }
8336
+ });
8337
+
8338
+ // Handle cache's special case and global
8339
+ jQuery.ajaxPrefilter( "script", function( s ) {
8340
+ if ( s.cache === undefined ) {
8341
+ s.cache = false;
8342
+ }
8343
+ if ( s.crossDomain ) {
8344
+ s.type = "GET";
8345
+ s.global = false;
8346
+ }
8347
+ });
8348
+
8349
+ // Bind script tag hack transport
8350
+ jQuery.ajaxTransport( "script", function(s) {
8351
+
8352
+ // This transport only deals with cross domain requests
8353
+ if ( s.crossDomain ) {
8354
+
8355
+ var script,
8356
+ head = document.head || jQuery("head")[0] || document.documentElement;
8357
+
8358
+ return {
8359
+
8360
+ send: function( _, callback ) {
8361
+
8362
+ script = document.createElement("script");
8363
+
8364
+ script.async = true;
8365
+
8366
+ if ( s.scriptCharset ) {
8367
+ script.charset = s.scriptCharset;
8368
+ }
8369
+
8370
+ script.src = s.url;
8371
+
8372
+ // Attach handlers for all browsers
8373
+ script.onload = script.onreadystatechange = function( _, isAbort ) {
8374
+
8375
+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
8376
+
8377
+ // Handle memory leak in IE
8378
+ script.onload = script.onreadystatechange = null;
8379
+
8380
+ // Remove the script
8381
+ if ( script.parentNode ) {
8382
+ script.parentNode.removeChild( script );
8383
+ }
8384
+
8385
+ // Dereference the script
8386
+ script = null;
8387
+
8388
+ // Callback if not abort
8389
+ if ( !isAbort ) {
8390
+ callback( 200, "success" );
8391
+ }
8392
+ }
8393
+ };
8394
+
8395
+ // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
8396
+ // Use native DOM manipulation to avoid our domManip AJAX trickery
8397
+ head.insertBefore( script, head.firstChild );
8398
+ },
8399
+
8400
+ abort: function() {
8401
+ if ( script ) {
8402
+ script.onload( undefined, true );
8403
+ }
8404
+ }
8405
+ };
8406
+ }
8407
+ });
8408
+ var oldCallbacks = [],
8409
+ rjsonp = /(=)\?(?=&|$)|\?\?/;
8410
+
8411
+ // Default jsonp settings
8412
+ jQuery.ajaxSetup({
8413
+ jsonp: "callback",
8414
+ jsonpCallback: function() {
8415
+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
8416
+ this[ callback ] = true;
8417
+ return callback;
8418
+ }
8419
+ });
8420
+
8421
+ // Detect, normalize options and install callbacks for jsonp requests
8422
+ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
8423
+
8424
+ var callbackName, overwritten, responseContainer,
8425
+ jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
8426
+ "url" :
8427
+ typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
8428
+ );
8429
+
8430
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
8431
+ if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
8432
+
8433
+ // Get callback name, remembering preexisting value associated with it
8434
+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
8435
+ s.jsonpCallback() :
8436
+ s.jsonpCallback;
8437
+
8438
+ // Insert callback into url or form data
8439
+ if ( jsonProp ) {
8440
+ s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
8441
+ } else if ( s.jsonp !== false ) {
8442
+ s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
8443
+ }
8444
+
8445
+ // Use data converter to retrieve json after script execution
8446
+ s.converters["script json"] = function() {
8447
+ if ( !responseContainer ) {
8448
+ jQuery.error( callbackName + " was not called" );
8449
+ }
8450
+ return responseContainer[ 0 ];
8451
+ };
8452
+
8453
+ // force json dataType
8454
+ s.dataTypes[ 0 ] = "json";
8455
+
8456
+ // Install callback
8457
+ overwritten = window[ callbackName ];
8458
+ window[ callbackName ] = function() {
8459
+ responseContainer = arguments;
8460
+ };
8461
+
8462
+ // Clean-up function (fires after converters)
8463
+ jqXHR.always(function() {
8464
+ // Restore preexisting value
8465
+ window[ callbackName ] = overwritten;
8466
+
8467
+ // Save back as free
8468
+ if ( s[ callbackName ] ) {
8469
+ // make sure that re-using the options doesn't screw things around
8470
+ s.jsonpCallback = originalSettings.jsonpCallback;
8471
+
8472
+ // save the callback name for future use
8473
+ oldCallbacks.push( callbackName );
8474
+ }
8475
+
8476
+ // Call if it was a function and we have a response
8477
+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
8478
+ overwritten( responseContainer[ 0 ] );
8479
+ }
8480
+
8481
+ responseContainer = overwritten = undefined;
8482
+ });
8483
+
8484
+ // Delegate to script
8485
+ return "script";
8486
+ }
8487
+ });
8488
+ var xhrCallbacks, xhrSupported,
8489
+ xhrId = 0,
8490
+ // #5280: Internet Explorer will keep connections alive if we don't abort on unload
8491
+ xhrOnUnloadAbort = window.ActiveXObject && function() {
8492
+ // Abort all pending requests
8493
+ var key;
8494
+ for ( key in xhrCallbacks ) {
8495
+ xhrCallbacks[ key ]( undefined, true );
8496
+ }
8497
+ };
8498
+
8499
+ // Functions to create xhrs
8500
+ function createStandardXHR() {
8501
+ try {
8502
+ return new window.XMLHttpRequest();
8503
+ } catch( e ) {}
8504
+ }
8505
+
8506
+ function createActiveXHR() {
8507
+ try {
8508
+ return new window.ActiveXObject("Microsoft.XMLHTTP");
8509
+ } catch( e ) {}
8510
+ }
8511
+
8512
+ // Create the request object
8513
+ // (This is still attached to ajaxSettings for backward compatibility)
8514
+ jQuery.ajaxSettings.xhr = window.ActiveXObject ?
8515
+ /* Microsoft failed to properly
8516
+ * implement the XMLHttpRequest in IE7 (can't request local files),
8517
+ * so we use the ActiveXObject when it is available
8518
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
8519
+ * we need a fallback.
8520
+ */
8521
+ function() {
8522
+ return !this.isLocal && createStandardXHR() || createActiveXHR();
8523
+ } :
8524
+ // For all other browsers, use the standard XMLHttpRequest object
8525
+ createStandardXHR;
8526
+
8527
+ // Determine support properties
8528
+ xhrSupported = jQuery.ajaxSettings.xhr();
8529
+ jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
8530
+ xhrSupported = jQuery.support.ajax = !!xhrSupported;
8531
+
8532
+ // Create transport if the browser can provide an xhr
8533
+ if ( xhrSupported ) {
8534
+
8535
+ jQuery.ajaxTransport(function( s ) {
8536
+ // Cross domain only allowed if supported through XMLHttpRequest
8537
+ if ( !s.crossDomain || jQuery.support.cors ) {
8538
+
8539
+ var callback;
8540
+
8541
+ return {
8542
+ send: function( headers, complete ) {
8543
+
8544
+ // Get a new xhr
8545
+ var handle, i,
8546
+ xhr = s.xhr();
8547
+
8548
+ // Open the socket
8549
+ // Passing null username, generates a login popup on Opera (#2865)
8550
+ if ( s.username ) {
8551
+ xhr.open( s.type, s.url, s.async, s.username, s.password );
8552
+ } else {
8553
+ xhr.open( s.type, s.url, s.async );
8554
+ }
8555
+
8556
+ // Apply custom fields if provided
8557
+ if ( s.xhrFields ) {
8558
+ for ( i in s.xhrFields ) {
8559
+ xhr[ i ] = s.xhrFields[ i ];
8560
+ }
8561
+ }
8562
+
8563
+ // Override mime type if needed
8564
+ if ( s.mimeType && xhr.overrideMimeType ) {
8565
+ xhr.overrideMimeType( s.mimeType );
8566
+ }
8567
+
8568
+ // X-Requested-With header
8569
+ // For cross-domain requests, seeing as conditions for a preflight are
8570
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
8571
+ // (it can always be set on a per-request basis or even using ajaxSetup)
8572
+ // For same-domain requests, won't change header if already provided.
8573
+ if ( !s.crossDomain && !headers["X-Requested-With"] ) {
8574
+ headers["X-Requested-With"] = "XMLHttpRequest";
8575
+ }
8576
+
8577
+ // Need an extra try/catch for cross domain requests in Firefox 3
8578
+ try {
8579
+ for ( i in headers ) {
8580
+ xhr.setRequestHeader( i, headers[ i ] );
8581
+ }
8582
+ } catch( err ) {}
8583
+
8584
+ // Do send the request
8585
+ // This may raise an exception which is actually
8586
+ // handled in jQuery.ajax (so no try/catch here)
8587
+ xhr.send( ( s.hasContent && s.data ) || null );
8588
+
8589
+ // Listener
8590
+ callback = function( _, isAbort ) {
8591
+ var status, responseHeaders, statusText, responses;
8592
+
8593
+ // Firefox throws exceptions when accessing properties
8594
+ // of an xhr when a network error occurred
8595
+ // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
8596
+ try {
8597
+
8598
+ // Was never called and is aborted or complete
8599
+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
8600
+
8601
+ // Only called once
8602
+ callback = undefined;
8603
+
8604
+ // Do not keep as active anymore
8605
+ if ( handle ) {
8606
+ xhr.onreadystatechange = jQuery.noop;
8607
+ if ( xhrOnUnloadAbort ) {
8608
+ delete xhrCallbacks[ handle ];
8609
+ }
8610
+ }
8611
+
8612
+ // If it's an abort
8613
+ if ( isAbort ) {
8614
+ // Abort it manually if needed
8615
+ if ( xhr.readyState !== 4 ) {
8616
+ xhr.abort();
8617
+ }
8618
+ } else {
8619
+ responses = {};
8620
+ status = xhr.status;
8621
+ responseHeaders = xhr.getAllResponseHeaders();
8622
+
8623
+ // When requesting binary data, IE6-9 will throw an exception
8624
+ // on any attempt to access responseText (#11426)
8625
+ if ( typeof xhr.responseText === "string" ) {
8626
+ responses.text = xhr.responseText;
8627
+ }
8628
+
8629
+ // Firefox throws an exception when accessing
8630
+ // statusText for faulty cross-domain requests
8631
+ try {
8632
+ statusText = xhr.statusText;
8633
+ } catch( e ) {
8634
+ // We normalize with Webkit giving an empty statusText
8635
+ statusText = "";
8636
+ }
8637
+
8638
+ // Filter status for non standard behaviors
8639
+
8640
+ // If the request is local and we have data: assume a success
8641
+ // (success with no data won't get notified, that's the best we
8642
+ // can do given current implementations)
8643
+ if ( !status && s.isLocal && !s.crossDomain ) {
8644
+ status = responses.text ? 200 : 404;
8645
+ // IE - #1450: sometimes returns 1223 when it should be 204
8646
+ } else if ( status === 1223 ) {
8647
+ status = 204;
8648
+ }
8649
+ }
8650
+ }
8651
+ } catch( firefoxAccessException ) {
8652
+ if ( !isAbort ) {
8653
+ complete( -1, firefoxAccessException );
8654
+ }
8655
+ }
8656
+
8657
+ // Call complete if needed
8658
+ if ( responses ) {
8659
+ complete( status, statusText, responses, responseHeaders );
8660
+ }
8661
+ };
8662
+
8663
+ if ( !s.async ) {
8664
+ // if we're in sync mode we fire the callback
8665
+ callback();
8666
+ } else if ( xhr.readyState === 4 ) {
8667
+ // (IE6 & IE7) if it's in cache and has been
8668
+ // retrieved directly we need to fire the callback
8669
+ setTimeout( callback );
8670
+ } else {
8671
+ handle = ++xhrId;
8672
+ if ( xhrOnUnloadAbort ) {
8673
+ // Create the active xhrs callbacks list if needed
8674
+ // and attach the unload handler
8675
+ if ( !xhrCallbacks ) {
8676
+ xhrCallbacks = {};
8677
+ jQuery( window ).unload( xhrOnUnloadAbort );
8678
+ }
8679
+ // Add to list of active xhrs callbacks
8680
+ xhrCallbacks[ handle ] = callback;
8681
+ }
8682
+ xhr.onreadystatechange = callback;
8683
+ }
8684
+ },
8685
+
8686
+ abort: function() {
8687
+ if ( callback ) {
8688
+ callback( undefined, true );
8689
+ }
8690
+ }
8691
+ };
8692
+ }
8693
+ });
8694
+ }
8695
+ var fxNow, timerId,
8696
+ rfxtypes = /^(?:toggle|show|hide)$/,
8697
+ rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
8698
+ rrun = /queueHooks$/,
8699
+ animationPrefilters = [ defaultPrefilter ],
8700
+ tweeners = {
8701
+ "*": [function( prop, value ) {
8702
+ var end, unit,
8703
+ tween = this.createTween( prop, value ),
8704
+ parts = rfxnum.exec( value ),
8705
+ target = tween.cur(),
8706
+ start = +target || 0,
8707
+ scale = 1,
8708
+ maxIterations = 20;
8709
+
8710
+ if ( parts ) {
8711
+ end = +parts[2];
8712
+ unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
8713
+
8714
+ // We need to compute starting value
8715
+ if ( unit !== "px" && start ) {
8716
+ // Iteratively approximate from a nonzero starting point
8717
+ // Prefer the current property, because this process will be trivial if it uses the same units
8718
+ // Fallback to end or a simple constant
8719
+ start = jQuery.css( tween.elem, prop, true ) || end || 1;
8720
+
8721
+ do {
8722
+ // If previous iteration zeroed out, double until we get *something*
8723
+ // Use a string for doubling factor so we don't accidentally see scale as unchanged below
8724
+ scale = scale || ".5";
8725
+
8726
+ // Adjust and apply
8727
+ start = start / scale;
8728
+ jQuery.style( tween.elem, prop, start + unit );
8729
+
8730
+ // Update scale, tolerating zero or NaN from tween.cur()
8731
+ // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
8732
+ } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
8733
+ }
8734
+
8735
+ tween.unit = unit;
8736
+ tween.start = start;
8737
+ // If a +=/-= token was provided, we're doing a relative animation
8738
+ tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
8739
+ }
8740
+ return tween;
8741
+ }]
8742
+ };
8743
+
8744
+ // Animations created synchronously will run synchronously
8745
+ function createFxNow() {
8746
+ setTimeout(function() {
8747
+ fxNow = undefined;
8748
+ });
8749
+ return ( fxNow = jQuery.now() );
8750
+ }
8751
+
8752
+ function createTweens( animation, props ) {
8753
+ jQuery.each( props, function( prop, value ) {
8754
+ var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
8755
+ index = 0,
8756
+ length = collection.length;
8757
+ for ( ; index < length; index++ ) {
8758
+ if ( collection[ index ].call( animation, prop, value ) ) {
8759
+
8760
+ // we're done with this property
8761
+ return;
8762
+ }
8763
+ }
8764
+ });
8765
+ }
8766
+
8767
+ function Animation( elem, properties, options ) {
8768
+ var result,
8769
+ stopped,
8770
+ index = 0,
8771
+ length = animationPrefilters.length,
8772
+ deferred = jQuery.Deferred().always( function() {
8773
+ // don't match elem in the :animated selector
8774
+ delete tick.elem;
8775
+ }),
8776
+ tick = function() {
8777
+ if ( stopped ) {
8778
+ return false;
8779
+ }
8780
+ var currentTime = fxNow || createFxNow(),
8781
+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
8782
+ // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
8783
+ temp = remaining / animation.duration || 0,
8784
+ percent = 1 - temp,
8785
+ index = 0,
8786
+ length = animation.tweens.length;
8787
+
8788
+ for ( ; index < length ; index++ ) {
8789
+ animation.tweens[ index ].run( percent );
8790
+ }
8791
+
8792
+ deferred.notifyWith( elem, [ animation, percent, remaining ]);
8793
+
8794
+ if ( percent < 1 && length ) {
8795
+ return remaining;
8796
+ } else {
8797
+ deferred.resolveWith( elem, [ animation ] );
8798
+ return false;
8799
+ }
8800
+ },
8801
+ animation = deferred.promise({
8802
+ elem: elem,
8803
+ props: jQuery.extend( {}, properties ),
8804
+ opts: jQuery.extend( true, {
8805
+ specialEasing: {}
8806
+ }, options ),
8807
+ originalProperties: properties,
8808
+ originalOptions: options,
8809
+ startTime: fxNow || createFxNow(),
8810
+ duration: options.duration,
8811
+ tweens: [],
8812
+ createTween: function( prop, end ) {
8813
+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
8814
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
8815
+ animation.tweens.push( tween );
8816
+ return tween;
8817
+ },
8818
+ stop: function( gotoEnd ) {
8819
+ var index = 0,
8820
+ // if we are going to the end, we want to run all the tweens
8821
+ // otherwise we skip this part
8822
+ length = gotoEnd ? animation.tweens.length : 0;
8823
+ if ( stopped ) {
8824
+ return this;
8825
+ }
8826
+ stopped = true;
8827
+ for ( ; index < length ; index++ ) {
8828
+ animation.tweens[ index ].run( 1 );
8829
+ }
8830
+
8831
+ // resolve when we played the last frame
8832
+ // otherwise, reject
8833
+ if ( gotoEnd ) {
8834
+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
8835
+ } else {
8836
+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
8837
+ }
8838
+ return this;
8839
+ }
8840
+ }),
8841
+ props = animation.props;
8842
+
8843
+ propFilter( props, animation.opts.specialEasing );
8844
+
8845
+ for ( ; index < length ; index++ ) {
8846
+ result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
8847
+ if ( result ) {
8848
+ return result;
8849
+ }
8850
+ }
8851
+
8852
+ createTweens( animation, props );
8853
+
8854
+ if ( jQuery.isFunction( animation.opts.start ) ) {
8855
+ animation.opts.start.call( elem, animation );
8856
+ }
8857
+
8858
+ jQuery.fx.timer(
8859
+ jQuery.extend( tick, {
8860
+ elem: elem,
8861
+ anim: animation,
8862
+ queue: animation.opts.queue
8863
+ })
8864
+ );
8865
+
8866
+ // attach callbacks from options
8867
+ return animation.progress( animation.opts.progress )
8868
+ .done( animation.opts.done, animation.opts.complete )
8869
+ .fail( animation.opts.fail )
8870
+ .always( animation.opts.always );
8871
+ }
8872
+
8873
+ function propFilter( props, specialEasing ) {
8874
+ var value, name, index, easing, hooks;
8875
+
8876
+ // camelCase, specialEasing and expand cssHook pass
8877
+ for ( index in props ) {
8878
+ name = jQuery.camelCase( index );
8879
+ easing = specialEasing[ name ];
8880
+ value = props[ index ];
8881
+ if ( jQuery.isArray( value ) ) {
8882
+ easing = value[ 1 ];
8883
+ value = props[ index ] = value[ 0 ];
8884
+ }
8885
+
8886
+ if ( index !== name ) {
8887
+ props[ name ] = value;
8888
+ delete props[ index ];
8889
+ }
8890
+
8891
+ hooks = jQuery.cssHooks[ name ];
8892
+ if ( hooks && "expand" in hooks ) {
8893
+ value = hooks.expand( value );
8894
+ delete props[ name ];
8895
+
8896
+ // not quite $.extend, this wont overwrite keys already present.
8897
+ // also - reusing 'index' from above because we have the correct "name"
8898
+ for ( index in value ) {
8899
+ if ( !( index in props ) ) {
8900
+ props[ index ] = value[ index ];
8901
+ specialEasing[ index ] = easing;
8902
+ }
8903
+ }
8904
+ } else {
8905
+ specialEasing[ name ] = easing;
8906
+ }
8907
+ }
8908
+ }
8909
+
8910
+ jQuery.Animation = jQuery.extend( Animation, {
8911
+
8912
+ tweener: function( props, callback ) {
8913
+ if ( jQuery.isFunction( props ) ) {
8914
+ callback = props;
8915
+ props = [ "*" ];
8916
+ } else {
8917
+ props = props.split(" ");
8918
+ }
8919
+
8920
+ var prop,
8921
+ index = 0,
8922
+ length = props.length;
8923
+
8924
+ for ( ; index < length ; index++ ) {
8925
+ prop = props[ index ];
8926
+ tweeners[ prop ] = tweeners[ prop ] || [];
8927
+ tweeners[ prop ].unshift( callback );
8928
+ }
8929
+ },
8930
+
8931
+ prefilter: function( callback, prepend ) {
8932
+ if ( prepend ) {
8933
+ animationPrefilters.unshift( callback );
8934
+ } else {
8935
+ animationPrefilters.push( callback );
8936
+ }
8937
+ }
8938
+ });
8939
+
8940
+ function defaultPrefilter( elem, props, opts ) {
8941
+ /*jshint validthis:true */
8942
+ var prop, index, length,
8943
+ value, dataShow, toggle,
8944
+ tween, hooks, oldfire,
8945
+ anim = this,
8946
+ style = elem.style,
8947
+ orig = {},
8948
+ handled = [],
8949
+ hidden = elem.nodeType && isHidden( elem );
8950
+
8951
+ // handle queue: false promises
8952
+ if ( !opts.queue ) {
8953
+ hooks = jQuery._queueHooks( elem, "fx" );
8954
+ if ( hooks.unqueued == null ) {
8955
+ hooks.unqueued = 0;
8956
+ oldfire = hooks.empty.fire;
8957
+ hooks.empty.fire = function() {
8958
+ if ( !hooks.unqueued ) {
8959
+ oldfire();
8960
+ }
8961
+ };
8962
+ }
8963
+ hooks.unqueued++;
8964
+
8965
+ anim.always(function() {
8966
+ // doing this makes sure that the complete handler will be called
8967
+ // before this completes
8968
+ anim.always(function() {
8969
+ hooks.unqueued--;
8970
+ if ( !jQuery.queue( elem, "fx" ).length ) {
8971
+ hooks.empty.fire();
8972
+ }
8973
+ });
8974
+ });
8975
+ }
8976
+
8977
+ // height/width overflow pass
8978
+ if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
8979
+ // Make sure that nothing sneaks out
8980
+ // Record all 3 overflow attributes because IE does not
8981
+ // change the overflow attribute when overflowX and
8982
+ // overflowY are set to the same value
8983
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
8984
+
8985
+ // Set display property to inline-block for height/width
8986
+ // animations on inline elements that are having width/height animated
8987
+ if ( jQuery.css( elem, "display" ) === "inline" &&
8988
+ jQuery.css( elem, "float" ) === "none" ) {
8989
+
8990
+ // inline-level elements accept inline-block;
8991
+ // block-level elements need to be inline with layout
8992
+ if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
8993
+ style.display = "inline-block";
8994
+
8995
+ } else {
8996
+ style.zoom = 1;
8997
+ }
8998
+ }
8999
+ }
9000
+
9001
+ if ( opts.overflow ) {
9002
+ style.overflow = "hidden";
9003
+ if ( !jQuery.support.shrinkWrapBlocks ) {
9004
+ anim.always(function() {
9005
+ style.overflow = opts.overflow[ 0 ];
9006
+ style.overflowX = opts.overflow[ 1 ];
9007
+ style.overflowY = opts.overflow[ 2 ];
9008
+ });
9009
+ }
9010
+ }
9011
+
9012
+
9013
+ // show/hide pass
9014
+ for ( index in props ) {
9015
+ value = props[ index ];
9016
+ if ( rfxtypes.exec( value ) ) {
9017
+ delete props[ index ];
9018
+ toggle = toggle || value === "toggle";
9019
+ if ( value === ( hidden ? "hide" : "show" ) ) {
9020
+ continue;
9021
+ }
9022
+ handled.push( index );
9023
+ }
9024
+ }
9025
+
9026
+ length = handled.length;
9027
+ if ( length ) {
9028
+ dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
9029
+ if ( "hidden" in dataShow ) {
9030
+ hidden = dataShow.hidden;
9031
+ }
9032
+
9033
+ // store state if its toggle - enables .stop().toggle() to "reverse"
9034
+ if ( toggle ) {
9035
+ dataShow.hidden = !hidden;
9036
+ }
9037
+ if ( hidden ) {
9038
+ jQuery( elem ).show();
9039
+ } else {
9040
+ anim.done(function() {
9041
+ jQuery( elem ).hide();
9042
+ });
9043
+ }
9044
+ anim.done(function() {
9045
+ var prop;
9046
+ jQuery._removeData( elem, "fxshow" );
9047
+ for ( prop in orig ) {
9048
+ jQuery.style( elem, prop, orig[ prop ] );
9049
+ }
9050
+ });
9051
+ for ( index = 0 ; index < length ; index++ ) {
9052
+ prop = handled[ index ];
9053
+ tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
9054
+ orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
9055
+
9056
+ if ( !( prop in dataShow ) ) {
9057
+ dataShow[ prop ] = tween.start;
9058
+ if ( hidden ) {
9059
+ tween.end = tween.start;
9060
+ tween.start = prop === "width" || prop === "height" ? 1 : 0;
9061
+ }
9062
+ }
9063
+ }
9064
+ }
9065
+ }
9066
+
9067
+ function Tween( elem, options, prop, end, easing ) {
9068
+ return new Tween.prototype.init( elem, options, prop, end, easing );
9069
+ }
9070
+ jQuery.Tween = Tween;
9071
+
9072
+ Tween.prototype = {
9073
+ constructor: Tween,
9074
+ init: function( elem, options, prop, end, easing, unit ) {
9075
+ this.elem = elem;
9076
+ this.prop = prop;
9077
+ this.easing = easing || "swing";
9078
+ this.options = options;
9079
+ this.start = this.now = this.cur();
9080
+ this.end = end;
9081
+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
9082
+ },
9083
+ cur: function() {
9084
+ var hooks = Tween.propHooks[ this.prop ];
9085
+
9086
+ return hooks && hooks.get ?
9087
+ hooks.get( this ) :
9088
+ Tween.propHooks._default.get( this );
9089
+ },
9090
+ run: function( percent ) {
9091
+ var eased,
9092
+ hooks = Tween.propHooks[ this.prop ];
9093
+
9094
+ if ( this.options.duration ) {
9095
+ this.pos = eased = jQuery.easing[ this.easing ](
9096
+ percent, this.options.duration * percent, 0, 1, this.options.duration
9097
+ );
9098
+ } else {
9099
+ this.pos = eased = percent;
9100
+ }
9101
+ this.now = ( this.end - this.start ) * eased + this.start;
9102
+
9103
+ if ( this.options.step ) {
9104
+ this.options.step.call( this.elem, this.now, this );
9105
+ }
9106
+
9107
+ if ( hooks && hooks.set ) {
9108
+ hooks.set( this );
9109
+ } else {
9110
+ Tween.propHooks._default.set( this );
9111
+ }
9112
+ return this;
9113
+ }
9114
+ };
9115
+
9116
+ Tween.prototype.init.prototype = Tween.prototype;
9117
+
9118
+ Tween.propHooks = {
9119
+ _default: {
9120
+ get: function( tween ) {
9121
+ var result;
9122
+
9123
+ if ( tween.elem[ tween.prop ] != null &&
9124
+ (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
9125
+ return tween.elem[ tween.prop ];
9126
+ }
9127
+
9128
+ // passing an empty string as a 3rd parameter to .css will automatically
9129
+ // attempt a parseFloat and fallback to a string if the parse fails
9130
+ // so, simple values such as "10px" are parsed to Float.
9131
+ // complex values such as "rotate(1rad)" are returned as is.
9132
+ result = jQuery.css( tween.elem, tween.prop, "" );
9133
+ // Empty strings, null, undefined and "auto" are converted to 0.
9134
+ return !result || result === "auto" ? 0 : result;
9135
+ },
9136
+ set: function( tween ) {
9137
+ // use step hook for back compat - use cssHook if its there - use .style if its
9138
+ // available and use plain properties where available
9139
+ if ( jQuery.fx.step[ tween.prop ] ) {
9140
+ jQuery.fx.step[ tween.prop ]( tween );
9141
+ } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
9142
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
9143
+ } else {
9144
+ tween.elem[ tween.prop ] = tween.now;
9145
+ }
9146
+ }
9147
+ }
9148
+ };
9149
+
9150
+ // Remove in 2.0 - this supports IE8's panic based approach
9151
+ // to setting things on disconnected nodes
9152
+
9153
+ Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
9154
+ set: function( tween ) {
9155
+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
9156
+ tween.elem[ tween.prop ] = tween.now;
9157
+ }
9158
+ }
9159
+ };
9160
+
9161
+ jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
9162
+ var cssFn = jQuery.fn[ name ];
9163
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
9164
+ return speed == null || typeof speed === "boolean" ?
9165
+ cssFn.apply( this, arguments ) :
9166
+ this.animate( genFx( name, true ), speed, easing, callback );
9167
+ };
9168
+ });
9169
+
9170
+ jQuery.fn.extend({
9171
+ fadeTo: function( speed, to, easing, callback ) {
9172
+
9173
+ // show any hidden elements after setting opacity to 0
9174
+ return this.filter( isHidden ).css( "opacity", 0 ).show()
9175
+
9176
+ // animate to the value specified
9177
+ .end().animate({
9178
+ opacity: to
9179
+ }, speed, easing, callback );
9180
+ },
9181
+ animate: function( prop, speed, easing, callback ) {
9182
+ var empty = jQuery.isEmptyObject( prop ),
9183
+ optall = jQuery.speed( speed, easing, callback ),
9184
+ doAnimation = function() {
9185
+ // Operate on a copy of prop so per-property easing won't be lost
9186
+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
9187
+ doAnimation.finish = function() {
9188
+ anim.stop( true );
9189
+ };
9190
+ // Empty animations, or finishing resolves immediately
9191
+ if ( empty || jQuery._data( this, "finish" ) ) {
9192
+ anim.stop( true );
9193
+ }
9194
+ };
9195
+ doAnimation.finish = doAnimation;
9196
+
9197
+ return empty || optall.queue === false ?
9198
+ this.each( doAnimation ) :
9199
+ this.queue( optall.queue, doAnimation );
9200
+ },
9201
+ stop: function( type, clearQueue, gotoEnd ) {
9202
+ var stopQueue = function( hooks ) {
9203
+ var stop = hooks.stop;
9204
+ delete hooks.stop;
9205
+ stop( gotoEnd );
9206
+ };
9207
+
9208
+ if ( typeof type !== "string" ) {
9209
+ gotoEnd = clearQueue;
9210
+ clearQueue = type;
9211
+ type = undefined;
9212
+ }
9213
+ if ( clearQueue && type !== false ) {
9214
+ this.queue( type || "fx", [] );
9215
+ }
9216
+
9217
+ return this.each(function() {
9218
+ var dequeue = true,
9219
+ index = type != null && type + "queueHooks",
9220
+ timers = jQuery.timers,
9221
+ data = jQuery._data( this );
9222
+
9223
+ if ( index ) {
9224
+ if ( data[ index ] && data[ index ].stop ) {
9225
+ stopQueue( data[ index ] );
9226
+ }
9227
+ } else {
9228
+ for ( index in data ) {
9229
+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
9230
+ stopQueue( data[ index ] );
9231
+ }
9232
+ }
9233
+ }
9234
+
9235
+ for ( index = timers.length; index--; ) {
9236
+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
9237
+ timers[ index ].anim.stop( gotoEnd );
9238
+ dequeue = false;
9239
+ timers.splice( index, 1 );
9240
+ }
9241
+ }
9242
+
9243
+ // start the next in the queue if the last step wasn't forced
9244
+ // timers currently will call their complete callbacks, which will dequeue
9245
+ // but only if they were gotoEnd
9246
+ if ( dequeue || !gotoEnd ) {
9247
+ jQuery.dequeue( this, type );
9248
+ }
9249
+ });
9250
+ },
9251
+ finish: function( type ) {
9252
+ if ( type !== false ) {
9253
+ type = type || "fx";
9254
+ }
9255
+ return this.each(function() {
9256
+ var index,
9257
+ data = jQuery._data( this ),
9258
+ queue = data[ type + "queue" ],
9259
+ hooks = data[ type + "queueHooks" ],
9260
+ timers = jQuery.timers,
9261
+ length = queue ? queue.length : 0;
9262
+
9263
+ // enable finishing flag on private data
9264
+ data.finish = true;
9265
+
9266
+ // empty the queue first
9267
+ jQuery.queue( this, type, [] );
9268
+
9269
+ if ( hooks && hooks.cur && hooks.cur.finish ) {
9270
+ hooks.cur.finish.call( this );
9271
+ }
9272
+
9273
+ // look for any active animations, and finish them
9274
+ for ( index = timers.length; index--; ) {
9275
+ if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
9276
+ timers[ index ].anim.stop( true );
9277
+ timers.splice( index, 1 );
9278
+ }
9279
+ }
9280
+
9281
+ // look for any animations in the old queue and finish them
9282
+ for ( index = 0; index < length; index++ ) {
9283
+ if ( queue[ index ] && queue[ index ].finish ) {
9284
+ queue[ index ].finish.call( this );
9285
+ }
9286
+ }
9287
+
9288
+ // turn off finishing flag
9289
+ delete data.finish;
9290
+ });
9291
+ }
9292
+ });
9293
+
9294
+ // Generate parameters to create a standard animation
9295
+ function genFx( type, includeWidth ) {
9296
+ var which,
9297
+ attrs = {
9298
+ height: type
9299
+ },
9300
+ i = 0;
9301
+
9302
+ // if we include width, step value is 1 to do all cssExpand values,
9303
+ // if we don't include width, step value is 2 to skip over Left and Right
9304
+ includeWidth = includeWidth? 1 : 0;
9305
+ for( ; i < 4 ; i += 2 - includeWidth ) {
9306
+ which = cssExpand[ i ];
9307
+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
9308
+ }
9309
+
9310
+ if ( includeWidth ) {
9311
+ attrs.opacity = attrs.width = type;
9312
+ }
9313
+
9314
+ return attrs;
9315
+ }
9316
+
9317
+ // Generate shortcuts for custom animations
9318
+ jQuery.each({
9319
+ slideDown: genFx("show"),
9320
+ slideUp: genFx("hide"),
9321
+ slideToggle: genFx("toggle"),
9322
+ fadeIn: {
9323
+ opacity: "show"
9324
+ },
9325
+ fadeOut: {
9326
+ opacity: "hide"
9327
+ },
9328
+ fadeToggle: {
9329
+ opacity: "toggle"
9330
+ }
9331
+ }, function( name, props ) {
9332
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
9333
+ return this.animate( props, speed, easing, callback );
9334
+ };
9335
+ });
9336
+
9337
+ jQuery.speed = function( speed, easing, fn ) {
9338
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
9339
+ complete: fn || !fn && easing ||
9340
+ jQuery.isFunction( speed ) && speed,
9341
+ duration: speed,
9342
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
9343
+ };
9344
+
9345
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
9346
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
9347
+
9348
+ // normalize opt.queue - true/undefined/null -> "fx"
9349
+ if ( opt.queue == null || opt.queue === true ) {
9350
+ opt.queue = "fx";
9351
+ }
9352
+
9353
+ // Queueing
9354
+ opt.old = opt.complete;
9355
+
9356
+ opt.complete = function() {
9357
+ if ( jQuery.isFunction( opt.old ) ) {
9358
+ opt.old.call( this );
9359
+ }
9360
+
9361
+ if ( opt.queue ) {
9362
+ jQuery.dequeue( this, opt.queue );
9363
+ }
9364
+ };
9365
+
9366
+ return opt;
9367
+ };
9368
+
9369
+ jQuery.easing = {
9370
+ linear: function( p ) {
9371
+ return p;
9372
+ },
9373
+ swing: function( p ) {
9374
+ return 0.5 - Math.cos( p*Math.PI ) / 2;
9375
+ }
9376
+ };
9377
+
9378
+ jQuery.timers = [];
9379
+ jQuery.fx = Tween.prototype.init;
9380
+ jQuery.fx.tick = function() {
9381
+ var timer,
9382
+ timers = jQuery.timers,
9383
+ i = 0;
9384
+
9385
+ fxNow = jQuery.now();
9386
+
9387
+ for ( ; i < timers.length; i++ ) {
9388
+ timer = timers[ i ];
9389
+ // Checks the timer has not already been removed
9390
+ if ( !timer() && timers[ i ] === timer ) {
9391
+ timers.splice( i--, 1 );
9392
+ }
9393
+ }
9394
+
9395
+ if ( !timers.length ) {
9396
+ jQuery.fx.stop();
9397
+ }
9398
+ fxNow = undefined;
9399
+ };
9400
+
9401
+ jQuery.fx.timer = function( timer ) {
9402
+ if ( timer() && jQuery.timers.push( timer ) ) {
9403
+ jQuery.fx.start();
9404
+ }
9405
+ };
9406
+
9407
+ jQuery.fx.interval = 13;
9408
+
9409
+ jQuery.fx.start = function() {
9410
+ if ( !timerId ) {
9411
+ timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
9412
+ }
9413
+ };
9414
+
9415
+ jQuery.fx.stop = function() {
9416
+ clearInterval( timerId );
9417
+ timerId = null;
9418
+ };
9419
+
9420
+ jQuery.fx.speeds = {
9421
+ slow: 600,
9422
+ fast: 200,
9423
+ // Default speed
9424
+ _default: 400
9425
+ };
9426
+
9427
+ // Back Compat <1.8 extension point
9428
+ jQuery.fx.step = {};
9429
+
9430
+ if ( jQuery.expr && jQuery.expr.filters ) {
9431
+ jQuery.expr.filters.animated = function( elem ) {
9432
+ return jQuery.grep(jQuery.timers, function( fn ) {
9433
+ return elem === fn.elem;
9434
+ }).length;
9435
+ };
9436
+ }
9437
+ jQuery.fn.offset = function( options ) {
9438
+ if ( arguments.length ) {
9439
+ return options === undefined ?
9440
+ this :
9441
+ this.each(function( i ) {
9442
+ jQuery.offset.setOffset( this, options, i );
9443
+ });
9444
+ }
9445
+
9446
+ var docElem, win,
9447
+ box = {
9448
+ top: 0,
9449
+ left: 0
9450
+ },
9451
+ elem = this[ 0 ],
9452
+ doc = elem && elem.ownerDocument;
9453
+
9454
+ if ( !doc ) {
9455
+ return;
9456
+ }
9457
+
9458
+ docElem = doc.documentElement;
9459
+
9460
+ // Make sure it's not a disconnected DOM node
9461
+ if ( !jQuery.contains( docElem, elem ) ) {
9462
+ return box;
9463
+ }
9464
+
9465
+ // If we don't have gBCR, just use 0,0 rather than error
9466
+ // BlackBerry 5, iOS 3 (original iPhone)
9467
+ if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
9468
+ box = elem.getBoundingClientRect();
9469
+ }
9470
+ win = getWindow( doc );
9471
+ return {
9472
+ top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
9473
+ left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
9474
+ };
9475
+ };
9476
+
9477
+ jQuery.offset = {
9478
+
9479
+ setOffset: function( elem, options, i ) {
9480
+ var position = jQuery.css( elem, "position" );
9481
+
9482
+ // set position first, in-case top/left are set even on static elem
9483
+ if ( position === "static" ) {
9484
+ elem.style.position = "relative";
9485
+ }
9486
+
9487
+ var curElem = jQuery( elem ),
9488
+ curOffset = curElem.offset(),
9489
+ curCSSTop = jQuery.css( elem, "top" ),
9490
+ curCSSLeft = jQuery.css( elem, "left" ),
9491
+ calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
9492
+ props = {}, curPosition = {}, curTop, curLeft;
9493
+
9494
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
9495
+ if ( calculatePosition ) {
9496
+ curPosition = curElem.position();
9497
+ curTop = curPosition.top;
9498
+ curLeft = curPosition.left;
9499
+ } else {
9500
+ curTop = parseFloat( curCSSTop ) || 0;
9501
+ curLeft = parseFloat( curCSSLeft ) || 0;
9502
+ }
9503
+
9504
+ if ( jQuery.isFunction( options ) ) {
9505
+ options = options.call( elem, i, curOffset );
9506
+ }
9507
+
9508
+ if ( options.top != null ) {
9509
+ props.top = ( options.top - curOffset.top ) + curTop;
9510
+ }
9511
+ if ( options.left != null ) {
9512
+ props.left = ( options.left - curOffset.left ) + curLeft;
9513
+ }
9514
+
9515
+ if ( "using" in options ) {
9516
+ options.using.call( elem, props );
9517
+ } else {
9518
+ curElem.css( props );
9519
+ }
9520
+ }
9521
+ };
9522
+
9523
+
9524
+ jQuery.fn.extend({
9525
+
9526
+ position: function() {
9527
+ if ( !this[ 0 ] ) {
9528
+ return;
9529
+ }
9530
+
9531
+ var offsetParent, offset,
9532
+ parentOffset = {
9533
+ top: 0,
9534
+ left: 0
9535
+ },
9536
+ elem = this[ 0 ];
9537
+
9538
+ // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
9539
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
9540
+ // we assume that getBoundingClientRect is available when computed position is fixed
9541
+ offset = elem.getBoundingClientRect();
9542
+ } else {
9543
+ // Get *real* offsetParent
9544
+ offsetParent = this.offsetParent();
9545
+
9546
+ // Get correct offsets
9547
+ offset = this.offset();
9548
+ if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
9549
+ parentOffset = offsetParent.offset();
9550
+ }
9551
+
9552
+ // Add offsetParent borders
9553
+ parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
9554
+ parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
9555
+ }
9556
+
9557
+ // Subtract parent offsets and element margins
9558
+ // note: when an element has margin: auto the offsetLeft and marginLeft
9559
+ // are the same in Safari causing offset.left to incorrectly be 0
9560
+ return {
9561
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
9562
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
9563
+ };
9564
+ },
9565
+
9566
+ offsetParent: function() {
9567
+ return this.map(function() {
9568
+ var offsetParent = this.offsetParent || document.documentElement;
9569
+ while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
9570
+ offsetParent = offsetParent.offsetParent;
9571
+ }
9572
+ return offsetParent || document.documentElement;
9573
+ });
9574
+ }
9575
+ });
9576
+
9577
+
9578
+ // Create scrollLeft and scrollTop methods
9579
+ jQuery.each( {
9580
+ scrollLeft: "pageXOffset",
9581
+ scrollTop: "pageYOffset"
9582
+ }, function( method, prop ) {
9583
+ var top = /Y/.test( prop );
9584
+
9585
+ jQuery.fn[ method ] = function( val ) {
9586
+ return jQuery.access( this, function( elem, method, val ) {
9587
+ var win = getWindow( elem );
9588
+
9589
+ if ( val === undefined ) {
9590
+ return win ? (prop in win) ? win[ prop ] :
9591
+ win.document.documentElement[ method ] :
9592
+ elem[ method ];
9593
+ }
9594
+
9595
+ if ( win ) {
9596
+ win.scrollTo(
9597
+ !top ? val : jQuery( win ).scrollLeft(),
9598
+ top ? val : jQuery( win ).scrollTop()
9599
+ );
9600
+
9601
+ } else {
9602
+ elem[ method ] = val;
9603
+ }
9604
+ }, method, val, arguments.length, null );
9605
+ };
9606
+ });
9607
+
9608
+ function getWindow( elem ) {
9609
+ return jQuery.isWindow( elem ) ?
9610
+ elem :
9611
+ elem.nodeType === 9 ?
9612
+ elem.defaultView || elem.parentWindow :
9613
+ false;
9614
+ }
9615
+ // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
9616
+ jQuery.each( {
9617
+ Height: "height",
9618
+ Width: "width"
9619
+ }, function( name, type ) {
9620
+ jQuery.each( {
9621
+ padding: "inner" + name,
9622
+ content: type,
9623
+ "": "outer" + name
9624
+ }, function( defaultExtra, funcName ) {
9625
+ // margin is only for outerHeight, outerWidth
9626
+ jQuery.fn[ funcName ] = function( margin, value ) {
9627
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
9628
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
9629
+
9630
+ return jQuery.access( this, function( elem, type, value ) {
9631
+ var doc;
9632
+
9633
+ if ( jQuery.isWindow( elem ) ) {
9634
+ // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
9635
+ // isn't a whole lot we can do. See pull request at this URL for discussion:
9636
+ // https://github.com/jquery/jquery/pull/764
9637
+ return elem.document.documentElement[ "client" + name ];
9638
+ }
9639
+
9640
+ // Get document width or height
9641
+ if ( elem.nodeType === 9 ) {
9642
+ doc = elem.documentElement;
9643
+
9644
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
9645
+ // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
9646
+ return Math.max(
9647
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
9648
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
9649
+ doc[ "client" + name ]
9650
+ );
9651
+ }
9652
+
9653
+ return value === undefined ?
9654
+ // Get width or height on the element, requesting but not forcing parseFloat
9655
+ jQuery.css( elem, type, extra ) :
9656
+
9657
+ // Set width or height on the element
9658
+ jQuery.style( elem, type, value, extra );
9659
+ }, type, chainable ? margin : undefined, chainable, null );
9660
+ };
9661
+ });
9662
+ });
9663
+ // Limit scope pollution from any deprecated API
9664
+ // (function() {
9665
+
9666
+ // })();
9667
+ // Expose jQuery to the global object
9668
+ window.jQuery = window.$ = jQuery;
9669
+
9670
+ // Expose jQuery as an AMD module, but only for AMD loaders that
9671
+ // understand the issues with loading multiple versions of jQuery
9672
+ // in a page that all might call define(). The loader will indicate
9673
+ // they have special allowances for multiple jQuery versions by
9674
+ // specifying define.amd.jQuery = true. Register as a named module,
9675
+ // since jQuery can be concatenated with other files that may use define,
9676
+ // but not use a proper concatenation script that understands anonymous
9677
+ // AMD modules. A named AMD is safest and most robust way to register.
9678
+ // Lowercase jquery is used because AMD module names are derived from
9679
+ // file names, and jQuery is normally delivered in a lowercase file name.
9680
+ // Do this after creating the global so that if an AMD module wants to call
9681
+ // noConflict to hide this version of jQuery, it will work.
9682
+ if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
9683
+ define( "jquery", [], function () {
9684
+ return jQuery;
9685
+ } );
9686
+ }
9687
+
9688
+ })( window );
9689
+
9690
+ jQuery.noConflict()
js/jquery/jquery.jOrgChart.js ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * jQuery org-chart/tree plugin.
3
+ *
4
+ * Author: Wes Nolte
5
+ * http://twitter.com/wesnolte
6
+ *
7
+ * Based on the work of Mark Lee
8
+ * http://www.capricasoftware.co.uk
9
+ *
10
+ * Copyright (c) 2011 Wesley Nolte
11
+ * Dual licensed under the MIT and GPL licenses.
12
+ *
13
+ */
14
+ (function(jQuery) {
15
+
16
+ jQuery.fn.jOrgChart = function(options) {
17
+ var opts = jQuery.extend({}, jQuery.fn.jOrgChart.defaults, options);
18
+ var jQueryappendTo = jQuery(opts.chartElement);
19
+
20
+ // build the tree
21
+ jQuerythis = jQuery(this);
22
+ var jQuerycontainer = jQuery("<div class='" + opts.chartClass + "'/>");
23
+ if(jQuerythis.is("ul")) {
24
+ buildNode(jQuerythis.find("li:first"), jQuerycontainer, 0, opts);
25
+ }
26
+ else if(jQuerythis.is("li")) {
27
+ buildNode(jQuerythis, jQuerycontainer, 0, opts);
28
+ }
29
+ jQueryappendTo.append(jQuerycontainer);
30
+
31
+ // add drag and drop if enabled
32
+ if(opts.dragAndDrop){
33
+ jQuery('div.node').draggable({
34
+ cursor : 'move',
35
+ distance : 40,
36
+ helper : 'clone',
37
+ opacity : 0.8,
38
+ revert : 'invalid',
39
+ revertDuration : 100,
40
+ snap : 'div.node.expanded',
41
+ snapMode : 'inner',
42
+ stack : 'div.node'
43
+ });
44
+
45
+ jQuery('div.node').droppable({
46
+ accept : '.node',
47
+ activeClass : 'drag-active',
48
+ hoverClass : 'drop-hover'
49
+ });
50
+
51
+ // Drag start event handler for nodes
52
+ jQuery('div.node').bind("dragstart", function handleDragStart( event, ui ){
53
+
54
+ var sourceNode = jQuery(this);
55
+ sourceNode.parentsUntil('.node-container')
56
+ .find('*')
57
+ .filter('.node')
58
+ .droppable('disable');
59
+ });
60
+
61
+ // Drag stop event handler for nodes
62
+ jQuery('div.node').bind("dragstop", function handleDragStop( event, ui ){
63
+
64
+ /* reload the plugin */
65
+ jQuery(opts.chartElement).children().remove();
66
+ jQuerythis.jOrgChart(opts);
67
+ });
68
+
69
+ // Drop event handler for nodes
70
+ jQuery('div.node').bind("drop", function handleDropEvent( event, ui ) {
71
+
72
+ var targetID = jQuery(this).data("tree-node");
73
+ var targetLi = jQuerythis.find("li").filter(function() { return jQuery(this).data("tree-node") === targetID; } );
74
+ var targetUl = targetLi.children('ul');
75
+
76
+ var sourceID = ui.draggable.data("tree-node");
77
+ var sourceLi = jQuerythis.find("li").filter(function() { return jQuery(this).data("tree-node") === sourceID; } );
78
+ var sourceUl = sourceLi.parent('ul');
79
+
80
+ if (targetUl.length > 0){
81
+ targetUl.append(sourceLi);
82
+ } else {
83
+ targetLi.append("<ul></ul>");
84
+ targetLi.children('ul').append(sourceLi);
85
+ }
86
+
87
+ //Removes any empty lists
88
+ if (sourceUl.children().length === 0){
89
+ sourceUl.remove();
90
+ }
91
+
92
+ }); // handleDropEvent
93
+
94
+ } // Drag and drop
95
+ };
96
+
97
+ // Option defaults
98
+ jQuery.fn.jOrgChart.defaults = {
99
+ chartElement : 'body',
100
+ depth : -1,
101
+ chartClass : "jOrgChart",
102
+ dragAndDrop: false
103
+ };
104
+
105
+ var nodeCount = 0;
106
+ // Method that recursively builds the tree
107
+ function buildNode(jQuerynode, jQueryappendTo, level, opts) {
108
+ var elementId = (jQuerynode.attr('id'));
109
+ var jQuerytable = jQuery("<table cellpadding='0' cellspacing='0' border='0' id='magemlm_structure'/>");
110
+ var jQuerytbody = jQuery("<tbody/>");
111
+
112
+ // Construct the node container(s)
113
+ var jQuerynodeRow = jQuery("<tr/>").addClass("node-cells");
114
+ var jQuerynodeCell = jQuery("<td/>").addClass("node-cell").attr("colspan", 2);
115
+ var jQuerychildNodes = jQuerynode.children("ul:first").children("li");
116
+ var jQuerynodeDiv;
117
+
118
+ if(jQuerychildNodes.length > 1) {
119
+ jQuerynodeCell.attr("colspan", jQuerychildNodes.length * 2);
120
+ }
121
+ // Draw the node
122
+ // Get the contents - any markup except li and ul allowed
123
+ var jQuerynodeContent = jQuerynode.clone()
124
+ .children("ul,li")
125
+ .remove()
126
+ .end()
127
+ .html();
128
+
129
+ //Increaments the node count which is used to link the source list and the org chart
130
+ nodeCount++;
131
+ jQuerynode.data("tree-node", nodeCount);
132
+ jQuerynodeDiv = jQuery("<div>").addClass("node")
133
+ .data("tree-node", nodeCount)
134
+ .attr('id', "customer_"+elementId)
135
+ .append(jQuerynodeContent);
136
+
137
+ // Expand and contract nodes
138
+ if (jQuerychildNodes.length > 0) {
139
+ jQuerynodeDiv.click(function() {
140
+ var jQuerythis = jQuery(this);
141
+ var jQuerytr = jQuerythis.closest("tr");
142
+
143
+ if(jQuerytr.hasClass('contracted')){
144
+ jQuerythis.css('cursor','n-resize');
145
+ jQuerytr.removeClass('contracted').addClass('expanded');
146
+ jQuerytr.nextAll("tr").show(500);
147
+
148
+ jQuerytr.find('.node-cell').find('.node').addClass('expanded');
149
+
150
+ // Update the <li> appropriately so that if the tree redraws collapsed/non-collapsed nodes
151
+ // maintain their appearance
152
+ jQuerynode.removeClass('collapsed');
153
+ }else{
154
+ jQuerythis.css('cursor','s-resize');
155
+ jQuerytr.removeClass('expanded').addClass('contracted');
156
+ jQuerytr.nextAll("tr").hide(500);
157
+ jQuerynode.addClass('collapsed');
158
+ }
159
+ });
160
+ }
161
+
162
+ jQuerynodeCell.append(jQuerynodeDiv);
163
+ jQuerynodeRow.append(jQuerynodeCell);
164
+ jQuerytbody.append(jQuerynodeRow);
165
+
166
+ if(jQuerychildNodes.length > 0) {
167
+ // if it can be expanded then change the cursor
168
+ jQuerynodeDiv.css('cursor','n-resize');
169
+
170
+ // recurse until leaves found (-1) or to the level specified
171
+ if(opts.depth == -1 || (level+1 < opts.depth)) {
172
+ var jQuerydownLineRow = jQuery("<tr/>");
173
+ var jQuerydownLineCell = jQuery("<td/>").attr("colspan", jQuerychildNodes.length*2);
174
+ jQuerydownLineRow.append(jQuerydownLineCell);
175
+
176
+ // draw the connecting line from the parent node to the horizontal line
177
+ jQuerydownLine = jQuery("<div></div>").addClass("struc_line struc_down");
178
+ jQuerydownLineCell.append(jQuerydownLine);
179
+ jQuerytbody.append(jQuerydownLineRow);
180
+
181
+ // Draw the horizontal lines
182
+ var jQuerylinesRow = jQuery("<tr/>");
183
+ jQuerychildNodes.each(function() {
184
+ var jQueryleft = jQuery("<td>&nbsp;</td>").addClass("struc_line struc_left struc_top");
185
+ var jQueryright = jQuery("<td>&nbsp;</td>").addClass("struc_line struc_right struc_top");
186
+ jQuerylinesRow.append(jQueryleft).append(jQueryright);
187
+ });
188
+
189
+ // horizontal line shouldn't extend beyond the first and last child branches
190
+ jQuerylinesRow.find("td:first")
191
+ .removeClass("struc_top")
192
+ .end()
193
+ .find("td:last")
194
+ .removeClass("struc_top");
195
+
196
+ jQuerytbody.append(jQuerylinesRow);
197
+ var jQuerychildNodesRow = jQuery("<tr/>");
198
+ jQuerychildNodes.each(function() {
199
+ var jQuerytd = jQuery("<td class='node-container'/>");
200
+ jQuerytd.attr("colspan", 2);
201
+ // recurse through children lists and items
202
+ buildNode(jQuery(this), jQuerytd, level+1, opts);
203
+ jQuerychildNodesRow.append(jQuerytd);
204
+ });
205
+
206
+ }
207
+ jQuerytbody.append(jQuerychildNodesRow);
208
+ }
209
+
210
+ // any classes on the LI element get copied to the relevant node in the tree
211
+ // apart from the special 'collapsed' class, which collapses the sub-tree at this point
212
+ if (jQuerynode.attr('class') != undefined) {
213
+ var classList = jQuerynode.attr('class').split(/\s+/);
214
+ jQuery.each(classList, function(index,item) {
215
+ if (item == 'collapsed') {
216
+ console.log(jQuerynode);
217
+ jQuerynodeRow.nextAll('tr').css('visibility', 'hidden');
218
+ jQuerynodeRow.removeClass('expanded');
219
+ jQuerynodeRow.addClass('contracted');
220
+ jQuerynodeDiv.css('cursor','s-resize');
221
+ } else {
222
+ jQuerynodeDiv.addClass(item);
223
+ }
224
+ });
225
+ }
226
+
227
+ jQuerytable.append(jQuerytbody);
228
+ jQueryappendTo.append(jQuerytable);
229
+
230
+ /* Prevent trees collapsing if a link inside a node is clicked */
231
+ jQuerynodeDiv.children('a').click(function(e){
232
+ console.log(e);
233
+ e.stopPropagation();
234
+ });
235
+ };
236
+
237
+ })(jQuery);
media/magemlm/female.png ADDED
Binary file
media/magemlm/male.png ADDED
Binary file
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Qsolutions_Magemlm</name>
4
+ <version>0.1.4</version>
5
+ <stability>stable</stability>
6
+ <license>OSL v3.0</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Multilevel Compensation Plan</summary>
10
+ <description>Allows to change any store into multilevel marketing system with unilevel compensation plan.</description>
11
+ <notes>First public release</notes>
12
+ <authors><author><name>Qsolutions</name><user>Qsolutions</user><email>jakub.winkler@gmail.com</email></author></authors>
13
+ <date>2013-05-12</date>
14
+ <time>15:56:10</time>
15
+ <contents><target name="magecommunity"><dir name="Qsolutions"><dir name="Magemlm"><dir name="Block"><dir name="Adminhtml"><file name="Commissions.php" hash="b5aaef0d0b32238e40331ab8a8c5c89b"/><dir name="Customer"><dir name="Edit"><dir name="Tab"><file name="Magemlm.php" hash="b4c44efc9f8ee71ff62546bce382e811"/></dir></dir></dir><dir name="Magemlm"><file name="Structure.php" hash="dbab084ac3a8ddfc2e494f0bf1761b01"/></dir><dir name="Unilevel"><dir name="Edit"><file name="Form.php" hash="699f25166ac0b214508bbf1c3ead17a8"/></dir><file name="Edit.php" hash="8ce5ec8c868ee9f6f5c31e117fdb53a8"/></dir><file name="Unilevel.php" hash="ba95547886c24462d9653872367c1adc"/></dir><dir name="Customer"><file name="Commissions.php" hash="ca752cc1c626c1b77bf6ea854037d3ca"/><file name="Plan.php" hash="c92a30f7360c85932db837c8c3bdb805"/><file name="Profile.php" hash="98aac856f837da6ad474694242569db9"/><dir name="Structure"><file name="Menu.php" hash="03ea646ccb0bca177c2ceaa577528001"/></dir><file name="Structure.php" hash="ac61c0a9bce333ded8513ca5b0dd7f7b"/></dir></dir><dir name="Helper"><file name="Data.php" hash="51dd2654b811731ffc549c8e2ef8f503"/></dir><dir name="Model"><file name="Commissions.php" hash="71715174db52c9fcc865933c78da671c"/><file name="Customer.php" hash="ef010ba362530a43ed78e197a3257d11"/><file name="Observer.php" hash="67fc27665e48036f6a07763d731d5fde"/><file name="Referrallink.php" hash="3e01acd508cae8b4d3f9c33cd3e539e6"/><dir name="Resource"><dir name="Commissions"><file name="Collection.php" hash="f58a0f47d576cbb32019c994494539dc"/></dir><file name="Commissions.php" hash="04cc326cdd01c34aad491f1705f48208"/><file name="Commissions.php._tmp_uploadphp" hash="02ec8045f775051781003ab0520a6787"/><dir name="Customer"><file name="Collection.php" hash="32254e607f15471e8ece56e9831c69fb"/></dir><file name="Customer.php" hash="1a98ff97625ca852e69742b876c3e3e7"/><dir name="Unilevel"><file name="Collection.php" hash="21b0d12cdf14a3549e85a81ef166639f"/></dir><file name="Unilevel.php" hash="f633b21e28389d1e30409e31ac39f904"/></dir><file name="Unilevel.php" hash="c716747dfc03aef17c9f57ed41c2d02b"/></dir><dir name="controllers"><dir name="Adminhtml"><file name="CommissionController.php" hash="3df9f2d246b1c6ed662319e372d4ec4d"/><file name="CommissionsController.php" hash="47639b9f963ddcf9dbb89682f84d8a19"/><file name="StructureController.php" hash="d7ccbb7699546c768a2323d0946bf02d"/><file name="UnilevelController.php" hash="8d5543bc11cf809c46fda95442aa106d"/></dir><file name="CustomerController.php" hash="0268a1d415f0850f8bdc21ddc068c262"/></dir><dir name="etc"><file name="config.xml" hash="81d8dd4b888e01102f4d8b686367f231"/></dir><dir name="sql"><dir name="magemlm_setup"><file name="mysql4-install-0.1.0.php" hash="36a5fb57d899c0b36ad1118b51f4b1ab"/><file name="mysql4-upgrade-0.1.0-0.1.1.php" hash="e41e849652f123943f0561a26f91ddda"/><file name="mysql4-upgrade-0.1.1-0.1.2.php" hash="bb5b3b3f5d29b9c239927ab65c914dd2"/><file name="mysql4-upgrade-0.1.2-0.1.3.php" hash="a494ff93d6c95a73e344dbb63828d050"/><file name="mysql4-upgrade-0.1.3-0.1.4.php" hash="ddef05b1dc6d63e795b04e0fa00a5804"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="magemlm.xml" hash="6a8201dde754105a9e86cc64517263cc"/></dir><dir name="template"><dir name="magemlm"><dir><dir name="commissions"><file name="view.phtml" hash="65de01c2004b93bdfed4fa46e6ceba40"/></dir><dir name="unilevel"><file name="edit.phtml" hash="d41d8cd98f00b204e9800998ecf8427e"/><file name="view.phtml" hash="ca6a7f9c95ee1333696df8fc159a7773"/></dir></dir><file name="customer.phtml" hash="24826311df7067c4a299c1490a61dbfb"/><file name="structure.phtml" hash="f8e0db88e6e2bc0f5efef9b44a601389"/></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="magemlm.xml" hash="0b70f4315bc1ebea8ae3c809784d542d"/></dir><dir name="template"><dir name="magemlm"><file name="commissions.phtml" hash="3d30019d3b355bfd9fdbd3f873cda209"/><file name="plan.phtml" hash="61dd69c8b37a50edf0da4d3c42e825a9"/><file name="profile.phtml" hash="e6ca2fc77b5cf5cceb384010db28cf63"/><dir><dir name="structure"><file name="menu.phtml" hash="088d4ffefcfc0ee3fff8795c67fc5264"/><dir name="page"><file name="structure.phtml" hash="58a3fd57a74bfc303786bb32da6b5571"/></dir></dir></dir><file name="structure.phtml" hash="2e6b0508ea3accd81bf33b2b99414a74"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Qsolutions_Magemlm.xml" hash="9f4aaaf0df178759512e97a836ead127"/></dir></target><target name="magelocale"><dir><dir name="pl_PL"><file name="Qsolutions_magemlm.csv" hash="e38ec571ed1c119cf68c06631af23737"/></dir></dir></target><target name="mageweb"><dir name="js"><dir name="jquery"><file name="jquery-1.9.1.js" hash="c06bd24bb55a0788b0efb37e0ece3f15"/><file name="jquery.jOrgChart.js" hash="d0b95c413d26a6f9b08e9603a7af38f4"/></dir></dir><dir name="media"><dir name="magemlm"><file name="female.png" hash="621441d34f9e834ea57e8b4ea3e71a67"/><file name="male.png" hash="a33cd92fdb9ef8589b8e592fb0211e6e"/></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><file name="magemlm.css" hash="148e083c8debf8a89e354f8f847d74af"/><dir name="images"><file name="admin_magemlm_arrow.png" hash="b25edfd2f560a59d905409fc82a68ab6"/><file name="admin_magemlm_delete.png" hash="d978593f07acfe05311085fbf5f9c5a2"/><file name="admin_magemlm_edit.png" hash="4d11b33066ef35b8b390cf187025d14c"/></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="css"><file name="magemlm.css" hash="755b49a6f3253e36ea18b3075c35e93a"/></dir><dir name="images"><file name="magemlm_arrow.png" hash="b25edfd2f560a59d905409fc82a68ab6"/><dir name="magemlm"><file name="male.png" hash="a33cd92fdb9ef8589b8e592fb0211e6e"/><file name="female.png" hash="621441d34f9e834ea57e8b4ea3e71a67"/></dir></dir></dir></dir></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.1.0</min><max>6.0.0</max></php></required></dependencies>
18
+ </package>
skin/adminhtml/default/default/images/admin_magemlm_arrow.png ADDED
Binary file
skin/adminhtml/default/default/images/admin_magemlm_delete.png ADDED
Binary file
skin/adminhtml/default/default/images/admin_magemlm_edit.png ADDED
Binary file
skin/adminhtml/default/default/magemlm.css ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Header */
2
+ .brand{
3
+ color : #777 !important;
4
+ font-family : georgia;
5
+ font-style : italic;
6
+ }
7
+
8
+ /* list stuff */
9
+ #org{
10
+ background-color : white;
11
+ margin : 10px;
12
+ padding : 10px;
13
+ }
14
+
15
+ #show-list{
16
+ cursor: pointer;
17
+ }
18
+
19
+ /* bootstrap overrides */
20
+ .alert-message{
21
+ margin : 1px 0;
22
+ }
23
+
24
+ .topbar{
25
+ position : absolute;
26
+ }
27
+
28
+ /* Custom chart styling */
29
+ .jOrgChart {
30
+ margin : 10px;
31
+ padding : 20px;
32
+ }
33
+
34
+ /* Custom node styling */
35
+ #magemlm_structure .node {
36
+ font-size : 12px;
37
+ background-color : silver;
38
+ border : 1px solid gray;
39
+ color : #555;
40
+ -moz-border-radius : 8px;
41
+ }
42
+ .node p{
43
+ font-family : tahoma;
44
+ font-size : 10px;
45
+ line-height : 11px;
46
+ padding : 2px;
47
+ }
48
+
49
+ /* Basic styling */
50
+ /* Draw the lines */
51
+ #magemlm_structure .struc_line {
52
+ height : 20px;
53
+ width : 4px;
54
+ }
55
+
56
+ #magemlm_structure .struc_down {
57
+ background-color : #444;
58
+ margin : 0px auto;
59
+ width : 2px;
60
+ }
61
+
62
+ #magemlm_structure .struc_top {
63
+ border-top : 1px solid #444;
64
+ }
65
+
66
+ #magemlm_structure .struc_left {
67
+ border-right :1px solid #444;
68
+ }
69
+
70
+ #magemlm_structure .struc_right {
71
+ border-left : 1px solid #444;
72
+ }
73
+
74
+ #magemlm_structure td {
75
+ text-align : center;
76
+ vertical-align : top;
77
+ padding : 0;
78
+ }
79
+
80
+ /* The node */
81
+ #magemlm_structure .node {
82
+
83
+ background : #FBFAF6;
84
+ display : inline-block;
85
+ width : 90px;
86
+ min-height : 105px;
87
+ z-index : 10;
88
+ margin-left : 2px;
89
+ margin-right : 2px;
90
+ font-size : 12px;
91
+ border : 1px solid silver;
92
+ color : #555;
93
+ padding: 0px;
94
+ }
95
+
96
+ .node .magemlm_name {
97
+ background-color : silver;
98
+ font-weight : bold;
99
+ margin-bottom : 3px;
100
+ color : white;
101
+ height : 40px;
102
+ background: url("../images/bkg_block-title-account.gif") repeat-x scroll 0 100% #FC9D36;
103
+ }
104
+
105
+
106
+ #magemlm_structure .node.expanded {
107
+ background: #E3EFF1;
108
+ }
109
+
110
+ #magemlm_structure .node.contracted {
111
+ background: url("images/filter_row_bg.gif") repeat-x scroll 0 0 #E3EFF1;
112
+ }
113
+
114
+ /* jQuery drag 'n drop */
115
+
116
+ .drag-active {
117
+ border-style : dotted !important;
118
+ }
119
+
120
+ .drop-hover {
121
+ border-style : solid !important;
122
+ border-color : #E05E00 !important;
123
+ }
124
+
125
+ .magemlm-buttons {
126
+ float: right;
127
+ }
128
+
129
+
130
+ .magemlm-level {
131
+ font-size : 20px;
132
+ text-align : center;
133
+ padding : 0px;
134
+ margin : 0px;
135
+ font-weight : bold;
136
+ }
137
+
138
+ .magemlm-admin-edit {
139
+ background-color: #f0f0f0; width: 100px; float: right; height: 80px; border: 1px solid silver; cursor: pointer; margin-left: 2px;
140
+ background-image: url("images/admin_magemlm_edit.png");
141
+ background-position:center ;
142
+ background-repeat: no-repeat;
143
+ border-radius: 5px;
144
+ }
145
+
146
+ .magemlm-admin-delete {
147
+ background-color: #f0f0f0; width: 100px; float: right; height: 80px; border: 1px solid silver; cursor: pointer;
148
+ background-image: url("images/admin_magemlm_delete.png");
149
+ background-position:center ;
150
+ background-repeat: no-repeat;
151
+ border-radius: 5px;
152
+ }
153
+
154
+ .magemlm-admin-delete:hover {
155
+ background-color: #f8f8f8; cursor: pointer;
156
+ background-image: url("images/admin_magemlm_delete.png");
157
+ background-position:center ;
158
+ background-repeat: no-repeat;
159
+ }
160
+
161
+ .magemlm-admin-edit:hover {
162
+ background-color: #f8f8f8; cursor: pointer;
163
+ background-image: url("images/admin_magemlm_edit.png");
164
+ background-position:center ;
165
+ background-repeat: no-repeat;
166
+ }
skin/frontend/base/default/css/magemlm.css ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Header */
2
+ .brand{
3
+ color : #777 !important;
4
+ font-family : georgia;
5
+ font-style : italic;
6
+ }
7
+
8
+ /* list stuff */
9
+ #org{
10
+ background-color : white;
11
+ margin : 10px;
12
+ padding : 10px;
13
+ }
14
+
15
+ #show-list{
16
+ cursor: pointer;
17
+ }
18
+
19
+ /* bootstrap overrides */
20
+ .alert-message{
21
+ margin : 1px 0;
22
+ }
23
+
24
+ .topbar{
25
+ position : absolute;
26
+ }
27
+
28
+ /* Custom chart styling */
29
+ .jOrgChart {
30
+ margin : 10px;
31
+ padding : 20px;
32
+ }
33
+
34
+ .node p{
35
+ font-family : tahoma;
36
+ font-size : 10px;
37
+ line-height : 11px;
38
+ padding : 2px;
39
+ }
40
+
41
+ /* Basic styling */
42
+ /* Draw the lines */
43
+ #magemlm_structure .struc_line {
44
+ height : 20px;
45
+ width : 4px;
46
+ }
47
+
48
+ #magemlm_structure .struc_down {
49
+ background-color : #444;
50
+ margin : 0px auto;
51
+ width : 2px;
52
+ }
53
+
54
+ #magemlm_structure .struc_top {
55
+ border-top : 1px solid #444;
56
+ }
57
+
58
+ #magemlm_structure .struc_left {
59
+ border-right :1px solid #444;
60
+ }
61
+
62
+ #magemlm_structure .struc_right {
63
+ border-left : 1px solid #444;
64
+ }
65
+
66
+ /* node cell */
67
+ #magemlm_structure td {
68
+ text-align : center;
69
+ vertical-align : top;
70
+ padding : 0;
71
+ }
72
+
73
+ /* The node */
74
+ #magemlm_structure .node {
75
+
76
+ background : #FBFAF6;
77
+ display : inline-block;
78
+ width : 100px;
79
+ min-height : 95px;
80
+ z-index : 10;
81
+ margin-left : 2px;
82
+ margin-right : 2px;
83
+ font-size : 12px;
84
+ border : 1px solid silver;
85
+ color : #555;
86
+ padding: 0px;
87
+ }
88
+
89
+
90
+ #magemlm_structure .node.expanded {
91
+ background: #E3EFF1;
92
+ }
93
+
94
+ #magemlm_structure .node.contracted {
95
+ background: url("images/filter_row_bg.gif") repeat-x scroll 0 0 #E3EFF1;
96
+ }
97
+
98
+ /* jQuery drag 'n drop */
99
+
100
+ .drag-active {
101
+ border-style : dotted !important;
102
+ }
103
+
104
+ .drop-hover {
105
+ border-style : solid !important;
106
+ border-color : #E05E00 !important;
107
+ }
108
+
109
+
110
+
111
+ #magemlm_menu {
112
+ border : 1px solid silver;
113
+ background-color : white;
114
+ width : 250px;
115
+ min-height : 100px;
116
+ display : none;
117
+ position : absolute;
118
+ }
119
+
120
+
121
+ .node .magemlm_name {
122
+ background-color : silver;
123
+ font-weight : bold;
124
+ margin-bottom : 3px;
125
+ height : 40px;
126
+ color : white;
127
+ background: url("../images/bkg_block-title-account.gif") repeat-x scroll 0 100% #FC9D36;
128
+ }
129
+
130
+
131
+ #magemlm_menu#magemlm_menu ul li{
132
+ background-color : #FBFAF6;
133
+ height : 25px;
134
+ padding-top : 5px;
135
+ padding-left : 5px;
136
+ }
137
+
138
+ #magemlm_menu#magemlm_menu ul li:hover{
139
+ background: url("../images/bkg_block-title-account.gif") repeat-x scroll 0 100% #FC9D36;
140
+ border: 0 none;
141
+ }
142
+
143
+ .magemlm-left {
144
+ width: 40%;
145
+ float: left;
146
+ margin-right: 10px;
147
+ margin-top: 0px;
148
+ }
149
+
150
+ .magemlm-right {
151
+ width: 40%;
152
+ float: right;
153
+ margin-top: 0px;
154
+ }
155
+
156
+
157
+ .magemlm-full {clear: both; }
158
+
159
+
160
+ .magemlm-full p{
161
+ text-align: center;
162
+ color: red;
163
+ margin: 0px;
164
+ font-size: 14px;
165
+ }
166
+
167
+
168
+ .magemlm-structure-body {
169
+ width: 100% ;
170
+ background: white;
171
+
172
+ }
skin/frontend/base/default/images/magemlm/female.png ADDED
Binary file
skin/frontend/base/default/images/magemlm/male.png ADDED
Binary file
skin/frontend/base/default/images/magemlm_arrow.png ADDED
Binary file