Finding Closest Matching Value using jQuery or javascript - javascript

Consider a markup such as
<select id="blah">
<option value="3">Some text</option>
<option value="4">Some text</option>
<option value="8">Some text</option> // <---- target this tag based on value 7
<option value="19">Some text</option>
</select>
Suppose I have a value with me, say 7. Is it possible to target the option tag whose value attribute is closest to 7 which, in this case, would be <option value="8">?
I'm aware of ^ which means starting with and $ which means ending with and was hoping if there is something like this to find the closest match for a given value.

I'll go like this:
http://jsfiddle.net/GNNHy/
var $tmpOption = $('<option value="7">Some text 7</option>');
$("#blah").append($tmpOption);
var my_options = $("#blah option");
my_options.sort(function(a,b) {
if (parseInt(a.value,10) > parseInt(b.value,10)) return 1;
else if (parseInt(a.value,10) < parseInt(b.value,10)) return -1;
else return 0
})
$("#blah").empty().append( my_options );

How about a recursion? It will find the closest value:
JS-BIN Demo
function getClosest(val, ddl, increment){
if(ddl.find('option[value="'+val+'"]').length){
return val;
}
else
try{
if(increment)
return getClosest(++val, ddl, increment);
else
return getClosest(--val, ddl, increment);
}
catch(err){
return -1;
}
}
function findClosest(val, ddl){
var larger = getClosest(val, ddl, true);
var smaller = getClosest(val, ddl, false);
if(larger == smaller == -1)
return -1;
else if (larger == -1)
return smaller;
else if (smaller == -1 )
return larger;
if(larger - val > val - smaller)
return smaller;
else
return larger
}

Yes just substract your value (7) with the option values(use each function)...the value with the minimum positive outcome will be your targeted option. I hope you will have the desired result.

