KAbel_BundlePlus - Version 0.2.1

Version Notes

Stability release for the Magento CE 1.7 branch.

Download this release

Release Info

Developer Kevin Abel
Extension KAbel_BundlePlus
Version 0.2.1
Comparing to
See all releases


Version 0.2.1

LICENSE_BSD_NU.txt ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2012, Regents of the University of Nebraska
2
+
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9
+ * Neither the name of the University of Nebraska nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
+
11
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
12
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
13
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
14
+ SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
15
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
16
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
17
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
18
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
19
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
20
+ DAMAGE.
app/code/community/KAbel/BundlePlus/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * KAbel_BundlePlus
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to a BSD 3-Clause License
8
+ * that is bundled with this package in the file LICENSE_BSD_NU.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www1.unl.edu/wdn/wiki/Software_License
11
+ *
12
+ * @category KAbel
13
+ * @package KAbel_BundlePlus
14
+ * @copyright Copyright (c) 2012 Regents of the University of Nebraska (http://www.nebraska.edu/)
15
+ * @license http://www1.unl.edu/wdn/wiki/Software_License BSD 3-Clause License
16
+ */
17
+
18
+ /**
19
+ * Bundle option renderer
20
+ *
21
+ * @category KAbel
22
+ * @package KAbel_BundlePlus
23
+ * @author Kevin Abel <kabel2@unl.edu>
24
+ */
25
+ class KAbel_BundlePlus_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle_Option
26
+ extends Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle_Option
27
+ {
28
+ public function __construct()
29
+ {
30
+ $this->setTemplate('kabel/bundleplus/product/edit/bundle/option.phtml');
31
+ }
32
+ }
app/code/community/KAbel/BundlePlus/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option/Selection.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * KAbel_BundlePlus
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to a BSD 3-Clause License
8
+ * that is bundled with this package in the file LICENSE_BSD_NU.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www1.unl.edu/wdn/wiki/Software_License
11
+ *
12
+ * @category KAbel
13
+ * @package KAbel_BundlePlus
14
+ * @copyright Copyright (c) 2012 Regents of the University of Nebraska (http://www.nebraska.edu/)
15
+ * @license http://www1.unl.edu/wdn/wiki/Software_License BSD 3-Clause License
16
+ */
17
+
18
+ /**
19
+ * Bundle selection renderer
20
+ *
21
+ * @category KAbel
22
+ * @package KAbel_BundlePlus
23
+ * @author Kevin Abel <kabel2@unl.edu>
24
+ */
25
+ class KAbel_BundlePlus_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle_Option_Selection
26
+ extends Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle_Option_Selection
27
+ {
28
+ public function __construct()
29
+ {
30
+ $this->setTemplate('kabel/bundleplus/product/edit/bundle/option/selection.phtml');
31
+ }
32
+ }
app/code/community/KAbel/BundlePlus/Block/Catalog/Product/View/Type/Bundle/Option/Checkbox.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * KAbel_BundlePlus
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to a BSD 3-Clause License
8
+ * that is bundled with this package in the file LICENSE_BSD_NU.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www1.unl.edu/wdn/wiki/Software_License
11
+ *
12
+ * @category KAbel
13
+ * @package KAbel_BundlePlus
14
+ * @copyright Copyright (c) 2012 Regents of the University of Nebraska (http://www.nebraska.edu/)
15
+ * @license http://www1.unl.edu/wdn/wiki/Software_License BSD 3-Clause License
16
+ */
17
+
18
+ /**
19
+ * Bundle option checkbox type renderer
20
+ *
21
+ * @category KAbel
22
+ * @package KAbel_BundlePlus
23
+ * @author Kevin Abel <kabel2@unl.edu>
24
+ */
25
+ class KAbel_BundlePlus_Block_Catalog_Product_View_Type_Bundle_Option_Checkbox
26
+ extends Mage_Bundle_Block_Catalog_Product_View_Type_Bundle_Option_Checkbox
27
+ {
28
+ protected function _construct()
29
+ {
30
+ $this->setTemplate('kabel/bundleplus/catalog/product/view/type/bundle/option/checkbox.phtml');
31
+ }
32
+
33
+ protected function _getSelectionQty($selection)
34
+ {
35
+ if ($this->getProduct()->hasPreconfiguredValues()) {
36
+ $selectedQty = $this->getProduct()->getPreconfiguredValues()
37
+ ->getData('bundle_option_qty/' . $this->getOption()->getId());
38
+ if (is_array($selectedQty)) {
39
+ if (isset($selectedQty[$selection->getSelectionId()])) {
40
+ $selectedQty = $selectedQty[$selection->getSelectionId()];
41
+ } else {
42
+ $selectedQty = 0;
43
+ }
44
+ }
45
+
46
+ $selectedQty = (float)$selectedQty;
47
+ if ($selectedQty < 0) {
48
+ $selectedQty = 0;
49
+ }
50
+ } else {
51
+ $selectedQty = 0;
52
+ }
53
+
54
+ return $selectedQty;
55
+ }
56
+ }
app/code/community/KAbel/BundlePlus/Model/Product/Type.php ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * KAbel_BundlePlus
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to a BSD 3-Clause License
8
+ * that is bundled with this package in the file LICENSE_BSD_NU.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www1.unl.edu/wdn/wiki/Software_License
11
+ *
12
+ * @category KAbel
13
+ * @package KAbel_BundlePlus
14
+ * @copyright Copyright (c) 2012 Regents of the University of Nebraska (http://www.nebraska.edu/)
15
+ * @license http://www1.unl.edu/wdn/wiki/Software_License BSD 3-Clause License
16
+ */
17
+
18
+ /**
19
+ * Bundle Type Model
20
+ *
21
+ * @category KAbel
22
+ * @package KAbel_BundlePlus
23
+ * @author Kevin Abel <kabel2@unl.edu>
24
+ */
25
+ class KAbel_BundlePlus_Model_Product_Type extends Mage_Bundle_Model_Product_Type
26
+ {
27
+ /* Overrides
28
+ * @see Mage_Bundle_Model_Product_Type::_prepareProduct($buyRequest, $product, $processMode)
29
+ * by allowing each bundle option selection to have a user-defined qty
30
+ */
31
+ protected function _prepareProduct(Varien_Object $buyRequest, $product, $processMode)
32
+ {
33
+ // completely bypass the parent:: call
34
+ $result = Mage_Catalog_Model_Product_Type_Abstract::_prepareProduct($buyRequest, $product, $processMode);
35
+
36
+ if (is_string($result)) {
37
+ return $result;
38
+ }
39
+
40
+ $selections = array();
41
+ $product = $this->getProduct($product);
42
+ $isStrictProcessMode = $this->_isStrictProcessMode($processMode);
43
+
44
+ $skipSaleableCheck = Mage::helper('catalog/product')->getSkipSaleableCheck();
45
+ $_appendAllSelections = (bool)$product->getSkipCheckRequiredOption() || $skipSaleableCheck;
46
+
47
+ $options = $buyRequest->getBundleOption();
48
+ if (is_array($options)) {
49
+ $options = array_filter($options, 'intval');
50
+ $qtys = $buyRequest->getBundleOptionQty();
51
+ foreach ($options as $_optionId => $_selections) {
52
+ if (empty($_selections)) {
53
+ unset($options[$_optionId]);
54
+ }
55
+ }
56
+ $optionIds = array_keys($options);
57
+
58
+ if (empty($optionIds) && $isStrictProcessMode) {
59
+ return Mage::helper('bundle')->__('Please select options for product.');
60
+ }
61
+
62
+ $product->getTypeInstance(true)->setStoreFilter($product->getStoreId(), $product);
63
+ $optionsCollection = $this->getOptionsCollection($product);
64
+ if (!$this->getProduct($product)->getSkipCheckRequiredOption() && $isStrictProcessMode) {
65
+ foreach ($optionsCollection->getItems() as $option) {
66
+ if ($option->getRequired() && !isset($options[$option->getId()])) {
67
+ return Mage::helper('bundle')->__('Required options are not selected.');
68
+ }
69
+ }
70
+ }
71
+ $selectionIds = array();
72
+
73
+ foreach ($options as $optionId => $selectionId) {
74
+ if (!is_array($selectionId)) {
75
+ if ($selectionId != '') {
76
+ $selectionIds[] = (int)$selectionId;
77
+ }
78
+ } else {
79
+ foreach ($selectionId as $id) {
80
+ if ($id != '') {
81
+ $selectionIds[] = (int)$id;
82
+ }
83
+ }
84
+ }
85
+ }
86
+ // If product has not been configured yet then $selections array should be empty
87
+ if (!empty($selectionIds)) {
88
+ $selections = $this->getSelectionsByIds($selectionIds, $product);
89
+
90
+ // Check if added selections are still on sale
91
+ foreach ($selections->getItems() as $key => $selection) {
92
+ if (!$selection->isSalable() && !$skipSaleableCheck) {
93
+ $_option = $optionsCollection->getItemById($selection->getOptionId());
94
+ if (is_array($options[$_option->getId()]) && count($options[$_option->getId()]) > 1) {
95
+ $moreSelections = true;
96
+ } else {
97
+ $moreSelections = false;
98
+ }
99
+ if ($_option->getRequired()
100
+ && (!$_option->isMultiSelection() || ($_option->isMultiSelection() && !$moreSelections))
101
+ ) {
102
+ return Mage::helper('bundle')->__('Selected required options are not available.');
103
+ }
104
+ }
105
+ }
106
+
107
+ $optionsCollection->appendSelections($selections, false, $_appendAllSelections);
108
+
109
+ $selections = $selections->getItems();
110
+ } else {
111
+ $selections = array();
112
+ }
113
+ } else {
114
+ $product->setOptionsValidationFail(true);
115
+ $product->getTypeInstance(true)->setStoreFilter($product->getStoreId(), $product);
116
+
117
+ $optionCollection = $product->getTypeInstance(true)->getOptionsCollection($product);
118
+
119
+ $optionIds = $product->getTypeInstance(true)->getOptionsIds($product);
120
+ $selectionIds = array();
121
+
122
+ $selectionCollection = $product->getTypeInstance(true)
123
+ ->getSelectionsCollection(
124
+ $optionIds,
125
+ $product
126
+ );
127
+
128
+ $options = $optionCollection->appendSelections($selectionCollection, false, $_appendAllSelections);
129
+
130
+ foreach ($options as $option) {
131
+ if ($option->getRequired() && count($option->getSelections()) == 1) {
132
+ $selections = array_merge($selections, $option->getSelections());
133
+ } else {
134
+ $selections = array();
135
+ break;
136
+ }
137
+ }
138
+ }
139
+ if (count($selections) > 0 || !$isStrictProcessMode) {
140
+ $uniqueKey = array($product->getId());
141
+ $selectionIds = array();
142
+
143
+ /*
144
+ * shaking selection array :) by option position
145
+ */
146
+ usort($selections, array($this, 'shakeSelections'));
147
+
148
+ foreach ($selections as $selection) {
149
+ if ($selection->getSelectionCanChangeQty() && isset($qtys[$selection->getOptionId()])) {
150
+ // allow options to have multiple qtys (for each selection)
151
+ if (is_array($qtys[$selection->getOptionId()])) {
152
+ if (isset($qtys[$selection->getOptionId()][$selection->getSelectionId()])) {
153
+ $qty = (float)$qtys[$selection->getOptionId()][$selection->getSelectionId()] > 0 ? $qtys[$selection->getOptionId()][$selection->getSelectionId()] : 1;
154
+ } else {
155
+ $qty = (float)$selection->getSelectionQty() ? $selection->getSelectionQty() : 1;
156
+ }
157
+ } else {
158
+ // original logic
159
+ $qty = (float)$qtys[$selection->getOptionId()] > 0 ? $qtys[$selection->getOptionId()] : 1;
160
+ }
161
+
162
+ } else {
163
+ $qty = (float)$selection->getSelectionQty() ? $selection->getSelectionQty() : 1;
164
+ }
165
+ $qty = (float)$qty;
166
+
167
+ $product->addCustomOption('selection_qty_' . $selection->getSelectionId(), $qty, $selection);
168
+ $selection->addCustomOption('selection_id', $selection->getSelectionId());
169
+
170
+ $beforeQty = 0;
171
+ if ($customOption = $product->getCustomOption('product_qty_' . $selection->getId())) {
172
+ $beforeQty = (float)$customOption->getValue();
173
+ }
174
+ $product->addCustomOption('product_qty_' . $selection->getId(), $qty + $beforeQty, $selection);
175
+
176
+ /*
177
+ * creating extra attributes that will be converted
178
+ * to product options in order item
179
+ * for selection (not for all bundle)
180
+ */
181
+ $price = $product->getPriceModel()->getSelectionPrice($product, $selection, $qty);
182
+ $attributes = array(
183
+ 'price' => Mage::app()->getStore()->convertPrice($price),
184
+ 'qty' => $qty,
185
+ 'option_label' => $selection->getOption()->getTitle(),
186
+ 'option_id' => $selection->getOption()->getId()
187
+ );
188
+
189
+ //if (!$product->getPriceType()) {
190
+ $_result = $selection->getTypeInstance(true)->prepareForCart($buyRequest, $selection);
191
+ if (is_string($_result) && !is_array($_result)) {
192
+ return $_result;
193
+ }
194
+
195
+ if (!isset($_result[0])) {
196
+ return Mage::helper('checkout')->__('Cannot add item to the shopping cart.');
197
+ }
198
+
199
+ $result[] = $_result[0]->setParentProductId($product->getId())
200
+ ->addCustomOption('bundle_option_ids', serialize(array_map('intval', $optionIds)))
201
+ ->addCustomOption('bundle_selection_attributes', serialize($attributes));
202
+ //}
203
+
204
+ if ($isStrictProcessMode) {
205
+ $_result[0]->setCartQty($qty);
206
+ }
207
+
208
+ $selectionIds[] = $_result[0]->getSelectionId();
209
+ $uniqueKey[] = $_result[0]->getSelectionId();
210
+ $uniqueKey[] = $qty;
211
+ }
212
+ /**
213
+ * "unique" key for bundle selection and add it to selections and bundle for selections
214
+ */
215
+ $uniqueKey = implode('_', $uniqueKey);
216
+ foreach ($result as $item) {
217
+ $item->addCustomOption('bundle_identity', $uniqueKey);
218
+ }
219
+ $product->addCustomOption('bundle_option_ids', serialize(array_map('intval',$optionIds)));
220
+ $product->addCustomOption('bundle_selection_ids', serialize($selectionIds));
221
+
222
+ return $result;
223
+ }
224
+
225
+ return $this->getSpecifyOptionMessage();
226
+ }
227
+ }
app/code/community/KAbel/BundlePlus/etc/config.xml ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * KAbel_BundlePlus
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to a BSD 3-Clause License
9
+ * that is bundled with this package in the file LICENSE_BSD_NU.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://www1.unl.edu/wdn/wiki/Software_License
12
+ *
13
+ * @category KAbel
14
+ * @package KAbel_BundlePlus
15
+ * @copyright Copyright (c) 2012 Regents of the University of Nebraska (http://www.nebraska.edu/)
16
+ * @license http://www1.unl.edu/wdn/wiki/Software_License BSD 3-Clause License
17
+ */
18
+ -->
19
+ <config>
20
+ <modules>
21
+ <KAbel_BundlePlus>
22
+ <version>0.2.1</version>
23
+ </KAbel_BundlePlus>
24
+ </modules>
25
+
26
+ <global>
27
+ <blocks>
28
+ <bundle>
29
+ <rewrite>
30
+ <!-- Unobtrusive Templates -->
31
+ <adminhtml_catalog_product_edit_tab_bundle_option>KAbel_BundlePlus_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle_Option</adminhtml_catalog_product_edit_tab_bundle_option>
32
+ <adminhtml_catalog_product_edit_tab_bundle_option_selection>KAbel_BundlePlus_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle_Option_Selection</adminhtml_catalog_product_edit_tab_bundle_option_selection>
33
+ <catalog_product_view_type_bundle_option_checkbox>KAbel_BundlePlus_Block_Catalog_Product_View_Type_Bundle_Option_Checkbox</catalog_product_view_type_bundle_option_checkbox>
34
+ </rewrite>
35
+ </bundle>
36
+ </blocks>
37
+ <models>
38
+ <bundle>
39
+ <rewrite>
40
+ <!-- User Defined Qty for Checkbox Bundle Option -->
41
+ <product_type>KAbel_BundlePlus_Model_Product_Type</product_type>
42
+ </rewrite>
43
+ </bundle>
44
+ </models>
45
+ </global>
46
+
47
+ <frontend>
48
+ <layout>
49
+ <updates>
50
+ <kabel_bundleplus module="KAbel_BundlePlus">
51
+ <file>kabel_bundleplus.xml</file>
52
+ </kabel_bundleplus>
53
+ </updates>
54
+ </layout>
55
+ </frontend>
56
+ </config>
app/design/adminhtml/default/default/template/kabel/bundleplus/product/edit/bundle/option.phtml ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * KAbel_BundlePlus
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to a BSD 3-Clause License
8
+ * that is bundled with this package in the file LICENSE_BSD_NU.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www1.unl.edu/wdn/wiki/Software_License
11
+ *
12
+ * @category design
13
+ * @package base_default
14
+ * @copyright Copyright (c) 2012 Regents of the University of Nebraska (http://www.nebraska.edu/)
15
+ * @license http://www1.unl.edu/wdn/wiki/Software_License BSD 3-Clause License
16
+ */
17
+ ?>
18
+ <script type="text/javascript">
19
+ optionTemplate = '<div id="<?php echo $this->getFieldId() ?>_{{index}}" class="option-box"> ' +
20
+ '<div class="option-title"> ' +
21
+ '<label for="<?php echo $this->getFieldName() ?>[{{index}}][title]"><?php echo Mage::helper('bundle')->__('Default Title') ?> <span class="required">*</span></label>' +
22
+ <?php if ($this->isDefaultStore()): ?>
23
+ '<input class="input-text required-entry" type="text" name="<?php echo $this->getFieldName() ?>[{{index}}][title]" id="id_<?php echo $this->getFieldName() ?>_{{index}}_title" value="{{title}}">' +
24
+ <?php else: ?>
25
+ '<input class="input-text required-entry" type="text" name="<?php echo $this->getFieldName() ?>[{{index}}][default_title]" id="id_<?php echo $this->getFieldName() ?>_{{index}}_default_title" value="{{default_title}}">' +
26
+ <?php endif; ?>
27
+ '<?php echo $this->jsQuoteEscape($this->getOptionDeleteButtonHtml()) ?>' +
28
+ '</div>' +
29
+ '<table class="option-header" cellpadding="0" cellspacing="0">' +
30
+ '<thead>' +
31
+ '<tr>' +
32
+ <?php if (!$this->isDefaultStore()): ?>
33
+ '<th class="opt-title"><?php echo Mage::helper('bundle')->__('Store View Title') ?> <span class="required">*</span></th>' +
34
+ <?php endif; ?>
35
+ '<th class="opt-type"><?php echo Mage::helper('bundle')->__('Input Type') ?></th>' +
36
+ '<th class="opt-req"><?php echo $this->jsQuoteEscape(Mage::helper('bundle')->__('Is Required')) ?></th>' +
37
+ '<th class="opt-order"><?php echo Mage::helper('bundle')->__('Position') ?></th>' +
38
+ '<th>&nbsp;</th>' +
39
+ '</tr>' +
40
+ '</thead>' +
41
+ '<tbody>' +
42
+ '<tr>' +
43
+ '<input type="hidden" id="<?php echo $this->getFieldId() ?>_id_{{index}}" name="<?php echo $this->getFieldName() ?>[{{index}}][option_id]" value="{{option_id}}">' +
44
+ '<input type="hidden" name="<?php echo $this->getFieldName() ?>[{{index}}][delete]" value="" class="delete">' +
45
+ <?php if (!$this->isDefaultStore()): ?>
46
+ '<td><input class="input-text required-entry" type="text" name="<?php echo $this->getFieldName() ?>[{{index}}][title]" id="id_<?php echo $this->getFieldName() ?>_{{index}}_title_store" value="{{title}}"></td>' +
47
+ <?php endif; ?>
48
+ '<td><?php echo $this->getTypeSelectHtml() ?></td>' +
49
+ '<td><?php echo $this->getRequireSelectHtml() ?></td>' +
50
+ '<td><input class="input-text validate-zero-or-greater" type="text" name="<?php echo $this->getFieldName() ?>[{{index}}][position]" value="{{position}}"></td>' +
51
+ '<td>&nbsp;<?php echo $this->jsQuoteEscape($this->getAddSelectionButtonHtml()) ?></td>' +
52
+ '</tr>' +
53
+ '</tbody>' +
54
+ '</table>' +
55
+ '<div id="<?php echo $this->getFieldId() ?>_search_{{index}}">' +
56
+ '</div>' +
57
+ '</div>';
58
+ </script>
59
+
60
+ <?php echo $this->getSelectionHtml() ?>
61
+
62
+ <script type="text/javascript">
63
+
64
+ function changeInputType(oldObject, oType) {
65
+ var newObject = document.createElement('input');
66
+ newObject.type = oType;
67
+ if(oldObject.size) newObject.size = oldObject.size;
68
+ if(oldObject.value) newObject.value = oldObject.value;
69
+ if(oldObject.name) newObject.name = oldObject.name;
70
+ if(oldObject.id) newObject.id = oldObject.id;
71
+ if(oldObject.onclick) newObject.onclick = oldObject.onclick;
72
+ if(oldObject.className) newObject.className = oldObject.className;
73
+ oldObject.parentNode.replaceChild(newObject,oldObject);
74
+ return newObject;
75
+ }
76
+
77
+ Bundle.Option = Class.create();
78
+ Bundle.Option.prototype = {
79
+ idLabel : '<?php echo $this->getFieldId() ?>',
80
+ top : '',
81
+ templateSyntax : /(^|.|\r|\n)({{(\w+)}})/,
82
+ templateText : '',
83
+ itemsCount : 0,
84
+ initialize : function(template) {
85
+ this.templateText = template;
86
+ this.top = $('product_bundle_container_top');
87
+ },
88
+
89
+ add : function(data) {
90
+ if(!data){
91
+ data = {};
92
+ this.top = $('product_bundle_container_top');
93
+ } else {
94
+ data.title = data.title.replace('"', "&quot;");
95
+ }
96
+
97
+ data.index = this.itemsCount++;
98
+
99
+ this.template = new Template(this.templateText, this.templateSyntax);
100
+
101
+ Element.insert(this.top, {'after':this.template.evaluate(data)});
102
+
103
+ this.top = $(this.idLabel + '_' + data.index);
104
+
105
+ //set selected type
106
+ if (data.type) {
107
+ $A($(this.idLabel + '_'+data.index+'_type').options).each(function(option){
108
+ if (option.value==data.type) option.selected = true;
109
+ });
110
+ }
111
+
112
+ //set selected is_require
113
+ if (data.required) {
114
+ $A($(this.idLabel + '_'+data.index+'_required').options).each(function(option){
115
+ if (option.value==data.required) option.selected = true;
116
+ });
117
+ }
118
+ // rebind change notifications
119
+ varienWindowOnload(true);
120
+
121
+ return data.index;
122
+ },
123
+
124
+ remove : function(event){
125
+ var element = $(Event.findElement(event, 'div')).parentNode;
126
+ if(element){
127
+ Element.select(element, '.delete').each(function(elem){elem.value='1'});
128
+ Element.select(element, ['input', 'select']).each(function(elem){elem.hide(); elem.className = '';});
129
+ Element.hide(element);
130
+ }
131
+ },
132
+
133
+ changeType : function(event) {
134
+ var element = Event.element(event);
135
+ parts = element.id.split('_');
136
+ i = parts[2];
137
+ if (element.value == 'multi' || element.value == 'checkbox') {
138
+ inputs = $A($$('#' + bSelection.idLabel + '_box_' + i + ' tr.selection input.default'));
139
+ inputs.each(
140
+ function(elem){
141
+ //elem.type = "checkbox";
142
+ changeInputType(elem, 'checkbox');
143
+ }
144
+ );
145
+ /**
146
+ * Hide/Show (user defined qty select box)
147
+ */
148
+ inputs = $A($$('#' + bSelection.idLabel + '_box_' + i + ' .qty-box'));
149
+ if (element.value == 'multi') {
150
+ inputs.each(
151
+ function(elem){
152
+ elem.hide();
153
+ }
154
+ );
155
+ } else {
156
+ inputs.each(
157
+ function(elem){
158
+ elem.show();
159
+ }
160
+ );
161
+ }
162
+
163
+ } else {
164
+ inputs = $A($$('#' + bSelection.idLabel + '_box_' + i + ' tr.selection input.default'));
165
+ have = false;
166
+ for (j=0; j< inputs.length; j++) {
167
+ //inputs[j].type = "radio";
168
+ changeInputType(inputs[j], 'radio');
169
+ if (inputs[j].checked && have) {
170
+ inputs[j].checked = false;
171
+ } else {
172
+ have = true;
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Show user defined select box
178
+ */
179
+ inputs = $A($$('#' + bSelection.idLabel + '_box_' + i + ' .qty-box'));
180
+ inputs.each(
181
+ function(elem){
182
+ elem.show();
183
+ }
184
+ );
185
+ }
186
+ },
187
+
188
+ priceTypeFixed : function() {
189
+ inputs = $A($$('.price-type-box'));
190
+ inputs.each(
191
+ function(elem){
192
+ elem.show();
193
+ }
194
+ );
195
+ },
196
+
197
+ priceTypeDynamic : function() {
198
+ inputs = $A($$('.price-type-box'));
199
+ inputs.each(
200
+ function(elem){
201
+ elem.hide();
202
+ }
203
+ );
204
+ }
205
+ }
206
+
207
+ var optionIndex = 0;
208
+ bOption = new Bundle.Option(optionTemplate);
209
+ //adding data to templates
210
+ <?php foreach ($this->getOptions() as $_option): ?>
211
+ optionIndex = bOption.add(<?php echo $_option->toJson() ?>);
212
+ <?php if ($_option->getSelections()):?>
213
+ <?php foreach ($_option->getSelections() as $_selection): ?>
214
+ <?php $_selection->setName($this->escapeHtml($_selection->getName())); ?>
215
+ bSelection.addRow(optionIndex, <?php echo $_selection->toJson() ?>);
216
+ <?php endforeach; ?>
217
+ <?php endif; ?>
218
+ <?php endforeach; ?>
219
+ /**
220
+ * Adding event on price type select box of product to hide or show prices for selections
221
+ */
222
+ function togglePriceType() {
223
+ if ($('price_type').value == '1') {
224
+ bOption.priceTypeFixed();
225
+ } else {
226
+ bOption.priceTypeDynamic();
227
+ }
228
+ }
229
+
230
+ togglePriceType();
231
+
232
+ Event.observe('price_type', 'change', togglePriceType);
233
+
234
+ </script>
app/design/adminhtml/default/default/template/kabel/bundleplus/product/edit/bundle/option/selection.phtml ADDED
@@ -0,0 +1,343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * KAbel_BundlePlus
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to a BSD 3-Clause License
8
+ * that is bundled with this package in the file LICENSE_BSD_NU.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www1.unl.edu/wdn/wiki/Software_License
11
+ *
12
+ * @category design
13
+ * @package base_default
14
+ * @copyright Copyright (c) 2012 Regents of the University of Nebraska (http://www.nebraska.edu/)
15
+ * @license http://www1.unl.edu/wdn/wiki/Software_License BSD 3-Clause License
16
+ */
17
+ ?>
18
+ <script type="text/javascript">
19
+ //<![CDATA[
20
+
21
+ var bundleTemplateBox = '<table class="border" cellpadding="0" cellspacing="0">' +
22
+ ' <thead>' +
23
+ ' <tr class="headings">' +
24
+ ' <th><?php echo Mage::helper('catalog')->__('Name') ?></th>' +
25
+ <?php if ($this->getCanReadPrice() !== false) : ?>
26
+ ' <th class="type-price price-type-box"><?php echo Mage::helper('catalog')->__('Price') ?></th>' +
27
+ ' <th class="type-type price-type-box"><?php echo Mage::helper('bundle')->__('Price Type') ?></th>' +
28
+ <?php endif; ?>
29
+ ' <th class="type-price"><?php echo Mage::helper('bundle')->__('Default Qty') ?></th>' +
30
+ ' <th class="type-uqty qty-box"><?php echo$this->jsQuoteEscape(Mage::helper('bundle')->__('User Defined Qty')) ?></th>' +
31
+ ' <th class="type-order"><?php echo Mage::helper('bundle')->__('Position') ?></th>' +
32
+ ' <th style="width:1px"><?php echo Mage::helper('bundle')->__('Default') ?></th>' +
33
+ ' <th class="last">&nbsp;</th>' +
34
+ ' </tr>' +
35
+ ' </thead> ' +
36
+ ' <tbody>' +
37
+ ' </tbody>' +
38
+ '</table>';
39
+
40
+ var bundleTemplateRow ='<td>' +
41
+ ' <input type="hidden" id="<?php echo $this->getFieldId() ?>_id_{{index}}" name="<?php echo $this->getFieldName() ?>[{{parentIndex}}][{{index}}][selection_id]" value="{{selection_id}}">' +
42
+ ' <input type="hidden" name="<?php echo $this->getFieldName() ?>[{{parentIndex}}][{{index}}][option_id]" value="{{option_id}}">' +
43
+ ' <input type="hidden" class="product" name="<?php echo $this->getFieldName() ?>[{{parentIndex}}][{{index}}][product_id]" value="{{product_id}}">' +
44
+ ' <input type="hidden" name="<?php echo $this->getFieldName() ?>[{{parentIndex}}][{{index}}][delete]" value="" class="delete">' +
45
+ ' {{name}}<br />' +
46
+ ' <div class="nobr">' +
47
+ ' <strong><?php echo $this->helper('sales')->__('SKU') ?>:</strong> {{sku}}' +
48
+ ' </div>' +
49
+ '</td>' +
50
+ <?php if ($this->getCanReadPrice() !== false) : ?>
51
+ '<td class="price-type-box"><input id="<?php echo $this->getFieldId() ?>_{{index}}_price_value" class="input-text required-entry validate-zero-or-greater" type="text" name="<?php echo $this->getFieldName() ?>[{{parentIndex}}][{{index}}][selection_price_value]" value="{{selection_price_value}}"<?php if($this->getCanEditPrice() === false) : ?> disabled="disabled"<?php endif; ?>></td>' +
52
+ '<td class="price-type-box"><?php echo $this->getPriceTypeSelectHtml() ?><div><?php echo $this->getCheckboxScopeHtml() ?></div></td>' +
53
+ <?php else : ?>
54
+ '<input type="hidden" id="<?php echo $this->getFieldId(); ?>_{{index}}_price_value" name="<?php echo $this->getFieldName(); ?>[{{parentIndex}}][{{index}}][selection_price_value]" value="0" />' +
55
+ '<input type="hidden" id="<?php echo $this->getFieldId(); ?>_{{index}}_price_type" name="<?php echo $this->getFieldName(); ?>[{{parentIndex}}][{{index}}][selection_price_type]" value="0" />' +
56
+ <?php if ($this->isUsedWebsitePrice()): ?>
57
+ '<input type="hidden" id="<?php echo $this->getFieldId(); ?>_{{index}}_price_scope" name="<?php echo $this->getFieldName(); ?>[{{parentIndex}}][{{index}}][default_price_scope]" value="1" />' +
58
+ <?php endif; ?>
59
+ <?php endif; ?>
60
+ '<td><input class="input-text required-entry validate-zero-or-greater" type="text" name="<?php echo $this->getFieldName() ?>[{{parentIndex}}][{{index}}][selection_qty]" value="{{selection_qty}}"></td>' +
61
+ '<td class="qty-box"><?php echo $this->getQtyTypeSelectHtml() ?></td>' +
62
+ '<td><input class="input-text required-entry validate-zero-or-greater" type="text" name="<?php echo $this->getFieldName() ?>[{{parentIndex}}][{{index}}][position]" value="{{position}}"></td>' +
63
+ '<td class="a-center"><input onclick="bSelection.checkGroup(event)" type="{{option_type}}" class="default" name="<?php echo $this->getFieldName() ?>[{{parentIndex}}][{{index}}][is_default]" value="1" {{checked}}></td>' +
64
+ '<td class="last"><span title="Delete Row"><?php echo $this->getSelectionDeleteButtonHtml() ?></span></td>';
65
+
66
+ Bundle.Selection = Class.create();
67
+ Bundle.Selection.prototype = {
68
+ idLabel : '<?php echo $this->getFieldId() ?>',
69
+ scopePrice : <?php echo (int)$this->isUsedWebsitePrice() ?>,
70
+ templateSyntax : /(^|.|\r|\n)({{(\w+)}})/,
71
+ templateBox : '',
72
+ templateRow : '',
73
+ itemsCount : 0,
74
+ row : null,
75
+ gridSelection : new Hash(),
76
+
77
+ initialize : function() {
78
+ this.templateBox = '<div class="grid tier form-list" id="' + this.idLabel + '_box_{{parentIndex}}">' + bundleTemplateBox + '</div>';
79
+
80
+ this.templateRow = '<tr class="selection" id="' + this.idLabel + '_row_{{index}}">' + bundleTemplateRow + '</tr>';
81
+ },
82
+
83
+ showSearch : function(event) {
84
+ var element = Event.findElement(event, 'div');
85
+ var parts = element.id.split('_');
86
+
87
+ var products = new Array();
88
+
89
+ var inputs = $A($$('#' + element.id + ' tr.selection input.product'));
90
+ for (i=0; i<inputs.length; i++) {
91
+ products.push(inputs[i].value);
92
+ }
93
+
94
+ this.gridSelection.set(parts[2], $H({}));
95
+
96
+ new Ajax.Updater(bOption.idLabel + '_search_' + parts[2], '<?php echo $this->getSelectionSearchUrl() ?>', {
97
+ method: 'post',
98
+ parameters : {'index' : parts[2], 'products[]' : products, 'form_key': FORM_KEY},
99
+ evalScripts : true
100
+ });
101
+
102
+ if (Event.element(event).tagName.toLowerCase() != 'button') {
103
+ var button = Event.element(event).up('button');
104
+ } else {
105
+ var button = Event.element(event);
106
+ }
107
+ button.hide();
108
+ },
109
+
110
+ addRow : function (parentIndex, data) {
111
+ var box = null;
112
+ if (!(box = $(this.idLabel + '_box_' + parentIndex))) {
113
+ this.addBox(parentIndex);
114
+ box = $(this.idLabel + '_box_' + parentIndex);
115
+ } else {
116
+ box.show();
117
+ }
118
+
119
+ var option_type = $(bOption.idLabel + '_' + parentIndex + '_type');
120
+
121
+ if(!data){
122
+ var data = {};
123
+ }
124
+
125
+ if (data.can_read_price != undefined && !data.can_read_price) {
126
+ data.selection_price_value = '';
127
+ } else {
128
+ data.selection_price_value = Number(data.selection_price_value).toFixed(2);
129
+ }
130
+
131
+ data.index = this.itemsCount++;
132
+ data.parentIndex = parentIndex;
133
+
134
+ if (option_type.value == 'multi' || option_type.value == 'checkbox') {
135
+ data.option_type = 'checkbox';
136
+ } else {
137
+ data.option_type = 'radio';
138
+ }
139
+
140
+ if (data.is_default == 1) {
141
+ data.checked = 'checked="checked"';
142
+ }
143
+
144
+ this.template = new Template(this.templateRow, this.templateSyntax);
145
+ var tbody = $$('#' + this.idLabel + '_box_' + parentIndex + ' tbody');
146
+
147
+ Element.insert(tbody[0], {'bottom':this.template.evaluate(data)});
148
+
149
+ if (data.selection_price_type) {
150
+ $A($(this.idLabel + '_'+data.index+'_price_type').options).each(function(option){
151
+ if (option.value==data.selection_price_type) option.selected = true;
152
+ });
153
+ }
154
+
155
+ if (data.selection_price_type) {
156
+ $A($(this.idLabel + '_'+data.index+'_can_change_qty').options).each(function(option){
157
+ if (option.value==data.selection_can_change_qty) option.selected = true;
158
+ });
159
+ }
160
+
161
+ var checkbox = $(this.idLabel + '_'+data.index+'_price_scope');
162
+ if (checkbox && this.scopePrice) {
163
+ if (data.price_scope === undefined) {
164
+ checkbox.up().hide();
165
+ } else if(!data.price_scope) {
166
+ checkbox.checked = true;
167
+ this.addScope(null, checkbox);
168
+ }
169
+ }
170
+
171
+ this.bindScopeCheckbox();
172
+
173
+ if (option_type.value == 'multi') {
174
+ /**
175
+ * Hide not needed elements (user defined qty select box)
176
+ */
177
+ inputs = $A($$('#' + this.idLabel + '_box_' + data.parentIndex + ' .qty-box'));
178
+ inputs.each(
179
+ function(elem){
180
+ elem.hide();
181
+ }
182
+ );
183
+ }
184
+
185
+ if (!$('price_type') || $('price_type').value != '1') {
186
+ /**
187
+ * Hide not needed elements (price type select and price input)
188
+ */
189
+ inputs = $A($$('#' + this.idLabel + '_box_' + data.parentIndex + ' .price-type-box'));
190
+ inputs.each(
191
+ function(elem){
192
+ elem.hide();
193
+ }
194
+ );
195
+ }
196
+ },
197
+
198
+ bindScopeCheckbox : function(){
199
+ var checkboxes = $$('.bundle-option-price-scope-checkbox');
200
+ for (var i=0;i<checkboxes.length;i++) {
201
+ if (!$(checkboxes[i]).binded) {
202
+ $(checkboxes[i]).binded = true;
203
+ Event.observe(checkboxes[i], 'click', this.addScope.bind(this));
204
+ }
205
+ }
206
+ },
207
+
208
+ addScope : function(event, element){
209
+ if (element == undefined) {
210
+ element = $(Event.element(event));
211
+ }
212
+ var priceValue = $(element.id.sub('scope', 'value'));
213
+ var priceType = $(element.id.sub('scope', 'type'));
214
+
215
+ if (element.checked) {
216
+ priceValue.disable();
217
+ priceType.disable();
218
+ } else {
219
+ priceValue.enable();
220
+ priceType.enable();
221
+ }
222
+ },
223
+
224
+ addBox : function (parentIndex) {
225
+ var div = $(bOption.idLabel + '_' + parentIndex)
226
+ this.template = new Template(this.templateBox, this.templateSyntax);
227
+ var data = {'parentIndex' : parentIndex};
228
+ Element.insert(div, {'bottom':this.template.evaluate(data)});
229
+ },
230
+
231
+ remove : function(event) {
232
+ var element = Event.findElement(event, 'tr');
233
+ var container = Event.findElement(event, 'div');
234
+
235
+ if (element) {
236
+ Element.select(element, '.delete').each(function(elem){elem.value='1'});
237
+ Element.select(element, ['input', 'select']).each(function(elem){elem.hide()});
238
+ Element.removeClassName(element, 'selection');
239
+ Element.hide(element);
240
+
241
+ if (container) {
242
+ if ($$('#' + container.id + ' tr.selection')) {
243
+ if (!$$('#' + container.id + ' tr.selection').length) {
244
+ container.hide();
245
+ }
246
+ }
247
+ }
248
+ }
249
+ },
250
+
251
+ checkGroup : function(event) {
252
+ var element = Event.element(event);
253
+ if (element.type == 'radio') {
254
+ var box = element.up('div');
255
+
256
+ var inputs = $$('div#' + box.id + ' input.default');
257
+ if (inputs) {
258
+ for (i=0; i< inputs.length; i++) {
259
+ if (inputs[i].name != element.name) {
260
+ inputs[i].checked = false;
261
+ }
262
+ }
263
+ }
264
+ }
265
+ },
266
+
267
+ productGridAddSelected : function(event) {
268
+ var element = Event.findElement(event, 'button');
269
+ var parts = element.id.split('_');
270
+
271
+ $(bOption.idLabel + '_search_' + parts[2]).innerHTML = '';
272
+ $(bOption.idLabel + '_' + parts[2] + '_add_button').show();
273
+
274
+ this.gridSelection.get(parts[2]).each(
275
+ function(pair) {
276
+ var qty = pair.value.get('qty');
277
+ var data = {
278
+ 'name' : pair.value.get('name'),
279
+ 'selection_price_value' : 0,
280
+ 'selection_qty' : (qty == '' ? 1 : qty),
281
+ 'sku' : pair.value.get('sku'),
282
+ 'position' : 0,
283
+ 'product_id' : pair.key,
284
+ 'option_id' : $(bOption.idLabel + '_id_' + parts[2]).value
285
+ };
286
+ bSelection.addRow(parts[2], data);
287
+ }
288
+ );
289
+ },
290
+
291
+ productGridRowInit : function(grid, row){
292
+ var checkbox = $(row).getElementsByClassName('checkbox')[0];
293
+ var inputs = $(row).getElementsByClassName('input-text');
294
+ for (var i = 0; i < inputs.length; i++) {
295
+ inputs[i].checkbox = checkbox;
296
+ Event.observe(inputs[i], 'keyup', this.productGridRowInputChange.bind(this));
297
+ Event.observe(inputs[i], 'change', this.productGridRowInputChange.bind(this));
298
+ }
299
+ },
300
+
301
+ productGridCheckboxCheck : function(grid, element, checked) {
302
+ var id = element.up('table').id.split('_')[4];
303
+ if (element.value > 0) {
304
+ if (element.checked) {
305
+ var tr = element.parentNode.parentNode;
306
+ if (!this.gridSelection.get(id)) {
307
+ this.gridSelection.set(id, new Hash());
308
+ }
309
+ this.gridSelection.get(id).set(element.value, $H({}));
310
+ this.gridSelection.get(id).get(element.value).set('name', tr.select('td.name')[0].innerHTML);
311
+ this.gridSelection.get(id).get(element.value).set('qty', tr.select('input.qty')[0].value);
312
+ this.gridSelection.get(id).get(element.value).set('sku', tr.select('td.sku')[0].innerHTML);
313
+ } else {
314
+ this.gridSelection.get(id).unset(element.value);
315
+ }
316
+ }
317
+ },
318
+
319
+ productGridRowClick : function(grid, event) {
320
+ var trElement = Event.findElement(event, 'tr');
321
+ var isInput = Event.element(event).tagName == 'INPUT';
322
+ if (trElement) {
323
+ var checkbox = Element.select(trElement, 'input');
324
+ if (checkbox[0]) {
325
+ var checked = isInput ? checkbox[0].checked : !checkbox[0].checked;
326
+ grid.setCheckboxChecked(checkbox[0], checked);
327
+ }
328
+ }
329
+ },
330
+
331
+ productGridRowInputChange : function(event) {
332
+ var element = Event.element(event);
333
+ if (!element.checkbox.checked) {
334
+ return;
335
+ }
336
+ var id = element.up('table').id.split('_')[4];
337
+ this.gridSelection.get(id).get(element.checkbox.value).set('qty', element.value);
338
+ }
339
+ }
340
+
341
+ bSelection = new Bundle.Selection();
342
+ //]]>
343
+ </script>
app/design/frontend/base/default/layout/kabel_bundleplus.xml ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * KAbel_BundlePlus
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to a BSD 3-Clause License
9
+ * that is bundled with this package in the file LICENSE_BSD_NU.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://www1.unl.edu/wdn/wiki/Software_License
12
+ *
13
+ * @category design
14
+ * @package base_default
15
+ * @copyright Copyright (c) 2012 Regents of the University of Nebraska (http://www.nebraska.edu/)
16
+ * @license http://www1.unl.edu/wdn/wiki/Software_License BSD 3-Clause License
17
+ */
18
+
19
+ -->
20
+ <layout version="0.1.0">
21
+
22
+ <PRODUCT_TYPE_bundle>
23
+ <!-- remove the original bundle.js and replace by the KAbel version -->
24
+ <!-- to not overwrite the original version, put yours into a self-defined folder -->
25
+ <reference name="head">
26
+ <action method="removeItem">
27
+ <type>skin_js</type>
28
+ <name>js/bundle.js</name>
29
+ </action>
30
+ <action method="addItem">
31
+ <type>skin_js</type>
32
+ <name>js/kabel/bundleplus/bundle.js</name>
33
+ </action>
34
+ </reference>
35
+ </PRODUCT_TYPE_bundle>
36
+
37
+ <!-- to add an extra css file to every page -->
38
+ <default>
39
+ <reference name="head">
40
+ <action method="addItem"><type>skin_css</type><file>css/kabel/bundleplus/extra.css</file></action>
41
+ </reference>
42
+ </default>
43
+
44
+ </layout>
app/design/frontend/base/default/template/kabel/bundleplus/catalog/product/view/type/bundle/option/checkbox.phtml ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * KAbel_BundlePlus
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to a BSD 3-Clause License
8
+ * that is bundled with this package in the file LICENSE_BSD_NU.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://www1.unl.edu/wdn/wiki/Software_License
11
+ *
12
+ * @category design
13
+ * @package base_default
14
+ * @copyright Copyright (c) 2012 Regents of the University of Nebraska (http://www.nebraska.edu/)
15
+ * @license http://www1.unl.edu/wdn/wiki/Software_License BSD 3-Clause License
16
+ */
17
+ ?>
18
+
19
+ <?php /* @var $this Mage_Bundle_Block_Catalog_Product_View_Type_Bundle_Option_Checkbox */ ?>
20
+ <?php $_option = $this->getOption() ?>
21
+ <?php $_selections = $_option->getSelections() ?>
22
+ <dt><label<?php if ($_option->getRequired()) echo ' class="required"' ?>><?php echo $this->htmlEscape($_option->getTitle()) ?><?php if ($_option->getRequired()) echo '<em>*</em>' ?></label></dt>
23
+ <dd<?php if ($_option->decoratedIsLast){?> class="last"<?php }?>>
24
+ <div class="input-box">
25
+ <?php if (count($_selections) == 1 && $_option->getRequired()): ?>
26
+ <?php echo $this->getSelectionQtyTitlePrice($_selections[0]) ?>
27
+ <input type="hidden" name="bundle_option[<?php echo $_option->getId() ?>]" value="<?php echo $_selections[0]->getSelectionId() ?>"/>
28
+ <?php else:?>
29
+ <ul class="options-list">
30
+ <?php foreach($_selections as $_selection): ?>
31
+ <?php /* @var $_selection Mage_Bundle_Model_Selection */ ?>
32
+ <li>
33
+ <?php $_isSelected = $this->_isSelected($_selection); ?>
34
+ <input onclick="bundle.changeSelection(this)" class="change-container-classname checkbox bundle-option-<?php echo $_option->getId() ?> <?php if ($_option->getRequired()) echo 'validate-one-required-by-name' ?>" id="bundle-option-<?php echo $_option->getId() ?>-<?php echo $_selection->getSelectionId() ?>" type="checkbox" name="bundle_option[<?php echo $_option->getId() ?>][]"<?php if ($_isSelected) echo ' checked="checked"' ?><?php if (!$_selection->isSaleable()) echo ' disabled="disabled"' ?> value="<?php echo $_selection->getSelectionId() ?>"/>
35
+
36
+ <?php if ($_selection->getSelectionCanChangeQty()): ?>
37
+ <span class="qty-holder"><label for="bundle-option-<?php echo $_option->getId() ?>-<?php echo $_selection->getSelectionId() ?>-qty-input"><?php echo $this->__('Qty:') ?>&nbsp;</label>
38
+ <input onkeyup="bundle.changeOptionQty(this, event)" onblur="bundle.changeOptionQty(this, event)" class="input-text qty<?php if (!$_isSelected) echo ' qty-disabled' ?>" id="bundle-option-<?php echo $_option->getId() ?>-<?php echo $_selection->getSelectionId() ?>-qty-input" type="text" name="bundle_option_qty[<?php echo $_option->getId() ?>][<?php echo $_selection->getSelectionId() ?>]"<?php if (!$_isSelected) echo ' disabled="disabled"' ?> value="<?php echo $this->_getSelectionQty($_selection)*1 ?>" /></span>
39
+ <?php else: ?>
40
+ <span class="qty-holder"><label><?php echo $this->__('Qty:') ?>&nbsp;</label><?php echo $_selection->getSelectionQty()*1 ?></span>
41
+ <?php endif; ?>
42
+ <span class="label"><label for="bundle-option-<?php echo $_option->getId() ?>-<?php echo $_selection->getSelectionId() ?>"><?php echo $this->getSelectionTitlePrice($_selection) ?></label></span>
43
+
44
+ <?php if($_option->getRequired()): ?>
45
+ <?php echo $this->setValidationContainer('bundle-option-'.$_option->getId().'-'.$_selection->getSelectionId(), 'bundle-option-'.$_option->getId().'-container') ?>
46
+ <?php endif; ?>
47
+ </li>
48
+ <?php endforeach; ?>
49
+ </ul>
50
+ <div id="bundle-option-<?php echo $_option->getId() ?>-container"></div>
51
+ <?php endif; ?>
52
+ </div>
53
+ </dd>
app/etc/modules/KAbel_BundlePlus.xml ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * KAbel_BundlePlus
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to a BSD 3-Clause License
9
+ * that is bundled with this package in the file LICENSE_BSD_NU.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://www1.unl.edu/wdn/wiki/Software_License
12
+ *
13
+ * @category KAbel
14
+ * @package KAbel_BundlePlus
15
+ * @copyright Copyright (c) 2012 Regents of the University of Nebraska (http://www.nebraska.edu/)
16
+ * @license http://www1.unl.edu/wdn/wiki/Software_License BSD 3-Clause License
17
+ */
18
+ -->
19
+ <config>
20
+ <modules>
21
+ <KAbel_BundlePlus>
22
+ <active>true</active>
23
+ <codePool>community</codePool>
24
+ <depends>
25
+ <Mage_Bundle />
26
+ </depends>
27
+ </KAbel_BundlePlus>
28
+ </modules>
29
+ </config>
package.xml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>KAbel_BundlePlus</name>
4
+ <version>0.2.1</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://www1.unl.edu/wdn/wiki/Software_License">BSD-3-Clause</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Extends the Bundle interfaces for checkbox selections to allow each selection to have a user-defined qty.</summary>
10
+ <description>This is the first release to the Magento Connect community.&#xD;
11
+ &#xD;
12
+ This extension was born from a discussion started at http://www.magentocommerce.com/boards/viewthread/33997/&#xD;
13
+ &#xD;
14
+ The base Magento version that is supported is 1.7.</description>
15
+ <notes>Stability release for the Magento CE 1.7 branch.</notes>
16
+ <authors><author><name>Kevin Abel</name><user>kabel</user><email>kabel2@unl.edu</email></author></authors>
17
+ <date>2012-08-01</date>
18
+ <time>22:38:11</time>
19
+ <contents><target name="magecommunity"><dir name="KAbel"><dir name="BundlePlus"><dir name="Block"><dir name="Adminhtml"><dir name="Catalog"><dir name="Product"><dir name="Edit"><dir name="Tab"><dir name="Bundle"><dir name="Option"><file name="Selection.php" hash="fcab2a621c82cd753f8ae6016ce8288b"/></dir><file name="Option.php" hash="8fff7c3e9f1bab22afb90a40789d87f8"/></dir></dir></dir></dir></dir></dir><dir name="Catalog"><dir name="Product"><dir name="View"><dir name="Type"><dir name="Bundle"><dir name="Option"><file name="Checkbox.php" hash="6ef19ad96ba19ca4e14327bc3f92f3ad"/></dir></dir></dir></dir></dir></dir></dir><dir name="Model"><dir name="Product"><file name="Type.php" hash="87307e188e8681c248558d1063870e5d"/></dir></dir><dir name="etc"><file name="config.xml" hash="81e263cc37f5f9c8e095f742a1e0600a"/></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="kabel"><dir name="bundleplus"><dir name="product"><dir name="edit"><dir name="bundle"><dir name="option"><file name="selection.phtml" hash="dae1c30d37a55c69b2f7c6115888aba4"/></dir><file name="option.phtml" hash="fb061926db275a32264317f93c3fd9c2"/></dir></dir></dir></dir></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="kabel_bundleplus.xml" hash="eb12c302b7f8beb35803de9747bdf432"/></dir><dir name="template"><dir name="kabel"><dir name="bundleplus"><dir name="catalog"><dir name="product"><dir name="view"><dir name="type"><dir name="bundle"><dir name="option"><file name="checkbox.phtml" hash="a81dba081733e27124b4cf03baae04ad"/></dir></dir></dir></dir></dir></dir></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="KAbel_BundlePlus.xml" hash="79958a8fedb36c001fed6a7885046de5"/></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="css"><dir name="kabel"><dir name="bundleplus"><file name="extra.css" hash="50d18ae01bf8157fa49a5b1144a98c67"/></dir></dir></dir><dir name="js"><dir name="kabel"><dir name="bundleplus"><file name="bundle.js" hash="3dc9c6ea1d9287c5592beddd0b031115"/></dir></dir></dir></dir></dir></dir></target><target name="mage"><dir name="."><file name="LICENSE_BSD_NU.txt" hash="1a1f681da978387de9a48b0604321909"/></dir></target></contents>
20
+ <compatible/>
21
+ <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php><package><name>Mage_Core_Modules</name><channel>community</channel><min>1.7</min><max></max></package></required></dependencies>
22
+ </package>
skin/frontend/base/default/css/kabel/bundleplus/extra.css ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * KAbel_BundlePlus
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to a BSD 3-Clause License
7
+ * that is bundled with this package in the file LICENSE_BSD_NU.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://www1.unl.edu/wdn/wiki/Software_License
10
+ *
11
+ * @category design
12
+ * @package base_default
13
+ * @copyright Copyright (c) 2012 Regents of the University of Nebraska (http://www.nebraska.edu/)
14
+ * @license http://www1.unl.edu/wdn/wiki/Software_License BSD 3-Clause License
15
+ */
16
+
17
+ .product-options .options-list input.checkbox + .qty-holder { padding:0; }
18
+ .product-options .options-list input.checkbox + .qty-holder .qty-disabled { background:#eee; color:#444; }
skin/frontend/base/default/js/kabel/bundleplus/bundle.js ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * KAbel_BundlePlus
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to a BSD 3-Clause License
7
+ * that is bundled with this package in the file LICENSE_BSD_NU.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://www1.unl.edu/wdn/wiki/Software_License
10
+ *
11
+ * @category design
12
+ * @package base_default
13
+ * @copyright Copyright (c) 2012 Regents of the University of Nebraska (http://www.nebraska.edu/)
14
+ * @license http://www1.unl.edu/wdn/wiki/Software_License BSD 3-Clause License
15
+ */
16
+ if(typeof Product=='undefined') {
17
+ var Product = {};
18
+ }
19
+ /**************************** BUNDLE PRODUCT **************************/
20
+ Product.Bundle = Class.create();
21
+ Product.Bundle.prototype = {
22
+ initialize: function(config){
23
+ this.config = config;
24
+
25
+ // Set preconfigured values for correct price base calculation
26
+ if (config.defaultValues) {
27
+ for (var option in config.defaultValues) {
28
+ if (this.config['options'][option].isMulti) {
29
+ var selected = new Array();
30
+ for (var i = 0; i < config.defaultValues[option].length; i++) {
31
+ selected.push(config.defaultValues[option][i]);
32
+ }
33
+ this.config.selected[option] = selected;
34
+ } else {
35
+ this.config.selected[option] = new Array(config.defaultValues[option] + "");
36
+ }
37
+ }
38
+ }
39
+
40
+ this.reloadPrice();
41
+ },
42
+ changeSelection: function(selection){
43
+ var parts = selection.id.split('-');
44
+ if (this.config['options'][parts[2]].isMulti) {
45
+ selected = new Array();
46
+ if (selection.tagName == 'SELECT') {
47
+ for (var i = 0; i < selection.options.length; i++) {
48
+ if (selection.options[i].selected && selection.options[i].value != '') {
49
+ selected.push(selection.options[i].value);
50
+ }
51
+ }
52
+ } else if (selection.tagName == 'INPUT') {
53
+ selector = parts[0]+'-'+parts[1]+'-'+parts[2];
54
+ selections = $$('.'+selector);
55
+ for (var i = 0; i < selections.length; i++) {
56
+ if (selections[i].checked && selections[i].value != '') {
57
+ selected.push(selections[i].value);
58
+ }
59
+ }
60
+ if (selection.value != '') {
61
+ if (selection.checked && this.config.options[parts[2]].selections[selection.value].customQty == 1) {
62
+ this.showQtyInput(parts[2] + '-' + selection.value, this.config.options[parts[2]].selections[selection.value].qty, true);
63
+ } else if (this.config.options[parts[2]].selections[selection.value].customQty == 1) {
64
+ this.showQtyInput(parts[2] + '-' + selection.value, '0', false);
65
+ }
66
+ }
67
+ }
68
+ this.config.selected[parts[2]] = selected;
69
+ } else {
70
+ if (selection.value != '') {
71
+ this.config.selected[parts[2]] = new Array(selection.value);
72
+ } else {
73
+ this.config.selected[parts[2]] = new Array();
74
+ }
75
+ this.populateQty(parts[2], selection.value);
76
+ }
77
+ this.reloadPrice();
78
+ },
79
+
80
+ reloadPrice: function() {
81
+ var calculatedPrice = 0;
82
+ var dispositionPrice = 0;
83
+ var includeTaxPrice = 0;
84
+ for (var option in this.config.selected) {
85
+ if (this.config.options[option]) {
86
+ for (var i=0; i < this.config.selected[option].length; i++) {
87
+ var prices = this.selectionPrice(option, this.config.selected[option][i]);
88
+ calculatedPrice += Number(prices[0]);
89
+ dispositionPrice += Number(prices[1]);
90
+ includeTaxPrice += Number(prices[2]);
91
+ }
92
+ }
93
+ }
94
+
95
+ var event = $(document).fire('bundle:reload-price', {
96
+ price: calculatedPrice,
97
+ priceInclTax: includeTaxPrice,
98
+ dispositionPrice: dispositionPrice,
99
+ bundle: this
100
+ });
101
+ if (!event.noReloadPrice) {
102
+ optionsPrice.specialTaxPrice = 'true';
103
+ optionsPrice.changePrice('bundle', calculatedPrice);
104
+ optionsPrice.changePrice('nontaxable', dispositionPrice);
105
+ optionsPrice.changePrice('priceInclTax', includeTaxPrice);
106
+ optionsPrice.reload();
107
+ }
108
+
109
+ return calculatedPrice;
110
+ },
111
+
112
+ selectionPrice: function(optionId, selectionId) {
113
+ if (selectionId == '' || selectionId == 'none') {
114
+ return 0;
115
+ }
116
+ var qty = null;
117
+ if (this.config.options[optionId].selections[selectionId].customQty == 1) {
118
+ if (this.config['options'][optionId].isMulti) {
119
+ if ($('bundle-option-' + optionId + '-' + selectionId + '-qty-input')) {
120
+ qty = $('bundle-option-' + optionId + '-' + selectionId + '-qty-input').value;
121
+ } else {
122
+ qty = 1;
123
+ }
124
+ } else {
125
+ if ($('bundle-option-' + optionId + '-qty-input')) {
126
+ qty = $('bundle-option-' + optionId + '-qty-input').value;
127
+ } else {
128
+ qty = 1;
129
+ }
130
+ }
131
+ } else {
132
+ qty = this.config.options[optionId].selections[selectionId].qty;
133
+ }
134
+
135
+ if (this.config.priceType == '0') {
136
+ price = this.config.options[optionId].selections[selectionId].price;
137
+ tierPrice = this.config.options[optionId].selections[selectionId].tierPrice;
138
+
139
+ for (var i=0; i < tierPrice.length; i++) {
140
+ if (Number(tierPrice[i].price_qty) <= qty && Number(tierPrice[i].price) <= price) {
141
+ price = tierPrice[i].price;
142
+ }
143
+ }
144
+ } else {
145
+ selection = this.config.options[optionId].selections[selectionId];
146
+ if (selection.priceType == '0') {
147
+ price = selection.priceValue;
148
+ } else {
149
+ price = (this.config.basePrice*selection.priceValue)/100;
150
+ }
151
+ }
152
+ //price += this.config.options[optionId].selections[selectionId].plusDisposition;
153
+ //price -= this.config.options[optionId].selections[selectionId].minusDisposition;
154
+ //return price*qty;
155
+ var disposition = this.config.options[optionId].selections[selectionId].plusDisposition +
156
+ this.config.options[optionId].selections[selectionId].minusDisposition;
157
+
158
+ if (this.config.specialPrice) {
159
+ newPrice = (price*this.config.specialPrice)/100;
160
+ newPrice = (Math.round(newPrice*100)/100).toString();
161
+ price = Math.min(newPrice, price);
162
+ }
163
+
164
+ selection = this.config.options[optionId].selections[selectionId];
165
+ if (selection.priceInclTax !== undefined) {
166
+ priceInclTax = selection.priceInclTax;
167
+ price = selection.priceExclTax !== undefined ? selection.priceExclTax : selection.price;
168
+ } else {
169
+ priceInclTax = price;
170
+ }
171
+
172
+ var result = new Array(price*qty, disposition*qty, priceInclTax*qty);
173
+ return result;
174
+ },
175
+
176
+ populateQty: function(optionId, selectionId){
177
+ if (selectionId == '' || selectionId == 'none') {
178
+ this.showQtyInput(optionId, '0', false);
179
+ return;
180
+ }
181
+ if (this.config.options[optionId].selections[selectionId].customQty == 1) {
182
+ this.showQtyInput(optionId, this.config.options[optionId].selections[selectionId].qty, true);
183
+ } else {
184
+ this.showQtyInput(optionId, this.config.options[optionId].selections[selectionId].qty, false);
185
+ }
186
+ },
187
+
188
+ showQtyInput: function(optionId, value, canEdit) {
189
+ elem = $('bundle-option-' + optionId + '-qty-input');
190
+ elem.value = value;
191
+ elem.disabled = !canEdit;
192
+ if (canEdit) {
193
+ elem.removeClassName('qty-disabled');
194
+ } else {
195
+ elem.addClassName('qty-disabled');
196
+ }
197
+ },
198
+
199
+ changeOptionQty: function (element, event) {
200
+ var checkQty = true;
201
+ if (typeof(event) != 'undefined') {
202
+ if (event.keyCode == 8 || event.keyCode == 46) {
203
+ checkQty = false;
204
+ }
205
+ }
206
+ if (checkQty && (Number(element.value) == 0 || isNaN(Number(element.value)))) {
207
+ element.value = 1;
208
+ }
209
+ parts = element.id.split('-');
210
+ optionId = parts[2];
211
+ if (!this.config['options'][optionId].isMulti) {
212
+ selectionId = this.config.selected[optionId][0];
213
+ this.config.options[optionId].selections[selectionId].qty = element.value*1;
214
+ this.reloadPrice();
215
+ } else if (parts[3] != 'qty') {
216
+ selectionId = parts[3];
217
+ this.config.options[optionId].selections[selectionId].qty = element.value*1;
218
+ this.reloadPrice();
219
+ }
220
+ },
221
+
222
+ changeOptionSelectionQty: function (element, event) {
223
+ var checkQty = true;
224
+ if (typeof(event) != 'undefined') {
225
+ if (event.keyCode == 8 || event.keyCode == 46) {
226
+ checkQty = false;
227
+ }
228
+ }
229
+ if (checkQty && (Number(element.value) == 0 || isNaN(Number(element.value)))) {
230
+ element.value = 1;
231
+ }
232
+ parts = element.id.split('-');
233
+ optionId = parts[2];
234
+ selectionId = parts[3];
235
+ this.config.options[optionId].selections[selectionId].qty = element.value*1;
236
+ this.reloadPrice();
237
+ },
238
+
239
+ validationCallback: function (elmId, result){
240
+ if (elmId == undefined || $(elmId) == undefined) {
241
+ return;
242
+ }
243
+ var container = $(elmId).up('ul.options-list');
244
+ if (typeof container != 'undefined') {
245
+ if (result == 'failed') {
246
+ container.removeClassName('validation-passed');
247
+ container.addClassName('validation-failed');
248
+ } else {
249
+ container.removeClassName('validation-failed');
250
+ container.addClassName('validation-passed');
251
+ }
252
+ }
253
+ }
254
+ };