Related select in Magento how I do - magento

It's possibile, in Magento, create two or more related select?
For example Country / Region
I try with jQuery but seem doesn't work.
Best Regards
I try with this code: in Mymodule output
app/design/frontend/base/default/template/mymodule/mymodule.phtml
<div id="continenti">
<?php
include_once 'option.class.php';
$obj = new Option();
$obj->ShowContinenti();
?>
</div>
<div id="nazioni">
Seleziona una nazione:<br>
<select id="sel_nazioni" name="sel_nazioni"><option value="no">Scegli...</option>
</select>
</div>
<div id="result"></div>
In my app/design/frontend/base/default/template/page/html/head.phtml
<script type="text/javascript" src="./jquery/jquery-1.3.2.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#sel_continenti').change(function(){
var cont = $('#sel_continenti').attr('value');
$.post("selection.php", {id_cont:cont}, function(data){
$("#sel_nazioni").empty();
$("div#result").empty();
$("#sel_nazioni").prepend(data);
});
});
$('#sel_nazioni').change(function(){
var id_naz = $('#sel_nazioni').attr('value');
$.post("result.php", {id:id_naz}, function(data){
$("div#result").empty();
$("div#result").prepend(data);
});
});
});
</script>
In my app/code/local/frontname/mymodule/sql/mysql4-install-0.1.0
<?php
$installer = $this;
$installer->startSetup();
$installer->run("
-- DROP TABLE IF EXISTS {$this->getTable('continenti')};
CREATE TABLE {$this->getTable('continenti')}
`id` INT(2) UNSIGNED NOT NULL AUTO_INCREMENT,
`continente` VARCHAR(40) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
INSERT INTO `continenti` (`id`, `continente`) VALUES
(1, 'Europa'),
(2, 'Africa'),
(3, 'Sud America');
-- DROP TABLE IF EXISTS {$this->getTable('nazioni')};
CREATE TABLE {$this->getTable('nazioni')}
`id` INT(3) UNSIGNED NOT NULL AUTO_INCREMENT,
`id_cont` INT(2) UNSIGNED NOT NULL,
`nazione` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=14 ;
INSERT INTO {$this->getTable('nazioni')} (`id`, `id_cont`, `nazione`) VALUES
(1, 1, 'Spagna'),
(2, 1, 'Francia'),
(3, 1, 'Italia'),
(4, 1, 'Germania'),
(5, 1, 'Belgio'),
(6, 2, 'Egitto'),
(7, 2, 'Marocco'),
(8, 2, 'Tunisia'),
(9, 2, 'Uganda'),
(10, 3, 'Argentina'),
(11, 3, 'Cile'),
(13, 3, 'Brasile');
")
;
$installer->endSetup();
File result.php
<?php
include_once 'option.class.php';
$obj = new Option();
$obj->ShowResult();
?>
File selection.php
<?php
include_once 'option.class.php';
$obj = new Option();
$obj->ShowNazioni();
?>
The first select appear with the content of Region Table but, if I click and choise one region, the second select doesn't load data inside itself.
EDIT: resolved!
I change my head.phtml in
<script type="text/javascript" src="./jquery/jquery-1.3.2.js"></script>
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery('#sel_continenti').change(function(){
var cont = jQuery('#sel_continenti').attr('value');
jQuery.post("selection.php", {id_cont:cont}, function(data){
jQuery("#sel_nazioni").empty();
jQuery("div#result").empty();
jQuery("#sel_nazioni").prepend(data);
});
});
jQuery('#sel_nazioni').change(function(){
var id_naz = jQuery('#sel_nazioni').attr('value');
jQuery.post("result.php", {id:id_naz}, function(data){
jQuery("div#result").empty();
jQuery("div#result").prepend(data);
});
});
});
</script>
I change $ with jQuery word!

