2

I've got a click handler that adds the parents data-attribute to an array, which works beautifully. I do however want to continue to add to my existing code.

I want to try add some more logic in there to build the array if the page loads with some of the items already selected. I'm just not sure on how to go about this.

I'm adding an is-checkedclass to my anchor on click, so I'm trying to first check when the page loads, if the class is already been assigned.

HTML

<div class="search-data__filter filter-open">
  <div class="filter__header">
    <h4>Brand</h4>
  </div>
  <ul>
    <li data-filter="prada">
      <a href="#" class="chkbox is-checked">Prada</a>
    </li>
    <li data-filter="oakley">
      <a href="#" class="chkbox">Oakley</a>
    </li>
    <li data-filter="ray-ban">
      <a href="#" class="chkbox is-checked">Ray-Ban</a>
    </li>
    <li data-filter="nike">
      <a href="#" class="chkbox">Nike</a>
    </li>
  </ul>
</div>

jQuery:

$(document).ready(function (){

    var checkbox = $(".chkbox"); //the anchor class for headers
    var filterHead = $(".filter__header"); //what are our filter head classes
    var criteria = []; // new array

    //controls the opening of the filter headers
    filterHead.on("click", function(e){
        $(this).parent("div").toggleClass("filter-open");
    });


    //build array of this data-type
    var array = checkbox.parent("li").attr('data-filter'); 

    //not quite doing what I thought... returns 'm' 'e' 'n' 's'
    for (var i = 0; i < array.length; i ++) {
        console.log(array[i]);
    }

    checkbox.on("click", function(e){
        $(this).toggleClass("is-checked");

        //if the data attr is already in the array remove it, else add it
        if (criteria.indexOf(array)!=-1){
            criteria.splice(criteria.indexOf(array),1);
        } else{
            criteria.push(array);
        }

        console.log(criteria);

        $.get( "/_ajax/_editir_ecommerce_search.aspx?theData=" + criteria + "theText" + $('#search-data__specific').val(), function( data ) {  
            $( ".search-data__returned" ).html( data );  
            console.log( "Load was performed." );
        });

        //prevent the hash of the anchor from 
        //sending you to top of screen
        e.preventDefault();
    });

});

However my attempt above to introduce the array variable outside of my click event means my click no longer works.

A working example might make things easier to look over, which you can find here

3
  • Okay, so your text is a bit confusing. Am I correct that you want to add the data-filter of the anchors with class is_checked added to your criteria on page load? Commented Jan 23, 2015 at 14:40
  • Did you console.log: console.log(array) after var array = checkbox.parent("li").attr('data-filter'); to test what you have inside? Commented Jan 23, 2015 at 14:42
  • Apologies. So by clicking an anchor, it was building an array of the parent li's data-attribute value. What I also am trying to do, is on page load, build the array of something is already assigned with the is-checked class. I hope I'm explaining things a little better. Commented Jan 23, 2015 at 14:43

3 Answers 3

1
var array = checkbox.parent("li").attr('data-filter'); 

returns a string not an Array. And if you for-loop a String, you're looping the charAt positions of your string therefore you got m, e, n, s

To fill the Array with existing data use:

checkbox.closest("li").attr("data-filter", function(i, v){
    if(v) criteria.push(v); // fill the Array with existing data!!
});

All you need is:

jsBin demo

$(function (){

  var checkbox = $(".chkbox"); //the anchor class for headers
  var checked  = $(".chkbox.is-checked"); // Get the already checked ones
  var filterHead = $(".filter__header"); //what are our filter head classes
  var criteria = []; //build array of this data-type

  //controls the opening of the filter headers
  filterHead.on("click", function(e){
    $(this).parent("div").toggleClass("filter-open");
  });

  checkbox.on("click", function(e){

    e.preventDefault();
    var data = $(this).closest("li").data("filter");
    $(this).toggleClass("is-checked");

    if (criteria.indexOf(data)!=-1){ // remove / add
      criteria.splice(criteria.indexOf(data),1);
    } else{
      criteria.push(data);
    }
    console.log(criteria);

  });
  checked.closest("li").attr("data-filter", function(i, v){
    if(v) criteria.push(v); // fill the Array with existing data!!
  });

  console.log(criteria);

});
Sign up to request clarification or add additional context in comments.

5 Comments

My mistake. Thanks. Starting to understand where I was going wrong thanks to you helpful guys
Thanks. Just tested this and it's populating the array with all the data attributes rather than just the ones where the child element has the class of is-checked. Neat though!
@Mat-visual sorry edited. (You simply needed the var checked = $(".chkbox.is-checked"); // Get the already checked ones)
Thank you sir. I'm not sure the rules on accepting an answer. The below method works and commented first, however this feels really clean and just... nice. Kudos to @super-qua and yourself.
@Mat-visual there's no special rule. You accept the answer that best suits your issue, the one that might be useful to other people (with a similar issue), and after all >> the one that you'll be using in your project. Happy coding
1

I adjusted your code a bit to make it work. Basically you have to cycle through the checkboxes and see if they have the class is-checked assigned, and add the filters to your criteria array.

$(document).ready(function (){

var checkbox = $(".chkbox"); //the anchor class for headers
var filterHead = $(".filter__header"); //what are our filter head classes
var criteria = []; // new array

//controls the opening of the filter headers
filterHead.on("click", function(e){
    $(this).parent("div").toggleClass("filter-open");
});

// go through each checkbox
$(checkbox).each(function(index, el){
  // check the class and add the data-filter if it fits
  if($(el).hasClass('is-checked')){
    criteria.push($(el).parent("li").attr('data-filter'));
  }
});

 console.log(criteria);

checkbox.on("click", function(e){
    //extract the filter on click
    var filter = $(this).parent("li").attr('data-filter'); 
    $(this).toggleClass("is-checked");

    //if the data attr is already in the array remove it, else add it
    if (criteria.indexOf(filter)!=-1){
        criteria.splice(criteria.indexOf(filter),1);
    } else{
        criteria.push(filter);
    }

    console.log(criteria);

    $.get( "/_ajax/_editir_ecommerce_search.aspx?theData=" + criteria + "theText" + $('#search-data__specific').val(), function( data ) {  
        $( ".search-data__returned" ).html( data );  
        console.log( "Load was performed." );
    });

    //prevent the hash of the anchor from 
    //sending you to top of screen
    e.preventDefault();
});

});

1 Comment

Yeh sorry the initial question wasn't overly clear. This is exactly what I trying to do, only badly! Thank you ever so much!
1

checkbox.parent("li").attr('data-filter'); will only ever return one value..the first match in collection. Thus what you assumed was array was simply a string

All jQuery getters work this way, returning only the value of the first element in the collection

You would need to map them all

var criteria = checkbox.filter('.is-checked').parent("li").map(function(){
      return $(this).attr('data-filter');
}).get();

1 Comment

Ah, this makes sense. I did wonder how I could get all their values. Thanks for this. Lesson learned

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.