Multiselect Detect Option Selected and Deselected On Change - javascript

I want to check the if the changed state of a multiselect is deselect or select.
pseudo-code:
$(document).on('change', '.mySelect', function (event) {
if(event === 'selected'){
alert("You have selected this item.");
} else {
alert("You have deselected this item.");
}
});
Something like this doesn't work. How can i check weather the event was a "select" event or a "deselect" event?
EDIT
Here is a jsfiddle DEMO

Try saving the current state of the select element on change:
http://jsfiddle.net/Wexcode/a4mf8akj/5/
function wasDeselected (sel, val) {
if (!val) {
return true;
}
return sel && sel.some(function(d) { return val.indexOf(d) == -1; })
}
$(document).on('change', 'select', function (event) {
var message,
$select = $(event.target),
val = $select.val(),
sel = $('select').data('selected');
// Store the array of selected elements
$select.data('selected', val);
// Check the previous and current val
if ( wasDeselected(sel, val) ) {
message = "You have deselected this item.";
} else {
message = "You have selected this item.";
}
alert(message);
});

The trick is to track the selected options length ..
var $select = $('select');
$select.change(function () {
// Last saved state;
var lastState = $(this).data('total'),
// New state;
changedState = $(this).find('option:selected').length,
txt = (lastState < changedState ?
'selected' : (
lastState > changedState ?
'Deselected' :
'Only one option is selected'));
// save state
$(this).data('total', changedState);
$('#console').append('<p>' + lastState + ' => ' + changedState + '<span>' + txt + '</span></p>');
// Initializing tracker
}).data('total', $select.find('option:selected').length);
Try this here

Related

show and hide element options for my case

