Add class to link slug based off array of slugs - javascript

I am creating a recipe tool that takes a user's input via selected checkboxes. See here: zelda.wptoolkit.us
Part One:
I have a script that will create an array of slugs based off of the selected input values. When a user clicks a checkbox, the associated slug is added to an array called checkedAttr.
<script>
var checkedAttr = [];
$('#wp-advanced-search :checkbox').change(function()
{
checkedAttr = [];
$('#wp-advanced-search :checkbox').each(function(i, item){
if($(item).is(':checked'))
{
checkedAttr.push($(item).val());
}
});
console.log("checkedAttr:", checkedAttr);
});
</script>
Part Two:
I am trying to use the code below to .addClass to any links that contain a slug found in the array from part one.
The link structure: http://zelda.wptoolkit.us/tag/any-crab/
The code:
<script type="text/javascript">
jQuery(function() {
jQuery('#wpas-results-inner > div > div > p > a[href^="/tag/' +
location.pathname.split("/") this.checkedAttr[0] + '"]').addClass('active');
});
</script>
What I am aiming to do is target the links in each card, then add a class to the links whose slug is found in my array. The end goal is to highlight checked 'ingredients' and fade out ingredients that haven't been checked.
I am not exactly sure how to make this function check my array for each slug, I would love to learn what steps are needed to accomplish this!
I am also not certain if my jQuery CSS path is correctly targeting the links
Thanks for any insights!

If you are looking for something like when select particular checkbox, all the card related to that checkbox should be enabled(lets say apply any class active) and once you dis-select the checkbox, we need to remove that particular class from all related checkbox??
you can check the given fiddle.
https://jsfiddle.net/stdeepak22/x1L95dw3/1/
var checkedAttr = [];
$('#checkBoxForCategory :checkbox').change(function()
{
var cardCategory = $(this).val();
var allCards = $('.myCard[card-category=' + cardCategory + ']');
if($(this).is(':checked'))
{
//add the selected category to array
checkedAttr.push(cardCategory);
//add the `active` class for all the card belongs to selected category
$(allCards).each(function()
{
$(this).addClass('active');
});
}
else
{
//remove from array
var index = checkedAttr.indexOf(cardCategory);
checkedAttr.splice(index, 1);
//remove the class for all the card belongs to selected category
$(allCards).each(function()
{
$(this).removeClass('active');
});
}
console.log("checkedAttr:", checkedAttr);
});

Related

Bootstrap form group checkboxes doesn't get checked in between nav pills

