0

I have multiple div's. If the user clicks on one of them, then it should start to blink for a few seconds and then return to its normal state.

They should all work completly independent, means multiple div's should be able to blink at the same time.

It is very easy to solve this if only one div is involved. But If more than one div's is clicked then only one blinks and the other stops...

So i thought it would work if I code it object oriented, but It still fails and I can't explain why.

This is my code so far, it is probably way too complicated, but I need to know why it does not work even though I've used objects.

JSFIDDLE

var OAHelper = new ObjectArrayHelper();

var taskList = new Array();

$(".blinkDivs").click(function() {
 
    var ElementID = $(this).attr("id");
    
    //ElementID is NOT in array
    if (!OAHelper.checkIfObjectExists(taskList, "id", ElementID)) {

        var task = new Task(ElementID);
        var newTask = { id: ElementID, task: task};
        taskList.push(newTask);

  var t = OAHelper.getValue(taskList, "task", "id", ElementID);

  if (t !== false) {
   t.blink();
  }
 }
});



function Task(ElementID)
{
    var self = this;
    this.id = ElementID;
    this.interval = null;
    this.limiter = 0;
    this.toggle = 0;
 this.blink = function()
 {
        $jqElement = $("#" + self.id);

        self.limiter = 0;
        self.interval = setInterval(function() {

            if (self.toggle == 0) {
                $jqElement.css("background-color", "blue");
                self.toggle = 1;
            } else {
                $jqElement.css("background-color", "white");
                self.toggle = 0;
            }

            if (self.limiter > 4) {

                OAHelper.deleteObject(taskList, "id", self.id);
                clearInterval(self.interval);
            }
            self.limiter++;
        }, 400);
 }
}



/**
 * This class provides helper functions to do operations on object arrays
 *
 * functions:
 *
 * delete objects,
 * output objects,
 * change value of specific key,
 * check if specific object exists,
 * check if specific object has specific key value pair
 *
 * Autor: Eduard Fekete
 * @constructor
 */
