2

I'm trying to make a grid that will gonna be controlled by some javascript code.

<div id="blockFrame">
    <div id="blockGrid">
        <div class="block 0-0">1</div>
        <div class="block 0-1">1</div>
        <div class="block 0-2">1</div>
        <div class="block 1-0">1</div>
        <div class="block 1-1">1</div>
        <div class="block 1-2">1</div>
        <div class="block 2-0">1</div>
        <div class="block 2-1">1</div>
        <div class="block 2-2">1</div>
        <div class="block 3-0">1</div>
        <div class="block 3-1">1</div>
        <div class="block 3-2">1</div>
        <div class="block 4-0">1</div>
        <div class="block 4-1">1</div>
        <div class="block 4-2">1</div>
    </div>
</div>

It's 5x3 table with each cell containing '1' currently. I want all the div with the class name block to have a certain size, so I wrote this code, saved as an external js file and made the page load the file. It worked.

var blockSize = document.getElementsByClassName("block");
for (i=0; i<blockSize.length; i++) {
    blockSize[i].style.width='2.85em';
    blockSize[i].style.height='2.85em';
    blockSize[i].style.position='absolute';
}

The problem was in the part which was meant to position the 'blocks' to a certain place. Code below was wrote in the same external js file, but it doesn't do the job.

for (i=0; i<chunkWidth; i++)
    for (j=0; j<10*5/chunkWidth; j++) {
        eval("document.getElementsByClassName('"+i+"-"+j+"')[0].style.bottom='"+(3.25*5/chunkWidth*j)+"em';")
        eval("document.getElementsByClassName('"+i+"-"+j+"')[0].style.left='"+(3.25*5/chunkWidth*i)+"em';")
    }

Variable chunkWidth is defined in another external js files the page will load, and it's a number. I got this error when loading the page.

TypeError: document.getElementsByClassName(...)[0] is undefined

It works if I put the eval code line by line in the browser console, but that's not what I meant (though it works only for divs that were made after loading the page, by writing appendChild into the console, not for divs that were loaded with the page).

What should I do to make this external js file exert the change to the page and all the divs in the page, so I get the blocks arranged?

Dinir
  • 171
  • 2
  • 10

2 Answers2

0

Try escaping the first digit with a \.

eval("document.getElementsByClassName('\\"+i+"-"+j+"')[0].style.bottom='"+(3.25*5/chunkWidth*j)+"em';")
eval("document.getElementsByClassName('\\"+i+"-"+j+"')[0].style.left='"+(3.25*5/chunkWidth*i)+"em';")

http://forums.mozillazine.org/viewtopic.php?f=9&t=277768

apandit
  • 808
  • 1
  • 7
  • 16
0

You've got several problems in your code:

The 1st problem is with the calculation:

for (var i=0; i<chunkWidth; i++) {
    for (j=0; j<10*5/chunkWidth; j++) {

From the html we can see that max i === 4, and max j === 2

  • If chunkWidth is 1 - max i = 0 and max j = 49 - illegal
  • If chunkWidth is 2 - max i = 1 and max j = 24 - illegal
  • If chunkWidth is 3 - max i = 2 and max j = 15 - illegal
  • If chunkWidth is 4 - max i = 3 and max j = 12 - illegal
  • If chunkWidth is 5 - max i = 4 and max j = 10 - illegal
  • Beyond 5 i < 5 - illegal

Class names should start with _ / - / a-z / A-Z, so change the numbering classes to block0-1, and so on.

<div id="blockFrame">
    <div id="blockGrid">
        <div class="block block0-0">1</div>
        <div class="block block0-1">1</div>
        <div class="block block0-2">1</div>
        <div class="block block1-0">1</div>
        <div class="block block1-1">1</div>
        <div class="block block1-2">1</div>
        <div class="block block2-0">1</div>
        <div class="block block2-1">1</div>
        <div class="block block2-2">1</div>
        <div class="block block3-0">1</div>
        <div class="block block3-1">1</div>
        <div class="block block3-2">1</div>
        <div class="block block4-0">1</div>
        <div class="block block4-1">1</div>
        <div class="block block4-2">1</div>
    </div>
</div>

You do all the work with the script instead of using css. So instead of this block:

var blockSize = document.getElementsByClassName("block");
for (i=0; i<blockSize.length; i++) {
    blockSize[i].style.width='2.85em';
    blockSize[i].style.height='2.85em';
    blockSize[i].style.position='absolute';
}

Just use this css:

.block {
    position: absolute;
    height: 2.85em;
    width: 2.85em;
}

You use eval when you can just concatenate a string to get the desired className - "block"+i+"-"+j. Use this code block instead:

var block;

for (var i=0; i<chunkWidth; i++) {
    for (j=0; j<10*5/chunkWidth; j++) {
        block = document.getElementsByClassName("block"+i+"-"+j)[0];
        console.log("block"+i+"-"+j);
        block.style.bottom = 3.25*5/chunkWidth*j+"em";
        block.style.left = 3.25*5/chunkWidth*i+"em";
    }
}

Your should wait 'till the elements are rendered, so put the external script reference at the end of body, or use this

document.addEventListener("DOMContentLoaded", function(event) { 
  // your code
});
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
  • I'll try `.addEventListener` and rename the class not to start with number. And thanks for let me getting out of the eval code. But I used `i – Dinir Aug 09 '15 at 07:02
  • Maybe you should use chunkWidth and chunkHeight, and then i < chunkWidth, and j < chunkHeight. – Ori Drori Aug 09 '15 at 07:07
  • Move script tag to end of body or use document.addEventListener("DOMContentLoaded", function() {}); – Ori Drori Aug 09 '15 at 07:14