Magento already has this kind of selects in checkout addresses phtmls, just that it uses Prototype.
<div class="field">
<label for="billing:region_id" class="required"><em>*</em><?php echo $this->__('State/Province') ?></label>
<div class="input-box">
<select id="billing:region_id" name="billing[region_id]" title="<?php echo $this->__('State/Province') ?>" class="validate-select" style="display:none;">
<option value=""><?php echo $this->__('Please select region, state or province') ?></option>
</select>
<script type="text/javascript">
//<![CDATA[
$('billing:region_id').setAttribute('defaultValue', "<?php echo $this->getAddress()->getRegionId() ?>");
//]]>
</script>
<input type="text" id="billing:region" name="billing[region]" value="<?php echo $this->escapeHtml($this->getAddress()->getRegion()) ?>" title="<?php echo $this->__('State/Province') ?>" class="input-text <?php echo $this->helper('customer/address')->getAttributeValidationClass('region') ?>" style="display:none;" />
</div>
<div class="field">
<label for="billing:country_id" class="required"><em>*</em><?php echo $this->__('Country') ?></label>
<div class="input-box">
<?php echo $this->getCountryHtmlSelect('billing') ?>
</div>
var billingRegionUpdater = new RegionUpdater('billing:country_id', 'billing:region', 'billing:region_id', <?php echo $this->helper('directory')->getRegionJson() ?>, undefined, 'billing:postcode');

Related

How to prepopulate a cascaded drop down and attachment on validation failure

I have 2 drop downs, just for simplicity let's say they are Country / States.
<select id="country_id" name = "country_id">
<option value="">Select...</option>
<?php foreach ($countries as $country): ?>
<option value="<?php echo $country->id; ?>" <?php if (null !== set_value("country_id") && set_value("country_id") == $country->id) : echo ' selected '; ?>>$country->name;
<?php endforeach?>
</select>
<select id="state_id" name = "state_id">
<option value="">Select...</option>
</select>
<input type="file" name="attachment_id" value="" />
What I do is when the country is selected I populate the states. This I do using AJAX and ".change" and this works well
The problem I'm having is when I do form_validation and
$this->form_validation->run() == FALSE
Then I reload all controls using set_value, which does work for the first drop down (the countries) just fine, however the second drop down stays empty( as there was no ".change" triggered on the "country_id" to populate "state_id".
Similarly I am asked to re-attach the file
So what I need and is not working is after form_validation fail to
Load up second drop down with data => RESOLVED see below with .trigger event
Select the previous selection int he second drop down => ALMOST RESOLVED however only if I use alert :)
The attachment should still stay attached until form is dismissed or committed successfully => NOT RESOLVED
I feel like I need to manually trigger the data change to get (1) but in my case I have a foreach (see above) where I just add lines and if the selection is the same I simply set is as "selected" but nothing happens after.
Here is the AJAX part
<script>
$(document).ready(function(){
$("#country_id").change(function(){
$.ajax({
url:"<?php echo base_url(); ?>location/getCountries",
data: {country_id: $(this).val()},
type: "POST",
success: function(data){
$("#state_id").html(data);
$("#state_id").val(null);
}
});
});
<?php if (!empty(set_value('country_id'))) : ?>
var value = "<?php echo set_value('country_id'); ?>";
$('#country_id').val(value);
$('#country_id').trigger('change');
<?php endif; ?>
<?php if (!empty(set_value('state_id'))) : ?>
var value = "<?php echo set_value('state_id'); ?>";
//without this alert the selection doesn't work
alert(value);
$('#state_id').val(value);
$('#state_id').trigger('change');
<?php endif; ?>
});
</script>
So I am getting the values saved only if I use an alert. This seems to be an asynchronous execution where the selection of second drop down is done before it gets populated, so the last thing to do is to figure out how to wait.
Still to do the attachment part
Thanks in advance!
Add this code at the end of view page
For country dropdown
<?php if (!empty(set_value('country_id'))) : ?>
<script type="text/javascript">
var value = "<?php echo set_value('country_id'); ?>";
$('select[name="country_id"]').find('option[value="'+value+'"]').attr("selected",true);
</script>
<?php endif; ?>
For state dropdown
<?php if (!empty(set_value('state_id'))) : ?>
<script type="text/javascript">
var value = "<?php echo set_value('state_id'); ?>";
$('select[name="state_id"]').find('option[value="'+value+'"]').attr("selected",true);
</script>
<?php endif; ?>
Follow the below points
1) For select tag, use set_select(), like this
<select name="myselect">
<option value="one" <?php echo set_select('myselect', 'one', TRUE); ?> >One</option>
<option value="two" <?php echo set_select('myselect', 'two'); ?> >Two</option>
<option value="three" <?php echo set_select('myselect', 'three'); ?> >Three</option>
</select>
2) If the form validation failed, call your ajax function to set second drop down.
3) For attachment, Whatever result of the form validation, first upload the image and keep the image path in session variable. After successful form validation, save the data into database and destroy the session variable.
edited >>>
**html**
<?php
if (isset($edit) && !empty($edit)) { //while editing
$StateID = $edit['StateID'];
$CountryID = $edit['CountryID'];
} else { // while adding
$StateID = set_value('StateID');
$CountryID = set_value('CountryID');
} ?>
<div class="col-3">
<div class="form-group">
<label class="mb-0">Country</label>
<select class="form-control Country" id="country" name="CountryID" data_state_value="<?php echo $StateID; ?>" >
<option value="">Select Country</option>
<?php
foreach ($country as $row) {
$selected = ($row->id == $CountryID) ? 'selected' : '';
echo '<option value="' . $row->id . '"' . $selected . '>' . $row->country_name . '</option>';
}
?>
</select>
<span class="text-danger font9"><?php echo form_error('CountryID'); ?></span>
</div>
</div>
<div class="col-3">
<div class="form-group">
<label class="mb-0">State</label>
<select class="form-control State" id="State" name="StateID">
</select>
<span class="text-danger font9"><?php echo form_error('StateID'); ?></span>
</div>
</div>
**script**
$(document).on('change', '.Country', function () {
var country_id = $(this).val();
var state_id = $(this).attr('data_state_value');
url = $("body").attr('b_url');
$.ajax({
url: url + "Education/fetch_state",
method: "POST",
data: {
country_id: country_id,
state_id: state_id
},
success: function (res) {
var response = $.parseJSON(res);
$('#State').html('<option value="">Select State</option>' + response.view);
$('.State').trigger('change');
}
});
});
$('.Country').trigger('change');
**controller**
public function fetch_state() {
$data = array();
if (isset($_POST['country_id']) && !empty($_POST['country_id'])) {
$states = $this->Location_model->fetch_state($this->input->post('country_id')); // array of states
$view = array();
if (!empty($states)) {
foreach ($states as $val) {
$selected = (isset($_POST['state_id']) && !empty($_POST['state_id']) && $_POST['state_id'] == $val['id']) ? 'selected' : '';
$view[] = "<option value='" . $val['id'] . "'" . $selected . ">" . $val['states_name'] . "</option>";
}
$data['view'] = $view;
$data['status'] = 0;
} else {
$data['status'] = 0;
$data['view'] = '<option value="">No State Found</option>';
}
} else {
$data['status'] = 0;
$data['view'] = '<option value="">Select State</option>';
}
echo json_encode($data);
}

