1

I am stuck on the event handler aspect of Javascript.

rowCells[j] is a reference to a unique object. galleryCell is also a reference to newly created object. It stands to reason that the two could link together.

However, it does not seem that the two references get bound together at all for the event listener to work properly. All cells get assigned to the same exact thing (the last galleryCell object).

The galleryCell variable is inside a for-loop getting a new reference at each iteration. Why are these references being lost ?

function TypeGallery (galleryObj)
{  //receives the <div> element that contains rows and cells of a gallery

   //Properties --------------
   var galleryCellArr = [];   //array of galleryZoomCell objects

   //Methods -----------------  
   var Initialize  = function ()
   {
      var rows     = galleryObj.children;
      var rowCount = rows.length;
      for (var i=0;i<rowCount;i++)
      {
         var rowCells     = rows[i].children;
         var rowCellCount = rowCells.length;
         for (var j=0;j<rowCellCount;j++)
         {
            var sliderObj   = new TypeSlider(300,1,false);
            var galleryCell = new TypeGalleryZoomCell(rowCells[j],sliderObj)
            galleryCellArr.push(galleryCell);

            rowCells[j].onmousedown = function () {galleryCell.Deploy();};
            rowCells[j].onmouseup   = function () {galleryCell.Retract();};
         }
      }
   }

   //Initialization
   Initialize();
}
Thomas An
  • 503
  • 2
  • 7
  • 17
  • 1
    The galleryCell variable is scoped not to the for block, but to the entire Initialize function. It's therefore completely rewritten with every iteration, and so when the event fires, the function that is called is just the most recent assignment for galleryCell. Take a look at http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – TAGraves Apr 06 '16 at 20:32

2 Answers2

2

Try to put a javascript closure inside a for loop like this:

function TypeGallery (galleryObj)
{  //receives the <div> element that contains rows and cells of a gallery

   //Properties --------------
   var galleryCellArr = [];   //array of galleryZoomCell objects

   //Methods -----------------  
   var Initialize  = function ()
   {
      var rows     = galleryObj.children;
      var rowCount = rows.length;
      for (var i=0;i<rowCount;i++)
      {
         var rowCells     = rows[i].children;
         var rowCellCount = rowCells.length;
         for (var j=0;j<rowCellCount;j++)
         {
            (function(j) {

                var sliderObj   = new TypeSlider(300,1,false);
                var galleryCell = new TypeGalleryZoomCell(rowCells[j],sliderObj)
                galleryCellArr.push(galleryCell);

                rowCells[j].onmousedown = function () {galleryCell.Deploy();};
                rowCells[j].onmouseup   = function () {galleryCell.Retract();};

            })(j);
         }
      }
   }

   //Initialization
   Initialize();
}
noviewpoint
  • 574
  • 1
  • 10
  • 20
  • Yes, although do note that it is probably better to create a single function outside of the loop and then call it inside the loop instead of making a new anonymous function at each iteration – TAGraves Apr 06 '16 at 20:37
  • Wow, yes, this works. Thank you for the answer ! Now I need to go back figure out why I have this blind spot in my understanding of Javascript scoping. – Thomas An Apr 06 '16 at 20:39
0

ok, I understand now the issues with Javascript and block-scope limitation.

Along the way I discovered a second possible fix:
Are there any objections or caveats in replacing the 'var' with 'let' inside for loops?
This code works fine as far as I can tell. Any hidden dangers ?

   var Initialize  = function ()
   {
      var rowsArr  = galleryObj.children;
      var rowCount = rowsArr.length;
      for (let i=0;i<rowCount;i++)
      {  //Javascript does not understand block-scope unless the let keyword
         let rowCellsArr  = rowsArr[i].children;
         let rowCellCount = rowCellsArr.length;
         for (let j=0;j<rowCellCount;j++) 
         {
            //Attach (rowCellsArr[j]);

            let sliderObj   = new TypeSlider(300,1,false);
            let galleryCell = new TypeGalleryZoomCell(rowCellsArr[j],sliderObj);
            galleryCellArr.push(galleryCell); 

            galleryCellArr[galleryCellArr.length-1].cell.onmousedown = function () {galleryCell.Deploy();};
            galleryCellArr[galleryCellArr.length-1].cell.onmouseup   = function () {galleryCell.Retract();};

         }
      }
   }
Thomas An
  • 503
  • 2
  • 7
  • 17