function ObjectArrayHelper()
{
    /**
     * Runs through all objects of an object array and searches for a record with specific identity.
     *
     * Return Values:
     *   true if record exists
     *   false if record does not exist
     *
     * Autor: Eduard Fekete
     *
     * @param pObjectArray   Array of objects
     * @param pIdentifier   Identifier Key of the object
     * @param pIdentifierValue  Searched Identifier Value
     * @returns {boolean}
     */
    this.checkIfObjectExists = function(pObjectArray, pIdentifier, pIdentifierValue) {
        for (var i in pObjectArray) {
            for (var key in pObjectArray[i]) {
                if (key == pIdentifier) {
                    if (pIdentifierValue == pObjectArray[i][key]) {
                        return true;
                    }
                }
            }
        }
        return false;
    },

 /**
  * Runs through all objects of an object array and searches for a record with specific identity
  * and checks if a specific key has a specific value.
  *
  * Return Values:
  *   true  if the value was found in the record,
  *   false  if not.
  *
  * Example:
  * var worker = new Array(
  *   { id: 1, status: "working" },
  *   { id: 2, status: "done" }
  * );
  *
  * checkKeyValueInObjectArray(worker, status, "done", "id", 1);  //returns: false
  * checkKeyValueInObjectArray(worker, status, "done", "id", 2);  //returns: true
  *
  * Autor: Eduard Fekete
  *
  * @param array pObjectArray Array of objects
  * @param string pSearchKey  Key to search for in the objects
  * @param pCheckValue   The value you are searching
  * @param string pIdentifier Identifier Key of the object
  * @param pIdentifierValue  Searched Identifier Value
  * @returns {boolean}
  */
 this.checkKeyValue = function(pObjectArray, pSearchKey, pCheckValue, pIdentifier, pIdentifierValue)
 {
  for(var i in pObjectArray) {
   for (var key in pObjectArray[i]) {

    if (key == pSearchKey) {

     if (pObjectArray[i][key] == pCheckValue) {
      if (pObjectArray[i][pIdentifier] == pIdentifierValue) {
       return true;
      }
     }
    }
   }
  }
  return false;
 },
 /**
  * Runs through all objects of an object array, searches for a record with specific identity
  * and sets the target key to the target value.
  *
  * Return Values:
  *   true  if the value was set
  *   false if the object was not found
  *
  * Autor: Eduard Fekete
  *
  * @param pObjectArray   Array of objects
  * @param pTargetKey
  * @param pTargetValue
  * @param pIdentifier   Identifier Key of the object
  * @param pIdentifierValue  Searched Identifier Value
  * @returns {boolean}
  */
 this.setValue = function(pObjectArray, pTargetKey, pTargetValue, pIdentifier, pIdentifierValue)
 {
  for(var i in pObjectArray) {
   if (pObjectArray[i][pIdentifier] == pIdentifierValue) {
    pObjectArray[i][pTargetKey] = pTargetValue;
    return true;
   }
  }
  return false;
 },
 /**
  * Runs through all objects of an object array, searches for a record with specific identity
  * and returns the target value.
  *
  * Return Values:
  *   true  if get value was successful
  *   false if the object was not found
  *
  * Autor: Eduard Fekete
  *
  * @param pObjectArray   Array of objects
  * @param pTargetKey   The target key
  * @param pIdentifier   Identifier Key of the object
  * @param pIdentifierValue  Searched Identifier Value
  * @returns {boolean}
  */
    this.getValue = function(pObjectArray, pTargetKey, pIdentifier, pIdentifierValue)
    {
        for(var i in pObjectArray) {
            if (pObjectArray[i][pIdentifier] == pIdentifierValue) {
                return pObjectArray[i][pTargetKey];
            }
        }
        return false;
    }
 /**
  * Runs through all objects of an object array, searches for a record with specific identity
  * and deletes it.
  *
  * Return Values:
  *   true  if the record was deleted successfully
  *   false if the record was not found
  *
  * Autor: Eduard Fekete
  *
  * @param pObjectArray   Array of objects
  * @param pIdentifier   Identifier Key of the object
  * @param pIdentifierValue  Searched Identifier Value
  * @returns {boolean}
  */
 this.deleteObject = function(pObjectArray, pIdentifier, pIdentifierValue)
 {
  for (var i in pObjectArray) {
   for (var key in pObjectArray[i]) {
    if (key == pIdentifier) {
     if (pIdentifierValue == pObjectArray[i][key]) {
      if (i > -1) {
       pObjectArray.splice(i, 1);
       return true;
      }
     }
    }
   }
  }
  return false;
 },
 /**
  *  Print every object of the object array and show it on the element with ID pOutputID
  */
 this.showObjects = function outputArray(pObjectArray, pOutputID)
    {
        var output = "";

        for(var i in pObjectArray) {
            output += "<ul>";
            for (var key in pObjectArray[i]) {
                output += "<li>" + key + ": " + pObjectArray[i][key] + "</li>";
            }
            output += "</ul>";
        }

        output += "<hr>";

        $("#"+pOutputID).html(output);
    }
}
.blinkDivs {
  background-color: white;
  border: 3px solid black;
  border-radius: 40px;
  height: 50px;
  width: 50px;
  margin-bottom: 1px;
}

.blinkDivs:hover {
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div_01" class="blinkDivs"></div>
<div id="div_02" class="blinkDivs"></div>
<div id="div_03" class="blinkDivs"></div>

First click only on one circle and notice that it blinks for 2 seconds and stops. Then click on all the circles and notice that other intervals are getting interrupted and stop blinking.

Black
  • 12,789
  • 26
  • 116
  • 196
  • I'm assuming you want to do this in JavaScript, otherwise, you could just create a class with a looping animation which gets added on click and is removed after however many seconds. – George May 26 '17 at 12:40
  • Yes in JavaScript. I try to understand how to solve this with objects. – Black May 26 '17 at 12:48
  • 1
    Fari enough, I thought it'd be quite fun to do it myself with CSS, so if you ever want that https://jsbin.com/tuhacepira/edit?html,css,js,output – George May 26 '17 at 12:49
  • @George, nice! You can also post this as answer, I will upvote. – Black May 26 '17 at 12:50
  • 1
    Nah it's fine, you want it done in JS, besides, I'll let someone else get some points :) – George May 26 '17 at 12:51

