Automatic_Configurables_1dot3 - Version 0.0.8

Version Notes

The wrong js file was included

Download this release

Release Info

Developer Magento Core Team
Extension Automatic_Configurables_1dot3
Version 0.0.8
Comparing to
See all releases


Version 0.0.8

app/code/local/QS/Quickconfigurables/Block/Adminhtml/Catalog/Product/Edit/Tab/Super/Config.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Open Software License (OSL 3.0)
8
+ * that is bundled with this package in the file LICENSE.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/osl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * DISCLAIMER
16
+ *
17
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
18
+ * versions in the future. If you wish to customize Magento for your
19
+ * needs please refer to http://www.magentocommerce.com for more information.
20
+ *
21
+ * @category Mage
22
+ * @package Mage_Adminhtml
23
+ * @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
24
+ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
25
+ */
26
+
27
+
28
+ /**
29
+ * Adminhtml catalog super product configurable tab
30
+ *
31
+ * @category Mage
32
+ * @package Mage_Adminhtml
33
+ * @author Magento Core Team <core@magentocommerce.com>
34
+ */
35
+ class QS_Quickconfigurables_Block_Adminhtml_Catalog_Product_Edit_Tab_Super_Config extends Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config implements Mage_Adminhtml_Block_Widget_Tab_Interface
36
+ {
37
+ /**
38
+ * Initialize block
39
+ *
40
+ */
41
+ public function __construct()
42
+ {
43
+ parent::__construct();
44
+ $this->setTemplate('quickconfigurables/catalog/product/edit/super/config.phtml');
45
+ }
46
+
47
+ /**
48
+ * Prepare Layout data
49
+ *
50
+ * @return Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config
51
+ */
52
+ protected function _prepareLayout()
53
+ {
54
+ if ($this->_getProduct()->getId()) {
55
+ $this->setChild('combination',
56
+ $this->getLayout()->createBlock('quickconfigurables/adminhtml_catalog_product_edit_tab_super_config_combination')
57
+ );
58
+ }
59
+ return parent::_prepareLayout();
60
+ }
61
+
62
+ /**
63
+ * Retrieve Create New Empty Product URL
64
+ *
65
+ * @return string
66
+ */
67
+ public function getCombinationsUrl()
68
+ {
69
+ return $this->getUrl(
70
+ 'quickconfigurables/adminhtml_product/combination',
71
+ array(
72
+ 'set' => $this->_getProduct()->getAttributeSetId(),
73
+ 'product' => $this->_getProduct()->getId(),
74
+ 'required' => $this->_getRequiredAttributesIds(),
75
+ )
76
+ );
77
+ }
78
+ }
app/code/local/QS/Quickconfigurables/Block/Adminhtml/Catalog/Product/Edit/Tab/Super/Config/Combination.php ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Adminhtml catalog super product configurable create combinations tab
4
+ *
5
+ * @category QS
6
+ * @package QS_Quickconfigurables
7
+ * @author Quart-soft Magento Team <info@quart-soft.com>
8
+ * @copyright Copyright (c) 2010 Quart-soft Ltd http://quart-soft.com
9
+ */
10
+ class QS_Quickconfigurables_Block_Adminhtml_Catalog_Product_Edit_Tab_Super_Config_Combination extends Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Attributes
11
+ {
12
+ protected function _prepareForm()
13
+ {
14
+ $form = new Varien_Data_Form();
15
+
16
+ $form->setFieldNameSuffix('combination');
17
+
18
+ $fieldset = $form->addFieldset('combination', array(
19
+ 'legend' => Mage::helper('quickconfigurables')->__('Create Combinations in One Click')
20
+ ));
21
+ $this->_addElementTypes($fieldset);
22
+ $attributesConfig = array(
23
+ 'autogenerate' => array('name'),
24
+ 'nonedit' => array('sku'),
25
+ 'additional' => array('name', 'sku', 'visibility', 'status')
26
+ );
27
+
28
+ $availableTypes = array('text', 'select', 'multiselect', 'textarea', 'price');
29
+
30
+ $attributes = Mage::getModel('catalog/product')
31
+ ->setTypeId(Mage_Catalog_Model_Product_Type::TYPE_SIMPLE)
32
+ ->setAttributeSetId($this->_getProduct()->getAttributeSetId())
33
+ ->getAttributes();
34
+
35
+ /* Standart attributes */
36
+ foreach ($attributes as $attribute) {
37
+ if (($attribute->getIsRequired()
38
+ && $attribute->getApplyTo()
39
+ // If not applied to configurable
40
+ && !in_array(Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE, $attribute->getApplyTo())
41
+ // If not used in configurable
42
+ && !in_array($attribute->getId(),$this->_getProduct()->getTypeInstance(true)->getUsedProductAttributeIds($this->_getProduct())))
43
+ // Or in additional
44
+ || in_array($attribute->getAttributeCode(), $attributesConfig['additional'])) {
45
+
46
+ $inputType = $attribute->getFrontend()->getInputType();
47
+ if (!in_array($inputType, $availableTypes)) {
48
+ continue;
49
+ }
50
+ $attributeCode = $attribute->getAttributeCode();
51
+ $element = $fieldset->addField(
52
+ 'combination_' . $attributeCode,
53
+ $inputType,
54
+ array(
55
+ 'label' => $attribute->getFrontend()->getLabel(),
56
+ 'name' => $attributeCode,
57
+ 'required' => $attribute->getIsRequired(),
58
+ )
59
+ )->setEntityAttribute($attribute);
60
+
61
+ if (in_array($attributeCode, $attributesConfig['autogenerate'])) {
62
+ $element->setDisabled('true');
63
+ $element->setValue($this->_getProduct()->getData($attributeCode));
64
+ $element->setAfterElementHtml(
65
+ '<input type="checkbox" id="combination_' . $attributeCode . '_autogenerate" '
66
+ . 'name="combination[' . $attributeCode . '_autogenerate]" value="1" '
67
+ . 'onclick="toggleValueElements(this, this.parentNode)" checked="checked" /> '
68
+ . '<label for="combination_' . $attributeCode . '_autogenerate" >'
69
+ . Mage::helper('catalog')->__('Autogenerate')
70
+ . '</label>'
71
+ );
72
+ }
73
+
74
+ if (in_array($attributeCode, $attributesConfig['nonedit'])) {
75
+ $element->setDisabled('true');
76
+ $element->setValue(Mage::helper('quickconfigurables')->__('Attribute value will be autogenerated'));
77
+ $element->setAfterElementHtml(
78
+ '<input type="hidden" id="combination_' . $attributeCode . '_autogenerate" '
79
+ . 'name="combination[' . $attributeCode . '_autogenerate]" value="1" '
80
+ );
81
+ }
82
+
83
+
84
+ if ($inputType == 'select' || $inputType == 'multiselect') {
85
+ $element->setValues($attribute->getFrontend()->getSelectOptions());
86
+ }
87
+ }
88
+ }
89
+
90
+ /* Configurable attributes */
91
+ foreach ($this->_getProduct()->getTypeInstance(true)->getUsedProductAttributes($this->_getProduct()) as $attribute) {
92
+ $attributeCode = $attribute->getAttributeCode();
93
+ $fieldset->addField( 'combination_' . $attributeCode, 'multiselect', array(
94
+ 'label' => $attribute->getFrontend()->getLabel(),
95
+ 'name' => $attributeCode,
96
+ 'values' => $attribute->getSource()->getAllOptions(true, true),
97
+ 'required' => true,
98
+ 'class' => 'validate-configurable',
99
+ ));
100
+ }
101
+
102
+ /* Inventory Data */
103
+ $fieldset->addField('combination_inventory_qty', 'text', array(
104
+ 'label' => Mage::helper('catalog')->__('Qty'),
105
+ 'name' => 'stock_data[qty]',
106
+ 'class' => 'validate-number',
107
+ 'required' => true,
108
+ 'value' => 0
109
+ ));
110
+
111
+ $fieldset->addField('combination_inventory_is_in_stock', 'select', array(
112
+ 'label' => Mage::helper('catalog')->__('Stock Availability'),
113
+ 'name' => 'stock_data[is_in_stock]',
114
+ 'values' => array(
115
+ array('value'=>1, 'label'=> Mage::helper('catalog')->__('In Stock')),
116
+ array('value'=>0, 'label'=> Mage::helper('catalog')->__('Out of Stock'))
117
+ ),
118
+ 'value' => 1
119
+ ));
120
+
121
+ $stockHiddenFields = array(
122
+ 'use_config_min_qty' => 1,
123
+ 'use_config_min_sale_qty' => 1,
124
+ 'use_config_max_sale_qty' => 1,
125
+ 'use_config_backorders' => 1,
126
+ 'use_config_notify_stock_qty' => 1,
127
+ 'is_qty_decimal' => 0
128
+ );
129
+
130
+ foreach ($stockHiddenFields as $fieldName=>$fieldValue) {
131
+ $fieldset->addField('combination_inventory_' . $fieldName, 'hidden', array(
132
+ 'name' => 'stock_data[' . $fieldName .']',
133
+ 'value' => $fieldValue
134
+ ));
135
+ }
136
+
137
+
138
+ $fieldset->addField('create_button', 'note', array(
139
+ 'text' => $this->getButtonHtml(
140
+ Mage::helper('catalog')->__('Create Combinations'),
141
+ //'superProduct.createPopup(createCombinationsUrl)',
142
+ 'superProduct.quickCombinations()',
143
+ 'save'
144
+ )
145
+ ));
146
+
147
+ $this->setForm($form);
148
+ }
149
+
150
+ /**
151
+ * Retrieve currently edited product object
152
+ *
153
+ * @return Mage_Catalog_Model_Product
154
+ */
155
+ protected function _getProduct()
156
+ {
157
+ return Mage::registry('current_product');
158
+ }
159
+ }
app/code/local/QS/Quickconfigurables/Helper/Data.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Quickconfigurables Helper Data
4
+ *
5
+ * @category QS
6
+ * @package QS_Quickconfigurables
7
+ * @author Quart-soft Magento Team <info@quart-soft.com>
8
+ * @copyright Copyright (c) 2010 Quart-soft Ltd http://quart-soft.com
9
+ */
10
+
11
+ class QS_Quickconfigurables_Helper_Data extends Mage_Core_Helper_Abstract
12
+ {
13
+ }
app/code/local/QS/Quickconfigurables/controllers/Adminhtml/ProductController.php ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Adminhtml quickconfigurable product controller
4
+ *
5
+ * @category QS
6
+ * @package QS_Quickconfigurables
7
+ * @author Quart-soft Magento Team <info@quart-soft.com>
8
+ * @copyright Copyright (c) 2010 Quart-soft Ltd http://quart-soft.com
9
+ */
10
+
11
+ class QS_Quickconfigurables_Adminhtml_ProductController extends Mage_Adminhtml_Controller_action
12
+ {
13
+ public function combinationAction()
14
+ {
15
+ $result = array();
16
+ $error = false;
17
+ $success = false;
18
+
19
+ /* @var $configurableProduct Mage_Catalog_Model_Product */
20
+ $configurableProduct = Mage::getModel('catalog/product')
21
+ ->setStoreId(0)
22
+ ->load($this->getRequest()->getParam('product'));
23
+
24
+ if (!$configurableProduct->isConfigurable()) {
25
+ // If invalid parent product
26
+ $this->_redirect('*/*/');
27
+ return;
28
+ }
29
+
30
+ $postData = $this->getRequest()->getParam('combination', array());
31
+
32
+ $attributeValues = array();
33
+ $requiredAttributesIds = explode(',',$this->getRequest()->getParam('required'));
34
+ foreach ($requiredAttributesIds as $requiredAttributeId){
35
+ $attributeData = Mage::getModel('eav/config')->getAttribute('catalog_product', $requiredAttributeId);
36
+ foreach ($postData[$attributeData->getAttributeCode()] as $option){
37
+ if ($option){
38
+ $attributeValues[$attributeData->getAttributeCode()][] = $option;
39
+ }
40
+ }
41
+ }
42
+
43
+ $combinationsTemp = array();
44
+ $combinationsFinal = array();
45
+ $i = 0;
46
+
47
+ foreach($attributeValues as $code=>$values){
48
+ $combinationsFinal = array();
49
+ if ($combinationsTemp){
50
+ foreach ($combinationsTemp as $tmpComb){
51
+ foreach ($values as $value){
52
+ $combinationsFinal[] = array(
53
+ 'codes' => $tmpComb['codes'] . ':' . $code,
54
+ 'values' => $tmpComb['values'] . ':' . $value,
55
+ );
56
+ }
57
+ }
58
+ } else {
59
+ foreach ($values as $value){
60
+ $combinationsFinal[] = array(
61
+ 'codes' => $code,
62
+ 'values' => $value,
63
+ );
64
+ }
65
+ }
66
+ $combinationsTemp = $combinationsFinal;
67
+ }
68
+
69
+ $result['product_ids'] = array();
70
+
71
+ foreach ($combinationsFinal as $comb){
72
+
73
+ /* @var $product Mage_Catalog_Model_Product */
74
+ $product = Mage::getModel('catalog/product')
75
+ ->setStoreId(0)
76
+ ->setTypeId(Mage_Catalog_Model_Product_Type::TYPE_SIMPLE)
77
+ ->setAttributeSetId($configurableProduct->getAttributeSetId());
78
+
79
+
80
+ foreach ($product->getTypeInstance()->getEditableAttributes() as $attribute) {
81
+ if ($attribute->getIsUnique()
82
+ || $attribute->getFrontend()->getInputType() == 'gallery'
83
+ || $attribute->getFrontend()->getInputType() == 'media_image'
84
+ || !$attribute->getIsVisible()) {
85
+ continue;
86
+ }
87
+
88
+ $product->setData(
89
+ $attribute->getAttributeCode(),
90
+ $configurableProduct->getData($attribute->getAttributeCode())
91
+ );
92
+ }
93
+
94
+ $product->addData($this->getRequest()->getParam('combination', array()));
95
+
96
+ $codesToSet = explode(':',$comb['codes']);
97
+ $valuesToSet = explode(':',$comb['values']);
98
+ $i = 0;
99
+ foreach ($codesToSet as $codeToSet ){
100
+ $product->setData(
101
+ $codeToSet,
102
+ $valuesToSet[$i++]
103
+ );
104
+ }
105
+
106
+ $product->setWebsiteIds($configurableProduct->getWebsiteIds());
107
+
108
+ $autogenerateOptions = array();
109
+
110
+ $attrsIds = explode(',',$this->getRequest()->getParam('required'));
111
+
112
+ foreach ($attrsIds as $attrId) {
113
+ $attribute = Mage::getModel('eav/entity_attribute')->load($attrId);
114
+ Mage::log($attribute);
115
+ $value = $product->getAttributeText($attribute->getAttributeCode());
116
+ $autogenerateOptions[] = $value;
117
+ $result['attributes'][] = array(
118
+ 'label' => $value,
119
+ 'value_index' => $product->getData($attribute->getAttributeCode()),
120
+ 'attribute_id' => $attribute->getId()
121
+ );
122
+ }
123
+
124
+ if ($product->getNameAutogenerate()) {
125
+ $product->setName($configurableProduct->getName() . '-' . implode('-', $autogenerateOptions));
126
+ }
127
+
128
+ if ($product->getSkuAutogenerate()) {
129
+ $product->setSku($configurableProduct->getSku() . '-' . implode('-', $autogenerateOptions));
130
+ }
131
+
132
+ if (is_array($product->getPricing())) {
133
+ $result['pricing'] = $product->getPricing();
134
+ $additionalPrice = 0;
135
+ foreach ($product->getPricing() as $pricing) {
136
+ if (empty($pricing['value'])) {
137
+ continue;
138
+ }
139
+
140
+ if (!empty($pricing['is_percent'])) {
141
+ $pricing['value'] = ($pricing['value']/100)*$product->getPrice();
142
+ }
143
+
144
+ $additionalPrice += $pricing['value'];
145
+ }
146
+
147
+ $product->setPrice($product->getPrice() + $additionalPrice);
148
+ $product->unsPricing();
149
+ }
150
+
151
+ try {
152
+ $success = true;
153
+ $product->validate();
154
+ $product->save();
155
+ $result['product_ids'][] = $product->getId();
156
+ } catch (Mage_Core_Exception $e) {
157
+ $result['error'] = array(
158
+ 'message' => $e->getMessage(),
159
+ 'fields' => array(
160
+ 'sku' => $product->getSku()
161
+ )
162
+ );
163
+
164
+ } catch (Exception $e) {
165
+ Mage::logException($e);
166
+ $result['error'] = array(
167
+ 'message' => $this->__('Product saving error. ') . $e->getMessage()
168
+ );
169
+ }
170
+ }
171
+
172
+ if ($success || $result['product_ids']){
173
+ $this->_getSession()->addSuccess(Mage::helper('catalog')->__('Total %s products were successfully created.',count($result['product_ids'])));
174
+ $this->_initLayoutMessages('adminhtml/session');
175
+ $result['messages'] = $this->getLayout()->getMessagesBlock()->getGroupedHtml();
176
+ }
177
+
178
+ //$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
179
+ $this->getResponse()->setBody(Zend_Json::encode($result));
180
+ }
181
+
182
+ }
app/code/local/QS/Quickconfigurables/etc/config.xml ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Adminhtml catalog super product configurable create combinations tab
5
+ *
6
+ * @category QS
7
+ * @package QS_Quickconfigurables
8
+ * @author Quart-soft Magento Team <info@quart-soft.com>
9
+ * @copyright Copyright (c) 2010 Quart-soft Ltd http://quart-soft.com
10
+ */
11
+ -->
12
+ <config>
13
+ <modules>
14
+ <QS_Quickconfigurables>
15
+ <version>0.1.0</version>
16
+ </QS_Quickconfigurables>
17
+ </modules>
18
+ <frontend>
19
+ <routers>
20
+ <quickconfigurables>
21
+ <use>standard</use>
22
+ <args>
23
+ <module>QS_Quickconfigurables</module>
24
+ <frontName>quickconfigurables</frontName>
25
+ </args>
26
+ </quickconfigurables>
27
+ </routers>
28
+ </frontend>
29
+ <adminhtml>
30
+ <layout>
31
+ <updates>
32
+ <quickconfigurables>
33
+ <file>quickconfigurables.xml</file>
34
+ </quickconfigurables>
35
+ </updates>
36
+ </layout>
37
+ </adminhtml>
38
+ <admin>
39
+ <routers>
40
+ <quickconfigurables>
41
+ <use>admin</use>
42
+ <args>
43
+ <module>QS_Quickconfigurables</module>
44
+ <frontName>quickconfigurables</frontName>
45
+ </args>
46
+ </quickconfigurables>
47
+ </routers>
48
+ </admin>
49
+ <global>
50
+ <models>
51
+ <quickconfigurables>
52
+ <class>QS_Quickconfigurables_Model</class>
53
+ </quickconfigurables>
54
+ </models>
55
+ <resources>
56
+ <quickconfigurables_setup>
57
+ <setup>
58
+ <module>QS_Quickconfigurables</module>
59
+ </setup>
60
+ <connection>
61
+ <use>core_setup</use>
62
+ </connection>
63
+ </quickconfigurables_setup>
64
+ <quickconfigurables_write>
65
+ <connection>
66
+ <use>core_write</use>
67
+ </connection>
68
+ </quickconfigurables_write>
69
+ <quickconfigurables_read>
70
+ <connection>
71
+ <use>core_read</use>
72
+ </connection>
73
+ </quickconfigurables_read>
74
+ </resources>
75
+ <blocks>
76
+ <quickconfigurables>
77
+ <class>QS_Quickconfigurables_Block</class>
78
+ </quickconfigurables>
79
+ <adminhtml>
80
+ <rewrite>
81
+ <catalog_product_edit_tab_super_config>QS_Quickconfigurables_Block_Adminhtml_Catalog_Product_Edit_Tab_Super_Config</catalog_product_edit_tab_super_config>
82
+ </rewrite>
83
+ </adminhtml>
84
+ </blocks>
85
+ <helpers>
86
+ <quickconfigurables>
87
+ <class>QS_Quickconfigurables_Helper</class>
88
+ </quickconfigurables>
89
+ </helpers>
90
+ </global>
91
+ </config>
app/design/adminhtml/default/default/layout/quickconfigurables.xml ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ /**
4
+ * Magento
5
+ *
6
+ * NOTICE OF LICENSE
7
+ *
8
+ * This source file is subject to the Academic Free License (AFL 3.0)
9
+ * that is bundled with this package in the file LICENSE_AFL.txt.
10
+ * It is also available through the world-wide-web at this URL:
11
+ * http://opensource.org/licenses/afl-3.0.php
12
+ * If you did not receive a copy of the license and are unable to
13
+ * obtain it through the world-wide-web, please send an email
14
+ * to license@magentocommerce.com so we can send you a copy immediately.
15
+ *
16
+ * DISCLAIMER
17
+ *
18
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
19
+ * versions in the future. If you wish to customize Magento for your
20
+ * needs please refer to http://www.magentocommerce.com for more information.
21
+ *
22
+ * @category design
23
+ * @package default_default
24
+ * @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
25
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
26
+ */
27
+ -->
28
+
29
+ <layout>
30
+ <default>
31
+ <reference name="head">
32
+ <action method="removeItem"><type>js</type><name>mage/adminhtml/product.js</name></action>
33
+ <action method="addJs"><script>qs/adminhtml/product_13.js</script></action>
34
+ </reference>
35
+ </default>
36
+ </layout>
app/design/adminhtml/default/default/template/quickconfigurables/catalog/product/edit/super/config.phtml ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ *
5
+ * NOTICE OF LICENSE
6
+ *
7
+ * This source file is subject to the Academic Free License (AFL 3.0)
8
+ * that is bundled with this package in the file LICENSE_AFL.txt.
9
+ * It is also available through the world-wide-web at this URL:
10
+ * http://opensource.org/licenses/afl-3.0.php
11
+ * If you did not receive a copy of the license and are unable to
12
+ * obtain it through the world-wide-web, please send an email
13
+ * to license@magentocommerce.com so we can send you a copy immediately.
14
+ *
15
+ * DISCLAIMER
16
+ *
17
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
18
+ * versions in the future. If you wish to customize Magento for your
19
+ * needs please refer to http://www.magentocommerce.com for more information.
20
+ *
21
+ * @category design
22
+ * @package default_default
23
+ * @copyright Copyright (c) 2009 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
24
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
25
+ */
26
+ ?>
27
+ <?php if (!$this->isReadonly()):?>
28
+ <div class="entry-edit">
29
+ <div id="assign_product_warrning" style="display: none;">
30
+ <ul class="messages">
31
+ <li class="error-msg">
32
+ <ul>
33
+ <li><?php echo $this->__('Links with associated products will retain only after saving current product.') ?></li>
34
+ </ul>
35
+ </li>
36
+ </ul>
37
+ </div>
38
+ <div class="entry-edit-head">
39
+ <h4 class="icon-head head-edit-form fieldset-legend"><?php echo Mage::helper('catalog')->__('Create Simple Associated Product') ?></h4>
40
+ </div>
41
+ <fieldset class="a-right">
42
+ <?php echo $this->getChildHtml('create_empty') ?> <?php echo $this->getChildHtml('create_from_configurable') ?>
43
+ </fieldset>
44
+ </div>
45
+
46
+ <?php // Externally Added ?>
47
+ <div id="<?php echo $this->getHtmlId() ?>_combination_form" class="ignore-validate configurable-combination">
48
+ <?php echo $this->getChildHtml('combination'); ?>
49
+ </div>
50
+ <?php //end ?>
51
+
52
+ <div id="<?php echo $this->getHtmlId() ?>_simple_form" class="ignore-validate configurable-simple-product">
53
+ <?php echo $this->getChildHtml('simple'); ?>
54
+ </div>
55
+ <?php endif;?>
56
+ <div class="entry-edit">
57
+ <div class="entry-edit-head">
58
+ <h4 class="icon-head head-edit-form fieldset-legend"><?php echo Mage::helper('catalog')->__('Super product attributes configuration') ?></h4>
59
+ </div>
60
+ <fieldset id="<?php echo $this->getHtmlId() ?>">
61
+ <legend><?php echo Mage::helper('catalog')->__('Super product attributes configuration') ?></legend>
62
+ <input type="hidden" id="<?php echo $this->getHtmlId() ?>_save_links" name="configurable_products_data" value=""/>
63
+ <input type="hidden" id="<?php echo $this->getHtmlId() ?>_save_attributes" name="configurable_attributes_data" />
64
+
65
+ <ul class="messages">
66
+ <li class="notice-msg">
67
+ <ul><li><?php echo Mage::helper('catalog')->__('Price values for options should be specified in system base currency.')?></li></ul>
68
+ <ul><li><?php echo Mage::helper('catalog')->__('Attrribute names can be specified per store.')?></li></ul>
69
+ </li>
70
+ </ul>
71
+ <ul id="<?php echo $this->getHtmlId() ?>_attributes" class="super-attributes">
72
+ </ul>
73
+ </fieldset>
74
+ </div>
75
+ <div class="no-display" id="<?php echo $this->getHtmlId() ?>_attribute_template">
76
+ <div class="<?php if (!$this->isReadonly()):?>attribute-name-container <?php endif;?>left">
77
+ '{{frontend_label}}'
78
+ </div>
79
+ <div class="values-container right">
80
+ <label for="__id___label" class="bold"><?php echo Mage::helper('catalog')->__('Attribute Name:') ?></label>
81
+ <input id="__id___label" type="text" <?php if ($this->isReadonly()):?> disabled="disabled" <?php endif;?> class="input-text attribute-label required-entry template no-display" value="'{{label}}'" readonly="label" />
82
+ <input id="__id___label_use_default" type="checkbox" value="1" " checked="use_default" class="attribute-use-default-label">
83
+ <label for="__id___label_use_default"><?php echo Mage::helper('catalog')->__('Use default')?> ('{{store_label}}')</label>
84
+ <ul class="attribute-values">
85
+ </ul>
86
+ </div>
87
+ </div>
88
+ <div class="no-display" id="<?php echo $this->getHtmlId() ?>_value_template">
89
+ <div class="attribute-value-label-container left">
90
+ <?php echo Mage::helper('catalog')->__('Option:') ?> <strong>'{{label}}'</strong>
91
+ </div>
92
+ <div class="attribute-values-container-main">
93
+ <div class="attribute-values-container left">
94
+ <?php echo Mage::helper('catalog')->__('Price:') ?>
95
+ <input id="__id___pricing" type="text" <?php if ($this->isReadonly()):?> disabled="disabled" <?php endif;?> class="input-text attribute-price validate-number template no-display" value="'{{pricing_value}}'"/>
96
+ </div>
97
+ <div class="attribute-values-container left">
98
+ &nbsp;<select class="attribute-price-type" <?php if ($this->isReadonly()):?> disabled="disabled" <?php endif;?>>
99
+ <option value="0"><?php echo Mage::helper('catalog')->__('Fixed') ?></option>
100
+ <option value="1"><?php echo Mage::helper('catalog')->__('Percentage') ?></option>
101
+ </select>
102
+ </div>
103
+ <?php if ($this->getShowUseDefaultPrice()):?>
104
+ <div class="attribute-values-container">
105
+ &nbsp;<input id="__id___default" type="checkbox" <?php if ($this->isReadonly()):?> disabled="disabled" <?php endif;?> class="attribute-use-default-value"> <label for="__id___default" class="normal"><?php echo Mage::helper('catalog')->__('Use Default Value') ?></label>
106
+ </div>
107
+ <?php endif;?>
108
+ </div>
109
+ </div>
110
+ <div class="template no-display" id="<?php echo $this->getHtmlId() ?>_simple_pricing">
111
+ <div class="attribute-values-container left v-middle">
112
+ &nbsp;<?php echo Mage::helper('catalog')->__('Price:') ?>
113
+ <input type="text" class="input-text attribute-price validate-number"/>
114
+ </div>
115
+ <div class="attribute-values-container left v-middle">
116
+ &nbsp;<select class="attribute-price-type">
117
+ <option value="0"><?php echo Mage::helper('catalog')->__('Fixed') ?></option>
118
+ <option value="1"><?php echo Mage::helper('catalog')->__('Percentage') ?></option>
119
+ </select>
120
+ </div>
121
+ </div>
122
+ <div class="template no-display" id="<?php echo $this->getHtmlId() ?>_simple_pricing_view">
123
+ &nbsp;<?php echo Mage::helper('catalog')->__('Price') ?> <strong>'{{value}}'</strong>
124
+ </div>
125
+ <?php echo $this->getGridHtml() ?>
126
+ <script type="text/javascript">
127
+ var superProduct = new Product.Configurable(<?php echo $this->getAttributesJson() ?>,<?php echo $this->getLinksJson() ?>,'<?php echo $this->getHtmlId() ?>_',<?php echo $this->getGridJsObject() ?>, <?php echo ( $this->isReadonly() ? 'true' : 'false'); ?>);
128
+ superProduct.createEmptyUrl = '<?php echo $this->getNewEmptyProductUrl() ?>';
129
+ superProduct.createNormalUrl = '<?php echo $this->getNewProductUrl() ?>';
130
+ superProduct.createQuickUrl = '<?php echo $this->getQuickCreationUrl() ?>';
131
+ <?php // Externally Added ?>
132
+ superProduct.createCombinationsUrl = '<?php echo $this->getCombinationsUrl() ?>';
133
+ <?php // End ?>
134
+
135
+ Validation.add(
136
+ 'validate-configurable',
137
+ '<?php echo $this->escapeJs(Mage::helper('catalog')->__('Product with this combination of attributes already associated to configurable.')) ?>',
138
+ superProduct.checkCreationUniqueAttributes.bind(superProduct)
139
+ )
140
+ </script>
141
+
142
+ <div><input type="hidden" name="affect_configurable_product_attributes" value="1" /></div>
app/etc/modules/QS_Quickconfigurables.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <QS_Quickconfigurables>
5
+ <active>true</active>
6
+ <codePool>local</codePool>
7
+ </QS_Quickconfigurables>
8
+ </modules>
9
+ </config>
js/qs/adminhtml/product_13.js ADDED
@@ -0,0 +1,1007 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Magento
3
+ *
4
+ * NOTICE OF LICENSE
5
+ *
6
+ * This source file is subject to the Academic Free License (AFL 3.0)
7
+ * that is bundled with this package in the file LICENSE_AFL.txt.
8
+ * It is also available through the world-wide-web at this URL:
9
+ * http://opensource.org/licenses/afl-3.0.php
10
+ * If you did not receive a copy of the license and are unable to
11
+ * obtain it through the world-wide-web, please send an email
12
+ * to license@magentocommerce.com so we can send you a copy immediately.
13
+ *
14
+ * DISCLAIMER
15
+ *
16
+ * Do not edit or add to this file if you wish to upgrade Magento to newer
17
+ * versions in the future. If you wish to customize Magento for your
18
+ * needs please refer to http://www.magentocommerce.com for more information.
19
+ *
20
+ * @copyright Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
21
+ * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
22
+ */
23
+
24
+ var Product = {};
25
+
26
+ Product.Gallery = Class.create();
27
+ Product.Gallery.prototype = {
28
+ images: [],
29
+ file2id: {'no_selection':0},
30
+ idIncrement: 1,
31
+ containerId: '',
32
+ container: null,
33
+ uploader: null,
34
+ imageTypes: {},
35
+ initialize: function (containerId, uploader, imageTypes) {
36
+ this.containerId = containerId,
37
+ this.container = $(this.containerId);
38
+ this.uploader = uploader;
39
+ this.imageTypes = imageTypes;
40
+ if (this.uploader) {
41
+ this.uploader.onFilesComplete = this.handleUploadComplete.bind(this);
42
+ }
43
+ //this.uploader.onFileProgress = this.handleUploadProgress.bind(this);
44
+ //this.uploader.onFileError = this.handleUploadError.bind(this);
45
+ this.images = this.getElement('save').value.evalJSON();
46
+ this.imagesValues = this.getElement('save_image').value.evalJSON();
47
+ this.template = new Template('<tr id="__id__" class="preview">' + this.getElement('template').innerHTML + '</tr>', new RegExp('(^|.|\\r|\\n)(__([a-zA-Z0-9_]+)__)', ''));
48
+ this.fixParentTable();
49
+ this.updateImages();
50
+ varienGlobalEvents.attachEventHandler('moveTab', this.onImageTabMove.bind(this));
51
+ },
52
+ onImageTabMove: function(event) {
53
+ var imagesTab = false;
54
+ this.container.ancestors().each(function(parentItem){
55
+ if (parentItem.tabObject) {
56
+ imagesTab = parentItem.tabObject;
57
+ throw $break;
58
+ }
59
+ }.bind(this));
60
+ if(imagesTab && event.tab && event.tab.name && imagesTab.name == event.tab.name) {
61
+ this.updateImages();
62
+ }
63
+ },
64
+ fixParentTable: function() {
65
+ this.container.ancestors().each(function(parentItem){
66
+ if(parentItem.tagName.toLowerCase()=='td') {
67
+ parentItem.style.width ='100%';
68
+ }
69
+ if(parentItem.tagName.toLowerCase()=='table') {
70
+ parentItem.style.width ='100%';
71
+ throw $break;
72
+ }
73
+ });
74
+ },
75
+ getElement: function (name) {
76
+ return $(this.containerId + '_' + name);
77
+ },
78
+ showUploader: function () {
79
+ this.getElement('add_images_button').hide();
80
+ this.getElement('uploader').show();
81
+ },
82
+ handleUploadComplete: function (files) {
83
+ files.each(function(item) {
84
+ if (!item.response.isJSON()) {
85
+ try {
86
+ console.log(item.response);
87
+ } catch (e2) {
88
+ alert(item.response);
89
+ }
90
+ return;
91
+ }
92
+ var response = item.response.evalJSON();
93
+ if (response.error) {
94
+ return;
95
+ }
96
+ var newImage = {};
97
+ newImage.url = response.url;
98
+ newImage.file = response.file;
99
+ newImage.label = '';
100
+ newImage.position = this.getNextPosition();
101
+ newImage.disabled = 0;
102
+ newImage.removed = 0;
103
+ this.images.push(newImage);
104
+ this.uploader.removeFile(item.id);
105
+ }.bind(this));
106
+ this.container.setHasChanges();
107
+ this.updateImages();
108
+ },
109
+ updateImages: function() {
110
+ this.getElement('save').value = this.images.toJSON();
111
+ $H(this.imageTypes).each(function(pair) {
112
+ this.getFileElement('no_selection', 'cell-' + pair.key + ' input').checked = true;
113
+ }.bind(this));
114
+ this.images.each(function(row){
115
+ if (!$(this.prepareId(row.file))) {
116
+ this.createImageRow(row);
117
+ }
118
+ this.updateVisualisation(row.file);
119
+ }.bind(this));
120
+ this.updateUseDefault(false);
121
+ },
122
+ createImageRow: function(image) {
123
+ var vars = Object.clone(image);
124
+ vars.id = this.prepareId(image.file);
125
+ var html = this.template.evaluate(vars);
126
+ Element.insert(this.getElement('list'), {bottom: html});
127
+ },
128
+ prepareId: function(file) {
129
+ if(typeof this.file2id[file] == 'undefined') {
130
+ this.file2id[file] = this.idIncrement++;
131
+ }
132
+ return this.containerId + '-image-' + this.file2id[file];
133
+ },
134
+ getNextPosition: function() {
135
+ var maxPosition = 0;
136
+ this.images.each(function (item) {
137
+ if (parseInt(item.position) > maxPosition) {
138
+ maxPosition = parseInt(item.position);
139
+ }
140
+ });
141
+ return maxPosition + 1;
142
+ },
143
+ updateImage: function(file) {
144
+ var index = this.getIndexByFile(file);
145
+ this.images[index].label = this.getFileElement(file, 'cell-label input').value;
146
+ this.images[index].position = this.getFileElement(file, 'cell-position input').value;
147
+ this.images[index].removed = (this.getFileElement(file, 'cell-remove input').checked ? 1 : 0);
148
+ this.images[index].disabled = (this.getFileElement(file, 'cell-disable input').checked ? 1 : 0);
149
+ this.getElement('save').value = this.images.toJSON();
150
+ this.updateState(file);
151
+ this.container.setHasChanges();
152
+ },
153
+ loadImage: function(file) {
154
+ var image = this.getImageByFile(file);
155
+ this.getFileElement(file, 'cell-image img').src = image.url;
156
+ this.getFileElement(file, 'cell-image img').show();
157
+ this.getFileElement(file, 'cell-image .place-holder').hide();
158
+ },
159
+ setProductImages: function(file) {
160
+ $H(this.imageTypes).each(function(pair){
161
+ if(this.getFileElement(file, 'cell-' + pair.key + ' input').checked) {
162
+ this.imagesValues[pair.key] = (file == 'no_selection' ? null : file);
163
+ }
164
+ }.bind(this));
165
+
166
+ this.getElement('save_image').value = $H(this.imagesValues).toJSON();
167
+ },
168
+ updateVisualisation: function(file) {
169
+ var image = this.getImageByFile(file);
170
+ this.getFileElement(file, 'cell-label input').value = image.label;
171
+ this.getFileElement(file, 'cell-position input').value = image.position;
172
+ this.getFileElement(file, 'cell-remove input').checked = (image.removed == 1);
173
+ this.getFileElement(file, 'cell-disable input').checked = (image.disabled == 1);
174
+ $H(this.imageTypes).each(function(pair) {
175
+ if(this.imagesValues[pair.key] == file) {
176
+ this.getFileElement(file, 'cell-' + pair.key + ' input').checked = true;
177
+ }
178
+ }.bind(this));
179
+ this.updateState(file);
180
+ },
181
+ updateState: function (file) {
182
+ if(this.getFileElement(file, 'cell-disable input').checked) {
183
+ this.getFileElement(file, 'cell-position input').disabled = true;
184
+ } else {
185
+ this.getFileElement(file, 'cell-position input').disabled = false;
186
+ }
187
+ },
188
+ getFileElement: function(file, element){
189
+ var selector = '#' + this.prepareId(file) + ' .' + element;
190
+ var elems = $$(selector);
191
+ if(!elems[0]) {
192
+ try {
193
+ console.log(selector);
194
+ } catch (e2) {
195
+ alert(selector);
196
+ }
197
+ }
198
+
199
+ return $$('#' + this.prepareId(file) + ' .' + element)[0];
200
+ },
201
+ getImageByFile: function(file) {
202
+ if (this.getIndexByFile(file)===null) {
203
+ return false;
204
+ }
205
+
206
+ return this.images[this.getIndexByFile(file)];
207
+ },
208
+ getIndexByFile: function(file) {
209
+ var index;
210
+ this.images.each(function (item, i) {
211
+ if (item.file == file) {
212
+ index = i;
213
+ }
214
+ });
215
+ return index;
216
+ },
217
+ updateUseDefault: function ()
218
+ {
219
+ if (this.getElement('default')) {
220
+ this.getElement('default').select('input').each(function(input){
221
+ $(this.containerId).select('.cell-' + input.value + ' input').each(function(radio) {
222
+ radio.disabled = input.checked;
223
+ });
224
+ }.bind(this));
225
+ }
226
+
227
+ if (arguments.length == 0) {
228
+ this.container.setHasChanges();
229
+ }
230
+ },
231
+ handleUploadProgress: function (file) {
232
+
233
+ },
234
+ handleUploadError: function (fileId) {
235
+
236
+ }
237
+ };
238
+
239
+ Product.AttributesBridge = {
240
+ tabsObject: false,
241
+ bindTabs2Attributes: {},
242
+ bind: function(tabId, attributesObject) {
243
+ this.bindTabs2Attributes[tabId] = attributesObject;
244
+ },
245
+ getAttributes: function(tabId) {
246
+ return this.bindTabs2Attributes[tabId];
247
+ },
248
+ setTabsObject: function(tabs) {
249
+ this.tabsObject = tabs;
250
+ },
251
+ getTabsObject: function() {
252
+ return this.tabsObject;
253
+ },
254
+ addAttributeRow: function(data)
255
+ {
256
+ $H(data).each(function(item){
257
+ if(this.getTabsObject().activeTab.name!=item.key) {
258
+ this.getTabsObject().showTabContent($(item.key));
259
+ }
260
+ this.getAttributes(item.key).addRow(item.value);
261
+ }.bind(this));
262
+ }
263
+ };
264
+
265
+ Product.Attributes = Class.create();
266
+ Product.Attributes.prototype = {
267
+ config: {},
268
+ containerId: null,
269
+ initialize: function(containerId) {
270
+ this.containerId = containerId;
271
+ },
272
+ setConfig: function(config) {
273
+ this.config = config;
274
+ Product.AttributesBridge.bind(this.getConfig().tab_id, this);
275
+ },
276
+ getConfig: function () {
277
+ return this.config;
278
+ },
279
+ create: function () {
280
+ var win = window.open(this.getConfig().url, 'new_attribute', 'width=900,height=600,resizable=1,scrollbars=1');
281
+ win.focus();
282
+ },
283
+ addRow: function(html) {
284
+ var attributesContainer = $$('#group_fields' + this.getConfig().group_id + ' .form-list tbody')[0];
285
+ Element.insert(attributesContainer, {bottom: html});
286
+
287
+ var childs = attributesContainer.childElements();
288
+ var element = childs[childs.size()-1].select('input','select','textarea')[0];
289
+ if (element) {
290
+ window.scrollTo(0, Position.cumulativeOffset(element)[1] + element.offsetHeight);
291
+ }
292
+ }
293
+ };
294
+
295
+ Product.Configurable = Class.create();
296
+ Product.Configurable.prototype = {
297
+ initialize: function (attributes, links, idPrefix, grid, readonly) {
298
+ this.templatesSyntax = new RegExp('(^|.|\\r|\\n)(\'{{\\s*(\\w+)\\s*}}\')', "");
299
+ this.attributes = attributes; // Attributes
300
+ this.idPrefix = idPrefix; // Container id prefix
301
+ this.links = $H(links); // Associated products
302
+ this.newProducts = []; // For product that's created througth Create Empty and Copy from Configurable
303
+ this.readonly = readonly;
304
+
305
+ /* Generation templates */
306
+ this.addAttributeTemplate = new Template($(idPrefix + 'attribute_template').innerHTML.replace(/__id__/g,"'{{html_id}}'").replace(/ template no-display/g,''), this.templatesSyntax);
307
+ this.addValueTemplate = new Template($(idPrefix + 'value_template').innerHTML.replace(/__id__/g,"'{{html_id}}'").replace(/ template no-display/g,''), this.templatesSyntax);
308
+ this.pricingValueTemplate = new Template($(idPrefix + 'simple_pricing').innerHTML, this.templatesSyntax);
309
+ this.pricingValueViewTemplate = new Template($(idPrefix + 'simple_pricing_view').innerHTML, this.templatesSyntax);
310
+
311
+ this.container = $(idPrefix + 'attributes');
312
+
313
+ /* Listeners */
314
+ this.onLabelUpdate = this.updateLabel.bindAsEventListener(this); // Update attribute label
315
+ this.onValuePriceUpdate = this.updateValuePrice.bindAsEventListener(this); // Update pricing value
316
+ this.onValueTypeUpdate = this.updateValueType.bindAsEventListener(this); // Update pricing type
317
+ this.onValueDefaultUpdate = this.updateValueUseDefault.bindAsEventListener(this);
318
+
319
+ /* Grid initialization and attributes initialization */
320
+ this.createAttributes(); // Creation of default attributes
321
+
322
+ this.grid = grid;
323
+ this.grid.rowClickCallback = this.rowClick.bind(this);
324
+ this.grid.initRowCallback = this.rowInit.bind(this);
325
+ this.grid.checkboxCheckCallback = this.registerProduct.bind(this); // Associate/Unassociate simple product
326
+
327
+ this.grid.rows.each(function(row) {
328
+ this.rowInit(this.grid, row);
329
+ }.bind(this));
330
+ },
331
+ createAttributes: function() {
332
+ this.attributes.each(function(attribute, index) {
333
+ //var li = Builder.node('li', {className:'attribute'});
334
+ var li = $(document.createElement('LI'));
335
+ li.className = 'attribute';
336
+ li.id = this.idPrefix + '_attribute_' + index;
337
+ attribute.html_id = li.id;
338
+ if(attribute && attribute.label && attribute.label.blank()) {
339
+ attribute.label = '&nbsp;'
340
+ }
341
+ li.update(this.addAttributeTemplate.evaluate(attribute));
342
+ li.attributeObject = attribute;
343
+
344
+ this.container.appendChild(li);
345
+ li.attributeValues = li.down('.attribute-values');
346
+
347
+ if (attribute.values) {
348
+ attribute.values.each(function(value){
349
+ this.createValueRow(li, value); // Add pricing values
350
+ }.bind(this));
351
+ }
352
+
353
+ /* Observe label change */
354
+ Event.observe(li.down('.attribute-label'),'change', this.onLabelUpdate);
355
+ Event.observe(li.down('.attribute-label'),'keyup', this.onLabelUpdate);
356
+ }.bind(this));
357
+ if (!this.readonly) {
358
+ // Creation of sortable for attributes sorting
359
+ Sortable.create(this.container, {handle:'attribute-name-container',onUpdate:this.updatePositions.bind(this)});
360
+ }
361
+ this.updateSaveInput();
362
+ },
363
+
364
+ updateLabel: function (event) {
365
+ var li = Event.findElement(event, 'LI');
366
+ li.attributeObject.label = Event.element(event).value;
367
+ this.updateSaveInput();
368
+ },
369
+ updatePositions: function(param) {
370
+ this.container.childElements().each(function(row, index) {
371
+ row.attributeObject.position = index;
372
+ });
373
+ this.updateSaveInput();
374
+ },
375
+ addNewProduct: function(productId, attributes) {
376
+ if (this.checkAttributes(attributes)) {
377
+ this.links.set(productId, this.cloneAttributes(attributes));
378
+ } else {
379
+ this.newProducts.push(productId);
380
+ }
381
+
382
+ this.updateGrid();
383
+ this.updateValues();
384
+ this.grid.reload(null);
385
+ },
386
+ createEmptyProduct: function() {
387
+ this.createPopup(this.createEmptyUrl)
388
+ },
389
+ createNewProduct: function() {
390
+ this.createPopup(this.createNormalUrl);
391
+ },
392
+ createPopup: function(url) {
393
+ if (this.win && !this.win.closed) {
394
+ this.win.close();
395
+ }
396
+
397
+ this.win = window.open(url, '','width=1000,height=700,resizable=1,scrollbars=1');
398
+ this.win.focus();
399
+ },
400
+ registerProduct: function(grid, element, checked) {
401
+ if(checked){
402
+ if(element.linkAttributes) {
403
+ this.links.set(element.value, element.linkAttributes);
404
+ }
405
+ }
406
+ else{
407
+ this.links.unset(element.value);
408
+ }
409
+ this.updateGrid();
410
+ this.grid.rows.each(function(row) {
411
+ this.revalidateRow(this.grid, row);
412
+ }.bind(this));
413
+ this.updateValues();
414
+ },
415
+ updateProduct: function(productId, attributes) {
416
+ var isAssociated = false;
417
+
418
+ if (typeof this.links.get(productId) != 'undefined') {
419
+ isAssociated = true;
420
+ this.links.unset(productId);
421
+ }
422
+
423
+ if (isAssociated && this.checkAttributes(attributes)) {
424
+ this.links.set(productId, this.cloneAttributes(attributes));
425
+ } else if (isAssociated) {
426
+ this.newProducts.push(productId);
427
+ }
428
+
429
+ this.updateGrid();
430
+ this.updateValues();
431
+ this.grid.reload(null);
432
+ },
433
+ cloneAttributes: function (attributes) {
434
+ var newObj = [];
435
+ for (var i=0, length=attributes.length; i<length; i++) {
436
+ newObj[i] = Object.clone(attributes[i]);
437
+ }
438
+ return newObj;
439
+ },
440
+ rowClick: function(grid, event) {
441
+ var trElement = Event.findElement(event, 'tr');
442
+ var isInput = Event.element(event).tagName.toUpperCase() == 'INPUT';
443
+
444
+ if ($(Event.findElement(event, 'td')).down('a')) {
445
+ return;
446
+ }
447
+
448
+ if(trElement){
449
+ var checkbox = $(trElement).down('input');
450
+ if(checkbox && !checkbox.disabled){
451
+ var checked = isInput ? checkbox.checked : !checkbox.checked;
452
+ grid.setCheckboxChecked(checkbox, checked);
453
+ }
454
+ }
455
+ },
456
+ rowInit: function(grid, row) {
457
+ var checkbox = $(row).down('.checkbox');
458
+ var input = $(row).down('.value-json');
459
+
460
+ if(checkbox && input) {
461
+ checkbox.linkAttributes = input.value.evalJSON();
462
+ if(!checkbox.checked) {
463
+ if(!this.checkAttributes(checkbox.linkAttributes)) {
464
+ $(row).addClassName('invalid');
465
+ checkbox.disable();
466
+ } else {
467
+ $(row).removeClassName('invalid');
468
+ checkbox.enable();
469
+ }
470
+ }
471
+ }
472
+ },
473
+ // Added by QS
474
+ revalidateRowAfterReload : function(grid, row) {
475
+ var checkbox = $(row).down('.checkbox');
476
+ if (checkbox) {
477
+ if (!checkbox.checked) {
478
+ if (!this.checkAttributes(checkbox.linkAttributes)) {
479
+ $(row).addClassName('invalid');
480
+ checkbox.disable();
481
+ } else {
482
+ $(row).removeClassName('invalid');
483
+ checkbox.enable();
484
+ }
485
+ } else {
486
+ if (!this.checkAttributes(checkbox.linkAttributes)) {
487
+ $(row).addClassName('invalid');
488
+ checkbox.checked = false;
489
+ this.updateValues();
490
+ } else {
491
+ $(row).removeClassName('invalid');
492
+ checkbox.enable();
493
+ this.updateValues();
494
+ }
495
+ }
496
+ }
497
+ },
498
+ // End
499
+ revalidateRow: function(grid, row) {
500
+ var checkbox = $(row).down('.checkbox');
501
+ if(checkbox ) {
502
+ if(!checkbox.checked) {
503
+ if(!this.checkAttributes(checkbox.linkAttributes)) {
504
+ $(row).addClassName('invalid');
505
+ checkbox.disable();
506
+ } else {
507
+ $(row).removeClassName('invalid');
508
+ checkbox.enable();
509
+ }
510
+ }
511
+ }
512
+ },
513
+ checkAttributes: function(attributes) {
514
+ var result = true;
515
+ this.links.each(function(pair) {
516
+ var fail = false;
517
+ for(var i = 0; i < pair.value.length && !fail; i++) {
518
+ for(var j = 0; j < attributes.length && !fail; j ++) {
519
+ if(pair.value[i].attribute_id == attributes[j].attribute_id && pair.value[i].value_index != attributes[j].value_index) {
520
+ fail = true;
521
+ }
522
+ }
523
+ }
524
+ if(!fail) {
525
+ result = false;
526
+ }
527
+ });
528
+ return result;
529
+ },
530
+ updateGrid: function () {
531
+ this.grid.reloadParams = {'products[]':this.links.keys().size() ? this.links.keys() : [0], 'new_products[]':this.newProducts};
532
+ },
533
+ updateValues: function () {
534
+ var uniqueAttributeValues = $H({});
535
+ /* Collect unique attributes */
536
+ this.links.each(function(pair) {
537
+ for (var i = 0, length=pair.value.length; i < length; i ++) {
538
+ var attribute = pair.value[i];
539
+ if (uniqueAttributeValues.keys().indexOf(attribute.attribute_id) == -1) {
540
+ uniqueAttributeValues.set(attribute.attribute_id, $H({}));
541
+ }
542
+ uniqueAttributeValues.get(attribute.attribute_id).set(attribute.value_index, attribute);
543
+ }
544
+ });
545
+ /* Updating attributes value container */
546
+ this.container.childElements().each(function(row) {
547
+ var attribute = row.attributeObject;
548
+ for (var i = 0, length=attribute.values.length; i < length; i ++) {
549
+ if (uniqueAttributeValues.keys().indexOf(attribute.attribute_id) == -1
550
+ || uniqueAttributeValues.get(attribute.attribute_id).keys().indexOf(attribute.values[i].value_index)==-1) {
551
+ row.attributeValues.childElements().each(function(elem) {
552
+ if (elem.valueObject.value_index==attribute.values[i].value_index) {
553
+ elem.remove();
554
+ }
555
+ });
556
+ attribute.values[i] = undefined;
557
+
558
+ } else {
559
+ uniqueAttributeValues.get(attribute.attribute_id).unset(attribute.values[i].value_index);
560
+ }
561
+ }
562
+ attribute.values = attribute.values.compact();
563
+ if (uniqueAttributeValues.get(attribute.attribute_id)) {
564
+ uniqueAttributeValues.get(attribute.attribute_id).each(function(pair) {
565
+ attribute.values.push(pair.value);
566
+ this.createValueRow(row, pair.value);
567
+ }.bind(this));
568
+ }
569
+ }.bind(this));
570
+ this.updateSaveInput();
571
+ this.updateSimpleForm();
572
+ },
573
+ createValueRow: function(container, value) {
574
+ var templateVariables = $H({});
575
+ if(!this.valueAutoIndex) {
576
+ this.valueAutoIndex = 1;
577
+ }
578
+ templateVariables.set('html_id', container.id + '_' + this.valueAutoIndex);
579
+ templateVariables = templateVariables.merge(value);
580
+ var pricingValue = parseFloat(templateVariables.get('pricing_value'));
581
+ if (!isNaN(pricingValue)) {
582
+ templateVariables.set('pricing_value', pricingValue);
583
+ } else {
584
+ templateVariables.unset('pricing_value');
585
+ }
586
+ this.valueAutoIndex++;
587
+
588
+ //var li = $(Builder.node('li', {className:'attribute-value'}));
589
+ var li = $(document.createElement('LI'));
590
+ li.className = 'attribute-value';
591
+ li.id = templateVariables.get('html_id');
592
+ li.update(this.addValueTemplate.evaluate(templateVariables));
593
+ li.valueObject = value;
594
+ if (typeof li.valueObject.is_percent == 'undefined') {
595
+ li.valueObject.is_percent = 0;
596
+ }
597
+
598
+ if (typeof li.valueObject.pricing_value == 'undefined') {
599
+ li.valueObject.pricing_value = '';
600
+ }
601
+
602
+ container.attributeValues.appendChild(li);
603
+ var priceField = li.down('.attribute-price');
604
+ var priceTypeField = li.down('.attribute-price-type');
605
+
606
+ if(parseInt(value.is_percent)) {
607
+ priceTypeField.options[1].selected = !(priceTypeField.options[0].selected = false);
608
+ } else {
609
+ priceTypeField.options[1].selected = !(priceTypeField.options[0].selected = true);
610
+ }
611
+ Event.observe(priceField, 'keyup', this.onValuePriceUpdate);
612
+ Event.observe(priceField, 'change', this.onValuePriceUpdate);
613
+ Event.observe(priceTypeField, 'change', this.onValueTypeUpdate);
614
+ var useDefaultEl = li.down('.attribute-use-default-value');
615
+ if (useDefaultEl) {
616
+ if (li.valueObject.use_default_value) {
617
+ useDefaultEl.checked = true;
618
+ this.updateUseDefaultRow(useDefaultEl, li);
619
+ }
620
+ Event.observe(useDefaultEl, 'change', this.onValueDefaultUpdate);
621
+ }
622
+ },
623
+ updateValuePrice: function(event) {
624
+ var li = Event.findElement(event, 'LI');
625
+ li.valueObject.pricing_value = (Event.element(event).value.blank() ? null : Event.element(event).value);
626
+ this.updateSimpleForm();
627
+ this.updateSaveInput();
628
+ },
629
+ updateValueType: function(event) {
630
+ var li = Event.findElement(event, 'LI');
631
+ li.valueObject.is_percent = (Event.element(event).value.blank() ? null : Event.element(event).value);
632
+ this.updateSimpleForm();
633
+ this.updateSaveInput();
634
+ },
635
+ updateValueUseDefault: function(event) {
636
+ var li = Event.findElement(event, 'LI');
637
+ var useDefaultEl = Event.element(event);
638
+ li.valueObject.use_default_value = useDefaultEl.checked;
639
+ this.updateUseDefaultRow(useDefaultEl, li);
640
+ },
641
+ updateUseDefaultRow: function(useDefaultEl, li)
642
+ {
643
+ var priceField = li.down('.attribute-price');
644
+ var priceTypeField = li.down('.attribute-price-type');
645
+ if (useDefaultEl.checked) {
646
+ priceField.disabled = true;
647
+ priceTypeField.disabled = true;
648
+ }
649
+ else {
650
+ priceField.disabled = false;
651
+ priceTypeField.disabled = false;
652
+ }
653
+ this.updateSimpleForm();
654
+ this.updateSaveInput();
655
+ },
656
+ updateSaveInput: function() {
657
+ $(this.idPrefix + 'save_attributes').value = this.attributes.toJSON();
658
+ $(this.idPrefix + 'save_links').value = this.links.toJSON();
659
+ },
660
+ initializeAdvicesForSimpleForm: function() {
661
+ if ($(this.idPrefix + 'simple_form').advicesInited) {
662
+ return;
663
+ }
664
+
665
+ $(this.idPrefix + 'simple_form').select('td.value').each(function (td) {
666
+ var adviceContainer = $(Builder.node('div'));
667
+ td.appendChild(adviceContainer);
668
+ td.select('input', 'select').each(function(element){
669
+ element.advaiceContainer = adviceContainer;
670
+ });
671
+ });
672
+ $(this.idPrefix + 'simple_form').advicesInited = true;
673
+ },
674
+ quickCreateNewProduct: function() {
675
+ this.initializeAdvicesForSimpleForm();
676
+ $(this.idPrefix + 'simple_form').removeClassName('ignore-validate');
677
+ var validationResult = $(this.idPrefix + 'simple_form').select('input','select','textarea').collect(
678
+ function(elm) {
679
+ return Validation.validate(elm,{useTitle : false, onElementValidate : function(){}});
680
+ }
681
+ ).all();
682
+ $(this.idPrefix + 'simple_form').addClassName('ignore-validate');
683
+
684
+ if (!validationResult) {
685
+ return;
686
+ }
687
+
688
+ var params = Form.serializeElements(
689
+ $(this.idPrefix + 'simple_form').select('input','select','textarea'),
690
+ true
691
+ );
692
+ params.form_key = FORM_KEY;
693
+ $('messages').update();
694
+ new Ajax.Request(this.createQuickUrl, {
695
+ parameters: params,
696
+ method:'post',
697
+ area: $(this.idPrefix + 'simple_form'),
698
+ onComplete: this.quickCreateNewProductComplete.bind(this)
699
+ });
700
+ },
701
+ // Added by QS
702
+ quickCombinations: function() {
703
+ this.initializeAdvicesForSimpleForm();
704
+ $(this.idPrefix + 'combination_form').removeClassName('ignore-validate');
705
+ var validationResult = $(this.idPrefix + 'combination_form').select('input','select','textarea').collect(
706
+ function(elm) {
707
+ return Validation.validate(elm,{useTitle : false, onElementValidate : function(){}});
708
+ }
709
+ ).all();
710
+ $(this.idPrefix + 'combination_form').addClassName('ignore-validate');
711
+
712
+ if (!validationResult) {
713
+ return;
714
+ }
715
+
716
+ var params = Form.serializeElements(
717
+ $(this.idPrefix + 'combination_form').select('input','select','textarea'),
718
+ true
719
+ );
720
+ params.form_key = FORM_KEY;
721
+ params.attribute_values = this.attributes;
722
+ $('messages').update();
723
+
724
+ new Ajax.Request(this.createCombinationsUrl, {
725
+ parameters: params,
726
+ method:'post',
727
+ area: $(this.idPrefix + 'combination_form'),
728
+ onComplete: this.quickCombinationComplete.bind(this)
729
+ });
730
+ },
731
+ quickCombinationComplete : function(transport) {
732
+ var result = transport.responseText.evalJSON();
733
+
734
+ if (result.error) {
735
+ if (result.error.fields) {
736
+ $(this.idPrefix + 'simple_form').removeClassName(
737
+ 'ignore-validate');
738
+ $H(result.error.fields)
739
+ .each(
740
+ function(pair) {
741
+ $('simple_product_' + pair.key).value = pair.value;
742
+ $('simple_product_' + pair.key + '_autogenerate').checked = false;
743
+ toggleValueElements(
744
+ $('simple_product_' + pair.key + '_autogenerate'),
745
+ $('simple_product_' + pair.key + '_autogenerate').parentNode);
746
+ Validation.ajaxError(
747
+ $('simple_product_' + pair.key),
748
+ result.error.message);
749
+ });
750
+ $(this.idPrefix + 'simple_form')
751
+ .addClassName('ignore-validate');
752
+ } else {
753
+ if (result.error.message) {
754
+ alert(result.error.message);
755
+ } else {
756
+ alert(result.error);
757
+ }
758
+ }
759
+ return;
760
+ } else if (result.messages) {
761
+ $('messages').update(result.messages);
762
+ }
763
+
764
+ result.attributes
765
+ .each( function(attribute) {
766
+ var attr = this.getAttributeById(attribute.attribute_id);
767
+ if (!this.getValueByIndex(attr, attribute.value_index)
768
+ && result.pricing
769
+ && result.pricing[attr.attribute_code]) {
770
+
771
+ attribute.is_percent = result.pricing[attr.attribute_code].is_percent;
772
+ attribute.pricing_value = (result.pricing[attr.attribute_code].value == null ? ''
773
+ : result.pricing[attr.attribute_code].value);
774
+ }
775
+ }.bind(this));
776
+
777
+ this.attributes.each( function(attribute) {
778
+ if ($('simple_product_' + attribute.attribute_code)) {
779
+ $('simple_product_' + attribute.attribute_code).value = '';
780
+ }
781
+ }.bind(this));
782
+
783
+ result.product_ids.each( function(product_id) {
784
+ this.links.set(product_id, result.attributes);
785
+ }.bind(this));
786
+
787
+ //this.links.set(result.product_id, result.attributes);
788
+ this.updateGrid();
789
+ this.updateValues();
790
+ this.grid.reload();
791
+ this.grid.rows.each( function(row) {
792
+ this.revalidateRowAfterReload(this.grid, row);
793
+ }.bind(this));
794
+ this.updateValues();
795
+ },
796
+ // End
797
+ quickCreateNewProductComplete: function (transport) {
798
+ var result = transport.responseText.evalJSON();
799
+
800
+ if (result.error) {
801
+ if (result.error.fields) {
802
+ $(this.idPrefix + 'simple_form').removeClassName('ignore-validate');
803
+ $H(result.error.fields).each(function(pair){
804
+ $('simple_product_' + pair.key).value = pair.value;
805
+ $('simple_product_' + pair.key + '_autogenerate').checked = false;
806
+ toggleValueElements(
807
+ $('simple_product_' + pair.key + '_autogenerate'),
808
+ $('simple_product_' + pair.key + '_autogenerate').parentNode
809
+ );
810
+ Validation.ajaxError($('simple_product_' + pair.key), result.error.message);
811
+ });
812
+ $(this.idPrefix + 'simple_form').addClassName('ignore-validate');
813
+ } else {
814
+ if (result.error.message) {
815
+ alert(result.error.message);
816
+ }
817
+ else {
818
+ alert(result.error);
819
+ }
820
+ }
821
+ return;
822
+ } else if(result.messages) {
823
+ $('messages').update(result.messages);
824
+ }
825
+
826
+
827
+ result.attributes.each(function(attribute) {
828
+ var attr = this.getAttributeById(attribute.attribute_id);
829
+ if (!this.getValueByIndex(attr, attribute.value_index)
830
+ && result.pricing
831
+ && result.pricing[attr.attribute_code]) {
832
+
833
+ attribute.is_percent = result.pricing[attr.attribute_code].is_percent;
834
+ attribute.pricing_value = (result.pricing[attr.attribute_code].value == null ? '' : result.pricing[attr.attribute_code].value);
835
+ }
836
+ }.bind(this));
837
+
838
+ this.attributes.each(function(attribute) {
839
+ if ($('simple_product_' + attribute.attribute_code)) {
840
+ $('simple_product_' + attribute.attribute_code).value = '';
841
+ }
842
+ }.bind(this));
843
+
844
+ this.links.set(result.product_id, result.attributes);
845
+ this.updateGrid();
846
+ this.updateValues();
847
+ this.grid.reload();
848
+ },
849
+ checkCreationUniqueAttributes: function () {
850
+ var attributes = [];
851
+ this.attributes.each(function(attribute) {
852
+ attributes.push({
853
+ attribute_id:attribute.attribute_id,
854
+ value_index: $('simple_product_' + attribute.attribute_code).value
855
+ });
856
+ }.bind(this));
857
+
858
+ return this.checkAttributes(attributes);
859
+ },
860
+ getAttributeByCode: function (attributeCode) {
861
+ var attribute = null;
862
+ this.attributes.each(function(item){
863
+ if (item.attribute_code == attributeCode) {
864
+ attribute = item;
865
+ throw $break;
866
+ }
867
+ });
868
+ return attribute;
869
+ },
870
+ getAttributeById: function (attributeId) {
871
+ var attribute = null;
872
+ this.attributes.each(function(item){
873
+ if (item.attribute_id == attributeId) {
874
+ attribute = item;
875
+ throw $break;
876
+ }
877
+ });
878
+ return attribute;
879
+ },
880
+ getValueByIndex: function (attribute, valueIndex) {
881
+ var result = null;
882
+ attribute.values.each(function(value){
883
+ if (value.value_index == valueIndex) {
884
+ result = value;
885
+ throw $break;
886
+ }
887
+ });
888
+ return result;
889
+ },
890
+ showPricing: function (select, attributeCode) {
891
+ var attribute = this.getAttributeByCode(attributeCode);
892
+ if (!attribute) {
893
+ return;
894
+ }
895
+
896
+ select = $(select);
897
+ if (select.value && !$('simple_product_' + attributeCode + '_pricing_container')) {
898
+ Element.insert(select, {after: '<div class="left"></div> <div id="simple_product_' + attributeCode + '_pricing_container" class="left"></div>'});
899
+ var newContainer = select.next('div');
900
+ select.parentNode.removeChild(select);
901
+ newContainer.appendChild(select);
902
+ // Fix visualization bug
903
+ $(this.idPrefix + 'simple_form').down('.form-list').style.width = '100%';
904
+ }
905
+
906
+ var container = $('simple_product_' + attributeCode + '_pricing_container');
907
+
908
+ if (select.value) {
909
+ var value = this.getValueByIndex(attribute,select.value);
910
+ if (!value) {
911
+ if (!container.down('.attribute-price')) {
912
+ if (value == null) {
913
+ value = {};
914
+ }
915
+ container.update(this.pricingValueTemplate.evaluate(value));
916
+ var priceValueField = container.down('.attribute-price');
917
+ var priceTypeField = container.down('.attribute-price-type');
918
+
919
+ priceValueField.attributeCode = attributeCode;
920
+ priceValueField.priceField = priceValueField;
921
+ priceValueField.typeField = priceTypeField;
922
+
923
+ priceTypeField.attributeCode = attributeCode;
924
+ priceTypeField.priceField = priceValueField;
925
+ priceTypeField.typeField = priceTypeField;
926
+
927
+ Event.observe(priceValueField, 'change', this.updateSimplePricing.bindAsEventListener(this));
928
+ Event.observe(priceValueField, 'keyup', this.updateSimplePricing.bindAsEventListener(this));
929
+ Event.observe(priceTypeField, 'change', this.updateSimplePricing.bindAsEventListener(this));
930
+
931
+ $('simple_product_' + attributeCode + '_pricing_value').value = null;
932
+ $('simple_product_' + attributeCode + '_pricing_type').value = null;
933
+ }
934
+ } else if (!isNaN(parseFloat(value.pricing_value))) {
935
+ container.update(this.pricingValueViewTemplate.evaluate({
936
+ 'value': (parseFloat(value.pricing_value) > 0 ? '+' : '') + parseFloat(value.pricing_value)
937
+ + ( parseInt(value.is_percent) > 0 ? '%' : '')
938
+ }));
939
+ $('simple_product_' + attributeCode + '_pricing_value').value = value.pricing_value;
940
+ $('simple_product_' + attributeCode + '_pricing_type').value = value.is_percent;
941
+ } else {
942
+ container.update('');
943
+ $('simple_product_' + attributeCode + '_pricing_value').value = null;
944
+ $('simple_product_' + attributeCode + '_pricing_type').value = null;
945
+ }
946
+ } else if(container) {
947
+ container.update('');
948
+ $('simple_product_' + attributeCode + '_pricing_value').value = null;
949
+ $('simple_product_' + attributeCode + '_pricing_type').value = null;
950
+ }
951
+ },
952
+ updateSimplePricing: function(evt) {
953
+ var element = Event.element(evt);
954
+ if (!element.priceField.value.blank()) {
955
+ $('simple_product_' + element.attributeCode + '_pricing_value').value = element.priceField.value;
956
+ $('simple_product_' + element.attributeCode + '_pricing_type').value = element.typeField.value;
957
+ } else {
958
+ $('simple_product_' + element.attributeCode + '_pricing_value').value = null;
959
+ $('simple_product_' + element.attributeCode + '_pricing_type').value = null;
960
+ }
961
+ },
962
+ updateSimpleForm: function() {
963
+ this.attributes.each(function(attribute) {
964
+ if ($('simple_product_' + attribute.attribute_code)) {
965
+ this.showPricing($('simple_product_' + attribute.attribute_code), attribute.attribute_code);
966
+ }
967
+ }.bind(this));
968
+ }
969
+ }
970
+
971
+ var onInitDisableFieldsList = [];
972
+
973
+ function toogleFieldEditMode(toogleIdentifier, fieldContainer) {
974
+ if($(toogleIdentifier).checked) {
975
+ enableFieldEditMode(fieldContainer);
976
+ } else {
977
+ disableFieldEditMode(fieldContainer);
978
+ }
979
+ }
980
+
981
+ function disableFieldEditMode(fieldContainer) {
982
+ $(fieldContainer).disabled = true;
983
+ if($(fieldContainer + '_hidden')) {
984
+ $(fieldContainer + '_hidden').disabled = true;
985
+ }
986
+ }
987
+
988
+ function enableFieldEditMode(fieldContainer) {
989
+ $(fieldContainer).disabled = false;
990
+ if($(fieldContainer + '_hidden')) {
991
+ $(fieldContainer + '_hidden').disabled = false;
992
+ }
993
+ }
994
+
995
+ function initDisableFields(fieldContainer)
996
+ {
997
+ onInitDisableFieldsList.push(fieldContainer);
998
+ }
999
+
1000
+ function onCompleteDisableInited()
1001
+ {
1002
+ onInitDisableFieldsList.each(function(item){
1003
+ disableFieldEditMode(item);
1004
+ });
1005
+ }
1006
+
1007
+ Event.observe(window, 'load', onCompleteDisableInited);
package.xml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Automatic_Configurables_1dot3</name>
4
+ <version>0.0.8</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://www.opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>This extension will help you to automatically create simple products for configurables.</summary>
10
+ <description>This extension will help you to automatically create simple associated products for configurable products and add them to the grid of associated products. It makes all combinations of attribute values that you will choose. The number of products is not limited. Please remember that you need to save configurable product first to see this module tab.
11
+ Overriden classes:
12
+ Adminhtml_Block_Catalog_Product_Edit_Tab_Super_Config
13
+ And overriden js:
14
+ js/mage/adminhtml/product.js</description>
15
+ <notes>The wrong js file was included</notes>
16
+ <authors><author><name>QuartSoft</name><user>auto-converted</user><email>alexeybulash@gmail.com</email></author></authors>
17
+ <date>2010-05-27</date>
18
+ <time>20:10:49</time>
19
+ <contents><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="quickconfigurables.xml" hash="993e213c74431667274ae1c828e983ec"/></dir><dir name="template"><dir name="quickconfigurables"><dir name="catalog"><dir name="product"><dir name="edit"><dir name="super"><file name="config.phtml" hash="5f9fadc3c04b5b2b35c8e05ed57c5160"/></dir></dir></dir></dir></dir></dir></dir></dir></dir></target><target name="mage"><dir name="js"><dir name="qs"><dir name="adminhtml"><file name="product_13.js" hash="e9309efb7632cb134aedee673b0cecaf"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="QS_Quickconfigurables.xml" hash="2fa9d665b16c54645966e27c693935f3"/></dir></target><target name="magelocal"><dir name="QS"><dir name="Quickconfigurables"><dir name="Block"><dir name="Adminhtml"><dir name="Catalog"><dir name="Product"><dir name="Edit"><dir name="Tab"><dir name="Super"><dir name="Config"><file name="Combination.php" hash="ad3779c9daf8b0bf21bf7a2a168db03a"/></dir><file name="Config.php" hash="ff0bf25c35bb5069e847e3230ce56eeb"/></dir></dir></dir></dir></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="ProductController.php" hash="1f62f04b1d3005c5064278ee790aedd6"/></dir></dir><dir name="etc"><file name="config.xml" hash="72157ba83c8281b13b0b4235328355e8"/></dir><dir name="Helper"><file name="Data.php" hash="a5651545c4121211e4fae9de2a5eddf7"/></dir></dir></dir></target></contents>
20
+ <compatible/>
21
+ <dependencies/>
22
+ </package>