2015-05-31 2 views
-1

Я создаю скрипт, который принимает два входных размеры, ширину и высоту, и создает масштабируется сетка, которая является представителем сколько блоков может поместиться в коробке с заданными размерами с помощью следующей функции:JavaScript уничтожает всех детей после добавления перерыва?

function makeRow() { 
     for (var i = 1; i <= blocksTall; i++) { 
      var mb = document.createElement("div"); 
      mb.setAttribute("class", "matrix-block mb-off"); 
      mb.setAttribute("onClick", "select_mb('" + j + "," + i + "');"); 
      placeBlocks.appendChild(mb); 
      if (i = blocksWide) { 
       placeBlocks.appendChild('br'); 
      } 
     } 
    } 

Эта функция отлично работает, чтобы отобразить первую строку блоков, а затем вставляет тэг break после того, как строка закончила визуализацию, что именно то, что я хочу сделать. Проблема в том, что мне нужно сгенерировать еще 17 строк с одинаковым количеством блоков, каждый из которых находится под предыдущей строкой, поэтому я впервые подумал, что я просто обернут еще один цикл вокруг этого первого цикла и, поскольку есть разрыв там, она будет оказывать новую строку ниже предыдущего:

for (var j = 1; j <= blocksTall; j++) { // Vertical for loop. 

    for (var i = 1; i <= blocksWide; i++) { // Horizontal for loop. 
     var mb = document.createElement("div"); 
     //mb.setAttribute("id", "matblock-" + i + "-" + j); 
     mb.setAttribute("class", "matrix-block mb-off"); 
     mb.setAttribute("onClick", "select_mb('" + i + "," + j + "');"); 
     placeBlocks.appendChild(mb); 
    } 

    if (j = blocksWide) { 
     placeBlocks.appendChild(brk); 
    } 

} 

Где blocksWide = 17. Here is a fiddle с полным сценарием. Когда я регистрирую значение для j в консоли, это фактически увеличивает (что говорит мне, что цикл for работает). То, что, кажется, происходит, состоит в том, что это почему-то рендеринг строки, а затем либо рендеринг новой строки поверх нее (кажется маловероятным, поскольку тэг break отображается после завершения каждой строки), либо по какой-то причине дети каждый раз, когда запускается новый цикл «горизонтальный».

Кто-нибудь знает, почему это может произойти, и как правильно получить каждую строку, добавляемую в последнюю строку, чтобы она создавала сетку из блоков вместо одной строки?

Заранее благодарю за любую помощь.

+0

Что такое 17 для? Infinity/17; o) – MaxZoom

ответ

3

Итак, я немного смущен некоторыми аспектами вашего сценария, но, думаю, у вас есть две основные проблемы.

Во-первых, вы когда-либо вызывали только document.createElement("br"), что означает, что вы когда-либо создавали единый перерыв; и один разрыв строки может появляться только в одном месте в DOM. Это:

 placeBlocks.appendChild(brk); 

удаляет brk из его текущей позиции в DOM, а затем помещает его в конце placeBlocks. Вы должны изменить его к этому:

 placeBlocks.appendChild(document.createElement("br")); 

