Need to do dynamic filtering options , namely age and do.My code jsfiddle.net,but came across a problem that does not work in chrome method hide.Found answers(1, 2) but do not know how to put them in my code.
Problem in:
$("#age_from").change(function(){
$("#age_to option").each(function(i) {
if(parseInt($("#age_from").val()) > parseInt($(this).val())) {
$(this).hide();
}
else {
$(this).show();
}
});
});
It seems that chrome wont let you simply hide option tags. You may have to resort to dynamically filling the from options after you select the to option. I've updated your jQuery code below to allow passing a range of numbers in:
function fill(element, range_start, range_end){
if(typeof range_start == 'undefined') {
range_start = 1;
}
if(typeof range_end == 'undefined') {
range_end = 100;
}
// STORE THE PREVIOUSLY SELECTED VALUE
var selected = element.val();
// RESET THE HTML OF THE ELEMENT TO THE FIRST OPTION ONLY
element.html(element.find('option').first());
var age_list = [];
for (var i = range_start; i < range_end; i++){
age_list.push(i);
}
$.each(age_list, function(key, value) {
$(element)
.append($("<option></option>")
.attr("value", value)
.text(value));
});
// RESET THE VALUE
element.val(selected);
}
fill($('#age_from'));
fill($('#age_to'));
$("#age_from").change(function(){
// FILL THE SELECT ELEMENT WITH NUMBERS FROM THE RANGE #age_from.val() + 1 TO 100
fill($('#age_to'), parseInt($("#age_from").val()) + 1, 100);
});
$("#age_to").change(function(){
// FILL THE SELECT ELEMENT WITH NUMBERS FROM THE RANGE 1 TO #age_to.val()
fill($('#age_from'), 1, parseInt($("#age_to").val()));
});
I'm not entirely sure about performance on this, but as I've removed the .each() for going through the select options to hide them, it may still perform well.
updated working fiddle here:
http://jsfiddle.net/andyface/GKVxu/1/
Related
Using Selectize.js in an Angular 9 application for selecting multiple values. Please see links to my UI at the end
https://selectize.github.io/selectize.js/
https://github.com/selectize/selectize.js
I'm trying enable the user to edit the already selected values by simply clicking on the selected item. Selectize has the concept of Plugins by which "features can be added to Selectize without modifying the main library." I'm making use of this concept to override onMouseDown event, where I'm attempting to make the clicked item editable. I have successfully used this method to override onKeyDown to implement editing of the last selected value by clicking on backspace. Please see code pasted at the bottom. this.onKeyDown = (function() {...
https://github.com/selectize/selectize.js/blob/master/docs/plugins.md
The already selected items are shown as a layer of div elements over the underlying input. To make a selected item editable, I'm removing the selected element div from the DOM, populating the underlying input element with the text from the div. That way that particular item becomes a input from a div and is editable.
There are a few issues im running into:
Its not possible to determine the caret position from the div that was clicked. I am able to get the div text and pre-populate the input element but not put the caret at the right place in input. By default the caret shows at the end and the user can move it around.
Corer cases around when a name is already being edited and the user clicks on another item to edit. The selectize library is giving api to insert selections only at the end of the already selected items. For me to keep deleting the div's and populating the input to mimic the editing effect I need to be able to insert at different positions but the library doesnt seem to have the capability for it.
Trying to see if anyone has worked on something similar or has any suggestions. Thanks in advance!
var Selectize = require('./selectize-standalone');
(function () {
Selectize.define('break_on_backspace_custom_plugin', function(options) {
var self = this;
options.text = options.text || function(option) {
return option[this.settings.labelField];
};
this.onMouseDown = (function() {
var original = self.onMouseDown;
return function(e) {
var index, option;
if (!this.$control_input.val().length && this.$activeItems.length > 0) {
index = this.caretPos - 1;
var toBeEdited = this.$activeItems[0];
var toBeEditedText = toBeEdited.textContent;
var text = toBeEditedText.substring(0, toBeEditedText.length - 1);
var prevEdit = localStorage.getItem("currentEdit");
if (index >= 0 && index < this.items.length) {
if (this.deleteSelection(e)) {
localStorage.setItem("currentEdit", text);
this.setTextboxValue(text);
this.refreshOptions(true);
if (prevEdit && prevEdit !== text) {
this.addItem(prevEdit);
}
}
//e.preventDefault();
//return;
}
}
//e.preventDefault();
return original.apply(this, arguments);
};
})();
this.onKeyDown = (function() {
var original = self.onKeyDown;
return function(e) {
var index, option;
if (e.keyCode === 8 && this.$control_input.val() === '' && !this.$activeItems.length) {
index = this.caretPos - 1;
if (index >= 0 && index < this.items.length) {
option = this.options[this.items[index]];
if (this.deleteSelection(e)) {
//option.value = option.value.substring(0, option.value.length - 1);
this.setTextboxValue(options.text.apply(this, [option]));
this.refreshOptions(true);
}
e.preventDefault();
return;
}
}
return original.apply(this, arguments);
};
})();
});
return Selectize;
})();
Pictures of UI and work in progress
Editing last element by clicking backspace
https://i.stack.imgur.com/wULcT.png
Editing middle element by clicking on it
https://i.stack.imgur.com/U5hxd.png
How do I use Jquery to find the last checked/unchecked item and so that I can add or remove them from other two listboxs?
I am creating a dropdown listbox(excludedPeople) with multiselect checkbox with two other listboxs(PrimaryPerson,secondaryPerson) in same form. All three list box are having same set of data during form load. If any item in excludedPeople is selected(checked), I need to remove that item from PrimaryPerson and secondaryPerson and vise-versa.
ASP.Net MVC multiselect Dropdown Listbox code:
#Html.ListBoxFor(m => m.ExcludedPeople, Model.AllPeopleListViewModel,
new { #class = "chkDrpDnExPeople" , #multiple = "multiple"})
jQuery code:
$(".chkDrpDnExPln").change(function ()
{
console.log("Trigger" + $(this).val()); //this code gets the list of all items selected. What I need is to log only last selected/unselected item's val & text into the console.
});
Any help is appreciated. Ask questions if any.
Well, after waiting for 2 days I made a solution myself and posting it here so that others can make use of it.
I made this code for multiselect dropdown listbox with checkboxes in each list item. I expect this to work on similar controls like checked listbox but haven't tested it.
I followed register control and get notified by event so the usage can be made seamless without getting into details.
Usage:
1) include the "JQuery based Library" part into your project as shared or same js script file.
2) Use the below approach to consume the functionality. The event should get you the changed values when the control selection is changed.
RegisterSelectedItemChangeEvent("chkDrpDnctrl#1");
RegisterSelectedItemChangeEvent("chkDrpDnctrl#2");
RegisterSelectedItemChangeEvent("chkDrpDnctrl#3");
$(".chkDrpDnctrl").on("OnSelectionChange", function (e,eventData)
{
var evntArgs = {
IsDeleted: false,
IsAdded: false,
AddedValues: [], //null if no change/None. Else changed value.
DeletedValues: [] //null if no change/None. Else changed value.
};
var source = e;
evntArgs = eventData;
var elementnm = $(this).attr("id");
if (evntArgs !== "undefined" && elementnm != "")
{
if (evntArgs.IsAdded == true)
{
//if excluded checked then remove.
for (var i = 0; i < evntArgs.AddedValues.length; i++)
{
PerformAction (control#, evntArgs.AddedValues[i]);
}
}
if (evntArgs.IsDeleted == true)
{
//if excluded checked then remove.
for (var i = 0; i < evntArgs.DeletedValues.length; i++)
{
PerformAction (control#, evntArgs.AddedValues[i]);
}
}
}
});
JQuery based Library:
function RegisterSelectedItemChangeEvent(selector) {
var dropdownElementRef = selector;
//Intializes the first time data and stores the values back to control. So if any of the checkboxes in dropdown is selected then it will be processe and added to control.
$(dropdownElementRef).data('lastsel', $(dropdownElementRef).val());
var beforeval = $(dropdownElementRef).data('lastsel');
var afterval = $(dropdownElementRef).val();
//storing the last value for next time change.
$(dropdownElementRef).data('lastsel', afterval);
//get changes details
var delta = GetWhatChanged(beforeval, afterval);
//stores the change details back into same object so that it can be used from anywhere regarless of who is calling it.
$(dropdownElementRef).data('SelectionChangeEventArgs', delta);
//prepares the event so that the same operation can be done everytime the object is changed.
$(dropdownElementRef).change(function () {
var beforeval = $(dropdownElementRef).data('lastsel');
var afterval = $(dropdownElementRef).val();
//storing the last value for next time change.
$(dropdownElementRef).data('lastsel', afterval);
//get changes details
var delta = GetWhatChanged(beforeval, afterval);
//stores the change details into same object so that it can be used from anywhere regarless of who is calling it.
$(dropdownElementRef).data('OnSelectionChangeEventArgs', delta);
//fires the event
$(dropdownElementRef).trigger('OnSelectionChange', [delta]);
//$.event.trigger('OnSelectionChange', [delta]);
});
var initdummy = [];
var firstval = GetWhatChanged(initdummy, afterval);
//fires the event to enable or disable the control on load itself based on current selection
$(dropdownElementRef).trigger('OnSelectionChange', [firstval]);
}
//assume this will never be called with both added and removed at same time.
//console.log(GetWhatChanged("39,96,121,107", "39,96,106,107,109")); //This will not work correctly since there are values added and removed at same time.
function GetWhatChanged(lastVals, currentVals)
{
if (typeof lastVals === 'undefined')
lastVals = '' //for the first time the last val will be empty in that case make both same.
if (typeof currentVals === 'undefined')
currentVals = ''
var ret = {
IsDeleted: false,
IsAdded: false,
AddedValues: [], //null if no change/None. Else changed value.
DeletedValues: [] //null if no change/None. Else changed value.
};
var addedvals;
var delvals;
var lastValsArr, currentValsArr;
if (Array.isArray(lastVals))
lastValsArr = lastVals;
else
lastValsArr = lastVals.split(",");
if (Array.isArray(currentVals))
currentValsArr = currentVals;
else
currentValsArr = currentVals.split(",");
delvals = $(lastValsArr).not(currentValsArr).get();
if (delvals.length > 0)
{
//console.log("Deleted :" + delvals[0]);
for (var i = 0; i < delvals.length; i++)
{
ret.DeletedValues.push(delvals[i]);
}
ret.IsDeleted = true;
}
addedvals = $(currentValsArr).not(lastValsArr).get();
if (addedvals.length > 0)
{
//console.log("Added:" + addedvals[0]);
for (var i = 0; i < addedvals.length; i++)
{
ret.AddedValues.push(addedvals[i]);
}
ret.IsAdded = true;
}
return ret;
};
On my website, users can click on some text to open up a Modal. This Modal allows users to choose a bunch of toppings to add to their Pizza.
Through Javascript, I add each selected topping to an array and change the text display to match their selected toppings. This more or less works, but the problem is for some reason, whenever they add a topping, it is added to ALL arrays, not just the item it's selected for. Can someone help me find why this is happening?
// Open Toppings Modal
$(document).ready(function() {
var count = -1
var tplist = []
$(".order").each(function(){
count += 1
tplist.push([])
var listeners = 0
setModal(count, tplist, listeners)
});
function setModal(count, tplist, listeners) {
$("#openModal" + count).click(function(){
console.log("clicked")
$("#toppingModal" + count).modal()
if (listeners == 0) {
listeners += 1
$("input[type='checkbox']").change(function() {
// TODO: Fix Bug
// Adding to all javascript lists
if (this.checked) {
tplist[count].push($(this).val());
console.log(tplist)
}
else {
ele = $(this).val();
pos = $.inArray(ele, tplist[count])
if ( ~pos ) tplist[count].splice(pos, 1);
}
// Change text to list
if (tplist[count].length > 0) {
$("#openModal" + count).text(tplist[count])
}
else {
$("#openModal" + count).text("Select Toppings")
}
})
}
});
};
});
I am suspecting your $("input[type='checkbox']").change(function() {} is called for every model. Try setting count number somewhere when you click select topping and compare inside $("input[type='checkbox']").change(function() {} to prevent adding of toppings in all arrays
I have a select field where users can select & I am using Select2 for multiple selection.
<select id="currency" name="currency_cc">
<option value="BDT">BDT - Bangladesh</option>
<option value="USD">USD - USA</option>
<option value="ZWL">ZWL - Zimbabwe</option>
</select>
But the problem is if I select option 2 from the list & then select option 1,
then select2 places option 1 val before option 2, but I selected option 2 first.
I want option 1 to be placed after option 2 as I selected in this order, How do I can do this? I think there's nothing on official documentation.
But I seen this working in a JS Fiddle which I get from the following Q/A page:
jQuery select2 control - retrieve last selected element
and the fiddle is:
http://jsfiddle.net/jEADR/1588/
Check, there's it works like I wanted, but it doesn't behave like that in my code.
Someone please help.
I managed to make it work with the following code, (I collected it from somewhere else & no longer can remember from where)
var $select2 = $('#currency-converter-currencies').select2({
templateSelection: template,
width: '100%'
}).val({!! $setting->convert_currencies !!}).trigger('change');
// cache order of initial values
var defaults = $select2.select2('data');
defaults.forEach(function (obj) {
var order = $select2.data('preserved-order') || [];
order[order.length] = obj.text;
$select2.data('preserved-order', order);
});
function select2_renderSelections($select2) {
var order = $select2.data('preserved-order') || [];
var $container = $select2.next('.select2-container');
var $tags = $container.find('li.select2-selection__choice');
var $input = $tags.last().next();
// apply tag order
order.forEach(function (val) {
var $el = $tags.filter(function (i, tag) {
return $(tag).data('data').id === val;
});
$input.before($el);
});
}
function selectionHandler(e) {
var $select2 = $(this);
var val = e.params.data.id;
var order = $select2.data('preserved-order') || [];
switch (e.type) {
case 'select2:select':
order[order.length] = val;
break;
case 'select2:unselect':
var found_index = order.indexOf(val);
if (found_index >= 0) order.splice(found_index, 1);
break;
}
$select2.data('preserved-order', order); // store it for later
select2_renderSelections($select2);
}
$select2.on('select2:select select2:unselect', selectionHandler);
/**
* Put select option's value instead on text in select box
* #param data
* #param container
*/
function template(data, container) {
return data.id;
}
Here we replacing original Select2 values with our filtered values using the "template" function.
This shouldn't be the permanent fix, Consider it as a temporary fix because of the way this programmed.
Hope this will help someone else in the future
Could someone please help me handle this issue in jQuery
I have a requirement where I have two dropdowns:
The no of floors of the flat (numberOfFloors)
The flat where the user stays (whichFloorYouStay)
I need to remove all the invalid options from the second dropdown. How do I achieve this?
For example:
If a user select the numberOfFloors option as 3, then I should remove options 4 and 5 from whichFloorYouStay dropdown and just load 1,2,3 as whichFloorYouStay options.
Similarly, if a user select the numberOfFloors option as 1, then I should remove options 2,3,4,5 from whichFloorYouStay dropdown and just load 1 as whichFloorYouStay option.
Please find my JSBin link:
http://jsbin.com/sibufive/1/edit?html,js,output
Try this:
$(document).ready(function () {
//NEW CODE:
var floorsvals = new Array();
var lastvalue = Number.MAX_VALUE; //Useful for checking whether we need to append or remove elements - Initialize this with an arbitrarily large number
//Fill possible floor vals with value of <option>'s
$("#numberOfFloors option").each(function () {
floorsvals.push($(this).val());
});
//NOTE: If you already know the values of the numberOfFloors array, you can just add those values straight into the "floorsvals" array
//The above loop is just handy if you are dynamically generating a <select> list and don't already know the values
$("#numberOfFloors").change(function () {
alert($("#numberOfFloors").val());
var value = $("#numberOfFloors").val();
//NEW CODE:
//If we need to append...
if (value > lastvalue) { //This value is larger than the last value we just had
for (i = 0; i < floorsvals.length; i++) {
if (floorsvals[i] <= value && $('#whichFloorYouStay option[value=' + floorsvals[i] + ']').length === 0) { //Floor value is less than the selected maxvalue and an option with this floor value doesn't already exist...
$('<option value="' + floorsvals[i] + '">' + floorsvals[i] + '</option>').appendTo("#whichFloorYouStay"); //...So add that floor value
}
}
} else { //Otherwise, we need to remove
//OLD CODE:
$('#whichFloorYouStay option').each(function () { //Go through each option
if ($(this).val() > value) { //If this option's value is greater than the numberOfFloors value, remove it
$(this).remove();
}
});
}
//NEW CODE:
lastvalue = value; //Update last value chosen with this value
});
});
Here's a demo: http://jsbin.com/sibufive/40/edit
var value = $("#numberOfFloors").val();
should become
var value = $("#numberOfFloors").val();
value-=1
I would also suggest adding a value 0 to the first set of options one so you never have a user begin at 1 and try to move to the second menu