I'm having a little bit of difficulties when I need to hide an element on a page.
I am using this script to create my multiselect dropdown element which is the main controller for the elements on the page (http://wenzhixin.net.cn/p/multiple-select/docs/#the-basics1).
It returns an array of selected elements and my elements have their showIfValues set in a JSON file.
My functions should do this:
I get selected values from the dropdown element in array (ex. ["value1", "value2"]).
Going through all the elements and find where in showIfValue is any value from the array above, show it
In the change of the multiselect dropdown, if any of the fields are removed, remove the element but leave the rest on the page.
Legend in showHideHendler function:
inp is the id of the input field I would like to show on the page
controlInp is the control input (in this case multiselect dropdown)
value is the array populated with the showIfValues from JSON file of the elements
So far I made it here. These are the things I have implemented.
function diffArray(arr1, arr2) {
return arr1.concat(arr2).filter(function (val) {
if (!(arr1.includes(val) && arr2.includes(val)))
return val;
});
}
function getSelectedValues(controlInput){
if($('#' + controlInput).attr("multiple") === "multiple"){
// var selectValues = $('#' + controlInput).multipleSelect("getSelects");
var selectValues = [];
if($('#' + controlInput).multipleSelect("getSelects") != null) {
selectValues = $('#' + controlInput).multipleSelect("getSelects");
}
return selectValues;
}
}
var multipleShowHideHandler = (function() {
var selectedValues = [];
function setSelectedValues(value){
selectedValues.push(value);
}
function overrideSelected(value){
selectedValues = value;
}
function getSelectedValues(){
return selectedValues;
}
return {
setSelectedValues: setSelectedValues,
getSelectedValues: getSelectedValues,
overrideSelected: overrideSelected
}
})();
function showHideHandler(inp, controlInp, value) {
if (!$('#' + controlInp).is(':checkbox') && !($.isArray(value))) {
value = $.makeArray(value);
}
var selectedValues = getSelectedValues(controlInp);
if(($('#' + controlInp).attr("multiple") === "multiple") && !$.isEmptyObject(selectedValues)){
$('#' + controlInp).change(function(){
var oldState = multipleShowHideHandler.getSelectedValues();
var selectedValues = getSelectedValues(controlInp);
if($.isEmptyObject(oldState)){
$.each(selectedValues, function(i, val){
multipleShowHideHandler.setSelectedValues(val);
});
}
var differentArray = diffArray(selectedValues, oldState);
if(!$.isEmptyObject(differentArray)){
if(($.inArray(differentArray[0], value) !== -1)){
$('#' + inp + 'Container').hide();
}
multipleShowHideHandler.overrideSelected(selectedValues);
}
//check diff
/*if(!$.isEmptyObject(selectedValues) && !$.isEmptyObject(oldState)){
var diff = diffArray(selectedValues, oldState);
}*/
$.each(selectedValues, function(i, val){
if(($.inArray(val, value) !== -1)){
$('#' + inp + 'Container').show();
}
});
});
}else if (($.inArray($('#' + controlInp).val(), value) > -1) || $('#' + controlInp).prop('checked') === value) {
$('#' + inp + 'Container').show();
} else {
$('#' + inp + 'Container').hide();
}
}
This works on some elements, but the moment it overrides my oldState the fields are not hidden.
Any kind of help is much appreciated. Thanks in advance.
After looking and trying many things, I have found that the easiest way is basically to remove all elements and show them again on any change of the multiple select dropdown element.
So the final code looks like this:
if(($('#' + controlInp).attr("multiple") === "multiple") && !$.isEmptyObject(selectedValues)){
$('#' + controlInp).change(function(){
var selectedValues = getSelectedValues(controlInp);
if(!$.isEmptyObject(selectedValues)){
$('#' + inp + 'Container').hide();
$.each(selectedValues, function(i, val){
if(($.inArray(val, value) !== -1)){
$('#' + inp + 'Container').show();
}
});
}else{
$('#' + inp + 'Container').hide();
}
});
}
There is no need to add a before state and after so this is the only thing I need.
DiffArray and multipleShowHideHandler are no longer needed.
Hope this helps someone in the future.

Filtering On Multiple Search Criteria With jQuery

I have a problem with my searching in JavaScript / jQuery. For example, if I choose "Two service" and "Online status" this function below returns all "Two service" and all "Online service".
The desired behavior has 3 parts:
1) For the different search criteria to be additive (i.e. ANDs instead of ORs).
2) Return all records when the search criteria is empty.
3) Make the data-name search from the #search input case insensitive
$(document).ready(function() {
$("#service").change(function(){ select(); });
$("#search").keyup(function(){ select(); });
$("#status").change(function(){ select(); });
select = function(){
var service = $("#service").val();
var search = $("#search").val();
var status = $("#status").val();
$(".box").hide();
$(".box[data-service='" + service + "']").show();
$(".box[data-search='" + search + "']").show();
$(".box[data-status='" + status + "']").show();
}
});
Example: https://jsfiddle.net/L7wyp13q/
You can try something like this :
$(document).ready(function() {
$("#service").change(function() {
select();
});
$("#search").keyup(function() {
select();
});
$("#status").change(function() {
select();
});
select = function() {
var service = $("#service").val();
var search = $("#search").val();
var status = $("#status").val();
$(".box").hide();
var boxes = $(".box").filter(function(index) {
return (service === 'all' || $(this).attr("data-service") === service) &&
(!search || $(this).attr("data-name").toLowerCase().indexOf(search.toLowerCase()) >= 0 ) &&
(status === 'all' || $(this).attr("data-status") === status);
});
console.log(boxes);
boxes.show();
}
});
fiddle demo : https://jsfiddle.net/xcrmyzgr/2/
The idea here is to build your selector dynamically based on the values of your filter criteria. I used an object to contain the filter values so that I could iterate over them and reuse the property names, but you can do it however you'd like.
Edit -- updated to return partial matches from search field, rather than only exact matches
Edit 2 -- added case insensitive searching
$(document).ready(function() {
$("#service, #status").change(function(){ select(); });
$("#search").keyup(function(){ select(); });
select = function(){
var selectorFilters = {
service: $("#service").val(),
status: $("#status").val()
};
$(".box").hide();
var selector = Object.keys(selectorFilters).reduce(function (sel, currentKey) {
var value = selectorFilters[currentKey];
if (value && value !== "" && value !== "all") {
sel += "[data-" + currentKey + "=" + value + "]";
}
return sel;
}, ".box"); // <-- start with .box and build from there
// will select even if search is partial match, rather than only exact match
$(selector).filter(function (){
var searchValue = $("#search").val().toLowerCase();
return (searchValue === "" || $(this).data("name").toLowerCase().indexOf(searchValue) > -1);
}).show();
}
});
Working DEMO

removing eventhandler seems not to work

