1

I have a grid of images, each with a data-image attribute and value.

When a user selects an image, its data-image attributes's value is added to an array.

I want the code to work so that when the user clicks an item, if the item already is in the array (that is, if the user has clicked on it before), then it gets removed.

Like a select/de-select option.

HTML

<div class="fifth" data-image="1">
    <div class="full clearfix relative">
        <img src="image.png" />

        <div class="overlay"></div>

    </div>
    <div class="options">
        <h4 class="txt-white left">#0001</h4>
        <h4 class="right txt-gold select-image" data-image="1">Select</h4>
    </div>
</div>

jQuery

var images = [];
var price = $('.order').data('price');

    // select
    $('.select-image').on('click', function() {

        $(this).parent().parent().toggleClass('selected');
        $(this).toggleClass('selected');

        if( $(this).hasClass('selected') ) {
            $(this).html('&#10005;');
        } else {
            $(this).html('Select');
        }

        images = $.grep(images, function(value) {
            return value != $(this).data('image');
        });

        console.log(images);

        images.push($(this).data('image'));

        var items = images.length;

        $('.total-price').html(items*price);

    });

But, I can't seem to figure out how $.grep works. Any ideas?

[UPDATE]

Here's a JS Fiddle of what I have so far, you can see the issue here.

3 Answers 3

1

No need to use $.grep here, a native indexOf and splice will suffice.

var images = [], image, index;
$('.select-image').on('click', function() {
    // ....
    image = $(this).data('image');
    // Lookup image in array
    index = images.indexOf(image);
    if(~index){ // ~ makes index evaluate as boolean (not really though)
         // If found, remove that entry from the array
         images.splice(index, 1);
    }else{
         // Otherwise, add it to the array
         images.push(image);
    }
    // ....
});
Sign up to request clarification or add additional context in comments.

Comments

0

Grep loops through an array in pretty much the same way as $.each with one exception. If you return true from the callback, the element is retained. Otherwise, it is removed from the array.

Your code should look something like this:

items = $.grep(items, function (el, i) {
if (i === 5) { // or whatever
    return false;
}

// do your normal code on el

return true; // keep the element in the array
});

6 Comments

Hey, thanks for the explanation. So, if I wanted to update the array I'd return el != $(this).data('image'); , where you've put return false; ?
yup - a return true will keep it, a return false will remove it :)
Hmm, struggling to see how this will be worked into the code I have, I've updated my question at the bottom with what I have. Any ideas where I'm going wrong?
@lukeseager seems like you have it all right.. try instead of: if (i === $(this).data('image')) { use if (i === $(this).attr('data-image')) {
Hmm, Doesn't seem to work. I have a JS fiddle of the issue: jsfiddle.net/zzgF6/1
|
0

Grep takes an array and performs a function for each element in this array. This function returns true or false, depending on a given criteria. Grep will then return every element for which the function returned true in an array.

$.grep( images, function($arrayElement, index) {
  return $arrayElement.attr("data-anything") == "yes i like fish";
});

I am not quite sure why you would need to use grep on a grid of images; How about giving a ".selected"-Class and use this in order to filter out the elements that have been selected?

Edit: You are basically asking for the not-case. You want to selected elements which do not have a certain value.

var a_preselected_value = 9;

var images_with_one_id_deselected = $.grep( images, function($arrayElement, index) {
  return $arrayElement.data("image") != a_preselected_value;
});

4 Comments

The idea is the user is selected images they wish to buy. As they select them, the total selected is used to work out the price, and the array of image ID's is stored so the system knows what they have purchased :) But if they de-select an image, I need the array to update so the price is reduced and the item is removed from the array.
In that case I understand where you are coming from. JF its answer should be what you want. return $arrayElement.data("image") != A_DESELECTED_VALUE; Should be what you want to happen in your grep callback. The images-Array returned by grep will not contain an element having the data-image-value of A_DESELECTED_VALUE`.
Hmm, I'm still struggling for some reason. Here's a JS fiddle of what I have if that helps: jsfiddle.net/zzgF6/1
I might have done the whole thing slightly different and probably would have avoided the use of $.grep altogether (though it can be a neat function to have). However, here is a fiddle which might solve your problem: jsfiddle.net/Pebqa The trick is to trigger pushing and filtering on whether or not selection or deselection has taken place. --- Be aware, that 'el' corresponds to the current element or value in the array at the index 'i'. Comparing with 'i', as seen in your original fiddle, would not have worked.

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.