The easiest way is perhaps the good old linear search (you can do binary, but it's more tricky than usual):
var target;
var $options;
var best=Infinity;
var bestAt;
$options.each(function(){
var error = this.value - target;
error = error>0 ? error : -error;
if(error<=best){
best=error;
bestAt=this;
}
})
//return $(bestAt);

function findClosest(num){
var select = document.getElementById('blah');
var options = select.options;
var dif = Infinity;
var index;
for(var i = 0; i < options.length; i++){
var newdif = Math.abs(parseInt(options[i].value) - num);
if(newdif < dif){
dif = newdif;
index = i;
}
}
select.selectedIndex = index;
}

If you can use jquery I would do something like
$(function () {
// comes from somewhere
var val = 7;
var sortByDifference = $("#blah option").sort(function (opt1, opt2) {
return Math.abs(parseInt($(opt1).val()) - val) - Math.abs(parseInt($(opt2).val()) - val);
});
alert($(sortByDifference[0]).val());
});
In sortByDifference you have all values sorted by how close they are to your value. The routine returns the closest greater or lower and doesn't require the options to be sorted.

Related

Dropdown selection value doesn't become a real value and work in JavaScript

I have a language dropdown and I try to alert the user to have to choose one language before doing anything further like languageOption can become a string and go into array. But it's not working and I don't understand why. I tried:
alert("You didn't choose any language.");
console.alert("You didn't choose any language.");
console.log("You didn't choose any language.");
But they all don't work.
And I thought another way to solve this, which I make
<option value="1" selected>English (American)</option>
but then the value = "1" doesn't become the a value for variable 'languageOption'. So the arrays don't respond and don't know what to do when I see in console. I don't understand why the array is not responding.
Any help I would appreciate.
Below is my code:
<select id="languageSelection" style=display:none>
<option value="">Choose a language</option>
<option value="1">English (American)</option>
<option value="2">Chinese (Mandarin)</option>
<option value="3">Japanese</option>
</select>
var audioSrc = "sound/"
var audioType = ".wav";
// default number of random question, if user this used the dropdown
var default_numFollowUp = 4;
// default delai (seconds) between random questions, if user this used the dropdown
var default_secFollowUp = 10;
// Create the audio element
var audioElement = document.createElement('audio');
var endingArr = [];
var runThroughArr = [];
var randomArr = [];
var languageOption = parseInt($("#languageSelection").val() );
$("#languageSelection").on("change", function(){
languageOption = $(this).val(); // Make languageOption value be string
//if(languageOption.length==0){languageOption=1;}
console.log("langugeOption is " + languageOption);
console.log("Language changed to: "+ $(this).find("option").eq( $(this)[0].selectedIndex ).text() + " (Index: "+languageOption+")" );
console.log(typeof(languageOption)); // Outputs string
endingArr = [];
runThroughArr = [];
randomArr = [];
if(languageOption === ""){
alert("You didn't choose any language.");
console.alert("You didn't choose any language.");
console.log("You didn't choose any language.");
}
else if(languageOption === "1"){
console.log("English");
for(i = 0; i < intro_playList.length; i++){
if(intro_playList[i].stage === "ending"){ endingArr.push(i); }
if(intro_playList[i].runThrough){ runThroughArr.push(i); }
if(intro_playList[i].random){ randomArr.push(i); }
}
}
else if (languageOption === "2"){
console.log("Chinese");
for(i = 0; i < intro_playList_chi.length; i++){
if(intro_playList_chi[i].stage === "ending"){ endingArr.push(i); }
if(intro_playList_chi[i].runThrough){ runThroughArr.push(i); }
if(intro_playList_chi[i].random){ randomArr.push(i); }
}
}
});
You need to assign the onchange function after loading the document. With jQuery, you can do it like this
var languageOption;
$(document).on("ready", function() {
languageOption = $("#languageSelection").val();
$("#languageSelection").on("change", function() {
your code here ...
}
}

How can I refresh second select option when first select option is changed?

How can I refresh second select option when first select option is changed?
I am generating the array here for patient_code2:
//GENERATE NUMBERS FOR CYCLE
function patsient(selector) {
var i;
for (i = 1; i <= 99; i++) {
var text = '0' + i;
selector.options[i - 1] = new Option(text.substr(text.length - 2, 2));
}
}
patsient(document.getElementById("patient_code2"));
I am generating the array for patient_code here:
function myFunction(selector) {
var i;
for (i = 1; i <= 999; i++) {
var text = '00' + i;
selector.options[i - 1] = new Option(text.substr(text.length - 3, 3));
}
}
//usage:
myFunction(document.getElementById("patient_code"));
Here I am inserting the last value from database to the field:
//INSERT THE VALUE FROM DATABASE
var tsykkel_id = '<?php foreach ($tsykkel_id as $row){echo $row['patsiendi_tsykkel'];}?>';
$('#patient_code2')[0].options[parseInt(tsykkel_id)].selected = true;
$(document).ready().on('change', '#patient_code2', function () {
var index = $('option:selected', $(this)).index();
$('option', $(this)).each(function (i, x) {
if (i < index) { $(this).remove(); }
});
});
HTML
<select name="patient_code" data-placeholder="" id="patient_code" class="chosen-select form-control" tabindex="2">
</select>
<label class="control-label">Tsükkel:</label>
<select name="patient_code2" data-placeholder="" id="patient_code2" class="chosen-select form-control" tabindex="2">
</select>
So lets say that person chooses 002 from the first then the second should start from 01 again.
try this then. Code is tested.
$(document).ready().on('change','#patient_code2',function(){
var index = $('option:selected',$(this)).index();
$('option',$(this)).each(function(i,x){
if(i<index){$(this).remove();}
});
$('select#patient_code').prop('selectedIndex', 0);
});
fiddle : http://jsfiddle.net/roullie666/69j94ro6/2/
You can just start printing after the match has been found. I am writing both ways since you asked?
For javascript version use roullie's no point duplicating.
<?php
$flag = false;
foreach ($tsykkel_id as $row) {
if ($selected) {
$flag = true;
}
if ($flag) {
$row['patsiendi_tsykkel'];
}
}?>

jQuery - Get Total value of the next options in a dropdown after the selected one based on attribute

HTML Output
<option data-task-hours="100" value="1"> - Parent Task</option>
<option data-task-hours="50" value="2"> - - Child task</option>
<option data-task-hours="50" value="3"> - - Child task</option>
jQuery Code to fetch value of next option:
$('#dropDownId option:selected').next().data('task-hours');
Tried looping for multiple child task(s) but its not working:
var foo = [];
$('#dropDownId :selected').each(function(i, selected){
foo[i] = $(selected).data('task-hours');
});
How can I fetch total/combined value of next options after the selected one ?
In above case total value should be 50 (child 1) + 50 (child 2) = 100 (parent task) i.e. child task(s) total value should not exceed the value of parent task
There's the nextAll() method for this :
var selectedOption = $('#dropDownId option:selected')
var selectedOptionValue = selectedOption.data('task-hours');
var sum = 0;
selectedOption.nextAll().each(function(){
if (sum < selectedOptionValue) {
sum += $(this).data('task-hours');
} else {
sum = selectedOptionValue;
return false;
}
});
Why dont you loop it.First get the selected value.Then run the loop like below.
Note : below is not error free code , Its just like alogirthm or steps.
var startfrom = $('#dropDownId option:selected').attr('value');
var alltext = "";
$('option').each(function(key,attr) {
{
if(key<startfrom) return;
alltext += attr.text;
}
console.log(alltext);
You can use:
var sum=0;
alert($('select option:first').attr('data-task-hours'))
$('select option:gt(0)').each(function(){
sum+= parseInt($(this).attr('data-task-hours'));
});
if($('select option:first').attr('data-task-hours')==sum){
alert("parent and children have same hours");
}
Working Demo
$("#dropDownId").on('change', function () {
var a=$('#dropDownId option:selected+option').attr('data-task-hours');
var b=$("#dropDownId option:selected").attr('data-task-hours');
var c=Number(a)+Number(b);
alert(c);
});
JS FIDDLE
Are you after something like this? Demo#Fiddle
var sOpt = $("#sel option:selected");
var nextOpts = sOpt.nextAll();
var sum = 0;
nextOpts.each(function() {
sum += $(this).data("taskHours");
});
if ( sum > sOpt.data("taskHours") ) {
alert ("Total is greater than parent");
} else {
alert (sum);
}
HTML:
<select id="sel">
<option data-task-hours="100" value="1" selected="selected"> - Parent Task</option>
<option data-task-hours="50" value="2"> - - Child task</option>
<option data-task-hours="50" value="3"> - - Child task</option>
</select>
This works:
var indexOfSelected = $("#dropDownId option:selected").index()
var options = $("#dropDownId option")
var children = options.slice(indexOfSelected + 1, options.length)
total = 0
$.each(children, function(){
total += $(this).data("task-hours")
});
console.log("Total sum of children: " + total)
Try this Working Demo
$("#dropDownId").on('change', function () {
var one=$('#dropDownId option:selected+option').attr('data-task-hours');
var onetwo=$("#dropDownId option:selected").attr('data-task-hours');
var onethree=Number(one)+Number(onetwo);
console.log(onethree);
});

Trying to sort listbox by clicking button, without using jQuery

I am working on a listbox that has items added by the user. I figured out how to delete items, but after a few hours of trying I am unable to sort alphabetically.
If you're using jQuery, you can do it that way:
var $listbox = document.getElementById('PairListBox');
var $options = $listbox.find('option');
$options.sort(function(a,b){
var an = a.textContent.toLowerCase(),
bn = b.textContent.toLowerCase();
if(an > bn) {
return 1;
}
if(an < bn) {
return -1;
}
return 0;
});
$options.detach().appendTo($listbox);
EDIT:
Without jQuery (probably you can do better):
var $options = [].map.call($listbox.children, function(option) { return option });;
$options.sort(function(a,b){
a = a.textContent.toLowerCase();
b = b.textContent.toLowerCase();
if(a > b) {
return 1;
}
if(a < b) {
return -1;
}
return 0;
});
$options.forEach(function($option) {
$listbox.remove($option);
});
$options.forEach(function($option) {
$listbox.appendChild($option);
});
Does this help?
function SortList(listname) {
var $r = $(listname + " option");
$r.sort(function(a, b) {
return (a.value < b.value) ? -1 : (a.value > b.value) ? 1 : 0;
//or you can have a.text, b.text, etc
});
$($r).remove();
$(listname).append($($r));
}
$('#sort').click(function(e) { SortList('#listbox'); });
From http://jsfiddle.net/Kz2bg/19/
The following will do the job in plain JS. It puts the options into an array, sorts that, then re–orders the select. You can make the sort function anything you like, this uses a simple numeric sort.
<script>
// Sort options of a select element by value
function sortSelectByValue(select) {
var arr = toArray(select.options);
arr.sort(function(a, b) {return a.value - b.value});
arr.forEach(function(opt) {
select.appendChild(opt);
})
// Optional - set first option as selected
select.selectedIndex = 0;
}
// Convert a list like object to an Array
function toArray(obj) {
var arr = [];
for (var i=0, iLen=obj.length; i<iLen; i++) {
if (i in obj) {
arr[i] = obj[i];
}
}
return arr;
}
</script>
Some play markup:
<select id="sel0">
<option value="2">2
<option value="0">0
<option value="1">1
</select>
<input type="button" value="sort select" onclick="
sortSelectByValue(document.getElementById('sel0'));
">
If you want to live on the edge, the following works in modern browsers:
// Sort options of a select element by value
function sortSelectByValue(select) {
var arr = Array.prototype.splice.call(select.options, 0, select.options.length)
.sort(function(a, b) {return a.value - b.value})
.forEach(function(opt) {select.appendChild(opt)});
}
Edit
BTW, in your original function, the following:
var newOption = document.createElement('option');
newOption.value = textbox.value; // The value that this option will have
newOption.innerHTML = textbox.value; // The displayed text inside of the <option> tags
can be:
var newOption = new Option(textbox.value, textbox.value);

if statement counter variable confusion javascript

As a novice in javascript, I am having trouble writing an If statement, with an event happening after the fourth turn. I want the alert to pop up after the user has clicked four options. I added the counter variable "turns" to the output so I can see if it has been counting correctly but it does not.
var question1 = new Array();
var turns = 0;
window.onload = function () {
var eSelect = document.getElementById('question1');
var optOtherReason = document.getElementById('displayresponse');
var options = document.getElementsByTagName("option");
eSelect.onchange = function () {
var li = document.createElement("li");
li.innerHTML = options[eSelect.selectedIndex].innerHTML;
var ol = document.getElementById("appendedtext");
ol.appendChild(li);
question1.push(li.innerHTML);
var x = document.getElementById("display");
x.innerHTML = question1 + turns;
turns + 1;
}
if (eSelect.selectedIndex == 3) {
optOtherReason.style.display = 'block';
turns - 1;
}
if (turns = 4) {
alert("hey your turn is over")
}
}
<select id="question1" name="question">
<option value="x">Reason1</option>
<option value="y">Reason2</option>
<option value="other">Otherreason</option>
<option value="none">None</option>
</select>
<br>
<div id="displayresponse" style="display:none;">If you did not see a choice here, you may search for other sites.</div>
<ol id="appendedtext"></ol>
<div id="display"></div>
To compare two expression you need to use == :
if ( turns == 4)
Also, turns is a variable, so to sum/substract one you should use:
turns += 1
turns -= 1
Or, as pointed out in comments, you could also use:
turns++;
turns--;

Categories

Resources