I have the next code (code does not run like copied here) that I would like to use for addressing errors on an input field of a form. The field is checked when the focus of the field is lost. An ajax request checks if the entry is allowed for that field (based on a lookup table). The two user functions set and remove error class around the input field.
When an error occurs, I want the field in error to have the only focus of the whole form (user has to correct this field before a different field is selected).
That last requirement does not work in the code. The focus is handed intermitted to the fields. It seems like if I have to click more then needed as well.
Question: What am I doing wrong?
$(document).ready(function() {
var errors = [];
//check value in lookup table with ajax
$("body").on("blur", "input[data-table]", function() {
var name = $(this).attr("id");
var table = $("input[name=" + name + "]").data().table;
var value = $(this).val();
var len = value.length;
//Only if an entry has been made in the field
if (len > 0) {
var jqxhr = $.post("/controller/lookup.php", {
table: table,
value: value
}, function() {});
//Done with the request
jqxhr.done(function(data) {
var e = JSON.parse(data).error;
if (e == "true") {
//set error
setError(name);
//prevent focus on other
$("body").on("click", "input", function(e) {
if (!(e.target.id == name))
$("input#" + name).focus();
});
} else {
removeError(name);
$("body").off("click", "input");
}
});
//A failure has occured
jqxhr.fails(function(xhr, msg) {
//TODO: exception handling
});
}
//if the field has been cleared remove error
removeError(name);
});
function setError(name) {
//Check if error already exists
if (!getErrors(name)) {
var e = getErrorIndex(name);
if (e > -1) errors[e].error = true;
else errors.push({
name: name,
error: true
});
var span = "<span class=\"glyphicon glyphicon-exclamation-sign\" style=\"color: red; float: left\"></span>";
//Decorate errors
$("input#" + name).parent().addClass("has-error");
$("input#" + name).after(span);
};
}
function removeError(name) {
var e = getErrorIndex(name);
if (e > -1) {
errors[e].error = false;
$("input#" + name).parent().removeClass("has-error");
$("input#" + name).next().remove();
}
}
function getErrors(needle) {
for (var i = 0; i < errors.length; i++) {
if (errors[i].name === needle) return errors[i].error;
}
return false;
}
function getErrorIndex(needle) {
for (var i = 0; i < errors.length; i++) {
if (errors[i].name === needle) return i;
}
return -1;
}
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

Lost in a sea of nodes

I have a function that is supposed to duplicate a form and clear it out. It's clearing everything except checkboxes. Why is this? http://jsfiddle.net/GM2GN/1/
function addForm(btn, prefix) {
var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
// You can only submit a maximum of 10 todo items
if (formCount < 100) {
// Clone a form (without event handlers) from the first form
var row = $(".item:first").clone(false).get(0);
// Insert it after the last form
$(row).removeAttr('id').hide().insertAfter(".item:last").slideDown(300);
// Remove the bits we don't want in the new row/form
// e.g. error messages
$(".errorlist", row).remove();
$(row).children().removeClass("error");
// Relabel or rename all the relevant bits
$(row).children().children().children().children().each(function () {
updateElementIndex(this, prefix, formCount);
$(this).val("");
});
// Add an event handler for the delete item/form link
$(row).find(".delete").click(function () {
return deleteForm(this, prefix);
});
// Update the total form count
$("#id_" + prefix + "-TOTAL_FORMS").val(formCount + 1);
} // End if
else {
alert("Sorry, you can only enter a maximum of 100 items.");
}
return false;
}
// Register the click event handlers
$("#add").click(function () {
return addForm(this, "form");
});
Different from other input elements like text input, changing the checkbox value does not change the 'checked' status. The val() only change the value of the checkbox that submits to server. to change the checked status:
checkBoxes.prop("checked", false);
Above is the complete modified code..
just check if the actual input you're resetting is a checkbox, in that case, $(this).val('') will set its value to an empty string, yet this does not remove it's "checked" property.
I've just added this check after $(this).val('') :
if ($(this).is('input[type="checkbox"]')) {
$(this).removeAttr("checked");
}
modified code:
$(document).ready(function () {
// Code adapted from http://djangosnippets.org/snippets/1389/
function updateElementIndex(el, prefix, ndx) {
var id_regex = new RegExp('(' + prefix + '-\\d+-)');
var replacement = prefix + '-' + ndx + '-';
if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex,
replacement));
if (el.id) el.id = el.id.replace(id_regex, replacement);
if (el.name) el.name = el.name.replace(id_regex, replacement);
}
function deleteForm(btn, prefix) {
var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
if (formCount > 1) {
$(btn).parents('.item').remove();
var forms = $('.item'); // Get all the forms
// Update the total number of forms (1 less than before)
$('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
var i = 0;
// Go through the forms and set their indices, names and IDs
for (formCount = forms.length; i < formCount; i++) {
$(forms.get(i)).children().children().children().children().each(function () {
if ($(this).attr('type') == 'text') updateElementIndex(this, prefix, i);
});
}
} // End if
else {
alert("You have to enter at least one student!");
}
return false;
}
function addForm(btn, prefix) {
var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
// You can only submit a maximum of 10 todo items
if (formCount < 100) {
// Clone a form (without event handlers) from the first form
var row = $(".item:first").clone(false).get(0);
// Insert it after the last form
$(row).removeAttr('id').hide().insertAfter(".item:last").slideDown(300);
// Remove the bits we don't want in the new row/form
// e.g. error messages
$(".errorlist", row).remove();
$(row).children().removeClass("error");
// Relabel or rename all the relevant bits
$(row).children().children().children().children().each(function () {
updateElementIndex(this, prefix, formCount);
$(this).val("");
if ($(this).is('input[type="checkbox"]')) {
$(this).removeAttr("checked");
}
});
// Add an event handler for the delete item/form link
$(row).find(".delete").click(function () {
return deleteForm(this, prefix);
});
// Update the total form count
$("#id_" + prefix + "-TOTAL_FORMS").val(formCount + 1);
} // End if
else {
alert("Sorry, you can only enter a maximum of 100 items.");
}
return false;
}
// Register the click event handlers
$("#add").click(function () {
return addForm(this, "form");
});
$(".delete").click(function () {
return deleteForm(this, "form");
});
});

Disabling check box and uncheck it using jQuery

In below code I am dynamically generating td elements in for loop.
jQuery("#dialog_load_content").load(url, function() {
var clientName = jQuery('#client option:selected').text();
var clientId = Number(jQuery('#client option').filter(function() {return jQuery(this).html() == clientName;}).val());
var navDate = jQuery('input:checkbox:checked.signOff').closest('tr').find('td:eq(2)').html();
var fundName = jQuery('input:checkbox:checked.signOff').closest('tr').find('td:eq(0)').html();
var fundId = Number(jQuery('#fund option').filter(function() {return jQuery(this).html() == fundName;}).val());
jQuery.post('getNavPackReportsStatus', {clientId: clientId, fundId: fundId, periodEndDate: navDate}, function(data) {
var reports = data;
for(var count = 0; count< reports.length; count++) {
jQuery('#wrkbkRptTable tbody').append('<tr>' +
'<td><input type="checkbox" id="'+reports[count].reportStoreId+'" name="'+reports[count].reportName+'" checked/></td>'+
'<td>' + (count + 1) + '</td>'+
'<td>' + reports[count].reportGroupDisplayName + '</td>'+
'<td>' + reports[count].reportName + '</td>'+
'<td id="chkReportID">' + ((reports[count].reportStoreId == null || reports[count].reportStoreId == '') ? '<font color="red">Not Available</font>' : '<font color="green">Available</font>') + '</td>'+
'</tr>');
}
});
});
I tried to disable check box and uncheck check box using this, but it's not working
jQuery('#wrkbkRptTable input:checked').each(function() {
var test=jQuery('#wrkbkRptTable input:checked').attr('id');
if(test==null || test=='' || test=='undefined')
{
alert(test);
jQuery("#"+test+"").prop( "disabled", true );
}
});
I want to disable check box and uncheck it using first td (id attribute value) like
this: if (id == null then disable & uncheck it)
Try this
jQuery.each( jQuery('#wrkbkRptTable input:checked'), function(_, item) {
var item = jQuery(item);
var id = item.attr('id');
if (typeof id == 'undefined') {
item.attr('checked', false);
item.attr('disabled', true);
}
} )
This code will receive all checked checkboxes. Then it will test if item's ID is present. If not, it will uncheck current checkbox and disable it.
try something like this
$(document).ready(function() {
jQuery('#wrkbkRptTable input:checked').each(function() {
var test = this.id;
if(test==null || test=='undefined' || test.trim()=='')
{
this.checked = false;
this.disabled = true;
}
});
});
Use firebug aor chrome debugger to debug this.Your code for disabling checkbox is right.
I guess the conditions in if are not quite fit
if(test==null || test=='' || test=='undefined')
{
// means not got test
}
try this
if(test)
{
// ur codes
}
jQuery('#wrkbkRptTable input:checked').each(function() {
var test=jQuery(this).attr('id');
if(!test)
{
alert(test);
jQuery(this).prop( "disabled", true );
}
});

Categories

Resources