I have a rather unique issue in jquery to solve. I have a div wrapper:
<div class="formWrapper"></div>
This contains a set of elements that should, when they change (doesn't matter which element changes) - should (for example) be stored in a data object, and that object logged to the console - for now.
So:
<div class="formWrapper">
<div class="floatRight">
<div>
<label>Select a Project Manager</label>
<select class="projectManager">
<?php foreach($projectManagers as $name){ ?>
<option><?php echo $name; ?></option>
<?php } ?>
</select>
</div>
<div>
<label>Select a Division</label>
<select class="division">
<?php foreach($divisions as $division){ ?>
<option><?php echo $division['division_name']; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="floatLeft">
<div>
<label>Select a Client</label>
<select class="client">
<?php foreach($clients as $client){ ?>
<option><?php echo $client['client_company_name']; ?></option>
<?php } ?>
</select>
</div>
<div>
<label>Choose a Date</label>
<input type="text" class="date" placeholder="Click to choose a date"/>
</div>
</div>
</div>
Pretty simple to see whats going on. But what if projectManager changes or divison or ... both, or all the elements, a simple change() might work for one element but I need to watch all the element and dynamically update a data object such that each time an element changes, the console spits out a different data object.
The end goal
Have a data object, for example data = {pm : pm_selected_value} for if the user JUST selects pm and then, if they change division - the data object should update to should: data = {pm : pm_selected_value, divsion: division_selected_value} and so on ...
I know how to get the value of each element, I don't know how to create a dynamic data object like this while watching each element.
The catch, and I think change() from reading the docs does this, is that even if I have a data object like this:
data = {pm : pm_selected_value, divsion: division_selected_value}
and I go an update the pm (so selecting a different pm), the data object should instantly update to reflect that change:
data = {pm : pm_selected_NEW_value, divsion: division_selected_value}
Now I can apply .change() to each element - but is there no way to apply it to a div to say - "excuse me mr JavaScript - please watch all form elements inside here for change, k thanks."
What you are looking to do it listen for any select value to get changed within the <div class="formWrapper"></div> so you should target the <div> and attach the change event to child <select>s
var choices = new Object();
$('.formwrapper').on('change', 'select', function(){
choices[$(this).attr('name')] = $(this).val();
console.log(choices);
});
One thing you should do is provide a unique name="" for each <select> so that you know what you are dealing with inside of the anonymous function()
Related
I am using PHP to dynamically populate a select box (a list of equipment). The value is set with the ID of the item selected so I can use it later in my programming.
What I need help with...
Based on the item selected I need to show/hide one of two form fields but I can't use the value as this is the id.
What I need to be able to do is read the text in the select box which will contain the item name with either (Service: Set by dates) or (Service: Set by hours) and show either the form field for the date or the form field for the hours?
Is this possible? I can find loads great resources based on the value but not on the text in the select.
I think something like this should work but not sure how to use the text in the select rather than the value.
$(function() {
$('#system').change(function(){
$('.system').hide();
$('#' + $(this).val()).show();
});
});
Any help would be greatly appreciated!!!!
Regards
Matt
(N.B this is what I'm working with at the mo based on the answers so far, thank you all so much for the help (and for your example Louys Patrice Bessette) - not quite there yet... I was getting an error and managed to track it back to the script not getting the result from the select box. See below now working code! Thanks all!!!
<div class="col">
<div class="form-group">
<label for="system_select">Equipment or System to be serviced</label>
<select class="form-control" name="system_select" id="system_select">
<option></option>
<?php
$systems = DB::getInstance()->get('ym_system', 'vessel_id', '=', $vid);
foreach ($systems->results() as $system) {
?><option data-type="<?php echo $system->service_type ?>" value="<?php echo $system->system_id ?>"><?php echo $system->system_name; ?></option> <?php
}
?>
</select>
</div>
</div>
</div>
<script type="text/javascript">
$( document ).ready(function() {
$("#due_dates").hide(); // Hide both divs
$("#due_hours").hide(); // Hide both divs
$('#system_select').change(function(){
var dataType = $(this).find(':selected').attr('data-type') // should be "Set by dates" or "Set by hours"
if (dataType == 'Set by dates') {
$("#due_hours").hide();
$("#due_dates").show();
} else if (dataType == 'Set by hours') {
$("#due_dates").hide();
$("#due_hours").show();
}
});
});
</script>
<div class="row">
<div class="col-md-3" id="due_date">
<div class="form-group">
<label for="service_date">Next Service (Set by dates)</label>
<input type="date" class="form-control" name="service_date" id="service_date" value="<?php echo escape(Input::get('service_date')); ?>" autocomplete="off">
</div>
</div>
<div class="col-md-3" id="due_hour">
<div class="form-group">
<label for="service_hours">Next Service (Set by hours)</label>
<input type="number" class="form-control" name="service_hours" id="service_hours" value="<?php echo escape(Input::get('service_hours')); ?>" autocomplete="off">
</div>
</div>
</div>
I think that you PHP $system->service_type; is echoing either "Set by dates" or "Set by hours".
If you echo that in a data attribute like this:
<select class="form-control" name="system_select" id="system_select">
<option></option>
<?php
$systems = DB::getInstance()->get('ym_system', 'vessel_id', '=', $vid);
foreach ($systems->results() as $system) {
?><option data-type="<?php echo $system->service_type; ?>" value="<?php echo $system->system_id ?>"><?php echo $system->system_name . ' (Service: '. $system->service_type .')'; ?></option> <?php
}
?>
</select>
Then, in jQuery, you could use it like this to decide to show <div id="due_hours" class="col-md-3"> or <div id="due_hours" class="col-md-3">.
$(function() {
$('#system').change(function(){
$('.system').hide(); // I don't know what this is for...
$("div[id=^'due']").hide(); // Hide both divs
var dataType = $(this).data("type"); // should be "Set by dates" or "Set by hours"
var type = dataType.split(" by ")[1]; // should be "dates" ot "hours"
$("#due_"+type).show();
});
});
Now be carefull with the s on dates...
Try this out... Console.log the values to make sure you have the correct one to match the id to show.
;)
If $(".classname").text() is not working you could try to add that info that you need in a "data" attribute.
Something like this ->
<option data-service="service name" class="myClass">15</option>
Using data attributes can give you a lot of freedom on what you can add. You could add lots of information that a normal user cant read (without inspecting element).
Then you would simply do something like this ->
$(".myClass").on("click", function() {
var serviceData = $(this).attr("data-service");
})
You can then do if checks, compare and whatever you need.
EDIT: Or you can use your approach with on.change and get the selected data attr, it would probably be better
If you change your select into something like this:
<select class="form-control" name="system_select" id="system_select">
<option data-hide='#due_date' data-show='#due_hours'>Show Hours</option>
<option data-hide='#due_hours' data-show='#due_date' value="B">Show Dates</option>
</select>
And your jquery like this:
$('#system_select').change(function () {
$($(this).children("option:selected").attr("data-hide")).hide();
$($(this).children("option:selected").attr("data-show")).show();
});
It could work.
It appears that I am facing a common beginer's problem but I haven't managed to solved it on my code.
What I want to do:
I have created a database and I am currently working on a simple UI for updating it. So, I use
One drop-down menu populated by a mySQL table
Some forms with their values changed accordingly to the drop down selection.
Code(Simplified a little):
<html>
<body>
<form method="post">
<select class="dropdown" id="dropdown_id" onChange='fillFun(this.value)' >
<option disabled selected value style="display:none"> -- select an option -- </option>
<?php
//stuff pdo connection
$pdo = new PDO("mysql:host=$servername;dbname=myDatabase", $user, $password);
try
{
$result = $pdo->query("SELECT * FROM dbTable");
foreach($result as $row)
{
echo '<option value="'.$row.'"';
echo '>'. $row['last_name'].' '. $row['first_name'].'</option>'."\n";
}
}
catch(PDOException $e) { echo 'No Results'; }
?>
</select >
</form>
<form id="forms" action="results.php" method="post">
Last Name: <input type="text" id="last_name" /><br><br>
First Name: <input type="text" id="first_name" /><br><br>
<input type="submit" />
</form>
<script>
function fillFun(fill)
{
document.getElementById('last_name').value = fill[1];
document.getElementById('first_name').value = fill[2];
}
</script>
<body>
Problem:
this.value = "Array"
After researching a little I found a couple of question with a similar problem.(For instace this one)
The thing is that I can't(or don't know how,to be precise) apply the given solution print_r() or var_dump() since I am echo-ing an option value. Another way to solve a similar problem was the use of json_encode() but after the change of
onChange='fillFun(this.value)'
with
onChange='fillFun(json_encode(this.value))'
the problem wasn't solved. On the contrary, it seems that now the fill parameter was null.(Nothing happens on change).
What am I missing here?Thanks.
Instead of referring to this.value you can pass the event object to fillFunc function and obtain the value through event.target.value.
So fillFunc will be updated to:
fillFunc(event) {
document.getElementById('last_name').value = event.target.value[1];
document.getElementById('first_name').value = event.target.value[2];
}
And pass event to your onchange handler.,
<select onchange="filFunc(event)"></select>
How do I add an ID to a select > option:selected HTML element?
Here is my code so far.
<!-- select time zone -->
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h3 id="stepOne"><b>Step 1:</b> Select your Time Zone</h3>
<select class="form-control" name="timeZone" id="getTimeZone" onchange="getTimeZone()">
<?php foreach ($time_zones as $key => $array) : ?>
<?php foreach ($array as $offset => $zone) : ?>
<option value="<?php echo $offset; ?>"><?php echo $zone; ?></option>
<?php endforeach; ?>
<?php endforeach; ?>
</select>
</div>
</div>
<!-- end select timezone -->
<!-- get timezone from dropdown -->
<script>
function getTimeZone() {
// if option is selected add an ID attribute
// then get that id attributes inner html
var id = $("#getTimeZone").children("option:selected").attr("timeZoneSelected");
var timeZone = document.getElementById("getTimeZone").value;
document.getElementById("showTimeZone").innerHTML = timeZone;
document.getElementById("timeZoneField").value = timeZone;
document.getElementById("stepOne").className = "text-success";
}
</script>
<!-- end get timezone from dropdown -->
So basically I am looping through a list of time zones. When the user selects a time zone I want to add an ID to the option, e.g id="timeZoneSelected".
Then I want to grab the innerHTML of that specific option element.
As you can see my code is not working, specifically:
var id = $("#getTimeZone").children("option:selected").attr("timeZoneSelected");
Where am I going wrong?
To do what you require you can simply retrieve the value and inner text of the selected option within the change event handler. There's no need to dynamically update identifiers or class attributes. Try this:
$('#getTimeZone').change(function() {
var name = $(this).find('option:selected').text();
var offset = this.value;
$('#name').html(name);
$('#offset').html(offset);
$('#stepOne').addClass('text-success');
});
.text-success { color: #0c0; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h3 id="stepOne"><b>Step 1:</b> Select your Time Zone</h3>
<select class="form-control" name="timeZone" id="getTimeZone">
<option value="-6">CST</option>
<option value="0">GMT</option>
<option value="+8">SGT</option>
</select>
</div>
</div>
<div id="name"></div>
<div id="offset"></div>
Note that I amended your code to use unobtrusive event handlers as on* event attributes are considered outdated.
I'm developing a Wordpress site that (of course) is composed of multiple PHP templates. The particular template fragment I'm having problems with is called with this line:
<script id="templatehidden">
<?php get_template_part( 'fragments/calculator', 'row-sa' ); ?>
</script>
And the contents of calculator-row-sa.php are:
<div class="form-row pricingrow select-multiple">
<div class="form-controls">
<img class="remove-field-sa" style="float: left; margin-right: 30px;" src="http://45.32.89.214/wp-content/uploads/2016/04/minus.png">
<i style="margin-left: 50px;" class="cardinal"></i>
<select name="field-followers[]" class="select followerselect">
<?php foreach ( $options as $option ) : ?>
<option value="<?php echo $option[ 'value' ] ?>"><?php echo $option[ 'label' ] ?></option>
<?php endforeach; ?>
</select>
<b class="fa fa-caret-down" aria-hidden="true" style="color: #747474";></b>
<span class="acctprice"></span>
</div><!-- /.form-controls -->
And the jQuery code behind it is
$('.remove-field-sa').click(function () {
$(this).closest('.form-row').remove();
});
My problem is with the img element inside the php. When the page first loads, it does its job and removes the row it's on. However, after I add more rows, no javascript code seems to execute within .form-content anymore. Any ideas on what's wrong?
Assuming that you are adding the rows using javascript, you need event delegation: At the moment you bind your even handler, the elements don't exist and when you add them, the click event is not automatically binded to these new elements unless you use event delegation.
You can easily change that using for example:
$('.form-content').on('click', '.remove-field-sa', function () {
$(this).closest('.form-row').remove();
});
Note that here the .form-content element has to be present on page-load. If it is not, you could also use something like:
// Any parent element that is present at page-load and will contain the child elements will do.
$('body').on('click', '.remove-field-sa', function () {
$(this).closest('.form-row').remove();
});
I am working on an ecommerce site and the products are being dynamically generated with foreach loop, within each product there are product options, when the product option is selected I my intended behaviour is for the price to update.
I have this working, however jQuery is updating every instance of the price on the page and the select option only works for the first item generated. How do I add/bind the jQuery to the object/every product and have the price change on individual basis?
<?php
foreach($items as $item):
<?php echo $the_name ?>
<select id="choose">
foreach($selection as $select):
<option value="$some_var" data-value="$the_price">$some_var</option>
endforeach;
</select>
<div id="price"><?php echo $the_price ?></div>
endforeach;
?>
<script type="text/javascript">
jQuery('#choose').change(function (event) {
jQuery('#price').html(jQuery('#choose option:selected').data('value'));
}).change();
</script>
Working Code
After playing about for a while, and taking into consideration the other comments below, this code works.
<script type="text/javascript">
jQuery('.choose').change(function (event) {
var $t = jQuery(this);
var price = $t.find('option:selected').data('value');
$t.parents('form').find('.price').html(price);
}).change();
</script>
ID's are unique. Because 'choose' is in a loop, you've got multiple choose ID's, which isn't helping things. Same with the 'price'. So, let's change it a bit:
<?php
foreach($items as $item):
<?php echo $the_name ?>
<select class="choose">
foreach($selection as $select):
<option value="$some_var" data-value="$the_price">$some_var</option>
endforeach;
</select>
<div class="price"><?php echo $the_price ?></div>
endforeach;
?>
<script type="text/javascript">
jQuery('.choose').change(function (event) {
jQuery(this).next().html(jQuery(this).data('value'));
}).change();
</script>
Explanation:
Since you can have more than one choose, you then need to do a bit of DOM navigation to get the price that is relative to the select. So, whenever a select box is changed it will look for the next element in the DOM tree that is a sibling , which if your code snippet is complete will be the price element, and then update the html to that value. One thought though - you may want to use text instead of html, unless you have HTML in your prices. Also, when you're inside an event (unless you've done something special to rebind the scope), in jQuery this will refer to the element that the event fired on. So, jQuery(this) will return a jQuery reference to the element that was changed.
<?php
foreach($items as $item):
<?php echo $the_name ?>
<select class="choose">
foreach($selection as $select):
<option value="$some_var" data-value="$the_price">$some_var</option>
endforeach;
</select>
<div class="price"><?php echo $the_price ?></div>
endforeach;
?>
<script type="text/javascript">
jQuery('.choose').change(function (event) {
jQuery$(this).parent().next(".price").html(jQuery('#choose option:selected').data('value'));
}).change();
</script>