Javascript issue with JQuery chosen and my calling code - javascript

The following code is exhibiting a very strange behavior...
I have two html selects: one for regions and another one for departments bearing in mind that for one selected region I am trying to load the corresponding departments.
The first html select (region) is populated upon normal page load and the second html select (departments) by an ajax call retrieving JSON from the server.
I use jquery chosen.
The strange behavior I am referring to is as follows:
upon a first change of the region select (say region A is selected), the department select is not populated.
Upon a second change of the region select (say region B is selected), the department select is populated by region A's departments!!!!
Javascript:
$(document).ready(function() {
$(".chzn-select").chosen({no_results_text: "No results matched"});
var geolocationRegionSelect = $("#geolocationRegionSelect");
var geolocationDepartmentSelect = $("#geolocationDepartmentSelect");
geolocationRegionSelect.bind('change', function(event) {
$.get("/kadjoukor/geolocations/findDepartmentsByRegion?regionId="+$(this).val(), function(result){
geolocationDepartmentSelect.empty();
$.each(result, function() {
geolocationDepartmentSelect.append($("<option />").val(this.id).text(this.department));
});
}, 'json');
$(".chzn-select").trigger("liszt:updated");
});
});
Here is the corresponding html:
<div class="control-group">
<label class="control-label" for="geolocationRegionSelect">geolocation region</label>
<div class="controls">
<select id="geolocationRegionSelect">
<option th:value="''" th:text="'Non renseigne'"></option>
<option th:each="geolocationRegion: ${geolocationRegions}" th:value="${geolocationRegion.id}" th:text="${geolocationRegion.region}"></option>
</select>
</div>
<div class="controls">
<select id="geolocationDepartmentSelect" th:field="*{geolocationDepartments}" data-placeholder="Choose a department" multiple="multiple" class="chzn-select">
</select>
</div>
</div>
Can anyone please advise?
EDIT: Generated HTML:
<label class="control-label" for="geolocationRegionSelect">geolocation region</label>
<div class="controls">
<select id="geolocationRegionSelect">
<option value="">Non renseigne</option>
<option value="1">Alsace</option><option value="2">Aquitaine</option><option value="3">Auvergne</option><option value="4">Basse-Normandie</option><option value="5">Bourgogne</option><option value="6">Bretagne</option><option value="7">Centre</option><option value="8">Champagne-Ardenne</option><option value="9">Corse</option><option value="10">DOM-TOM</option><option value="11">Franche-Comté</option><option value="12">Haute-Normandie</option><option value="13">Ile-de-France</option><option value="14">Languedoc-Roussillon</option><option value="15">Limousin</option><option value="16">Lorraine</option><option value="17">Midi-Pyrénées</option><option value="18">Nord-Pas-de-Calais</option><option value="19">Pays de la Loire</option><option value="20">Picardie</option><option value="21">Poitou-Charentes</option><option value="22">Provence-Alpes-Côte d'Azur</option><option value="23">Rhône-Alpes</option>
</select>
</div>
<div class="controls">
<select id="geolocationDepartmentSelect" data-placeholder="Choose a department" multiple="multiple" class="chzn-select">
</select>
</div>

You should trigger update after element updated, inside handler...
$(document).ready(function() {
$(".chzn-select").chosen({no_results_text: "No results matched"});
var geolocationRegionSelect = $("#geolocationRegionSelect");
var geolocationDepartmentSelect = $("#geolocationDepartmentSelect");
geolocationRegionSelect.bind('change', function(event) {
$.get("/kadjoukor/geolocations/findDepartmentsByRegion?regionId="+$(this).val(), function(result){
geolocationDepartmentSelect.empty();
$.each(result, function() {
geolocationDepartmentSelect.append($("<option />").val(this.id).text(this.department));
geolocationDepartmentSelect.trigger("liszt:updated"); // <--TO HERE
});
}, 'json');
//<-FROM HERE
});
});
http://jsfiddle.net/oceog/rQJeX/
You not get epected results because $.get() here is asynchronous, get the analogy:
You ask your wife to go to the post office and ask them how much you should pay for your father's annual magazine subscription, you tell her - "when you back leave note on that table, and remove old note from here" (on table already the note for 100$, subscription is 50$).
After she leaves you ask your mother to check a note on the table and give it to your father to make him pay...
your question is equal to that - "why my father payed 100$" ?
the answer is equal to that - you had to ask your wife to tell your mother to bring note to your father, when note on the table will be refreshed by your wife.
sorry for english, feel free to edit that if needed.

