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.
Related
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);
});
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");
}
});
});
Ok, here's my problem. I have a select dropdown with different values. If i select one of them, a template is cloned into an unordered list. The thing is, i want to make sure that you cant clone the same element twice.
In the cloned list-elements there is a which has an inner-text that is the same as the corresponding label of the option in the select dropdown.
Alas i try to find a label in the unordered-list with the same text as the currently selected option in the dropdown. If there is such a label, it should not proceed with the cloning.
Here's my code:
$ ->
$('#add_feature').change -> //#add_feature is the id of my select option dropdown
features = $('ul#features') //features is the unordered list, where i append my
//cloned list elements
...
selected = $(this).find('option:selected') //here i find the currently selected
//option
//this is where i want to have an if clause or something that compares the
//inner text of all the labels in the UL to the text of the currently
//selected option
//this is the cloning procedure which should only be called if there is
//no label found above
feature = $('#template_feature li').clone()
features.append(feature)
$(feature).find('#home_features_attributes_new_type').val(selected.data('type'))
$(feature).find('#home_features_attributes_new_name').val($(this).val())
$(feature).find('label[for="home_features_attributes"]').prepend(selected.text())
Use a filter for exact text matching:
var selectedText = selected.text();
var matches = $('option', this).filter(function() {
return $(this).text() == selectedText;
});
if (matches.length == 0){
// No match!
}
If you need case-insensitve either use a constructed regex with the /i option, or just make both lowercase:
var selectedText = selected.text().toLowerCase();
var matches = $('option', this).filter(function() {
return $(this).text().toLowerCase() == selectedText;
});
if (matches.length == 0){
// No match!
}
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
I have the following javascript/jquery code, the purpose of which is to -
Deselect a previously selected item from the list, if the selected item value exists in an array
Hide/display each list item dependent on whether they exist in the array
var list = $(row).find("select > option")
var selectedValue = $(row).find("select > option:selected")
if (selectedValue) {
if ($.inArray(selectedValue[0].value, dependencyListItemValues) == -1) {
alert('deselect');
$(selectedValue).attr("selected", false);
}
}
$(list).each(function () {
var value = this.value;
if (value != "") {
if ($.inArray(value, dependencyListItemValues) > -1) {
alert('show');
$(this).show();
}
else {
alert('hide');
$(this).hide();
}
}
});
This is working fine in chrome and firefox, but not in IE9. When running in IE, the alert lines are hit, but the following lines seemingly do nothing:
$(selectedValue).attr("selected", false);
$(this).show();
$(this).hide();
Do I need to use alternative code so this will work in IE?
First: You can use
list.each
instead of $(list).each.
Second, you cannot hide an OPTION element in crossbrowser way.
So, you must remove it (for hide) and re-create it (for show).
You can store all options (and them parent) in array, like so:
var cache_options= [];
list.each(function(index) {
cache_options.push({el:$(this), parent:$(this).parent()});
});
and after
for(var i = 0; i<cache_options.length; i++) {
var value = cache_options[i].el[0].value;
if (value != "") {
if ($.inArray(value, dependencyListItemValues) > -1) {
cache_options[i].parent.append(cache_options[i].el);
}
else {
cache_options[i].el.remove();
}
}
}
Tested!
OK my solution was as follows ... this is based on the answer by meder (thanks!) on this question - Hide select option in IE using jQuery
Firstly, in place of this line:
$(selectedValue).attr("selected", false);
I did this:
$(row).find("select")[0].selectedIndex = -1;
And to show/hide the relevant list items, I had to first wrap those that I needed to hide in a span and then apply the .hide() command, and for those I needed to display, replace the span with the original option element:
//first we need to hide the visible list values that are not in the list of dependent list values.
//get the list values which are currently displayed, these will be the 'option' elements of the 'select' element (list).
//the hidden values are within a span so will not be picked up by this selector
var displayedListValues = $(row).find("select > option")
//loop through the displayed list values
$(displayedListValues).each(function () {
//get the value from this 'option' element
var displayedValue = this.value;
//ignore empty values (first blank line in list)
if (displayedValue != "") {
//if the value is not in the list of dependent list values, wrap in span and apply .hide() command
if ($.inArray(displayedValue, dependencyListItemValues) == -1) {
$(this).wrap('<span>').hide();
}
}
});
//now we need to display the hidden list values that are in the list of dependent list values.
//get the list values which are currently hidden, these will be the 'span' elements of the 'select' element (list).
//the visible values are within an 'option' so will not be picked up by this selector
var hiddenListValues = $(row).find("select > span")
//loop through the hidden list values
$(hiddenListValues).each(function () {
//find the 'option' element from this 'span' element and get its value
var opt = $(this).find('option');
var hiddenValue = opt[0].value;
//ignore empty values (first blank line in list)
if (hiddenValue != "") {
//if the value is in the list of dependent list values, apply .show() command on the 'option' element
//(not sure why the .show() command works in this case?)
//and then replace the 'span' element with the 'option' element, which is effectively removing the span wrapper
if ($.inArray(hiddenValue, dependencyListItemValues) > -1) {
$(opt).show();
$(this).replaceWith(opt);
}
}
});
Which works fine ... although rather annoying I had to do this rather messy re-coding just because IE doesn't support .show() and .hide() of list values!!!!!
Here is a good solution:
http://ajax911.com/hide-option-elements-jquery/