Here's the JSFiddle of my work: https://jsfiddle.net/pb23Ljd8/5/
I use Bootstrap nav-pills to show all products and categorized too like this:
And I based my checkboxes from here: http://bootsnipp.com/snippets/featured/fancy-bootstrap-checkboxes
I count the number of products checked in between the tabs like this:
jQuery(document).ready(function($) {
jQuery(".select-product").change(function() {
jQuery(".counter").text(jQuery("[type='checkbox']:checked").length);
});
});
But the glyphicon check icons doesn't appear on the second and third tabs for some reason. But when I click the products on the second and third, it increases the counter and also when I view it on the first tab, it is checked.
I just need the products to also be visibly checked on the second and third tabs and not only on the first one so it's not confusing for the user.
Ideas, anyone?
Edit: I fetch the list of products from CMS so it's dynamic. I now understand that the duplication of IDs is causing the problem.
Before we try and resolve this issues, we should break it down and see what the actual problem is.
First, let's check if we remove the content from tab 1b is the issue still present?
Nope, if we remove the checkboxes from the first tab, the checkboxes function normally on the second and third.
Fiddle #1
What if we change the id of the checkboxes (remember ids should be unique).
Notice how Book #1 now works if we change the first checkbox's id to 1a.
Fiddle #2
So now we "know" the issue is likely due to the fact that we are using checkboxes with the same id value (ref). The "issue" is now:
How do we check multiple checkboxes if one is checked
(or something like that)
Here's what I would do:
assign all "like" checkboxes the same class (ex. Book #1 checkboxes will have class b1)
use jQuery/javascript to make sure all that all "like" checkboxes, check and uncheck in unison
Working Example
EDIT
Dynamic values for the classes can be achieved by putting the IDs as classes so the similar products would match. These can be passed to JS like this assuming that $products_id_array is a PHP array that contains all the classes needed.
var productIDs = <?php echo json_encode($products_id_array) ?>;
and then creating the snippet of jQuery code on the fiddle like this
productIDs.forEach(function(val, key) {
jQuery('.' + val).on('change', function(){
jQuery('.' + val).prop('checked',this.checked);
});
})
Try this JS, This will work
jQuery(".select-product").change(function() {
var checkValue = jQuery(this).prop('checked');
$('.select-product#' + jQuery(this)[0].id).each(function() {
if (checkValue == true) {
jQuery(this).prop('checked', true)
} else {
jQuery(this).prop('checked', false);
}
});
var uniqueId = [];
jQuery("[type='checkbox']:checked").each(function() {
uniqueId.push(jQuery(this)[0].id);
});
Array.prototype.getUnique = function() {
var u = {},
a = [];
for (var i = 0, l = this.length; i < l; ++i) {
if (u.hasOwnProperty(this[i])) {
continue;
}
a.push(this[i]);
u[this[i]] = 1;
}
return a;
}
jQuery(".counter").text(uniqueId.getUnique().length);
});

Need JQuery or JavaScript to use .contains() with && logic

I am attempting to build a simple narrow by filter using given key word buttons on an otherwise static list of items.
The buttons are in an unordered list and when selected get the class ".selected-tag-button" added to them.
The items are divs with class ".item" and get class ".included-item" when they are active. Inside the div is another UL with list items that contain key words that match the text node on the buttons.
Right now it is working, except, instead of using "buttonName" which contains only the key word for the clicked button, I would like to use "buttonArray" which contains an array of all the selected key words.
I assume I will need some kind of function, but I am not sure where to start. If more than one are selected I want the result to be limited to only items that contain ALL of the selected key words. All of the solutions I have been able to figure out will return the divs that contain ANY of the key words in the array.
$(document).ready(function() {
$("li.tag-button").on("click", function() {
// Toggle button
$(this).toggleClass("selected-tag-button");
// Remove included-item class from all items
$(".item" ).removeClass("included-item");
// Pass the button text into variable
var buttonName = $(this).text().slice(2);
// Create array with button text for all active buttons
var buttonArray = $(".selected-tag-button").map(function() {
return $(this).text().slice(2);
}).get();
console.log(buttonArray);
// Add included-item class to divs containing the button text
$('li:contains("' + buttonName + '")').parents().parents().addClass("included-item");
// If all buttons are inactive, add included-item class to all items
if ($(".selected-tag-button").length == 0 ) {
$(".item" ).addClass("included-item");
}
});
});
Consider this fiddle:
http://jsfiddle.net/6qavvth8/
for(i=0; i<buttonArray.length;i++){
contains += ':contains("' + buttonArray[i] + '")';
}
$('ul' + contains).parents().addClass("included-item");
Loop through your button array to build your jquery selector and keep adding :contains()
Slight modification of #bingo's solution. Works perfectly, thanks.
$(document).ready(function() {
$("li.tag-button").on("click", function() {
// Toggle button
$(this).toggleClass("selected-tag-button");
// Remove included-item class from all items
$(".item" ).removeClass("included-item");
// Create array with button text for all active buttons
var buttonArray = $(".selected-tag-button").map(function() {
return $(this).text().slice(2);
}).get();
// Add included-item class to divs containing the button text
var contains = "";
for(i = 0; i < buttonArray.length; i++){
contains += ':contains("' + buttonArray[i] + '")';
}
$('ul' + contains).parents().addClass("included-item");
// If all buttons are inactive, add included-item class to all items
if ($(".selected-tag-button").length == 0 ) {
$(".item" ).addClass("included-item");
}
});
});

Checkboxes that display results with jQuery

I am trying to have the user check the boxes they are interested in getting resources for and then click the button to get a list of those resources that are hyperlinked to those resources. The hyperlinks (ul id="results” in HTML) are hidden until they called upon by the button “Get Resources”.
Plus I would like to add text to it before results saying “You have indicated an interest in:” (line break) then a listing the hyperlinks (line break) “Please click on the links to learn more”. If no check box is selected the div id=“alert” displays, which I got to work.
I think I am very close, I just can’t seem to get the list of resources.
Here is a link to my coding:
JSFiddle Code sample
$(document).ready(function() {
$('#alert').hide();
$('#results > li').hide();
/* Get the checkboxes values based on the parent div id */
$("#resourcesButton").click(function() {
getValue();
});
});
function getValue(){
var chkArray = [];
/* look for all checkboxes that have a parent id called 'checkboxlist' attached to it and check if it was checked */
$("#checkBoxes input:checked").each(function() {
chkArray.push($(this).val());
});
/* we join the array separated by the comma */
var selected;
selected = chkArray.join(',') + ",";
/* check if there is selected checkboxes, by default the length is 1 as it contains one single comma */
if(selected.length > 1){
// Would like it to say something before and after what is displayed
$('#results > li.' + $(this).attr('value')).show();
} else {
$('#alert').show();
}
}
I'd ditch the selected variable and just check the chkArray contents against the list item classes like:
function getValue() {
var chkArray = [];
/* look for all checkboxes that have a parent id called 'checkboxlist' attached to it and check if it was checked */
$("#checkBoxes input:checked").each(function () {
chkArray.push($(this).val());
});
$('#results li').each(function () {
if ($.inArray($(this).attr('class'), chkArray) > -1) $(this).show()
else($(this).hide())
})
/* check if there is selected checkboxes, by default the length is 1 as it contains one single comma */
if (!chkArray.length) {
$('#alert').show();
//alert("Please at least one of the checkbox");
}
}
jsFiddle example
I found a straightforward way of achieving what you want. DEMO: https://jsfiddle.net/erkaner/oagc50gy/8/
Here is my approach: I looped through all checkboxes. This way I could get the index of the current item in the original list, i, and use this index to display the corresponding item in the second list. I filter the checked items by using .is(':checked') condition, and then added them item to the array:
function getValue() {
var chkArray = [];
$("#checkBoxes input").each(function (i) {//now we can get the original index anytime
if($(this).is(':checked')){//is the item checked?
chkArray.push($(this).val());//if so add it to the array
var selected;
selected = chkArray.join(", ");
if (selected.length) {
$('#results').find('li').eq(i).show();//show the corresponding link by using `i`
} else {
$('#alert').show();
}
}
});
}
Last thing in your $(document).ready function, add:
$("#checkBoxes input:checkbox").click(function() {
$('li.' + $(this).val().replace(/ /g, '.')).show()
});
JSFiddle
Explanation:
On document ready, add a click handler to the checkboxes that shows the corresponding hidden list item below. The tricky thing here is the spaces in the list names. This makes each word a separate classname, so simply combine the list names with a dot . which results in a sequential classname call in jQuery.
By using <li class="Fitness & Recreation"> as a list item classname, you are giving this item 3 classnames: Fitness, &, and Recreation. In jQuery you select elements with multiple classnames by including each name preceded by a dot .. For example, selecting a list item element with the classnames foo, bar, and baz:
$('li.foo.bar.baz').show()
In the case of <li class="Fitness & Recreation">:
$('li.Fitness.&.Recreation').show()
Since these values are stored in the value attribute of the checkboxes we use jQuery to pull these values: $(this).val(), replace the spaces with dots: .replace(/ /g, '.'), and concatenate the result to the li. portion to access the appropriate list item.

jquery selection attributes

Let's say I have a sample table like this :
http://jsfiddle.net/65BkH/
Now what i want is, if there is this <button id="invite">Invite</button>. I want this button to select the "invite url" of the selected contact. If you see the jsfiddle, if you click the checkbox, it will crop all the others contacts. How could i do that?
I've tried to target the contact, but i can only get the top contact.
$('#linkedin_match tbody .match .m a').attr('href');
what i want is to target the currently selected.
FURTHER PROBLEM :
This button I'm talking about is not the table per say.
$('#btn_save').click(function(e) {
var hrefVar = $('#linkedin_match tbody .match .m').find('a').attr('href');
alert(hrefVar);
});
Now if i used that, it still searches for the first link, even though i've selected the others. So, any changes?.
You can use this:
$('#invite').on('click',function(){
var url = $this.closest('tr').find('a').prop('href');
});
To get all the checked href related with the checked inputs in a array use this:
$('#invite').on('click', function () {
var all_url = [];
$('input:checked').each(function () {
var url = $(this).closest('tr').find(' td.m a').prop('href');
all_url.push(url);
});
});
Demo here
$('.m').click(function(e){
var hrefVar = $(this).find('a').attr('href');
alert(hrefVar);
});
fiddle

Modify function to filter by several data-attributes simultaneously

The function below allows users to filter products by data-attributes, and accommodates filtering by multiple values simultaneously. It does this by creating an array of the values selected, and when any of the values are clicked (in this case checked/unchecked) it hides all the items and then re-shows those that match the values in the updated array.
It works correctly when filtering for one data-attribute, but when combined to filter by more than one attribute it no longer shows all results matching any of the values and instead only shows results matching all the specified values.
I've posted a fiddle which demonstrates the problem here: http://jsfiddle.net/chayacooper/WZpMh/94/ All but one of the items have the values of both data-style="V-Neck" and data-color="Black" and they should therefore remain visible if either of the filters are selected, but if another value from a different data-attribute some of the items are hidden.
$(document).ready(function () {
var selected = [];
$('#attributes-Colors *').click(function () {
var attrColor = $(this).data('color');
var $this = $(this);
if ($this.parent().hasClass("active")) {
$this.parent().removeClass("active");
selected.splice(selected.indexOf(attrColor),1);
}
else {
$this.parent().addClass("active");
selected.push(attrColor);
}
$("#content").find("*").hide();
$.each(selected, function(index,item) {
$('#content').find('[data-color *="' + item + '"]').show();
});
return false;
});
$('#attributes-Silhouettes *').click(function () {
var attrStyle = $(this).data('style');
var $this = $(this);
if ($this.parent().hasClass("active")) {
$this.parent().removeClass("active");
selected.splice(selected.indexOf(attrStyle),1);
}
else {
$this.parent().addClass("active");
selected.push(attrStyle);
}
$("#content").find("*").hide();
$.each(selected, function(index,item) {
$('#content').find('[data-style *="' + item + '"]').show();
});
return false;
});
});
Both of your handlers are updating the selected array, but only one handler executes on a click. The first one if a color was (de)selected, the second if a style. Let's say you've clicked on "Black" and "Crew Neck". At that time your selected array would look like this: [ "Black", "Crew_Neck" ]. The next time you make a selection, let's say you click "Short Sleeves", the second (style) handler executes. Here's what is happening:
Short_Sleeves gets added to the selected array.
All of the items are hidden using $("#content").find("*").hide();
The selected array is iterated and items are shown again based on a dynamic selector.
Number 3 is the problem. In the above example, a style was clicked so the style handler is executing. Any items in the selected array that are colors will fail because, for example, no elements will be found with a selector such as $('#content').find('[data-style *="Black"]').show();.
I would suggest 2 things.
Keep 2 arrays of selections, one for color, one for style.
Combine your code to use only a single handler for both groups.
Here's a (mostly) working example.
Note that I added a data-type="color|style" to your .filterOptions containers to allow for combining to use a single handler and still know which group was changed.
Here's the full script:
$(document).ready(function () {
// use 2 arrays so the combined handler uses correct group
var selected = { color: [], style: [] };
// code was similar enough to combine to 1 handler for both groups
$('.filterOptions').on("click", "a", function (e) {
// figure out which group...
var type = $(e.delegateTarget).data("type");
var $this = $(this);
// ...and the value of the checkbox checked
var attrValue = $this.data(type);
// same as before but using 'type' to access the correct array
if ($this.parent().hasClass("active")) {
$this.parent().removeClass("active");
selected[type].splice(selected[type].indexOf(attrValue),1);
}
else {
$this.parent().addClass("active");
selected[type].push(attrValue);
}
// also showing all again if no more boxes are checked
if (attrValue == 'All' || $(".active", ".filterOptions").length == 0) {
$('#content').find('*').show();
}
else {
// hide 'em all
$("#content").find("*").hide();
// go through both style and color arrays
for (var key in selected) {
// and show any that have been checked
$.each(selected[key], function(index,item) {
$('#content').find('[data-' + key + ' *="' + item + '"]').show();
});
}
}
});
});
UPDATE: incorporating suggestions from comments
To make the handler work with checkboxes instead of links was a small change to the event binding code. It now uses the change method instead of click and listens for :checkbox elements instead of a:
$('.filterOptions').on("change", ":checkbox", function (e) {
// handler code
});
The "All" options "hiccup" was a little harder to fix than I thought it would be. Here's what I ended up with:
// get a jQuery object with all the options the user selected
var checked = $(":checked", ".filterOptions");
// show all of the available options if...
if (checked.length == 0 // ...no boxes are checked
|| // ...or...
checked.filter(".all").length > 0) // ...at least one "All" box is checked...
{
// remainder of code, including else block, unchanged
}
I also added an all class to the appropriate checkbox elements to simplify the above conditional.
Updated Fiddle

Categories