Related

How to prevent user entering value if previous field is empty?

I have City and Building fields in my form. Before user submits the form I need to check if building already exist in selected city. Building number can be the same since building with the same number can belong to different city. I want to prevent same building numbers that belong to same city. In order to accomplish this I have to send City+Building concatenated value to the server and check if that value exist in database table. I'm trying to find good solution for this problem. So far I used focus/blur function for this purpose. If user clicks on the Building input field once finished entering value, on blur I will send an ajax request to the server and return true or false. In this case that is a little different, before I send request I have to make sure that City field has entered value. Here is example of my f
$("#frm_building").focus(function() {
var submitBtn = $(this).closest("form").find(":submit").prop("disabled", true), //Disable submit button on field focus.
}).blur(function() {
var fldObj = $(this),
frmMessage = $(this).closest("form").find(".message-submit"),
submitBtn = $(this).closest("form").find(":submit"),
distVal = $("");
if (String(fldObj.val()) && String(fldObj.val()) !== String(fldObj.attr("data-current"))) {
//if (obj.RESULT === true) { // This will be the result returned after ajax call
if(1===1)
fldObj.get(0).setCustomValidity("");
} else {
fldObj.get(0).setCustomValidity("Building already exists for that City.");
}
submitBtn.prop("disabled", false);
} else {
fldObj.get(0).setCustomValidity("");
submitBtn.prop("disabled", false);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script language="javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<form name="frmBuilding" id="frmBuilding">
<div class="form-group">
<label class="control-label" for="City"><span class="label label-primary">City:</span></label>
<select class="form-control" name="frm_city" id="frm_city" required>
<option value="">--Choose City--</option>
<option value="1003">New York</option>
<option value="2341">Chicago</option>
<option value="4343">Miami</option>
<option value="7865">San Francisco</option>
</select>
</div>
<div class="form-group">
<label class="control-label" for="Building"><span class="label label-primary">Building:</span></label>
<input type="text" class="form-control check-value" name="frm_building" id="frm_building" data-current="" data-fldname="building" maxlength="4" pattern="[0-9]{4}$" title="Number field requires 4 digits" placeholder="Select City first then enter Building number. Example: 1108"
required>
</div>
</form>
In code above if user first entered Building and City is blank my code won't send request to the server on blur. Then if user tries to submit the form they will get the message City field is required. Let's say they enter City, Building will remain the same as they originally entered. In that case on blur is never triggered and request won't be sent. I'm wondering how I can prevent this to happen, is there a way to prevent user entering Building if City field is empty? Also I have to consider the case when user want to update the record. If they click edit and form gets populated that functionality should work and populate both fields without Building being disabled. I hope this part make sense. Originally I have tried setting Building with attribute disabled and setting on change function on the City field. That worked fine until I discovered the issue with edit situation. If anyone knows a good way to solve this situation please let me know.
is there a way to prevent user entering Building if City field is empty?
When focus is on Buildings you can move focus on City if this field is empty.
$("#frm_building").on('focus', function (e) {
if ($('#frm_city').val().length==0) {
$('#frm_city').focus();
}
});
$("#frm_building").on('focus', function (e) {
if ($('#frm_city').val().length==0) {
$('#frm_city').focus();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script language="javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<form name="frmBuilding" id="frmBuilding">
<div class="form-group">
<label class="control-label" for="frm_city"><span class="label label-primary">City:</span></label>
<select class="form-control" name="frm_city" id="frm_city" required>
<option value="">--Choose City--</option>
<option value="1003">New York</option>
<option value="2341">Chicago</option>
<option value="4343">Miami</option>
<option value="7865">San Francisco</option>
</select>
</div>
<div class="form-group">
<label class="control-label" for="frm_building"><span class="label label-primary">Building:</span></label>
<input type="text" class="form-control check-value" name="frm_building" id="frm_building" data-current=""
data-fldname="building" maxlength="4" pattern="[0-9]{4}$" title="Number field requires 4 digits"
placeholder="Select City first then enter Building number. Example: 1108"
required>
</div>
<input type="submit" value="submit">
</form>

Meteor dependent select

I need to implement 2 dependent selects in my meteor app. I am new with web development in general and very new with meteor. However I have done something that works but I would like to know if that is the correct way or if there is any other better way to do it. Why I am wondering this is because I have seen some code on the web which I can understand very well yet so I prefer to do it as I think it should be.
The selects are one with car brands and the second one with the models of the selected brand.
I am using the Session in meteor 1.3 (although I've read a little bit that there is something call reactive vars which can be used as well).
Please do not take into account security issues for now.
Thanks in advance.
Here is my code:
const VEHICLE_MODELS = "vehicleModels";
function setVehicleModels(vehicleModels){
Session.set(VEHICLE_MODELS, vehicleModels);
}
function getVehicleModels(){
return Session.get(VEHICLE_MODELS);
}
Template.startJob.events({
'change #carBrands': function(e){
e.preventDefault();
var selectedBrand = $("#carBrands").val();
var vehicleData = Vehicles.findOne({"make":selectedBrand})
setVehicleModels(vehicleData.models);
}
});
Template.startJob.helpers({
carBrands(){
return Vehicles.find();
},
carModels(){
return getVehicleModels();
}
});
<div class="form-group">
<label for="carBrands" class="col-sm-2 control-label">
Make
</label>
<div class="col-sm-10">
<select id="carBrands" class="form-control select2">
<option value="">Select a brand...</option>
{{#each carBrands}}
<option value="{{make}}">{{make}}</option>
{{/each}}
</select>
</div>
</div>
<div class="form-group">
<label for="carModels" class="col-sm-2 control-label">
Model
</label>
<div class="col-sm-10">
<select id="carModels" class="form-control select2">
<option value="">Select a model...</option>
{{#each carModels}}
<option value="{{this}}">{{this}}</option>
{{/each}}
</select>
</div>
</div>
The classic pattern for this in Meteor is to use a Session variable which is set by an event and drives the data context of the dependent menu. This simplifies your code a tiny bit since only one Session variable (or alternatively a reactive variable) is required.
Template.startJob.events({
'change #carBrands': function(e){
e.preventDefault();
var selectedBrand = $("#carBrands").val();
var vehicleData = Vehicles.findOne({ make: selectedBrand })
Session.set('brandId', selectedBrand._id);
}
});
Template.startJob.helpers({
carBrands(){
return Vehicles.find();
},
carModels(){
return VehicleModels.find({ brandId: Session.get('brandId') });
}
});
With no changes to your html.

Submit and Generate Dynamic PHP Form

I have a form with text boxes and drop down menus. One of the drop down menus is Dependant on the value of another, e.g. InventoryUsage is dependent on the value in InventoryID.
So far I have done the entire site using PHP since I do not know JavaScript, though I found a JavaScript function that can get the value entered in InventoryID, but I cannot use that value in the PHP since PHP is server-side.
What I need to do is change the second dropdown options depending on that of the first dropdown. Then submit the data as I would with a normal form.
Edit:
I used ob_start and included the tpl page and sent all the variables to the page which were pulled from the database prior. All the variables have the same index meaning that InventoryID['0']=ID3456 corresponds to InventoryUsage['0']=60. Therefore when InventoryID is ID3456 i would like to display the Number located at InventoryUsage['0']. I hope this adds some context to the problem.
The index is determined by the php variable $i in my code snippet. The $i would be changed to match the index of the InventoryID field. Say the value of InventoryUsage is 20 then I want to display numbers 1 to 20.
Snippet of code below:
<label>TypeOfSurgery</label> <input type="text" name="TypeOfSurgery" size="35" value="" />
<label>CauseOfSurgery</label> <input type="text" name="CauseOfSurgery" size="35" value="" />
<label>AnaesthesiaUsage</label> <input type="text" name="AnaesthesiaUsage" size="35" value="" />
<label>SurgeryOutcome </label> <input type="text" name="SurgeryOutcome" size="35" value="" />
<label>RecoveryTime</label> <input type="text" name="RecoveryTime" size="35" value="" />
<label>Stages </label> <input type="text" name="Stages" size="35" value="" />
<label>EmployeeName </label> <p>
<select name="EmployeeName">
<option value=""></option>
<?php
for($i=0;!empty($EmployeeName[$i]);$i++)
echo '<option value="">'.$EmployeeName[$i].'</option>';
?>
</select><p>
<label>Cost</label> <input type="text" name="Cost" size="35" value="" />
<label>InventoryID</label> <p>
<select name="InventoryID">
<option value=""></option>
<?php
for($i=0;!empty($InventoryID[$i]);$i++)
echo '<option value="">'.$InventoryID[$i].'</option>';
?>
</select><p>
<label>InventoryUsage </label> <p>
<select name="InventoryUsage">
<option value=""></option>
<script type="text/javascript">
var model= document.getElementById('InventoryUsage');
</script>
<?php
//if inventory in
for($i=0;!empty($InventoryUsage[$i]);$i++)
echo '<option value="">'.$InventoryUsage[$i].'</option>';
?>
</select><p>
In order to populate the InventoryUsage dropdown you need to use JavaScript.
You can use the onChange event for the dropdown InventoryID then fetch the corresponding values via Ajax.
$('#InventoryID').change(function () {
var value =$(this).val(); // selected InventoryID option
//get InventoryUsage values
$.ajax({
method: "POST",
url: "myfile.php",
data: { data: value },
success: function(data){
// Populate new dropdown $("#InventoryUsage")
// this is an example without knowing what is the returned data
var Newoptions = [];
for (var i = 0; i < data.length; i++) {
Newoptions.push('<option value="',
data[i].someValue, '">',
data[i].someName, '</option>');
}
$("#InventoryUsage").html(Newoptions .join(''));
}
});
});
});
then in your PHP file you need to handle the $_POST['data'] , then query your database and return the drop-down options( Arrays ) that will be populated above...
edit :
If you are sure that this index matches the Inventory_Usage and that the InventoryUsage dropdown has previously been populated then
you could try to select the InventoryUsage option using the index of the InventoryID dropdown on change and load events...
try adding this function to you select :
<select name="InventoryID" onChange="set_inventory_usage()"></select>
then add this script to your page's HEAD section..
<head>
<script type="text/javascript">
function set_inventory_usage(){
// Change to getElementById if it is the ID not the name
var Inventory_ID = document.getElementsByName('InventoryID')[0];
var Inventory_Usage = document.getElementsByName('InventoryUsage')[0];
// returns the index of the selected option in the InventoryID dropdown
var InventorySelected = Inventory_ID.selectedIndex ;
// Sets the Usage dropdown to the same index as the Inventory selected option
Inventory_Usage.selectedIndex = InventorySelected ;
}
window.onload = set_inventory_usage ;
</script>
</head>
Option 1: Without JavaScript, the best option is to add an onchange to your first dropdwon list, and when a value is selected submit the form. Since the form is not complete, and only the dropdown value and elements before that are passed, you can set a condition to query the database, get values based on first drop down and reload the form with those options. IThere is nothing wrong with this solution if done properly but to be honest I perfer to do such things with Ajax, hence option 2 below.
Option 2: Learn some JavaScript and use Ajax (Use caution when using other people's scripts in your system)
Edit: Perhaps instead of wring Ajax code from scratch, use jQuery where most things are already done for you. Learning jQuery is very useful if you are going to do web development

remove last inserted element by php in JQUERY

I have container called interest_type_container. In which 2 fields are there interest type and period.
HTML:
<div id="interest_type_container">
<label class="col-md-4">Interest Type *</label>
<select name="interest_type[]" class="form-control">
<option value="">Select</option>
// Some options...
</select>
<label class="col-md-4">Interest Period *</label>
<select name="interest_period[]" class="form-control">
<option value="">Select</option>
// Some options...
</select>
</div>
<button type="button" name="add_more_interest" id="add_more_interest">Add</button>
<button type="button" name="remove_more_interest" id="remove_more_interest">Remove</button>
JQUERY:
I this I have add and remove functions. So, when user clicks on add it will add those two fields from ajax request.
AJAX:
$("#add_more_interest").on('click',function(){
$.ajax({
type: 'post',
url: '/transaction/fetch_interest_type_and_period',
success: function (res) {
$('#interest_type_container').append(res);
}
});
});
And when user clicks on remove. It should remove last inserted 2 fields. I tried with this. But, it's not working.
$("#remove_more_interest").on('click', function(){
$('#interest_type_container:last-child', this).remove();
});
Here is an example of something you could do given the HTML (pairs of labels and selects with no surrounding element) that you have:
$("#remove_more_interest").on('click', function () {
var labelLength = $('#interest_type_container > label').length - 1;
var selectLength = $('#interest_type_container > select').length - 1;
$('#interest_type_container > label').eq(labelLength).remove();
$('#interest_type_container > label').eq(labelLength - 1).remove();
$('#interest_type_container > select').eq(selectLength).remove();
$('#interest_type_container > select').eq(selectLength -1).remove();
});
This is using straight up brute force though, there may be better, more elegant ways to accomplish this.
http://jsfiddle.net/jayblanchard/uohc23xd/
You have to specify the tag type and use "last" selector
$(document).on('click', '#remove_more_interest', function(){
$('#interest_type_container').children('label:last').remove();
$('#interest_type_container').children('select:last').remove();
});
You can test your selector from your web browser console by hitting F12 and select console tab. Wrote these lines and you'll see what it returns. This Console is your best friend!
Your onclick method is not good! The complete code HERE
<html><head>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
$(document).on('click', '#remove_more_interest', function(){
$('#interest_type_container').children('label:last').remove();
$('#interest_type_container').children('select:last').remove();
$('#interest_type_container').children('label:last').remove();
$('#interest_type_container').children('select:last').remove();
});
</script>
</head><body>
<div id="interest_type_container">
<label class="col-md-4">Interest Type *</label>
<select name="interest_type[]" class="form-control">
<option value="">Select</option>
</select>
<label class="col-md-4">Interest Period *</label>
<select name="interest_period[]" class="form-control">
<option value="">Select</option>
</select>
</div>
<button type="button" name="remove_more_interest" id="remove_more_interest">Remove</button>
</body></html>
You can do one thing. When you append the result, put it in a container e.g.
$('#interest_type_container').append('<span class="appended_res">'+res+'</span>');
After that, you can use class 'appended_res' to remove the elements.
Thank you guys for your efforts. I come up with a solution. And it works.
Dynamic generated elements, which are coming from ajax. I put those elements under new_inserted_elements ID.
Now in, JQUERY:
$("#remove_more_interest").on('click', function(){
$('#new_inserted_elements').remove();
});
It removes last inserted id, those are my 2 elements.

Show multiple fields based on dropdown - doesn't work when other dropdowns are on page

I previously asked about showing mulple fields based on a dropdown which used JQuery:
Show multiple fields based on dropdown
However when I have other dropdown fields on my page, this no longer works. I did wonder it it was interfering with other JavaScript / JQuery elements, but removing those didn't correct the issue. I've also tried putting the elements into separate ULs and DIVS with no luck. Can someone help?
In my example, when selecting 'Taking over existing Mobile' it should display 'Existing Mobile No', however it won't when the 'Existing PC' is still listed on my page.
HTML:
<ul>
<li>
<label for>NS - Mobile</label>
<select class="selectmenu" id="_1_1_81_1" name="_1_1_81_1" onchange="markDirty();">
<option value="" ><None></option>
<option value="Mobile" >Mobile</option>
<option value="Blackberry" >Blackberry</option>
<option value="otheros" >Taking over Existing Mobile</option>
</select>
</li>
<li class="osother">
<label for>NS - Existing Mobile No</label>
<input class="valueEditable" TYPE="text" name="_1_1_83_1" title="NS - Existing Mobile No" id="_1_1_83_1" value="[LL_FormTag_1_1_83_1 /]" size="12" MAXLENGTH="11" ONCHANGE="markDirty();">
</li>
<li>
<label for>NS - Existing PC</label>
<select class="selectMenu" id="_1_1_84_1" name="_1_1_84_1" onchange="markDirty();">
<option value="" ><None></option>
<option value="Yes" >Yes</option>
<option value="No" >No</option>
</select>
</li>
</ul>
JQ:
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("select").change(function () {
$("select option:selected").each(function () {
if ($(this).attr("value") == "otheros") {
$(".osother").show();
} else {
$(".osother").hide();
}
});
}).change();
});
</script>
CS:
.osother{display:none;}
My other JQ is here and collapses sections on the page - maybe irrelevant:
<script type="text/javascript" src="[LL_SUPPORTPATH /]core/jquery.collapsible.js"> </script>
<script type="text/javascript">
$(document).ready(function() {
//collapsible management
$('.collapsible').collapsible({
defaultOpen: 'section1,section2,section3,section4,section5'
});
});
</script>
There is also some JavaScript here and there that adds in TABS and Date dropdowns, but have tested without these elements and it seems still not to work.
Basically you're looping through every select in the page and checking for their values, when you actually should observe just the one with ID _1_1_81_1.
Also, you can simplify your code:
$(function () {
// Observe the particular select for changes in its value.
// As every element in the page should have its on ID, you can
// select it straight away (omitting the type - select).
$("#_1_1_81_1").on("change", function () {
// Toggle the input visibility based on the selected value.
// The .val() method works here just like for every type of
// input. You don't need to go through all the select options
// and test their values.
$(".osother").toggle($(this).val() == "otheros");
});
});
Demo
jQuery .toggle()
Note: This answer is based on the code you provided. If there are any other requirements or code involved, you should state it in the question.

Categories