How to condense hardcoded jQuery code to smaller generic code? - javascript

I have a code that works perfectly fine because it is hardcoded but extremely large. I would like to simplify this code to make it general and of course smaller. Does anybody know how to do this? Since it is so large I will shrink it down for this question.
var theform1 = $('#form1').find('.state option');
var stateForm1 = Object.keys(localStorage).filter(key => key.endsWith('-state1'));
var stateChoice1 = JSON.parse(localStorage.getItem(stateForm1));
var theform2 = $('#form2').find('.state option');
var stateForm2 = Object.keys(localStorage).filter(key => key.endsWith('-state2'));
var stateChoice2 = JSON.parse(localStorage.getItem(stateForm2));
var theform3 = $('#form3').find('.state option');
var stateForm3 = Object.keys(localStorage).filter(key => key.endsWith('-state3'));
var stateChoice3 = JSON.parse(localStorage.getItem(stateForm3));
if (localStorage.getItem(stateForm1)) {
$(theform1).empty();
$(theform1).val(stateChoice1).append(`<option value="${stateChoice1}">${stateChoice1}</option>`).trigger('window.load');
};
if (localStorage.getItem(stateForm2)) {
$(theform2).empty();
$(theform2).val(stateChoice2).append(`<option value="${stateChoice2}">${stateChoice2}</option>`).trigger('window.load');
};
if (localStorage.getItem(stateForm3)) {
$(theform3).empty();
$(theform3).val(stateChoice3).append(`<option value="${stateChoice3}">${stateChoice3}</option>`).trigger('window.load');
};
The HTML markup is as follows:
<form id="form1" autocomplete="off">
<select id="country1" class="country" name="country">
<?php include("countryAjaxData.php"); ?>
</select>
<select id="state1" class="state" name="state">
<option value="" selected="selected">Select state</option>
</select>
<select id="city1" class="city" name="city">
<option value="" selected="selected">Select city</option>
</select>
</form>
<form id="form2" autocomplete="off">
<select id="country2" class="country" name="country">
<?php include("countryAjaxData.php"); ?>
</select>
<select id="state2" class="state" name="state">
<option value="" selected="selected">Select state</option>
</select>
<select id="city2" class="city" name="city">
<option value="" selected="selected">Select city</option>
</select>
</form>
<form id="form3" autocomplete="off">
<select id="country3" class="country" name="country">
<?php include("countryAjaxData.php"); ?>
</select>
<select id="state3" class="state" name="state">
<option value="" selected="selected">Select state</option>
</select>
<select id="city3" class="city" name="city">
<option value="" selected="selected">Select city</option>
</select>
</form>

Maybe you're looking for this compressed version:
$('#form1,#form2,#form3').each(function () {
var index = this.id.substring(this.id.length - 1, this.id.length);
var stateForm = Object.keys(localStorage).filter(key => key.endsWith('-state' + index));
var stateChoice = JSON.parse(localStorage.getItem(stateForm));
if (localStorage.getItem(stateForm)) {
var theform = $(this).find('.state option').empty();
theform.val(stateChoice)
.append(`<option value="${stateChoice}">${stateChoice}</option>`)
.trigger('window.load');
}
});
If you have more than 10 forms with the index increasing from 1 to 99 or 999... You can edit the way to name your form id to: form01 form02 form03 or form001 form002 form003...
Then, because all of the id names start with form, you can update the selectors like this:
Changing $('#form1,#form2,#form3') to $('[id^="form"]'). That selector means: selecting some element(s) which contains the id starts with form.
Lastly, if your form id following by 2 digits (form01), you update the line to get the index to:
var index = this.id.substring(this.id.length - 2, this.id.length);
You can do the same way for the ids following by 3 digits (form001):
var index = this.id.substring(this.id.length - 3, this.id.length);

Loop over all the select.state and get the number from the parent form.
Something like:
$('select.state').each(function() {
const $sel = $(this),
formNum = $sel.closest('form').attr('id').replace('form', ''),
stateForm = Object.keys(localStorage).find(key => key.endsWith(`-state${formNum }`)),
stateChoice = localStorage.getItem(stateForm);
if (stateChoice) {
$sel.append(new Option(stateChoice. stateChoice))
.val(stateChoice)
.trigger('window.load');
}
})
Note I changed filter() to find() for the keys since filter returns an array