Во-вторых, я не думаю, что if (j = blocksWide) { имеет смысл. Обратите внимание, что это эквивалентно следующему:

j = blocksWide; 
if (blocksWide != 0) { 

, что означает, что она мешает вашему для цикла путем манипулирования значения j. Я думаю, что исправление для этой проблемы - просто удалить весь if -check и выполнить свое тело безоговорочно.

+0

j == blocksWide not j = blocksWide, нет? –

+0

@SteveHynding: Я не думаю, что 'if (j == blocksWide)' имеет гораздо больше смысла, чем 'if (j = blocksWide)' прямо там. Логически, должен быть разрыв строки в конце каждой отдельной строки, а не только в конце строки, индекс которой больше ширины. Нет? – ruakh

+0

Хороший вопрос, недосмотр с моей стороны; нет, если требуется условное заявление +1 –

1

Я действительно не понимаю, что вы пытаетесь сделать с операторами остаточных и разделяющим, но blocksWide решен до бесконечности вызывает бесконечный цикл, и blocksHigh было только 17. Всеми остальными переменными, кроме full не были используемый.


Вам не нужны две петли, хотя это нормально. Если вы хотите использовать только один цикл, вам в принципе просто нужно знать, является ли i кратным dispW.

Так вы разделите i на dispW, то вы хотите знать, если это целое число, чтобы найти этого используется оператор остатка для 1 и если он решает 0 это целое число. Похоже, что это ...

if ((i/dispW) % 1 === 0) 
    // if (dispW=3 && (i=3 || i=6 || i=9 || ...)) true; 

Это в цикле будет выглядеть

totalWidth = dispW * dispH; // total number of blocks 
for (var i = 1; i <= totalWidth; i++) { 
    // do stuff; 
    if((i/dispW) % 1 === 0) { 
     // insert new line break; 
    } 
} 

Метод, используемый для выбора блоков был окрест способ сделать это. Сначала вы не должны использовать встроенный javascript, во-вторых, вы не должны использовать javascript для встраивания встроенного javascript в динамически созданный элемент. Вместо этого используйте element.onclick = function;.

Обратите внимание, что после функции нет брекетов. Это связано с тем, что вы фактически передаете ссылку на функцию, а не возвращаемое значение функции.

element.onclick передает объект события в функцию ссылки. Вы можете использовать это, чтобы выбрать блок, на который был нажат так.

for (...) { 
    ... 
    var element = document.createElement('div'); 
    element.onclick = myFunction; 
    ... 
} 

function myFunction(e) { 
    var clicked = e.target // this is the element that was clicked on 
} 

Кроме того, вы создавали один <br> элемент вне цикла. Поскольку appendChild перемещает элементы и не создает элементы, он просто продолжит перемещение линии до тех пор, пока цикл не закончится. Это должно выглядеть так.

placeBox.appendChild(document.createElement('br')) 
    // append a newly created line break; 

Тогда, даже если вся логика работала как задумано, и вы создаете новый разрыв строки каждый раз, плавал блоки означает разрывы строк не использовать display: inline-block; вместо этого.

Таким образом, в конце концов, что вы получите ...

(Full difference)

window.onload = function() { 
 
    renderGrid(); 
 
}; 
 
function renderGrid() { 
 
    var blocksTall = document.getElementById('height-in').value; 
 
    var blocksWide = document.getElementById('width-in').value; 
 
    var blocksTotal = blocksWide * blocksTall; 
 
    var placeBlocks = document.getElementById('matrix-shell'); 
 
    while (placeBlocks.firstChild) { 
 
     placeBlocks.firstChild.remove(); 
 
    } 
 
    console.log(blocksWide + "/" + blocksTall); 
 
    for (var i = 1; i <= blocksTotal; i++) { 
 
     var mb = document.createElement("div"); 
 
     mb.className = 'matrix-block mb-off'; 
 
     mb.onclick = select_mb; 
 
     placeBlocks.appendChild(mb); 
 
     if (((i/blocksWide) % 1) === 0) { 
 
      var brk = document.createElement("br"); 
 
      placeBlocks.appendChild(brk); 
 
     } 
 
    } 
 
} 
 
function select_mb(e) { 
 
    var cur_mb = e.target; 
 
    if (cur_mb.className == "matrix-block mb-off") { 
 
     // Turn cell on. 
 
     cur_mb.style.backgroundColor = "#00FF00"; 
 
     cur_mb.className = "matrix-block mb-on"; 
 
    } else { 
 
     //Turn cell off. 
 
     cur_mb.style.backgroundColor = "#000"; 
 
     cur_mb.className = "matrix-block mb-off"; 
 
    } 
 
}
.matrix-block { 
 
    height: 10px; 
 
    width: 10px; 
 
    border: 1px solid #fff; 
 
    display: inline-block; 
 
    background-color: black; 
 
} 
 
.mb-off { 
 
    background-color: black; 
 
} 
 
#matrix-shell { 
 
    font-size: 0; 
 
    display: inline-block; 
 
    border: 1px solid red; 
 
    white-space: nowrap;}
<table> 
 
    <tr> 
 
     <td>Width:</td> 
 
     <td> 
 
      <input id="width-in" name="width-in" type="text" /> 
 
     </td> 
 
    </tr> 
 
    <tr> 
 
     <td>Height:</td> 
 
     <td> 
 
      <input id="height-in" name="height-in" type="text" /> 
 
     </td> 
 
    </tr> 
 
    <tr> 
 
     <td colspan="2"> 
 
      <button onClick="renderGrid()">Compute</button> 
 
     </td> 
 
    </tr> 
 
</table> 
 
<br/> 
 
<div id="matrix-shell"></div>

+0

Спасибо за ваш ответ. Это было очень полезно. Я ценю дополнительную работу, которую вы сделали, помогая мне очистить свой сценарий. Некоторые из вещей, которые вы устранили, где переменные, которые мне нужны для будущей функциональности, но в контексте этого вопроса, вы правы, и их можно устранить без проблем. Просто любопытство об одном последнем, а именно: Каковы преимущества вызова функции с использованием метода, который вы предложили, или использования встроенных js? Является ли это аргументацией только потому, что это была куча неаккуратного кода, который генерируется снова и снова, или есть другие причины, о которых я должен знать? –

Смежные вопросы