2016-06-26 2 views
1

Я пытаюсь динамически добавлять элементы HTML с обработчиками кликов. Когда активируется обработчик кликов, он нацеливается на неправильный элемент (он всегда нацелен на внешний круг). Где может быть проблема?Получение неправильного элемента в обработчике кликов с перекрывающимися «круглыми» divs

(function() { 
 

 
    //selector, jQuery style 
 
    var $ = function(selector) { 
 
    return document.querySelector(selector); 
 
    } 
 

 
    //getting quantity of circles 
 
    var quantity = $('.circles').getAttribute('quantity'); 
 

 
    //setting outer width/height for circles 
 
    $('.circles').style.width = (quantity * 50) + 4 + 'px'; 
 
    $('.circles').style.height = (quantity * 50) + 4 + 'px'; 
 

 
    //creating element for children 
 
    var childCircle = document.createElement('div'); 
 
    childCircle.className = 'subCircle'; 
 

 
    //click function for children 
 
    function onClick() { 
 
    this.attributes.style.value += 'border-color: red;' 
 
    alert(this.clientHeight); 
 
    } 
 

 
    //append sub circles 
 
    for (var i = 0; i < quantity; i++) { 
 
    $('.circles').appendChild(childCircle.cloneNode()); 
 
    } 
 

 
    //iterate over .circles .subCircle and add onClick function for each subCircle and css aswell 
 

 
    var subCircle = $('.circles').getElementsByClassName('subCircle'); 
 
    for (var i = 0; i < subCircle.length; i++) { 
 
    subCircle[i].onclick = onClick; 
 
    subCircle[i].style.width = ((i + 1) * 50) + 'px'; 
 
    subCircle[i].style.height = ((i + 1) * 50) + 'px'; 
 
    } 
 

 
})();
.circles { 
 
    position: absolute; 
 
} 
 

 
.subCircle { 
 
    position: absolute; 
 
    border-radius: 50%; 
 
    transform: translateX(-50%) translateY(-50%); 
 
    border: 2px solid black; 
 
    top: 50%; 
 
    left: 50%; 
 
}
<body> 
 
    <div class="circles" quantity=10></div> 
 
</body>

Также на jsFiddle: https://jsfiddle.net/martin_borman/1srkL5bf/

+0

'subCircle [i] .onclick = onClick', вы потеряли' this' там. Не точка, не 'это'. – elclanrs

+0

сделайте ваши слушатели событий такими, как 'function (e) {e.target.attributes.style.value + = 'border-color: red;'}' – Redu

+0

@elclanrs: Это хорошо с вышесказанным, 'this' будет установлено вызов. –

ответ

4

Проблема не this, которая на самом деле получить устанавливается с помощью механизма обратного вызова событие просто отлично. Это то, что ваш самый большой круг на вершине.

Изменение цикла, который устанавливает размер позволяет поместить меньшие круги на вершине:

for (var i = 0; i < subCircle.length; i++) { 
    subCircle[i].onclick = onClick; 
    subCircle[i].style.width = ((subCircle.length - i) * 50) + 'px'; 
    subCircle[i].style.height = ((subCircle.length - i) * 50) + 'px'; 
} 

Ключ немного есть (subCircle.length - i) * 50, а не (i + 1) * 50.

Я бы также использовать

this.style.borderColor = 'red'; 

вместо

this.attributes.style.value += 'border-color: red;' 

Пример:

(function() { 
 

 
    //selector, jQuery style 
 
    var $ = function(selector) { 
 
    return document.querySelector(selector); 
 
    } 
 

 
    //getting quantity of circles 
 
    var quantity = $('.circles').getAttribute('quantity'); 
 

 
    //setting outer width/height for circles 
 
    $('.circles').style.width = (quantity * 50) + 4 + 'px'; 
 
    $('.circles').style.height = (quantity * 50) + 4 + 'px'; 
 

 
    //creating element for children 
 
    var childCircle = document.createElement('div'); 
 
    childCircle.className = 'subCircle'; 
 

 
    //click function for children 
 
    function onClick() { 
 
    this.style.borderColor = 'red'; 
 
    alert(this.clientHeight); 
 
    } 
 

 
    //append sub circles 
 
    for (var i = 0; i < quantity; i++) { 
 
    $('.circles').appendChild(childCircle.cloneNode()); 
 
    } 
 

 
    //iterate over .circles .subCircle and add onClick function for each subCircle and css aswell 
 

 
    var subCircle = $('.circles').getElementsByClassName('subCircle'); 
 
    for (var i = 0; i < subCircle.length; i++) { 
 
    subCircle[i].onclick = onClick; 
 
    subCircle[i].style.width = ((subCircle.length - i) * 50) + 'px'; 
 
    subCircle[i].style.height = ((subCircle.length - i) * 50) + 'px'; 
 
    } 
 

 
})();
.circles { 
 
    position: absolute; 
 
} 
 

 
.subCircle { 
 
    position: absolute; 
 
    border-radius: 50%; 
 
    transform: translateX(-50%) translateY(-50%); 
 
    border: 2px solid black; 
 
    top: 50%; 
 
    left: 50%; 
 
}
<body> 
 
    <div class="circles" quantity=10></div> 
 
</body>

+0

Ха, так оно и работает, приятно! Меня смутило то обстоятельство, что инструменты разработчика выделяют прямоугольник при наведении на элементы и предполагают, что все еще будут проблемы из-за перекрытия. Мне еще рано ... –

+0

@FelixKling: Да. Не столько их реверсирование, сколько то, что самый маленький был на вершине. Я продолжал смотреть на этот код и говорил: «Нет, это не так». и это заставило меня подумать: «Что, если это правильно»? Что еще это может быть? И довольно быстро «самый большой элемент на вершине» пришел из моего заднего мозга. То, что заняло у меня какое-то время, заключалось в выяснении того, почему мы не видели «щелчок» на других. Тогда я понял, да, они все братья и сестры, пузырь не имеет значения. –

+1

@ T.J.Crowder вот и все! Я полностью забыл о слоях. Спасибо вам за быстрый ответ. –

0

Просто добавьте Z-индекс имущество для каждого круга

subCircle[i].style['z-index'] = subCircle.length-i; 

На самом деле, большой круг перекрывает весь внутренний круг.

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