I have a multiselect with many options. When 'everybody' is selected it removes other selected, if other are selected and the 'everybody' is selected it should remove it.
To remove the other and keep the item 'everybody' it's ok. But I have problem to keep other and only remove everybody.
For the moment I have something like :
resetGroupSelectionWhenEverybody: function() {
$(".group_ids").on("select2:select", function (e){
if (e.params.data.text === 'everybody') {
$('#scheduled_publication_groups_ids').select2({width: '50%'}).val(group_everybody_id).trigger("change");
} else {
if ($('[title="everybody"]').length > 0) {
var idToRemove = 0;
groupIdsData = $('#scheduled_publication_groups_ids').select2('data');
groupIdsData.forEach(function(e, i) {
if (e.text === 'everybody') {
idToRemove = i;
}
});
groupIdsData.splice(idToRemove, 1);
$('#scheduled_publication_groups_ids').select2({'data': groupIdsData}).trigger("change");
}
}
});
},
With this code groupIdsData is tonly the selected elements I want (all expect everybody's group). But after I'm stuck to change the view. select2({'data': groupIdsData}) doesn't seems to be the right choice.
Few things :
I don't think I'm setting the idToRemove properly
What the best way to update the value of the select2 multiselect? It seems it can be a hash
The answer is to use select2('val') to get a array of ids, and then work with this. Code is better using .val() not full select2 objects.
resetGroupSelectionWhenEverybody: function() {
$(".group_ids").on("select2:select", function (e){
if (e.params.data.text === 'everybody') {
$('#scheduled_publication_groups_ids').select2({width: '50%'}).val(group_everybody_id).trigger("change");
} else {
if ($('[title="everybody"]').length > 0) {
groupIds = $('#scheduled_publication_groups_ids').select2('val');
groupToKeep = groupIds.splice( $.inArray(group_everybody_id, groupIds), 1);
$('#scheduled_publication_groups_ids').select2({width: '50%'}).val(groupToKeep).trigger("change");
}
}
});
},
Related
Context:
I have a gallery of images. The user can select each image, when they click it, the "selected" attribute is added to the individual element and a new class is added to their chosen image.
The thing is, I want to limit this to only 2 selections being available.
I want to edit my script to only run up until the length is 2 or less. If the length reaches 2, no more Selected attributes to be added and no more class changes to be toggled.
I feel like I'm close. Right now my users can select/deselect but they can just do it too many times. Where am I going wrong?
function NFTSelector() {
$("#NFTGallery2 > img").each(function() {
$(this).on("click", function() {
if($(this).filter("[selected]").length>=2) {
alert('true');
} else
console.log("less than 2 or undefined so letting them choose more");
{
$(this).toggleClass('chosenNFT');
if ($(this).attr('selected')) {
$(this).removeAttr('selected');
} else {
$(this).attr('selected', 'selected');
}
}
})
});
}
I changed my approach, I instead set it up as checkboxes and limited the checkboxes this way
function NFTSelector() {
var limit = 3;
$('#NFTGallery2 > li > input').on('change', function(evt) {
if($('#NFTGallery2 > li > input:checked').length >= limit) {
this.checked = false;
}
});
}
I'm having troubles with setting default category to this script. I want by default to be listed only Category 1 with one news in it insead of All but nothing I tried seem to work. Any ideas?
This is the full code with HTML and some CSS: https://codepen.io/NickyCDK/pen/lhaiz
//Filter News
$('select#sort-news').change(function() {
var filter = $(this).val()
filterList(filter);
});
//News filter function
function filterList(value) {
var list = $(".news-list .news-item");
$(list).fadeOut("fast");
if (value == "All") {
$(".news-list").find("article").each(function (i) {
$(this).delay(200).slideDown("fast");
});
} else {
//Notice this *=" <- This means that if the data-category contains multiple options, it will find them
//Ex: data-category="Cat1, Cat2"
$(".news-list").find("article[data-category*=" + value + "]").each(function (i) {
$(this).delay(200).slideDown("fast");
});
}
}
You could use a trigger
$('select#sort-news').trigger(filterList('Cat1'), 'click');
$('.checkbox').on('change', function() {
$('.pagination').hide();
$('.callout').hide();
$('.checkbox').each(function() {
if ($(this).prop('checked') === true) {
var checkboxName = $(this).val();
$('.callout').each(function() {
var calloutArray = $(this).data();
var i;
for (i = 0; i < calloutArray.category.length; i++) {
$(this).hide();
if (checkboxName === calloutArray.category[i]) {
$(this).show();
}
}
});
}
});
});
To explain this function it basically listens to see if a checkbox has been clicked and then hides all the callouts on the page.
It then loops through each one of those checkboxes and checks which ones are true on the page. I then create a variable that stores the current checkbox value.
After this I then want to loop through each callout and pull its data from a data attribute.
I then loop through each string in the array and hide the callout no matter what. However if the callout has an array value that is the same as the checkbox value then I need to show it.
This seems to be working without the hide. However I need to hide the callouts if they do not hold the same checked category names which is where I'm running into problems.
The If statement seems to never return true if I have already hidden the callout. So the question is how do I show the callout if the selected checkboxes match one of the callout array strings but hide the callout if the string is not in the callout array.
From what I've understand, the following code is equivalent
$('.checkbox').on('change', function () {
$('.pagination, .callout').hide();
$('.checkbox:checked').each(function () {
var checkboxName = $(this).val();
$('.callout').hide().each(function () {
var calloutArray = $(this).data();
if (calloutArray.category.indexOf(checkboxName) !== -1) {
$(this).show();
}
});
});
});
Merge selectors having common actions(hide())
Use :checked pseudo-selector to select only checked elements
Use hide() on selector and then iterate over it using each()
Use indexOf to check if element is in array
You're showing/hiding your element on each iteration of the loop. That means the result of the last iteration wins, as though you hadn't done the earlier ones at all.
You can just use Array#indexOf to see if the name is in the array, and use the resulting flag to show/hide the callout:
$(this).toggle(calloutArray.category.indexOf(checkboxName) != -1);
E.g.:
$('.checkbox').on('change', function() {
$('.pagination').hide();
$('.callout').hide();
$('.checkbox').each(function() {
if ($(this).prop('checked') === true) {
var checkboxName = $(this).val();
$('.callout').each(function() {
var calloutArray = $(this).data();
$(this).toggle(calloutArray.category.indexOf(checkboxName) != -1);
});
}
});
});
Also note that
if ($(this).prop('checked') === true) {
is quite a long way to write
if (this.checked) {
Similarly, with inputelements, this.value is the same as $(this).val().
I have this wizard step form that I simulated with <ul> list items by overlapping inactive <li> items with absolute positioning.
The wizard form is working as desired except that I want to hide next or previous button on a certain step.
This is my logic in jQuery but it doesn't do any good.
if (index === 0) {
$('#prev').addClass(invisible);
$('#prev').removeClass(visible);
} else if (index === 1) {
$('#prev').addClass(visible);
$('#prev').removeClass(invisible);
} else {
$('#next').addClass(invisible);
}
To get the index value I used eq() chained on a current step element like the following
var current;
var index = 0;
$(function () {
current = $('.pg-wrapper').find('.current');
$('#next').on('click', function() {
if (current.next().length===0) return;
current.next().addClass('current').show();
current.removeClass('current').hide();
navstep.next().addClass('active');
navstep.removeClass('active');
current = current.next();
navstep = navstep.next();
index = current.eq();
});
I tried to isolate it as much as possible but my full code will give you a better idea.
If you would care to assist please check my JS BIN
There were several issues
you used .eq instead of index
you were missing quotes around the class names
your navigation logic was flawed
no need to have two classes to change visibility
I believe the following is an improvement, but let me know if you have questions.
I added class="navBut" to the prev/next and rewrote the setting of the visibility
Live Demo
var current;
var navstep;
$(function () {
current = $('.pg-wrapper').find('.current');
navstep=$('.nav-step').find('.active');
$('.pg-wrapper div').not(current).hide();
setBut(current);
$('.navBut').on('click', function() {
var next = this.id=="next";
if (next) {
if (current.next().length===0) return;
current.next().addClass('current').show();
navstep.next().addClass('active');
}
else {
if (current.prev().length===0) return;
current.prev().addClass('current').show();
navstep.prev().addClass('active');
}
current.removeClass('current').hide();
navstep.removeClass('active');
current = (next)?current.next():current.prev();
navstep = (next)?navstep.next():navstep.prev();
setBut(current);
});
});
function setBut(current) {
var index=current.index();
var max = current.parent().children().length-1;
$('#prev').toggleClass("invisible",index<1);
$('#next').toggleClass("invisible",index>=max);
}
The eq function will not give you the index, for that you need to use the index() function.
I have not looked at the whole code but shouldn't your class assignemnts look like:
$('#prev').addClass('invisible');
$('#prev').removeClass('visible');
i.e. with quotes around the class names? And is it really necessary to have a class visible? Assigning and removing the class invisible should easily do the job (provided the right styles have been set for this class).
You should make 4 modifications.
1) Use .index() instead of .eq();
2) Add a function changeIndex which changes the class depends on the index and call it on click of prev and next.
3) add quotes to invisible and visible
4) There is a bug in your logic, try going to 3rd step and come back to 1st step. Both buttons will disappear. So you have to make next button visible if index = 0
Here is the demo :
http://jsfiddle.net/ChaitanyaMunipalle/9SzWB/
Use index() function instead of eq() because eq() will return object and index() will return the integer value.
DEMO HERE
var current;
var navstep;
var index = 0;
$(function () {
current = $('.pg-wrapper').find('.current');
navstep=$('.nav-step').find('.active');
$('.pg-wrapper div').not(current).hide();
}(jQuery));
$('#next').on('click', function() {
if (current.next().length===0) return;
current.next().addClass('current').show();
current.removeClass('current').hide();
navstep.next().addClass('active');
navstep.removeClass('active');
current = current.next();
navstep = navstep.next();
index = current.index();
change_step(index)
});
$('#prev').on('click', function() {
if (current.prev().length===0) return;
current.prev().addClass('current').show();
current.removeClass('current').hide();
navstep.prev().addClass('active');
navstep.removeClass('active');
current = current.prev();
navstep = navstep.prev();
index = current.index();
change_step(index)
});
function change_step(value)
{
if (value === 0) {
$('#prev').hide();
$('#next').show();
} else if (value === 1) {
$('#prev').show();
$('#next').show();
} else {
$('#next').hide();
$('#prev').show();
}
}
I'm trying to figure out a way to verify an ID from a button being clicked, does not already exist in a set of inputs.
Code that gets ID from button clicked
$(".detail-view button").on("click", function() {
var detailID = $(this).attr('id');
Code that checks ID doesn't exist
function itemExists() {
$("input#lunchorder_item_entry_id").each(function() {
existingID = $(this).val();
if(detailID == existingID) {
alert("You have already added this item. If you want to change item details, please remove the item and re-add it to your cart. Thank You!");
} else {
}
});
}
The issue I'm having this only works part of the time, if anyone has a suggestion on a better way to do this I'm sure this isn't the best way to achieve my goal. Thank you!
detailID isn't visible in your itemExists() function, either make it global, or pass it to the function.
itemExists(detailID){
// if(detailID == existingID) {
}
The whole this should look something like this
$(".detail-view button").on("click", function() {
var detailID = $(this).attr('id');
itemExists(detailID);
});
function itemExists(detailID) {
$("input#lunchorder_item_entry_id").each(function() {
var existingID = $(this).val();
if(detailID == existingID) {
alert("You have already added this item. If you want to change item details, please remove the item and re-add it to your cart. Thank You!");
} else {
}
});
}