Related

Why does localstorage store the wrong value?

I am a newbie with a localstorage issue. I have a few dependent dropdowns that are loaded via ajax from a server. When the user makes a selection the localstorage stores the wrong value...the last value. From my research I thought that .map() may be a solution to my problem but being a newbie I am not familiar with the syntax and I have not been able to get it to work. Can anyone figure out what is causing this problem? Is .map() the correct solution? Here is a photo of what I am having an issue with.
Here is the code
$('.country').on('change', function () {
var countryId = $(this).val();
var state_select = $(this).closest('form').find('.state');
var city_select = $(this).closest('form').find('.city');
if (countryId) {
$.ajax({
type: 'POST',
dataType: 'JSON',
url: 'ajaxData3.php',
data: {
country_id: countryId
},
success: function (r) {
console.log('States', r);
$(state_select).html('<option value="" selected="selected">State</option>');
$(city_select).html('<option value="" selected="selected">City </option>');
if (r.status) {
r.data.forEach(function (state) {
$(state_select).append(`<option value="${state.id}">${state.name}</option>`);
$('.state').each(function(r) {
var stateList = $(state);
var thisSelection = $(this);
var thisId = thisSelection.attr('id');
var storageId = 'state-' + thisId;
var storedInfo = JSON.parse(localStorage.getItem(storageId));
thisSelection.change(function(i) {
var selectedOptions = []; // create an array to hold all currently selected options
thisSelection.find('option:selected').each(function(i) {
var thisOption = $(this);
selectedOptions.push(thisOption.val());
});
localStorage.setItem(storageId, JSON.stringify(state.name));
})
})
})
} else {
$(state_select).html('<option value="" selected="selected">Unavailable </option>');
$(city_select).html('<option value="" selected="selected">Unavailable </option>');
}
}
})
};
Here is the markup
<form id="form1" autocomplete="off">
<select id="country1" class="country" name="country">
<?php include("countryAjaxData.php"); ?>
</select>
<select id="state1" class="state" name="state">
<option value="" selected="selected">Select state</option>
</select>
<select id="city1" class="city" name="city">
<option value="" selected="selected">Select city</option>
</select>
</form>
<form id="form2" autocomplete="off">
<select id="country2" class="country" name="country">
<?php include("countryAjaxData.php"); ?>
</select>
<select id="state2" class="state" name="state">
<option value="" selected="selected">Select state</option>
</select>
<select id="city2" class="city" name="city">
<option value="" selected="selected">Select city</option>
</select>
</form>
<form id="form3" autocomplete="off">
<select id="country3" class="country" name="country">
<?php include("countryAjaxData.php"); ?>
</select>
<select id="state3" class="state" name="state">
<option value="" selected="selected">Select state</option>
</select>
<select id="city3" class="city" name="city">
<option value="" selected="selected">Select city</option>
</select>
</form>
I decided to post the answer so others can see. Hopefully someone here on stackoverflow will take the time to help me next time. This 'voting', 'points' and 'badge' thing gets in the way of actual learning.
The forEach() reiterates the function each time it is called. So the last entry will be where the reiteration completes. The localStorage.setItem needs to be moved into a .change() function or .on('change', function()) and the value needs to be .text() to simply read the text that was displayed.
localStorage.setItem('yourkeyhere', JSON.stringify($(this).text()));

How to get multiple values from an HTML <select> element

How to take the values of value1 and value2 in two variables using javascript?
<select class="form-control" id="country" name="country">
<option value="**value1**" "**value2**" >Select Item</option>
</select>
You could make your own attribute. I know you probably do not want to get the element with an ID, but I don't know the context. You can just call getAttribute on the option and use any name you gave to the "custom" attribute.
window.addEventListener('load', ()=>
{
const option = document.getElementById('option');
function init()
{
//Use this to get the values
console.log(option.getAttribute('other-value'));
}
init();
});
<select class="form-control" id="country" name="country">
<option id="option" value="value1" other-value="value2">Select Item</option>
</select>
I don't know what you really want to do with your piece of code,
but here is a proper way to use the option elements, and a way to split multiple values with a fixed separator:
var example = document.getElementById('example');
example.addEventListener('change', function() {
// Console displays the “value”, and not the text, of the selected option
console.log("option value:", example.value);
});
// Here is what I'll do with your "multiple" values
var country = document.getElementById('country');
var options = country.querySelector('option');
var values = options.value.split("/");
values.forEach(function(val) {
country.innerHTML += "<option value=" + val + ">" + val + "</option>";
});
<p>My simple example</p>
<select id="example" name="country">
<option value="--">Select Country</option>
<option value="GB">Great Britain</option>
<option value="FR">France</option>
</select>
<br>
<br>
<p>Example with option getting splitted</p>
<select class="form-control" id="country" name="country">
<!-- Let's say your multiple values are separated by a "/" -->
<option value="**value1**/**value2**">Select Item</option>
</select>
Hope it helps.
$('select').on('change', function() {
console.log( $('#country').val() );
console.log($(this).find(':selected').data('second'));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="form-control" id="country" name="country">
<option value="value1" data-second ="value2" >Select Item 1</option>
<option value="value3" data-second ="value4" >Select Item 2</option>
</select>

Disable specific option in specific dropdown

I'm working on a small website and I currently have two dropdowns in my form, both are below:
<select name="classType" id="classType" required>
<option value="" disabled selected>Select Your Class Type</option>
<option value = "Beginner">Beginner</option>
<option value = "Intermediate">Intermediate</option>
<option value = "Advanced">Advanced</option>
</select>
<br/>
<select name="studentType" id="studentType" required>
<option value="" disabled selected>Select Your Student Type</option>
<option value = "lowerLevel">Lower Level</option>
<option value = "upperLevel">Upper Level</option>
</select>
<br/>
I've experimented with some javascript but only at a beginner level. I was wondering if there's a way to disable a specific value in the studentType dropdown.
So for example if i select "Beginner" in the first dropdown then the option for "UpperLevel" in the second dropdown should be disabled.
This is what I tried, but it was not working:
var dropdown = document.getElementById("classType");
dropdown.onchange = function(event){
if (dropdown.value == "Beginner") {
// .....
Any ideas?
Thanks!
You can achieve this by hooking an event handler to the change event of the first select which sets the disabled property of the relevant option in the second select based on the chosen option, something like this:
$('#classType').change(function() {
$('#studentType option[value="upperLevel"]').prop('disabled', $(this).val() == 'Beginner')
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select name="classType" id="classType" required>
<option value="" disabled="true" selected="true">Select Your Class Type</option>
<option value="Beginner">Beginner</option>
<option value="Intermediate">Intermediate</option>
<option value="Advanced">Advanced</option>
</select><br/>
<select name="studentType" id="studentType" required>
<option value="" disabled="true" selected="true">Select Your Student Type</option>
<option value="lowerLevel">Lower Level</option>
<option value="upperLevel">Upper Level</option>
</select><br/>
This should fit your needs:
http://codepen.io/themeler/pen/yOjWXB
<select name="classType" id="classType" required>
<option value="" disabled selected>Select Your Class Type</option>
<option value = "Beginner">Beginner</option>
<option value = "Intermediate">Intermediate</option>
<option value = "Advanced">Advanced</option>
</select>
<br/>
<select name="studentType" id="studentType" required>
<option value="" disabled selected>Select Your Student Type</option>
<option value="lowerLevel">Lower Level</option>
<option value="upperLevel">Upper Level</option>
</select>
<br/>
$(function () {
var $class = $('#classType'),
$student = $('#studentType');
$class.on('change', function () {
var $this = $(this),
$ul = $student.find('[value="upperLevel"]');
// clear value of student type on class type change
$student.find(':selected').prop('selected', false);
$student.find('option:first-child').prop('selected', true);
// lock / unlock position
if ($this.val() === 'Beginner') {
$ul.prop('disabled', true);
} else {
$ul.prop('disabled', false);
}
});
});
By jQuery:
$('#studentType option[value="upperLevel"]').attr('disabled','disabled');
Here is how I would do it, add a data-enabled tag to each option like this:
<select name="classType" id="classType" required>
<option value="" disabled selected>Select Your Class Type</option>
<option value = "Beginner" data-enabled="lowerLevel">Beginner</option>
<option value = "Intermediate" data-enabled="lowerLevel,upperLevel">Intermediate</option>
<option value = "Advanced" data-enabled="upperLevel">Advanced</option>
</select>
<br/>
<select name="studentType" id="studentType" required>
<option value="" disabled selected>Select Your Student Type</option>
<option value = "lowerLevel">Lower Level</option>
<option value = "upperLevel">Upper Level</option>
</select>
<br/>
And on change of the drop down, disable all options in the other drop down, then loop through and see if they're either in the enabled tag of the selected, or blank like this:
$('#classType').on('change', function(){
var allowed = $('#classType option:selected').attr('data-enabled').split(',');
$('#studentType option').attr('disabled','disabled');
$('#studentType option').each(function(){
if (allowed.indexOf($(this).val()) > -1 || !$(this).val()) {
$(this).removeAttr('disabled');
}
});
});

Filter an Object

I'm hoping someone will point me in the right direction or give me an example. I'm trying to filter through this multidimensional json object using a form with four filter options (see below).
After the user makes their selections and hits the submit button the results of that product or service's details are displayed on the page (ie...link to that product, content of that product), there can also be more than one product or service to display based on the search filter. Can someone please help me out?
Here is my object:
var data = {
"Product":{"url":["http://www.google.com"],"mode":["gyro"],"modeOptions":["drop-controlled-descent","seated-wireline-steering","slickline-memory","surface-readout-ms","wireline-orientation"],"diameter":{"usa":"1.75","intl":"44.5mm"},"accuracy":{"usa":"0.5 deg","intl":"0.5 deg"},"temp":{"usa":"400F","intl":"204C"},"speed":{"usa":"250 ft\/min","intl":"76.2m\/min"}},
"Service":{"url":["http://www.google.com"],"mode":["gyro"],"modeOptions":["drop-controlled-descent","seated-wireline-steering","slickline-memory","surface-readout-ms","wireline-orientation"],"diameter":{"usa":"(2.2)","intl":"(55.9mm)"},"accuracy":{"usa":"0.15 deg","intl":"0.15 deg"},"temp":{"usa":"(400F)","intl":"(204C)"},"speed":{"usa":"600 ft\/min","intl":"182.9m\/min"}}
};
Her is my html form:
<form name="searchForm" id="searchForm">
<select name="diameter">
<option value="" selected="">Select One</option>
<option value="1.2">1.2</option>
<option value="1.75">1.75</option>
<option value="2.2">2.2</option>
</select>
<select name="accuracy">
<option value="" selected="">Select One</option>
<option value="0.15 deg">0.15</option>
<option value="0.5 deg">0.5</option>
<option value="1 deg">1</option>
<option value="2.5 deg">2.5</option>
</select>
<select name="temp">
<option value="" selected="">Select One</option>
<option value="257F">257F</option>
<option value="300F">300F</option>
<option value="400F">400F</option>
</select>
<select name="modeOptions">
<option value="" selected="">Select One</option>
<option value="surface-readout-ms">Surface Readout/MS</option>
<option value="wireline-orientation">Wireline Orientation</option>
<option value="memory-orientation">Memory Orientation</option>
<option value="slickline-memory">Slickline memory</option>
<option value="drop-controlled-descent">Drop – Controlled Descent</option>
<option value="drop–freefall-descent">Drop – Freefall Descent</option>
<option value="seated-wireline-steering">Seated Wireline Steering</option>
</select>
<input type="submit" value="submit"/>
</form>
Get TaffyDB. It is made for these sorts of things.
Try something like
var $form = $('#searchForm'),
$diameter = $form.find('select[name="diameter"]'),
$accuracy = $form.find('select[name="accuracy"]'),
$temp = $form.find('select[name="temp"]'),
$modeOptions = $form.find('select[name="modeOptions"]');
$('#searchForm').submit(function (e) {
e.preventDefault();
var diameter = $diameter.val(),
accuracy = $accuracy.val(),
temp = $temp.val(),
modeOptions = $modeOptions.val();
var selected = $.map(data, function (obj) {
return (!diameter || diameter == obj.diameter.usa) && (!accuracy || accuracy == obj.accuracy.usa) && (!temp || temp == obj.temp.usa) && (!modeOptions || $.inArray(modeOptions, obj.modeOptions) > -1) ? obj : undefined
});
//print result
console.log('found:', selected);
$('#result').html($.map(selected, function (val) {
return '<p>' + JSON.stringify(val) + '</p>'
}))
})
Demo: Fiddle

Changing one form value based on onChange of another with javascript

I can't seem to get this function to work out. I'm trying to change the "business" input value of my form based on an amount selected in the "amount" dropdown. What am I missing!!! I've been trying this for an hour.
<script type="text/javascript">
function chPy()
{
var businessvar = "paypals#ramatico.com";
if (document.forms['5'].amount.value > 11){
businessvar = "paypall#ramatico.com"
}
document.forms['5'].business.value = businessvar;
}
</script>
<form name="5">
<select name="amount" OnChange="chPy()">
<option value="na">Select</option>
<option value="1.00">$1</option>
<option value="5.00">$5</option>
<option value="10.00">$10</option>
<option value="15.00">$15</option>
<option value="20.00">$20</option>
<option value="25.00">$25</option>
</select>
<input name="business" type="text" value="">
</form>
Ok. The next step. I have about 100 of these forms on a page. Instead of creating one for each form, I'd like to have one script that changes based on which form is being changed with "onChange". Each of the forms on the page have values of the same name (but not ID) (they are for paypal). I think it will be ok if I can change the"formname" in the following: "document.forms['formname']" based on a variable populated by something like chPy("formname") etc..... I can't seem to get that to work either.
Removing the form reference would take care of both of your items.
<script type="text/javascript">
function chPy(oSelect)
{
var businessvar = "paypals#ramatico.com";
if (oSelect.form.amount.value > 11){
businessvar = "paypall#ramatico.com"
}
oSelect.form.business.value = businessvar;
}
</script>
<form name="5">
<select name="amount" OnChange="chPy(this)">
<option value="na">Select</option>
<option value="1.00">$1</option>
<option value="5.00">$5</option>
<option value="10.00">$10</option>
<option value="15.00">$15</option>
<option value="20.00">$20</option>
<option value="25.00">$25</option>
</select>
<input name="business" type="text" value="">
</form>
Problem is that you are using a number as form name.
Add some letters to the name and it will work:
<script type="text/javascript">
function chPy()
{
var businessvar = "paypals#XYZ.com";
if (document.forms['form5'].amount.value > 11){
businessvar = "paypall#XYZ.com"
}
document.forms['form5'].business.value = businessvar;
}
</script>
<form name="form5">
<select name="amount" OnChange="chPy()">
<option value="na">Select</option>
<option value="1.00">$1</option>
<option value="5.00">$5</option>
<option value="10.00">$10</option>
<option value="15.00">$15</option>
<option value="20.00">$20</option>
<option value="25.00">$25</option>
</select>
<input name="business" type="text" value="">
</form>
HTML:
<form name="form5">
<select name="amount">
<option value="na">Select</option>
<option value="1.00">$1</option>
<option value="5.00">$5</option>
<option value="10.00">$10</option>
<option value="15.00">$15</option>
<option value="20.00">$20</option>
<option value="25.00">$25</option>
</select>
<input type="text" name="business">
</form>
JavaScript:
var form5 = document.forms['form5'];
form5.amount.onchange = function() {
form5.business.value =
(this.value > 11 ? 'paypall' : 'paypals') + '#ramatico.com';
}
Live demo: http://jsfiddle.net/Fx7zh/
For multiple forms, you can use this JavaScript code:
for (var i = 0, l = document.forms.length; i < l; i++) {
document.forms[i].amount.onchange = function(i) {
this.form.business.value =
(this.value > 11 ? 'paypall' : 'paypals') + '#ramatico.com';
}
}
Live demo: http://jsfiddle.net/Fx7zh/2/

Categories

Resources