3 Answers3

2

$jqElement = $("#" + self.id); exposes $jqElement to the global scope (window.$jqElement). That's why each time blink is called, it replace $jqElement with a new one.

Put $jqElement in self (or simply put var/let in front of it):

function Task(ElementID)
{
    var self = this;
    self.id = ElementID;
    self.interval = null;
    self.limiter = 0;
    self.toggle = 0;
    self.$jqElement = $("#" + self.id);
    self.blink = function()
    {
        self.limiter = 0;
        self.interval = setInterval(function() {

            if (self.toggle == 0) {
                self.$jqElement.css("background-color", "blue");
                self.toggle = 1;
            } else {
                self.$jqElement.css("background-color", "white");
                self.toggle = 0;
            }

            if (self.limiter > 4) {

                OAHelper.deleteObject(taskList, "id", self.id);
                clearInterval(self.interval);
            }
            self.limiter++;
        }, 400);
    }
}

https://jsfiddle.net/g128aunr/1/

Using a factory, Task become createTask

//Call var task = createTask(elId); instead of new Task();
var createTask = function createTask(elementId) {
    var self = {
        id: elementId
      , interval: 0
      , limiter: 0
      , toggle: 0
      , $element: $jqElement = $("#" + elementId)
      , blink: function blink() {
            self.limiter = 0;
          self.interval = setInterval(function() {
                            if (self.toggle == 0) {
                self.$element.css("background-color", "blue");
                self.toggle = 1;
                } else {
                self.$element.css("background-color", "white");
                self.toggle = 0;
                }

            if (self.limiter > 4) {
                clearInterval(self.interval);
            }
            self.limiter++;
          }, 400);
        }
    };
    return self;
}
Booster2ooo
  • 1,140
  • 8
  • 11
1

See if this helps you:

$(document).on("click", ".blinkDivs", function() {
  var el     = $(this),  
      newone = el.clone(true);
           
  el.before(newone);
  $(this).remove();
  
  $(newone).addClass("blinking");
})
.blinkDivs {
  background-color: white;
  border: 3px solid black;
  border-radius: 40px;
  height: 50px;
  width: 50px;
  margin-bottom: 1px;
}
.blinking {
  width: 50px;
  height: 50px;
  animation: myBlink 3s;
}

@-webkit-keyframes myBlink {
  0%, 25%, 50%, 75% {
    background-color: blue;
  }
  1%, 26%, 51%, 76% {
    background-color: white;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div_01" class="blinkDivs"></div>
<div id="div_02" class="blinkDivs"></div>
<div id="div_03" class="blinkDivs"></div>
Gerard
  • 13,747
  • 5
  • 24
  • 44
0

Replace your task function with this....

function Task(ElementID)
{
   var self = this;
   this.id = ElementID;
   this.interval = null;
   this.limiter = 0;
   this.toggle = 0;
   $(".blinkDivs").css("background-color", "white");
   this.blink = function()
   {
    $jqElement = $("#" + self.id);

    self.limiter = 0;
    self.interval = setInterval(function() {

        if (self.toggle == 0) {
            $jqElement.css("background-color", "blue");
            self.toggle = 1;
        } else {
            $jqElement.css("background-color", "white");
            self.toggle = 0;
        }

        if (self.limiter > 4) {

            OAHelper.deleteObject(taskList, "id", self.id);
            clearInterval(self.interval);
        }
        self.limiter++;
    }, 400);
}

}

Manav Sharma
  • 187
  • 1
  • 8