0

I am making use of Gridster widgets on webpage.Each widget is having a button on it which changes the color to red of widget after that is clicked.Once that button is pressed the parent element gets added to an array as well.

My overall aim

I want the parent element to go in array when user clicks the element and if he clicks the same elements it should come out of that array.

What I have tried so far

I am able to add the elements which are clicked in to the array but not able to remove the element from array which is clicked again.(also want to remove the red color if clicked for second time)

Just to check if the elements is present in an array or not I tried with this function

 function checkIfArrayIsUnique(myArray) 
    {
        for (var i = 0; i < myArray.length; i++) 
        {
            for (var j = 0; j < myArray.length; j++) 
            {
                if (i != j) 
                {
                    if (myArray[i] == myArray[j]) 
                    {
                        return false; // means there are duplicate values
                    }
                }
            }
        }
        return true; // means there are no duplicate values.
    }

The problem The function always returns true even when same element is clicked twice

My Overall JS

var parentElement = [];

$(document).on("click", ".select-element", function() {

     $(this).closest('li').attr("style", "background-color:red");
         parentElement.push($(this).closest('li'));

     console.log("Parent Element Array Length");
         for (var i = 0; i < parentElement.length; i++) {
                 console.log(parentElement[i]);
        }

});


$(document).on("click", "#check", function() {

     alert(checkIfArrayIsUnique(parentElement));

    });

Fiddle

NewBie
  • 3,124
  • 2
  • 11
  • 19
  • If you want to check if the array is unique, have a look at [this](https://stackoverflow.com/questions/7376598/in-javascript-how-do-i-check-if-an-array-has-duplicate-values?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa). – Robert Bisschop Apr 19 '18 at 12:47
  • @NewBie have you checed [this](https://stackoverflow.com/a/49921660/6804958) answer – Muhammad Usman Apr 19 '18 at 12:54
  • check my edit, feedback appreciated – Scaramouche Apr 19 '18 at 18:48

4 Answers4

1

The thing is, I don't think myArray[i] == myArray[j] is going to get you far when comparing jQuery objects, my proposition is you use objects instead of arrays and manage a way of assigning unique ids to li parents, so you have a fast way of knowing if it is already in the object.

var parentElement = {};
var uniqueId = 0;
$(document).on("click", ".select-element", function() {
     var closestLI = $(this).closest('li');
     closestLI.attr("style", "background-color:red");
     closestLI.attr('id', uniqueId);
         parentElement[uniqueId++] = closestLI;

     console.log("Parent Element Array Length");
         $.each(parentElement, function(i, v){
             console.log(v);
         });
});

This way to check if a li is already in the object and remove it if so:

if(parentElement[$('li').attr('id')] !== undefined)
    delete parentElement[$('li').attr('id')];

EDIT

  1. Maybe you got confused with the second chunk of code, when merging it with the first, you cannot use $('li').attr('id') but instead parentLI.attr('id'),
  2. You were still using an array var parentElement = []; instead of an object var parentElement = {};. Without using objects, associations like idx: element_with_idx and approaches like delete won't work.
  3. Lastly, this line closestLI.attr('id', uniqueId); has to go inside the else since we're only going to assign a new id if the element is not in the object yet.

let me know

HIH

Scaramouche
  • 3,188
  • 2
  • 20
  • 46
  • I tried with this but it is still adding the elements already present Check it here https://jsfiddle.net/jjgu4edu/3/ – NewBie Apr 19 '18 at 14:00
  • But is there not any way that we can do this without Id's to each element – NewBie Apr 20 '18 at 08:46
  • Just by simple comparision and then removing if the elements is found in array – NewBie Apr 20 '18 at 08:46
  • 1
    @NewBie, the great thing about the `uniqueId` approach is that you severely cut down on time cost since you are not going through the (potentially) entire array to find out if the object is already there. but if you want to stick to your `loop` approach, just scroll down a few pixels and you will see [muecas' answer](https://stackoverflow.com/a/49921593/4770813) with the right way to compare jQuery objects, see further details [here](https://makandracards.com/makandra/13445-compare-two-jquery-objects-for-equality) and [here](https://stackoverflow.com/a/3177083/4770813) – Scaramouche Apr 20 '18 at 12:01
0

You can use html as well with your approach, you just need to do the comparison using native jQuery function for html elements, so you can get if an element is equal (or the same) element as another one:

$(myArray[i]).is($(myArray[j])); // true is both are the same element

I updated you fiddle: https://jsfiddle.net/45psxegx/49/

Edit you can add and remove widgets from the array with each widget button now.

muecas
  • 4,265
  • 1
  • 8
  • 18
0

well I've make some changes in the way you were adding elements in the array. You can always check before pushing that element into array if that element is already there or not. Check here

parentElement.includes($(this).closest('li').attr("id")) ? 
parentElement.splice(parentElement.indexOf($(this).closest('li').attr("id"),1)) : 
parentElement.push($(this).closest('li').attr("id"));

To keep track of what elements are there in your array, I've added ids to li tag. And pushed the same ids into the array and do all related to push if not there and pop if already there.

Moreover, you can always use .toggleClass to toggle class of an element as you were trying to toggle red color of element.

Anyways enough talking, here is the updated fiddle

Array is printed in console. You can check your console to see how elements are being added and removed from array.

Thanks

Muhammad Usman
  • 10,039
  • 22
  • 39
  • Extremely sorry for late reply.But can I use the index variable at some other place(The index variable which you added as an id) – NewBie Apr 19 '18 at 14:04
  • The problem I am facing is I also add widgets manually.(aprart from which are generated from JSON).So I will need to assign an id to those as well.So If it was possible to continue the index variable value from the point it has ended when I go on adding a widget – NewBie Apr 19 '18 at 14:05
  • Wait a second I will update the fiddle and post it here – NewBie Apr 19 '18 at 14:09
  • Yeah another thing is I also delete widgets.Should I include that as well ? – NewBie Apr 19 '18 at 14:19
  • Please tell me if you want something more – NewBie Apr 19 '18 at 14:28
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/169349/discussion-between-george-bailey-and-newbie). – Muhammad Usman Apr 19 '18 at 14:43
  • The color of widget and the console.log output is not removing the widget which I click twice – NewBie Apr 19 '18 at 15:12
  • Twice as in select that and then deselct.Click to add and a click to remove – NewBie Apr 20 '18 at 16:22
0

@Scaramouche and @muesac both right. You are comparing objects. It is a different situation. Another approach you can append your element like

parentElement.push($(this).closest('li').html().toString());

Just gettig html as a string will able your code to compare them. it will resolve your problem.

Ozan Ertürk
  • 465
  • 5
  • 17