Get select information before submitting

well i was reading around the solutions that stack-overflow was giving but i couldn't find the correct one... so here is my question:
Im creating a form with multiple selects ( not the select multiple="true" ) , no , i mean a form with lets say 4 different selects... retrieving data from a database so if i fill my first "select" lets say Style1 then i would like to get the "style1" selection so i can configure my second select query based on that and i can DISTINCT the values im looking for... i don't know if you get my idea, i've read i need to use AJAX but i couldn't figure out how to...
<form method="post">
<select name="category">
<?php $test = mysql_query("SELECT category FROM test_table GROUP BY category");
while($testing = mysql_fetch_array($test)){
echo "<option value=".$testing["category"].">".$testing["category"]."</option>";
}
?>
</select>
<select name="model">
<?php $test2 = mysql_query("SELECT model FROM test_table WHERE model = 'TRYING TO COMPARE WITH THE VALUE WITH THE FIRST SELECT' GROUP BY model");
while($testing2 = mysql_fetch_array($test2)){
echo "<option value=".$testing2["model"].">".$testing2["model"]."</option>";
</select>
</form>
Well that was just to get an idea, is not like the real one but its a pretty close example.
Sorry for my weird spelling
Thanks for your help !
<form method="post">
<select name="category" onchange="javascript:getDroupDownValues(this.value);">
<?php $test = mysql_query("SELECT category FROM test_table GROUP BY category");?>
<?php while($testing = mysql_fetch_array($test)):?>
<option value="<?php echo $testing["category"];?>"><?php echo $testing["category"];?></option>
<?php endwhile;?>
</select>
<div id="model-category">
</div>
</form>
<script type="text/javascript">
function getDroupDownValues(value)
{
jQuery.ajax({
dataType: "html",
type: "POST",
evalScripts: true,
url: 'your ajax url', // example your site url /ajax.php
data: ({category:value}),
success: function(data, textStatus) {
jQuery("#model-category").html(data);
}
});
}
</script>
Now in ajax.php script
<?php if(isset($_REQUEST['category']) && $_REQUEST['category']):?>
<select name="model">
<?php $test2 = mysql_query("SELECT model FROM test_table WHERE model = '{$_REQUEST['category']}' GROUP BY model");?>
<?php while($testing2 = mysql_fetch_array($test2)):?>
<option value="<?php echo $testing2["model"];?>"><?php echo $testing2["model"];?></option>
<?php endwhile;?>
</select>
<?php endif;?>

Display Dynamic SKU on configurable product view Magento

I have this script to show the dynamic sku on select option, but i cannot get working.
Is loading the correct sku, but on select nothing happen.
This code get list of sku on Javascript and update a div on select option for product on configurable product view.
<?php
$_product = $this->getProduct();
$_attributes = Mage::helper('core')->decorateArray($this->getAllowAttributes());
?>
<?php if ($_product->isSaleable() && count($_attributes)):?>
<dl>
<?php foreach($_attributes as $_attribute): ?>
<dt><label class="required"><em>*</em><?php echo $_attribute->getLabel() ?></label></dt>
<dd<?php if ($_attribute->decoratedIsLast){?> class="last"<?php }?>>
<div class="input-box">
<select name="super_attribute[<?php echo $_attribute->getAttributeId() ?>]" id="attribute<?php echo $_attribute->getAttributeId() ?>" class="required-entry super-attribute-select" onchange="return changeSku(this);">
<option><?php echo $this->__('Choose an Option...') ?></option>
</select>
</div>
</dd>
<?php endforeach; ?>
</dl>
<script type="text/javascript">
var spConfig = new Product.Config(<?php echo $this->getJsonConfig() ?>);
</script>
<?php endif;?>
<?php
$conf = Mage::getModel('catalog/product_type_configurable')->setProduct($_product);
$col = $conf->getUsedProductCollection()->addAttributeToSelect('*')->addFilterByRequiredOptions();
echo '<script type="text/javascript">';
echo '
document.observe("dom:loaded", function() {
$("sku-container").update("<strong>Product Id: </strong> Select an option to display Product Id");
});
';
echo ' function changeSku(sel){';
$itemId = array();
foreach($col as $simple_product){
$itemId[] = array($simple_product->getSelectLabel() => $simple_product->getSku());
}
//echo "<pre>";
//print_r($itemId);
//echo "</pre>";
foreach($itemId as $val){
foreach($val as $k => $v){
echo "\n".'if(sel.options[sel.selectedIndex].value == "'.$k.'"){'."\n";
echo '$("sku-container").update("<strong>Product Id: </strong>'.$v.'");'. "\n";
echo '}';
}
}
echo "\n".'if(sel.options[sel.selectedIndex].value == ""){'."\n";
echo '$("sku-container").update("<strong>Product Id: </strong> Select an option to display Product Id");'. "\n";
echo '}';
echo "}";
echo "\n</script>";
?>
I appreciate any help.
Thanks
The script is almost correct except for $simple_product->getSelectLabel() being a wrong key. No such method/property exists in a simple product model. In order to make the script work, this key should be replaced with a right one - a Product Id. Utilizing product id, it is possible to find the sku of the product being selected.
So, first of all you need to reorganize itemId array to make it a "productId => productSku" map:
$productMap = array();
foreach($col as $simpleProduct){
$productMap[$simpleProduct->getId()] = $simpleProduct->getSku();
}
Then you need to change the "onchange" function call to pass Configurable's attribute id to the changeSku() function. Thus the underlying logic is able to search appropriate simple product's attributes.
onchange="return changeSku(<?php echo $_attribute->getAttributeId() ?>, this);">
And after that you need utilize configurable's config in order to map selected simple product's attribute id to the product id selected:
function changeSku(confAttributeId, sel) {
var productMap = <?php echo Mage::helper('core')->jsonEncode($productMap);?>;
var selectedAttributeId = sel.options[sel.selectedIndex].value;
if (selectedAttributeId) {
var options = spConfig.config.attributes[confAttributeId].options;
var productId = options.find(function (option) {return option.id == selectedAttributeId}).products[0]
$("sku-container").update("<strong>Product Id: </strong>" + productMap[productId]);
} else {
$("sku-container").update("<strong>Product Id: </strong> Select an option to display Product Id");
}
}
For your reference, below is the summary of how the whole template looks like (I've beautified it a little):
<?php
$_product = $this->getProduct();
$_attributes = Mage::helper('core')->decorateArray($this->getAllowAttributes());
?>
<?php if ($_product->isSaleable() && count($_attributes)):?>
<dl>
<?php foreach($_attributes as $_attribute): ?>
<dt><label class="required"><em>*</em><?php echo $_attribute->getLabel() ?></label></dt>
<dd<?php if ($_attribute->decoratedIsLast){?> class="last"<?php }?>>
<div class="input-box">
<select name="super_attribute[<?php echo $_attribute->getAttributeId() ?>]" id="attribute<?php echo $_attribute->getAttributeId() ?>" class="required-entry super-attribute-select"
onchange="return changeSku(<?php echo $_attribute->getAttributeId() ?>, this);">
<option><?php echo $this->__('Choose an Option...') ?></option>
</select>
</div>
</dd>
<?php endforeach; ?>
</dl>
<script type="text/javascript">
var spConfig = new Product.Config(<?php echo $this->getJsonConfig() ?>);
</script>
<?php endif;?>
<div id="sku-container"></div>
<?php
$conf = Mage::getModel('catalog/product_type_configurable')->setProduct($_product);
$col = $conf->getUsedProductCollection()->addAttributeToSelect('*')->addFilterByRequiredOptions();
$productMap = array();
foreach($col as $simpleProduct){
$productMap[$simpleProduct->getId()] = $simpleProduct->getSku();
}
?>
<script type="text/javascript">
document.observe("dom:loaded", function() {
$("sku-container").update("<strong>Product Id: </strong> Select an option to display Product Id");
});
function changeSku(confAttributeId, sel) {
var productMap = <?php echo Mage::helper('core')->jsonEncode($productMap);?>;
var selectedAttributeId = sel.options[sel.selectedIndex].value;
if (selectedAttributeId) {
var options = spConfig.config.attributes[confAttributeId].options;
var productId = options.find(function (option) {return option.id == selectedAttributeId}).products[0]
$("sku-container").update("<strong>Product Id: </strong>" + productMap[productId]);
} else {
$("sku-container").update("<strong>Product Id: </strong> Select an option to display Product Id");
}
}
</script>
This will do the task you originally needed.
Also note the following
Your approach won't work for a configurable product with two or more configurable attributes. For that product a final simple product is not known until a user selects values for all the select inputs. So an approach should be changed to check all the selects before outputting SKU.
The code doesn't consider a case, when user edits product configuration, rather than specifying configuration for a new product. You can go to editing mode from the Shopping Cart clicking the Edit link. In such a case all the select inputs will be pre-filled with previously chosen values. But the text will say "Select an option to display Product Id". The script might also produce other Javascript errors in Edit mode. The code should be slightly modified in order to support Edit mode as well.
The template is overfilled with logic. A Magento template should have only simple prints and foreach-iterations. All the methods like $conf->getUsedProductCollection()->addAttributeToSelect('*')->addFilterByRequiredOptions() are better to be moved to block. This reduces code complexity.
Hope it helps.

can't use multiple ajaxLink for loading CJuiDialog widget

I have a problem when using multiple ajaxLink for loading CJuiDialog widget in yii. I'm using multiple dropdowns, each dropdown's value determine next dropdown.
Here is my code for viewing first dropdown and a link to create new item using Cdialog widget.
<?php $cs = Yii::app()->getClientScript();
$cs->registerCoreScript("jquery");
?>
<div class="form">
<?php $form=$this->beginWidget('CActiveForm', array(
'enableAjaxValidation'=>false,
)); ?>
<div class="row">
<?php
echo $form->labelEx($model,'uname'); ?>
<?php echo $form->dropDownList($model,'uname',$model- >getUniversityList(),array('onchange'=>'getSchemes(this.value)','empty'=>'Select university')); ?>
<?php echo $form->error($model,'uname'); ?>
<?php //create university dialoge box
if(!Yii::app()->user->isGuest)
{
echo CHtml::ajaxLink('create new university',array('university/dialoge'),array(
'success'=>'js:function(data){
$("#createUniversity").dialog("open");
document.getElementById("create_university").innerHTML=data;
}'));
$this->beginWidget('zii.widgets.jui.CJuiDialog',array(
'id'=>'createUniversity',
'options'=>array(
'title'=>'Create University',
'autoOpen'=>false,
'modal'=>'true',
'width'=>'auto',
'height'=>'auto',
),
));
echo "<div id='create_university'></div>";
$this->endWidget('zii.widgets.jui.CJuiDialog');
}
?>
<div id="scheme">
</div>
</div>
<?php $this->endWidget(); ?>
</div>
<input type="hidden" id="url" value="<?php echo $this->createUrl('scheme/test'); ?>">
this works pretty good.
here is the javascript code for loading next dropdown in the same view file
<script type="text/javascript">
function getSchemes(uid)
{
if(uid==""){
document.getElementById("scheme").innerHTML='';
return;
}
jQuery(function($){
var url=document.getElementById("url").value;
$.post(url, { uid:uid },
function(data){
document.getElementById("scheme").innerHTML=data;
document.getElementById("scheme_link").style.display="block";
});
});
}
The scheme drop down is loaded as the scheme view code is
<?php $cs = Yii::app()->getClientScript();
$cs->registerCoreScript("jquery");
?>
<?php
echo "<div class=".'label'."><label for=".'sch'.">Scheme</label></div>";
echo "<select id=".'sch'." onchange='getDepartments(this.value);'>";
echo "<option value=".''.">"."Select Scheme</option>";
foreach($schemes as $s)
{
echo "<option value='".$s->schemeid."' >".$s->scheme_name."</option>";
}
echo "</select>";
?>
<?php
if(!Yii::app()->user->isGuest)
{
echo CHtml::ajaxLink('create new Scheme',array('scheme/dialoge','id'=>5),array(
'success'=>'js:function(data1){
$("#createScheme").dialog("open");
document.getElementById("create_scheme").innerHTML=data;
}'));?>
<?php
$this->beginWidget('zii.widgets.jui.CJuiDialog',array(
'id'=>'createScheme',
'options'=>array(
'title'=>'Create Scheme',
'autoOpen'=>false,
'modal'=>'true',
'width'=>'auto',
'height'=>'auto',
),
));
echo "<div id='create_scheme'></div>";
$this->endWidget('zii.widgets.jui.CJuiDialog');
}
?>
<div id="department">
</div>
<input type="hidden" id="urldepart" value="<?php echo $this->createUrl('department/test'); ?> ">
the second ajaxLink is shown as create new scheme but on clicking the link it shows the old create university dialog box instead of create scheme.
The simplest solution for this is to create the ID of the element that is causing problems as random.
Try adding:
'id' => 'some-element'.uniqid() // avoid mutliple ajax request because of using live
in the $htmlOptions array of ajaxLink

Change the text "Choose an option..." on Magento product page

I created a configurable product, it has three option: color, size and style.
Now in product page, each option has the default text "Choose an Option..." in dropdown, but I want the text should be "Select color", "Select size" and "Select style".
I edited function getJsonConfig() in app\code\core\Mage\Catalog\Block\View\Type\Configurable.php
From:
'chooseText' => Mage::helper('catalog')->__('Choose an Option...'),
To:
'chooseText' => ('Select ').$attribute->getLabel(),
And edit line 39 of the file frontend/base/default/template/catalog/product/view/type/options/configurable.phtml to:
<option><?php echo $this->__('Select ') ?><?php echo $_attribute->getLabel() ?></option>
But the result is not good, it alway show the text "Choose style" in three options.
Please give me a hint for this issue, thank you very much!
My version of the same problem. You need to change only template
catalog/product/view/type/options/configurable.phtml:
<?php
$_product = $this->getProduct();
$_attributes = Mage::helper('core')->decorateArray($this->getAllowAttributes());
?>
<?php if ($_product->isSaleable() && count($_attributes)):?>
<dl>
<?php foreach($_attributes as $_attribute): ?>
<dt><label class="required"><em>*</em><?php echo $_attribute->getLabel() ?></label></dt>
<dd<?php if ($_attribute->decoratedIsLast){?> class="last"<?php }?>>
<div class="input-box">
<?php $chooseText = $this->__('Select %s', $_attribute->getLabel()); ?>
<select data-choose-text="<?php echo $chooseText; ?>" name="super_attribute[<?php echo $_attribute->getAttributeId() ?>]" id="attribute<?php echo $_attribute->getAttributeId() ?>" class="required-entry super-attribute-select">
<option><?php echo $chooseText; ?></option>
</select>
</div>
</dd>
<?php endforeach; ?>
</dl>
<script type="text/javascript">
Product.ConfigDefaultText = new Class.create(Product.Config, {
fillSelect: function($super, element) {
$super(element);
var chooseDefaultText = element.getAttribute('data-choose-text');
$(element).options[0] = new Option(chooseDefaultText, '');
}
});
var spConfig = new Product.ConfigDefaultText(<?php echo $this->getJsonConfig() ?>);
</script>
<?php endif;?>
Note (extracted from comments)
If the selected default value happens not to be "Select %s", replace
$(element).options[0] = new Option(chooseDefaultText, '');
with
$(element).options[0].innerHTML = chooseDefaultText;
I was looking for a more simple way to do this. I didn't want to extend any core files or muck around with extending JavaScript. Instead I parsed the settings JSON, updated the chooseText setting, and converted back to JSON:
/~theme/default/template/catalog/product/view/type/options/configurable.phtml
<?php
$jsonConfig = json_decode($this->getJsonConfig());
$jsonConfig->chooseText = 'Select..';
?>
<script type="text/javascript">
var spConfig = new Product.Config(<?php echo json_encode($jsonConfig); ?>);
</script>
More information and further examples here.
The only way I think is just to modify the javascript class that populates that dropdowns. As we can see in frontend/base/default/template/catalog/product/view/type/options/configurable.phtml that class is:
<script type="text/javascript">
var spConfig = new Product.Config(<?php echo $this->getJsonConfig() ?>);
</script>
The file with needed class located in js/varien/product.js
The place where first <option> tag is set up is:
fillSelect: function(element){
var attributeId = element.id.replace(/[a-z]*/, '');
var options = this.getAttributeOptions(attributeId);
this.clearSelect(element);
element.options[0] = new Option(this.config.chooseText, '');
...
The variable chooseText used there on line 368. This variable was created in function getJsonConfig() in app/code/core/Mage/Catalog/Block/Product/View/Type/Configurable.php (you was digging the right way). You need to modify the javascript that I described earlier to achive what you need (based on var attributeId you can assign options with different text to elements you need)
If you only change file configurable.js
It will only change first select when page load
So I must change template file
Get attached file for test.(I just write it to an small extension)
<?php
$_product = $this->getProduct();
$_attributes = Mage::helper('core')->decorateArray($this->getAllowAttributes());
?>
<?php if ($_product->isSaleable() && count($_attributes)):?>
<dl>
<?php foreach($_attributes as $_attribute): ?>
<?php
$_attributeId = $_attribute->getAttributeId();
$_attributeInfo = Mage::getModel('eav/entity_attribute')->load($_attributeId);
$_attributeLabel = str_replace(' ','-',strtolower($_attributeInfo->getFrontendLabel()));
?>
<dd<?php if ($_attribute->decoratedIsLast){?> class="last"<?php }?>>
<div class="input-box">
<select name="super_attribute[<?php echo $_attribute->getAttributeId() ?>]" id="attribute<?php echo $_attribute->getAttributeId() ?>" class="required-entry super-attribute-select kevin-black-<?php echo $_attributeLabel;?>">
<option><?php echo $_attributeInfo->getFrontendLabel() ?></option>
</select>
</div>
</dd>
<?php endforeach; ?>
</dl>
<script type="text/javascript">
var spConfig = new Product.Config(<?php echo $this->getJsonConfig() ?>);
//kevin.qazware#gmail.com Change Text follow attribute Label
function changeFristText(){
<?php foreach($_attributes as $_attribute): ?>
<?php
$_attributeId = $_attribute->getAttributeId();
$_attributeInfo = Mage::getModel('eav/entity_attribute')->load($_attributeId);
?>
var label = '<?php echo $_attributeInfo->getFrontendLabel();?>';
$$('select.kevin-black-'+label).each(function(elem){
var options = elem.childElements();
options[0].update(label);
});
<?php endforeach;?>
}
</script>
<?php endif;?>
in file : js/varien/configurable.js replace line 171 = element.options[0] = new Option(element.config.label, ‘’);
It for all attribute set .
simplest answer:
replace js/varien/configurable.js line 172
element.options[0].innerHTML = 'Choose ' + this.config.attributes[attributeId].label;
I extended class Product.Config (method fillselect) by these code:
fillSelect: function(element){
var attributeId = element.id.replace(/[a-z]*/, '');
var options = this.getAttributeOptions(attributeId);
this.clearSelect(element);
element.options[0] = new Option('Select '+element.config.label,'');
........
It's ok!
<script type="text/javascript">
<?php
$jsonConfig = $this->getJsonConfig();
$jsonConfig = str_replace("Choose an Option...", "Select Size", $jsonConfig);
?>
var spConfig = new Product.Config(<?php echo $jsonConfig; ?>);
</script>
file catalog/product/view/type/options/configurable.phml
<?php
$_product = $this->getProduct();
$_attributes = Mage::helper('core')->decorateArray($this->getAllowAttributes());
?>
<?php if ($_product->isSaleable() && count($_attributes)):?>
<dl>
<?php foreach($_attributes as $_attribute): ?>
<?php
$_attributeId = $_attribute->getAttributeId();
$_attributeInfo = Mage::getModel('eav/entity_attribute')->load($_attributeId);
$_attributeLabel = str_replace(' ','-',strtolower($_attributeInfo->getFrontendLabel()));
?>
<dd<?php if ($_attribute->decoratedIsLast){?> class="last"<?php }?>>
<div class="input-box">
<select name="super_attribute[<?php echo $_attribute->getAttributeId() ?>]" id="attribute<?php echo $_attribute->getAttributeId() ?>" class="required-entry super-attribute-select kevin-black-<?php echo $_attributeLabel;?>">
<option><?php echo $this->__('Select '.$_attributeLabel) ?></option>
</select>
</div>
</dd>
<?php endforeach; ?>
</dl>
<script type="text/javascript">
var spConfig = new Product.Config(<?php echo $this->getJsonConfig() ?>);
//Change Text follow attribute Label
function changeFristText(){
<?php foreach($_attributes as $_attribute): ?>
<?php
$_attributeId = $_attribute->getAttributeId();
$_attributeInfo = Mage::getModel('eav/entity_attribute')->load($_attributeId);
$_attributeLabel = str_replace(' ','-',strtolower($_attributeInfo->getFrontendLabel()));
?>
var label = '<?php echo $_attributeLabel;?>';
$$('select.kevin-black-'+label).each(function(elem){
var options = elem.childElements();
options[0].update('Select ' + label);
});
<?php endforeach;?>
}
</script>
<?php endif;?>
and add one line changeFristText(); after line 171 (element.options[0] = new Option(this.config.chooseText, '');) in file js/varien/configurable.js
It for all attribute set.
This worked for me on CE 1.8.1. It's based off Shein's answer, and addresses the wrong option getting selected on load. I basically just copied/pasted the Product.Config.fillSelect() method from /js/varien/product.js. Within the pasted code I changed:
element.options[0].innerHTML = this.config.chooseText;
to
element.options[0].innerHTML = element.config.label;
This allows keeping product.js unmodified, and just override the method. The only drawback is any future core updates to that method will need migrating.
Since the new code just gets the "label" setting, the data-choose-text attribute on isn't needed on the select tag
<?php
$_product = $this->getProduct();
$_attributes = Mage::helper('core')->decorateArray($this->getAllowAttributes());
?>
<?php if ($_product->isSaleable() && count($_attributes)):?>
<dl>
<?php foreach($_attributes as $_attribute): ?>
<dt><label class="required"><em>*</em><?php echo $_attribute->getLabel() ?></label></dt>
<dd<?php if ($_attribute->decoratedIsLast){?> class="last"<?php }?>>
<div class="input-box">
<select name="super_attribute[<?php echo $_attribute->getAttributeId() ?>]" id="attribute<?php echo $_attribute->getAttributeId() ?>" class="required-entry super-attribute-select">
<option><?php echo $_attribute->getLabel() ?></option>
</select>
</div>
</dd>
<?php endforeach; ?>
</dl>
<script type="text/javascript">
Product.ConfigDefaultText = new Class.create(Product.Config, {
fillSelect: function (element) {
var attributeId = element.id.replace(/[a-z]*/, '');
var options = this.getAttributeOptions(attributeId);
this.clearSelect(element);
element.options[0] = new Option('', '');
element.options[0].innerHTML = element.config.label;
var prevConfig = false;
if (element.prevSetting) {
prevConfig = element.prevSetting.options[element.prevSetting.selectedIndex];
}
if (options) {
var index = 1;
for (var i = 0; i < options.length; i++) {
var allowedProducts = [];
if (prevConfig) {
for (var j = 0; j < options[i].products.length; j++) {
if (prevConfig.config.allowedProducts
&& prevConfig.config.allowedProducts.indexOf(options[i].products[j]) > -1) {
allowedProducts.push(options[i].products[j]);
}
}
} else {
allowedProducts = options[i].products.clone();
}
if (allowedProducts.size() > 0) {
options[i].allowedProducts = allowedProducts;
element.options[index] = new Option(this.getOptionLabel(options[i], options[i].price), options[i].id);
element.options[index].config = options[i];
index++;
}
}
}
}
});
var spConfig = new Product.ConfigDefaultText(<?php echo $this->getJsonConfig() ?>);
</script>
<?php endif;?>

Resources