Reputation: 109
I'm trying to find a way to assign event handlers to each box that I create dynamically. At the moment the user can click "Add above" or "Add below" and 2 rows of boxes will appear wherever they clicked.
I'm also trying to make it so that when the user clicks on a specific square, a colorPicker will pop up and that specific square's color can be changed.
For some reason though, the colorpicker only pops up when the user clicks on the first two rows of squares. If more rows are dynamically added below or above the current set, nothing happens when you click on the squares.
Does anyone know why this might be happening?
What I have done/tried so far :
http://codepen.io/anon/pen/bwBRmw
var theParent = document.querySelector(".container");
theParent.addEventListener("click", doSomething, false)
function doSomething(e) {
console.log("gets inside doSomething")
console.log(e.target)
console.log(e.currentTarget)
if (e.target !== e.currentTarget && e.target.id !== "") {
var clickedItem = e.target.id;
console.log("Clicked on " + clickedItem);
var led = document.getElementById(clickedItem)
if(!picker){
console.log("new picker initialized")
picker = new Picker(led)
}
else{
console.log("gets inside else case")
picker.settings.parent = led;
}
picker.show();
}
picker.on_done = function(colour) {
$(led).css('background-color',colour.rgba().toString());
picker.hide()
}
//e.stopPropagation();
}
Upvotes: 0
Views: 1045
Reputation: 5796
If you want it to work for dynamically generated inputs as well, you'll have to change your function a little.
This doesn't work on dynamically generated inputs (Demo)
$('input').keyup(function() {
for (var i = 0; i < triggerWords.length; i++) {
if ($(this).val().toLowerCase().indexOf(triggerWords[i]) != -1) {
alert("Alert! You've typed a blocked word.");
}
}
});
But this does (Demo)
$(document).on('keyup', 'input', function() {
for (var i = 0; i < triggerWords.length; i++) {
if ($(this).val().toLowerCase().indexOf(triggerWords[i]) != -1) {
alert("Alert! You've typed a blocked word.");
}
}
});
Upvotes: 1
Reputation: 717
Your event handlers are actually working well, the problem is your id's declarations in your HTML!
When you click on any .repeat button, you are cloning the current #repeatable and changing its id, but you forget to change the .startLEDs and .endLEDs element id's, which end up being repeated, this is why the picker never works when you click in #repeatable squares below the first #repeatable, because the browser never find these square elements, and instead find the first ones in the page!
Instead of associating id's to .startLEDs and .endLEDs elements, you can associate another data attribute instead, like 'data-id' or something that can be repeated.
You also have another problem, since the plugin you use for the picker appends the picker to the clicked led (the a element) with the id '#picker_wrapper', when you clone the #repeatable, you're also cloning the picker element, so for the same reason, even after changing the led id's to data-id, the pickers below the first picker in the page after cloning would stop working. To fix this, we should first either destroy or remove from the DOM the picker used last time, before cloning.
Here is a possible solution:
// vars
var repeatableId = 0,
picker,
$led;
// functions
function removePicker () {
if (picker) {
$led.removeClass('selected').find('#picker_wrapper').remove();
picker = null;
}
}
function onPickerDone (color) {
$led.css('background-color', color.rgba().toString());
removePicker();
}
$(document).ready(function () {
// event listeners
$('body').on('click', '.repeat', function (e) {
var $self = $(this),
$parent = $self.parent(),
$parentClone;
removePicker();
$parentClone = $parent.clone(true).attr('id', 'repeatable' + ++repeatableId);
if ($self.hasClass('add-bottom')) {
$parent.after($parentClone);
} else {
$parent.before($parentClone);
}
});
$('.container').on('click', function (e) {
var $target = $(e.target);
if ($target.hasClass('js-led')) {
removePicker();
$led = $target;
$led.addClass('selected');
picker = new Picker($led[0]);
picker.on_done = onPickerDone;
picker.show();
}
});
});
.bottomdiv {
clear: both;
position: fixed;
bottom: 0;
height: 50%;
width: 100%;
font-size: 16px;
text-align: center;
overflow: auto;
}
.bottomdiv > .container {
margin-top: 60px;
float: left
}
.bottomdiv > .container > .repeatable > .timeMilli {
display: inline-block;
}
.bottomdiv > .container > .repeatable > .repeat {
display: block;
}
.bottomdiv > .container > .repeatable a {
position: relative;
display: inline-block;
width: 30px;
height: 30px;
background-color: #ccc;
border: 1px solid #000000;
z-index: 0;
}
.bottomdiv > .container > .repeatable a.selected {
z-index: 1;
}
<script src="http://iamsaravieira.com/picker.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<div class="bottomdiv">
<div class="container">
<div class="repeatable">
<button class="repeat add-top">Add above</button>
<div class="startLEDs">
<a class="js-led startLEDs" data-id="sLED1"></a>
<a class="js-led startLEDs" data-id="sLED2"></a>
<a class="js-led startLEDs" data-id="sLED3"></a>
<a class="js-led startLEDs" data-id="sLED4"></a>
<a class="js-led startLEDs" data-id="sLED5"></a>
<a class="js-led startLEDs" data-id="sLED6"></a>
<a class="js-led startLEDs" data-id="sLED7"></a>
<a class="js-led startLEDs" data-id="sLED8"></a>
<a class="js-led startLEDs" data-id="sLED9"></a>
<a class="js-led startLEDs" data-id="sLED10"></a>
<a class="js-led startLEDs" data-id="sLED11"></a>
<a class="js-led startLEDs" data-id="sLED12"></a>
</div>
<div class="endLEDs">
<a class="js-led endLEDs" data-id="eLED1"></a>
<a class="js-led endLEDs" data-id="eLED2"></a>
<a class="js-led endLEDs" data-id="eLED3"></a>
<a class="js-led endLEDs" data-id="eLED4"></a>
<a class="js-led endLEDs" data-id="eLED5"></a>
<a class="js-led endLEDs" data-id="eLED6"></a>
<a class="js-led endLEDs" data-id="eLED7"></a>
<a class="js-led endLEDs" data-id="eLED8"></a>
<a class="js-led endLEDs" data-id="eLED9"></a>
<a class="js-led endLEDs" data-id="eLED10"></a>
<a class="js-led endLEDs" data-id="eLED11"></a>
<a class="js-led endLEDs" data-id="eLED12"></a>
</div>
<div class="timeMilli">Time(ms): <input type="text" name="time" form="form1"></div>
<button class="repeat add-bottom">Add below</button>
</div>
</div>
</div>
Conclusion
- Never use repeated id's in your HTML
PS: I didn't changed any of your classes because you might need them in your project somehow
Upvotes: 0
Reputation: 1894
$(document).on('click', '.your-element', function (e) {
e.preventDefault();
doSomething();
);
Upvotes: 0