I currently have a dynamically generated checkbox which when clicked creates a table. Multiple selections can be selected on my checkbox and I store this in an array. I have a loop for storing different selections e.g 1st, 2nd and 3rd checked selections.
Checkbox
option_one
option_two
options_three
The problem I am facing is, if I select the options in ascending order like 1>2>3 the tables are generated correctly:
Table_One
Table_two
Table_Three
However if I I select in a descending order, or I mix it up, option_one always ends up being passed as the first selection even when this isn't true.
My code:
$(document).on("change", ".tbl_list", function () {
var tbls = [];
$("input:checkbox[name='tbl[]']:checked").each(function () {
tbls.push($(this).val());
var tbl2Name = " ";
var tbl3Name = " ";
var tblName = " ";
for (i = 0; i < tbls.length; i++) {
if (i === 0) {
tblName = tbls[i];
}
if (i == 1) {
tbl2Name = tbls[i];
}
if (i == 2) {
tbl3Name = tbls[i];
}
}
$("#table").html(tblName);
Where tbl_list is the checkbox class-name and tbl[] is the name. So why does tblName always assume the value of the first object in the checkbox list?
Lets break this down a bit, every time one of your checkboxes changes you create a brand new array
$(document).on("change", ".tbl_list", function () {
var tbls = [];
Then you loop through all the checked checkboxes filling this list
$("input:checkbox[name='tbl[]']:checked").each(function () {
tbls.push($(this).val());
jquery .each will iterate over all the checkboxes which are checked, it does this in the order they appear in the DOM, not in the order you happen to have checked them in (why would it? how would it know?)
If you want to preserrve the order that you checked them in then you need to maintain a persistant list, and push a new item to the end of the list when checked, and remove an item when unchecked.
$(".checkbox").change(function() {
if(this.checked) {
//push into array
else {
//remove from array
}
});
Cant you just check which checkbox has been selected and add its value to an array this way you can keep the order.
After the suggestions I made a few amendments and it now works as intended.
var tbls = [];
$(document).on("change", ".tbl_list", function () {
if (this.checked){
tbls.push($(this).val());
console.log(tbls);
var tbl2Name = " ";
var tbl3Name = " ";
var tblName = " ";
for (i = 0; i < tbls.length; i++) {
if (i === 0) {
tblName = tbls[i];
}
if (i == 1) {
tbl2Name = tbls[i];
}
if (i == 2) {
tbl3Name = tbls[i];
}
}
}
$("#table").html(tblName);
window.sessionStorage.setItem("tblN", tblName);
window.sessionStorage.setItem("tblN2", tbl2Name);
window.sessionStorage.setItem("tblN3", tbl3Name);
Related
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
How to create 2 checkboxes, displaying (i.e.) 1. Food and 2. Musician…
Where
1) if both checkboxes are checked, food and musicians are displayed;
2) if food is checked and musician is unchecked, the element is still visible, because it contains food, dispite it also contains musician;
3) if musician is checked and food is unchecked, it is also still visible, because it contains musician, dispite it also contains food;
4) if both food and musician are unchecked, the li item disappears.
My html is:
<html>
<head>
</head>
<body>
<ul class="filterSection">
<li>
<input checked="true" type="checkbox" value="Food"/>
<label>Food</label>
</li>
<li>
<input checked="true" type="checkbox" value="Musician"/>
<label>Musician</label>
</li>
</ul>
<ul id="itemsToFilter">
<li data-type="Food">Food</li>
<li data-type="Musician">Musician</li>
<li data-type="Food Musician">Food & Musician</li>
<ul>
</body>
</html>
And the following javascript code (integrated below the two lists):
<script>
// get all of our list items
var itemsToFilter = document.querySelectorAll("#itemsToFilter li");
//setup click event handlers on our checkboxes
var checkBoxes = document.querySelectorAll(".filterSection li input");
for (var i = 0; i < checkBoxes.length; i++) {
checkBoxes[i].addEventListener("click", filterItems, false);
checkBoxes[i].checked = true;
}
// the event handler!
function filterItems(e) {
var clickedItem = e.target;
if (clickedItem.checked == true) {
hideOrShowItems(clickedItem.value, "hideItem", "showItem");
} else if (clickedItem.checked == false) {
hideOrShowItems(clickedItem.value, "showItem", "hideItem");
} else {
// deal with the indeterminate state if needed
}
}
// add or remove classes to show or hide our content
function hideOrShowItems(itemType, classToRemove, classToAdd) {
for (var i = 0; i < itemsToFilter.length; i++) {
var currentItem = itemsToFilter[i];
if (currentItem.getAttribute("data-type") == itemType) {
removeClass(currentItem, classToRemove);
addClass(currentItem, classToAdd);
}
}
}
//
// Helper functions for adding and removing class values
//
function addClass(element, classToAdd) {
var currentClassValue = element.className;
if (currentClassValue.indexOf(classToAdd) == -1) {
if ((currentClassValue == null) || (currentClassValue === "")) {
element.className = classToAdd;
} else {
element.className += " " + classToAdd;
}
}
}
function removeClass(element, classToRemove) {
var currentClassValue = element.className;
if (currentClassValue == classToRemove) {
element.className = "";
return;
}
var classValues = currentClassValue.split(" ");
var filteredList = [];
for (var i = 0 ; i < classValues.length; i++) {
if (classToRemove != classValues[i]) {
filteredList.push(classValues[i]);
}
}
element.className = filteredList.join(" ");
}
</script>
I found out that in css you can do the following:
#itemsToFilter li[data-type*=Food] {background-color: green;}
#itemsToFilter li[data-type*=Musician] {background-color: yellow;}
(The asterisk causes one or multiple data-type attributes to be recognised)
No problems there, so I'm interested in the javascript-part:
Where
1) if both checkboxes are checked, food and musicians are displayed;
2) if food is checked and musician is unchecked, the element is still visible, because it contains food, dispite it also contains musician;
3) if musician is checked and food is unchecked, it is also still visible, because it contains musician, dispite it also contains food;
4) if both food and musician are unchecked, the li item disappears.
I want this without having to make a new checkbox called 'Food Musician'. Which could be done by adding
#itemsToFilter li[data-type*='Food Musician'] {background:pink;}
So only working with the checkboxes 'Food' and 'Musician'.
See or follow this example on http://test.kompagniekistemaker.nl
My question was raised after reading this article from Kirupa:
https://www.kirupa.com/html5/filtering_items_in_a_list.htm
I also found this example, which is kinda what I want:
Filter by multiple data attribute elements
Winning answer gets a bar of chocolate.
Thanks a lot in advance!
Try modifying your if statement like this:
if (currentItem.getAttribute("data-type").indexOf(itemType) !== -1)
I'm pretty sure that you know what it's doing. It searches for a substring in your data attribute. indexOf() returns position of first character of substring if found or -1 if a substring was not found. Does it solves your problem?
A friend solved the problem using this piece of javascript. Every piece is explained separately.
In short:
If I create a checkbox in an ul with a class of '.filterSection' corresponding with another ul containing a li-element with a class of '.itemsToFilter' the following happens:
if no checkbox is selected, it will show everything of that specific ul
if one or more checkboxes is selected, it will show the content of the corresponding checkbox
If you want only one li-element in your ul, you can add an 'invisible' extra li-element using the display:none; attribute in css and let it be 'checked="true"' in html. This way there will always be a checked element in your list of seemingly one item, causing the single visible li-element to behave the same as li elements in a list of two or more li-elements. If you don't do this, your one li-element will always be visible, because when it's unchecked, it will display everything (rule 1, above).
var sections;
var items;
init();
// Initializing function
function init() {
// Get the checkbox sections and the items to filter
sections = query('.filterSection');
items = query('.itemsToFilter li');
// Create a section for every group of checkboxes
for (var i = 0; i < sections.length; i++) {
sections[i] = query('input', sections[i]);
// Loop over the checkboxes in a section
for (var j = 0; j < sections[i].length; j++) {
// Add event listener (filter on change)
sections[i][j].addEventListener('change', filter);
}
}
}
// Function that is called when a checkbox is clicked or unclicked
function filter() {
// Get the selected checkboxes
var selection = getSelection();
// Loop over all items
for (var i = 0; i < items.length; i++) {
// Initially, every item will be shown
var show = true;
// Get the tags associated with the item
var tags = items[i].dataset.type.split(',');
// Loop over each tag section
for (var j = 0; j < selection.length; j++) {
// If the section has no checked boxes, it will be ignored
if (selection[j].length == 0) continue;
// Hide the item, unless we tell it to be shown later
var allow = false;
// Loop over the associated tags
for (var k = 0; k < tags.length; k++) {
// If the tag is also one that has been selected, allow the item to be shown
if (selection[j].indexOf(tags[k]) > -1) {
allow = true;
}
}
// If one of the tags was disallowed, hide the item. Do not keep checking as this is unnecessary
if (!allow) {
show = false;
break;
}
}
// Add the appropriate class
if (!show) items[i].classList.add('hideItem');
else items[i].classList.remove('hideItem');
}
}
// Function to get the selected checkboxes
function getSelection() {
// Here we will keep track of checked boxes
var selection = [];
// Loop over each section
for (var i = 0; i < sections.length; i++) {
// Initialize an empty selection list per section
selection[i] = [];
// Loop over the checkboxes in this section
for (var j = 0; j < sections[i].length; j++) {
// Get the checkbox
var checkbox = sections[i][j];
// If the checkbox is checked, add it to the selection list
if (checkbox.checked) selection[i].push(checkbox.value);
}
}
return selection;
}
// Utility function to query the DOM and return elements
function query(q, container) {
// If no container was given, revert to the entire document
container = container || document;
// Query the container
var results = container.querySelectorAll(q);
// Return the results as an array
return Array.prototype.slice.call(results);
}
On a webpage I give the user the option of hiding table elements (which contain checkboxes) like this:
mytable.style.display = 'none'; //the table and the enclosed textbox is hidden
I am now trying to find all of the tables that are not hidden like this:
var frm = document.forms[0];
var arrayDisposals;
var intCount;
var arrayDisposals = new Array();
for (i = 0; i < frm.elements.length; i++) {
if (frm.elements[i].type == "checkbox" && frm.elements[i].name.substr(0, 3) == "Del") {
if ('none' != frm.elements[i].style.display) {
{
arrayDisposals.push(frm.elements[i].id + '|' + frm.elements[i].checked)
}
}
}
The problem is that the second IF statement does not work i.e. all elements are added to the array. How do I only add checkboxes that are not hidden?
If you were looking for a jQuery solution this should suffice. Use .map()
var arrayDisposals = $('input[type="checkbox"][name*="Del"]:visible').map(function(){
return this.id+ "|" + this.checked
}).get();
Use attribute selector to find checkboxes and where the name contains "Del" and :visible to check if it is not hidden.
DEMO
I have one HTML table and I don't want the value of 2nd column to repeat in the grid.
Here is my jQuery:
$('#tb_cartTable tr td:nth-child(2)').each(function() {
$ele=$(this).text();
if($ele==$productCode)
{
flag="x";
return false;
}
});
if($rowCounter>0 && flag=="x")
{
alert("Duplicate");
}
else
{
//...
}
One way will be to "map" the text of the cells into a JavaScript complex array having the text as key, then compare the amount of keys to amount of cells. If more cells than keys it means there are cells with the same text.
Code for this:
var allCells = $('#tb_cartTable tr td:nth-child(2)');
var textMapping = {};
allCells.each(function() {
textMapping[$(this).text()] = true;
});
var count = 0;
for (var text in textMapping)
count++;
if (count !== allCells.length) {
alert("found duplicate values");
} else {
alert("no duplicates found");
}
Live test case.
Note the above is case sensitive: if there is a cell with "hello" and cell with "Hello" those will be considered different and it will think there are no duplicates. If case doesn't matter fix is simple case of changing the line to:
textMapping[$(this).text().toLowerCase()] = true;
Updated test case where it ignores case.
In your specific case you can store all the added values in plain array then check the array using the jQuery inArray() method:
var $addedProductCodes = [];
$("#button_addItem").click(function(event)
{
$("span.errorText").remove();
$(".errorField").addClass("notErrorField");
//Change background color of textbox to normal
$("#frmRegisterForm :input[type='text']").attr('class','notErrorField');
$hasError = false;
$ele = $(event.target);
if($ele.is("input[type=button]"))
{
$td_productCode1=$("#td_productCode1").val();
var index = $.inArray($td_productCode1, $addedProductCodes);
if (index >= 0) {
alert("You already added this product code in line #" + (index + 1));
} else {
$text_productDescription= $("#text_productDescription").val();
$text_basicDealerPrice = $("#text_basicDealerPrice").val();
$('#table_viewContent').append("<tr><td>"+$text_productDescription+"</td><td>"+$td_productCode1+"</td><td><td>"+$text_basicDealerPrice+"</td><td><input type='button' name='deleteRow' id='btn_deleteRow' value='Delete' id='deleteItem' class='deleteItem button-red'></td></tr>");
$addedProductCodes.push($td_productCode1);
}
}
});
Updated fiddle where adding same product code will give alert and won't insert.