Change event firing without click - javascript

I am currently using the isotope plugin to create a function that allows me to place multiple select dropdowns. When the user has selected the dropdowns and when they click submit, it fires the event and rearranges the items.
The problem i am recieving is that the change event is firing and removing everything, but when i click submit, the right results are returned.
Jquery:
jQuery(document).ready(function($) {
var $container = $('.finalblock'),
filters = {},
selector;
$container.isotope({
itemSelector : '.finalchannel',
layoutMode: 'none'
});
$('select').change(function(){
var $this = $(this);
$('#mainSubmission').click(function() {
var group = $this.attr('data-filter-group');
filters[ group ] = $this.find(':selected').attr('data-filter-value');
var isoFilters = [];
for ( var prop in filters ) {
isoFilters.push( filters[ prop ] )
}
var selector = isoFilters.join('');
$container.isotope({ filter: selector });
return false;
});
});
});
Iv been looking into the bind() function but that doesnt seem to be giving me the right thing (maybe cause i must be doing something wrong.
$('select').bind('initCheckboxes change', function() {
// do some stuff including ajax work
}).trigger('initCheckboxes');
EDIT:
JSFIDDLE: http://jsfiddle.net/Lnzkv3v7/

Just looking at your code, (on the website itself, not the jsfiddle):
The first select element has the id of filters
<select id="filters" data-filter-group="mainfilter">
but did you know that was stored as a variable in your js?
var $container = $('.finalblock'),
filters = {},
selector;
Since most of these elements are being pulled in by Isotope anyways, this could be the issue. The reason why this is a theory is because your second select element doesnt seem to be causing an issue. So change the first select id to something else and see if it works.

Related

Isotope v2 Grid - Multiple Filters - Hide empty filters

My current isotope grid has two dropdown filters that sort the grid items. The first filter is menu type, and the second filter is drink type. Each menu type however does not contain all drink types so when some filter configurations are chosen, no results are showed, which is correct. But i would like to stop this from happening by when the user selects the first filter, the second filter hides the empty types.
Working Codepen of current filters: https://codepen.io/whitinggg/pen/zYGEaNb
This was my old filter code:
// Select Filters
jQuery(function ($) {
var $grid = $('.grid');
var $selects = $('div#filterGroup select').change(function() {
var selector = $selects.get().map(function(el) { // map the select elements ...
return $(el).val(); // ... to an array of values
}).join('') || '*'; // if joined array is empty-string, then default to a single '*'
$grid.isotope({
'filter': selector
});
return false;
});
$grid.imagesLoaded().progress( function() {
$grid.isotope('layout');
});
});
I have tried to change my code to the below from other links around the internet on this topic but havent had any luck getting it to work.
// Select Filters
jQuery(function ($) {
var $grid = $('.grid');
var $selects = $('div#filterGroup select').change(function() {
var selector = $selects.get().map(function(el) { // map the select elements ...
return $(el).val(); // ... to an array of values
}).join('') || '*'; // if joined array is empty-string, then default to a single '*'
$grid.isotope({
'filter': selector
});
return false;
});
//Hide Empty Filters
var DROP = $('div#filterGroup select option:not([data-filter=""])');
// list of all class in html
var strall = ''; $('.grid-item').each(function(el){ strall += $(this).attr('class') });
// remove select if not in strall.. TODO : needs improvement, this is kind a hack
DROP.each(function(el){
var nowfilter = $(this).attr('data-filter').replace('.', ''); // co_kenya
if( strall.indexOf( nowfilter ) == -1 ){
console.log( 'this one is missing ' + nowfilter );
$(this).remove();
}
});
$grid.imagesLoaded().progress( function() {
$grid.isotope('layout');
});
});
Is this possible? Any help much appreciated!
Working codepen
First, add an ID to each drop-down so that we can distinguish them.
<select id="menu-selector" class="filter option-set" data-filter-group="menu">
[...]
<select id="type-selector" class="filter option-set" data-filter-group="categories">
Then, for each drop-down, add a change listener. We'll look at the code for the menu drop-down change listener.
First, get the class filter from the selected drop-down:
$('#menu-selector').change(function() {
var selectedClass = $('#menu-selector option:selected').attr('value');
Then we're going to select all of the grid items matching that type, to see what other classes they have. These other classes will be the available types
var availableTypes = $(`.grid-item${selectedClass}`)
.toArray()
.flatMap(div => Array.from(div.classList.values())) //get all of the classes
.filter(i => !['grid-item', selectedClass.substring(1)].includes(i)); //eliminate useless ones
Last, toggle the disabled property on the other drop-down, enabling only those that are available.
$('#type-selector option')
.each( (i,el) => $(el).prop('disabled', el.value != "" && !availableTypes.includes(el.value.substring(1))));
That should do it. The change handler for the type drop-down is the same but references the opposite drop-down. Check the codepen for details.

How to hide or show divs based on checkbox change event

I am trying to show the values based on Checkbox check and uncheck
I have got two checkboxes MNC and Worth (Only the Top Ones), i am trying to show or hide the values based on it (pesent under class pack-panel div)
This is my code
$(document).on('change', '.filtermnc', function() {
$(".pack-panel").each(function () {
var visible = $(this).find('.mnccheckbox').prop('checked')
$(this).toggle(visible);
});
});
$(document).on('change', '.filterworth', function() {
$(".pack-panel").each(function () {
var visible = $(this).find('.worthcheckbox').prop('checked')
$(this).toggle(visible);
});
});
When i tried with this code , it is not working and also it is checking all the correspondng checkboxes
Could you please let me know how to achieve this .
http://jsfiddle.net/F8Vk2/121/
I made for one, but it's just a mater of changing the other one likewise:
$(document).on('change', '.filterworth, .filtermnc', function() {
var $this = $(this),
isChecked = $this.is(':checked'),
$packPanel = $('.pack-panel');
isChecked ? $packPanel.show() : $packPanel.hide()
});
You could use this to get the target of the event and verify if it's checked by .is(':checked'). Also, you don't need to iterate over $('.pack-panel') in order to apply your changes. .toggle() will change the visibility by it's previous one, so I think you should hard code to hide or show the panels.
Change your js to
$(document).on('change', '.filtermnc', function() {
var visible = $(this).prop('checked')
if(visible)
$('.mnccheckbox').closest("li").show();
else
$('.mnccheckbox').closest("li").hide();
});
$(document).on('change', '.filterworth', function() {
var visible = $(this).prop('checked')
if(visible)
$('.worthcheckbox').closest("li").show();
else
$('.worthcheckbox').closest("li").hide();
});
http://jsfiddle.net/F8Vk2/123/
You could try ->
$(document).on('change', '.filtermnc', function() {
$('.mnccheckbox').
closest("li").
toggle($(this).prop('checked'));
});
This is basically finding all with .mccheckbox class, and then toggling based on the property of the checkbox you assigned the event too.

Isotope filtering using checkboxes issue

I'm trying to make filtering Isotope to work out but I'm stuck.
I have two lists of checkbox filters in which every list there is a clear-list button, in order to uncheck the checkboxes in their list and one clear-all button that unchecks all the checkboxes and does isotope({filter: '*' }) when clicked, which is desired.
My problem is that I cannot figure out how to make the clear-list button to isotope the grid container when a clearlist button is clicked.
Logically, the grid container must isotope without the values of the certain list.
And when all lists are clear with the clear-list button then the grid should isotope({ filter: '*' })
Here is my js code
function initIsotope(){
var $wrapper = $('.wrapper');
if($wrapper.length < 1){
return;
}
var $filters = $('.filters', $wrapper);
var $grid = $('.grid-container', $wrapper);
var $checkboxList = $ ('.checkbox-list', $wrapper);
var $checkboxes = $('.checkbox-control', $wrapper);
var $clearList = $('.clear-list', $wrapper);
var $clearAll= $('.clear-all', $wrapper);
//init Isotope
$grid.isotope({
itemSelector: '.grid-item',
layoutMode: 'fitRows'
});
//isotope filtering on checkbox click
// this part of code is from http://jsfiddle.net/desandro/DQydj/
$checkboxes.change(function(){
var filters = [];
// get checked checkboxes values
$checkboxes.filter(':checked').each(function(){
filters.push( this.value );
});
filters = filters.join(', ');
$grid.isotope({ filter: filters });
});
//clear list
$clearList.on('click', function(e){
e.preventDefault();
var $self = $(this);
$self.closest($checkboxList).find($checkboxes).prop("checked", false);
//Im stuck here
});
//clear-all lists
$clearAll.on('click',function(e){
e.preventDefault();
$checkboxes.prop("checked", false);
$grid.isotope({ filter: '*' });
});
}
$(function(){
initIsotope();
});
Have jsfiddle example for you to see:
https://jsfiddle.net/timosergio/at7gtc1g/35/
Can you help me out please?
PS: I've updated my jsFiddle, I'm closer but to the desire result. Check it out if you mind
The only thing missing in your $clearList.on('click'), after having the correct closest($checkboxList) cleared is to "reset" the filter array... And "repopulate" it with the possible values of the other checkbox-list.
// Empty filter array
var filters = [];
// get checked checkboxes values
$checkboxes.filter(':checked').each(function(){
filters.push( this.value );
});
filters = filters.join(', ');
$grid.isotope({ filter: filters });
Like you do in the function $checkboxes.change...
You send a value array to grid.isotope to use as filter.
You already do the right thing in $clearAll.on('click')
You are sending '*'.
EDIT
I just updated my fiddle to simplify the script by avoiding redundant code.
I made a "sub-function" with the part that gets the checkboxes values.
;)
Updated Fiddle
NOTE to other SO readers: "isotope" is a cool js library.

jQuery Isotope filter to no items?

I'm using isotope to filter a list with multiple filters where it is possible that based on a combination of certain filters no items will be displayed. In this case I want to display a message to the user that based on their filter parameters, no results exist. How would I go about that and does isotope have something built in to handle this? Here is a jsfiddle example. should be displayed if no items match filter set...
http://jsfiddle.net/cssguru/e4vA3/
$(function(){
var $container = $('#container'),
$checkboxes = $('#filters input');
$container.isotope({
itemSelector: '.item'
});
$checkboxes.change(function(){
var filters = [];
// get checked checkboxes values
$checkboxes.filter(':checked').each(function(){
filters.push( this.value );
});
// ['.red', '.blue'] -> '.red, .blue'
filters = filters.join('');
$container.isotope({ filter: filters });
});
});
You can could to see how many isotope items do not have the "isotope-hidden" class added to it. When the result is 0, it means that all of your elements will be hidden and you can trigger something to happen. You could use a callback function, like reLayout to run every time the isotope gets filtered.
function noResultsCheck() {
var numItems = $('.item:not(.isotope-hidden)').length;
if (numItems == 0) {
//do something here, like turn on a div, or insert a msg with jQuery's .html() function
alert("There are no results");
}
}
Add this to your change function:
$container.isotope( 'reLayout', noResultsCheck );
http://jsfiddle.net/xvU8D/
Just to add to what nspace said...
You don't need to add the 'reLayout' callback, you can make the callback in the code you already had here $container.isotope({ filter: filters }); like this:
$container.isotope({ filter: filters }, function noResultsCheck() {
var numItems = $('.item:not(.isotope-hidden)').length;
if (numItems == 0) {
alert("There are no results");
}
});
http://jsfiddle.net/xvU8D/33/
This is taken from the docs here:
http://isotope.metafizzy.co/docs/introduction.html#script - do a page search for 'callback'.
Just found a great solution at isotopes github issue-page.
Isotope v1:
$container.isotope({ filter: '.my-crazy.awesome.filter' });
if ( !$container.data('isotope').$filteredAtoms.length == 0) {
// do stuff when no element was found
}
See Isotope Help - accessing the instance
Isotope v2
if ( !$container.data('isotope').filteredItems.length == 0) {
// do stuff when no element was found
}
See Isotope - Filtered Items
see full post here
In addition, to work in Isotope 2 you have to check if it is visible/not visible instead of having the class isotope-hidden:
Like this
var numItems = $('.item:visible').length;

Create hidden field element for each drop

I know this is a similar question to my previous one however its slightly different.
I have this script adding each 'dropped' element to a list. Now i need it adding into a variable / hidden field so i can pass it to the next page via a form.
When i run it at the moment. It alerts for each one however, it does it not just for every item dropped but if there are 10 items dropped it will run 10 times per item droped rather than once per item dropped.
Any help would be great.
//Record and add dropped items to list
var txt = $("#listbox");
var dtstart = copiedEventObject.start + '\n'
var caltitle = copiedEventObject.title
var txt = $('#listbox');
txt.append("<li class ='listItem'> "+dtstart +"</li>")
var listItems = $('.listItem');
$('#calendarform').submit(function() {
listItems.each(function(){ //For each event do this:
alert( listItems.text() );
});
return false;
});
// remove the element from the "Draggable Events" list
$(this).remove();
the problem lies in this code
listItems.each(function(){ //For each event do this:
alert( listItems.text() );
});
you are alerting the text of all the list items for each list item.
use jQuery(this) to access the current item within an each block
listItems.each(function(){ //For each event do this:
alert( $(this).text() );
});
Assuming your code is within a drop event handler, you are also adding a submit handler each time you drop. This means that each time you drop, you queue up another submit event. This is probably not desired. Move this submit(function(){}) block outside your drop handler to prevent it from firing that function more than once.
$('#calendarform').submit(function(e) {
var listItems = $('.listItem');
listItems.each(function(){ //For each event do this:
alert( listItems.text() );
});
e.preventDefault();//stop normal behavior
return false;
});
and to create elements on the fly you just pass jQuery the html, and append it to your form.
$('<input type="hidden" name="listItem[]"/>').appendTo("#calendarForm").val(listItem.text())
you may have to fiddle with the name element to get it to submit as an array in your server side language, but you're also within an each loop, which provides you with an index, so you can do the following.
$('#calendarform').submit(function(e) {
var form = $(this);
var listItems = $('.listItem');
listItems.each(function(index){ //For each event do this:
var listItem = $(this);
$("<input type='hidden'/>").val(listItem.text()).appendTo(form).attr('name', 'listItem[' + index + ']');
});
e.preventDefault();//stop normal behavior
return false;
});

Categories

Resources