The $('select').focus
function below works with an html <select>
element, but it isn't being triggered when used with a <select>
element where the options are generated by the php function 'printSelectOptions' shown below.
The $('select').focus
function allows me to differentiate between the default value of select elements (or 'default state', which are pre-set to the most commonly chosen options), vs. when a user has actively chosen that value by clicking on the form element (indicating that they made an active decision to leave it set to that value). I've posted a fiddle with a working example of the function here: http://jsfiddle.net/chayacooper/JHAPp/6/
I'm trying to use this function on a page where users can review and edit their account information, and the <select>
element options on this page are generated by the $options array in the php 'printSelectOptions' functions so that it can pre-select the options matching the db information. As a result I've added code which allows me to select the correct option matching the db value, regardless of whether or not it's set to a default value *(i.e. value="$50_default" vs. value="$50")*, and unless it's changed by the js $('select').focus
function it submits the same value that was fetched from the db. However, since the $('select').focus
function isn't getting triggered on the account page, it is submitting the same value for both "$50_default" and "$50" if the value fetched from the db was "$50_default".
JS Function
<script>
$('select').focus(function () {
var option = $(this).find("option[value*=default]");
option.attr('value', option.attr('value').replace(/_default/g, ''));
});
</script>
<select name="jeans">
<option value="$0">$0</option>
<option value="$50_default" selected="selected">$50</option>
<option value="$100">$100</option>
<option value="$150">$150</option>
</select>
PHP & HTML - Account Page
<?php
try {
$stmt = $conn->prepare("SELECT * FROM price WHERE user_id = :user_id");
$stmt->bindValue(':user_id', $user_id);
$stmt->execute();
} catch(PDOException $e) {
echo $e->getMessage();
}
$row = $stmt->fetch();
$search_default = array('_default');
$replace_default = array('');
$row_default = str_replace($search_default, $replace_default, $row);
// This function selects the option matching the value in the db
function printSelectOptions($dataArray, $currentSelection) {
foreach ($dataArray as $key => $value) {
echo '<option ' . (($key == $currentSelection) ? 'selected="selected"' : '') . ' value="' . $key . '">' . $value . '</option>';
}
}
?>
<select name="jeans">
<?php
// Generates a <select> element with the options specified in this array
$options = array("Null"=>"", "$0"=>"$0", "$50"=>"$50", "$100"=>"$100", "$150"=>"$150");
if ($row_default['jeans'] !== $row['jeans']) {
$newOptions = array();
foreach ($options as $key => $value) {
if ($key === $row_default['jeans']) {
$newOptions[$row['jeans']] = $value;
} else {
$newOptions[$key] = $value;
}
}
$options = $newOptions;
}
$selected = $row['jeans'];
// Pre-selects the option matching the db information
echo printSelectOptions($options, $selected);
?>
</select>
In your comment you say you are trying to use Dropkick or the jQuery UI MultiSelect Widget. Since this is not a multi-select drop-down, I would assume Dropkick would be what you want.
Here is a jsfiddle that shows the code does not work with Dropdkick.
My understanding is that normal event binding will not work with Dropkick. Instead, you have to use a dropkick callback, like this:
$('select').dropkick({
change: function(value, label) {
alert('You picked: ' + label + ':' + value);
}
});
It also appears that the "change" callback is the only one available. There doesn't appear to be support for a "focus" callback.
A further issue is that there doesn't appear to be a way to change the options for a Dropkick select. (I tried your code in a jsfiddle and the value went to "0".)
If you are fine with being limited to using the "change" callback, a work-around for the fact that you cannot change the option values would be to not include "_default" on any of the values. Instead, you would include a hidden field in the form. When the value from the db ends with "_default", the hidden field is set to "true"; otherwise it is set to "false". The "change" callback for the dropkick select would set the hidden value to "false". When the form is posted, the server checks if the hidden value is "true" and appends "_default" on the end of the posted select value when it is.
UPDATE:
Here is what the code to display the page would look like if you were to implement the hidden field:
<script>
$(function() {
$('select').dropkick({
change: function() {
$('input[name=isDefaultPriceSelected]').val('false');
}
});
});
</script>
<?php
// Helper method that tells if the given string ends with the given substring.
function endsWith($str, $substr) {
$substrLength = strlen($substr);
return substr_compare($str, $substr, -substrLength, substrLength) === 0;
}
// Helper method that prints out a hidden input element.
function printHiddenInput($name, $value) {
echo '<input type="hidden" name="' . $name . '" value="' . $value . '" />
}
?>
<select name="jeans">
<?php
$options = array("Null"=>"", "$0"=>"$0", "$50"=>"$50", "$100"=>"$100", "$150"=>"$150");
echo printSelectOptions($options, $row_default['jeans']);
?>
</select>
<?php
echo printHiddenInput('isDefaultPriceSelected', endsWith($row['jeans'], '_default') ? 'true' : 'false');
?>
You still need to deal with the code that handles the form post. It will have to look for both the select value and the hidden value. If the hidden value is "true", then "_default" should be appended on the to the end of the posted select value.
Note: You would no longer be using the replaceKey()
helper function. :(
I should have noticed this before, but the call to $('select').focus
is not in a document ready handler, and it comes before the <select>
is added to the DOM. Therefore, it isn't getting bound to the <select>
.
Try:
<script>
$(function() {
$('select').focus(function () {
var option = $(this).find("option[value*=default]");
option.attr('value', option.attr('value').replace(/_default/g, ''));
});
});
</script>
Have you tried using
$(document).on('focus', 'select', function() {
//code here
});