事件处理程序不适用于动态添加的元素

时间:2016-09-21 19:49:34

标签: javascript jquery html css

我正在尝试找到一种方法来为我动态创建的每个框分配事件处理程序。用户可以点击“上方添加”或“下方添加”,只需点击一下就会出现2行框。

我也试图这样做,以便当用户点击特定方格时,会弹出一个colorPicker,并且可以更改特定方块的颜色。

出于某种原因,只有当用户点击前两行正方形时,才会弹出颜色选择器。如果在当前集合的下方或上方动态添加更多行,则单击正方形时不会发生任何事情。

有谁知道为什么会这样?

到目前为止我做过/尝试过的事情:

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();
}

3 个答案:

答案 0 :(得分:1)

如果您希望它也能用于动态生成的输入,那么您必须稍微更改一下您的功能。

这不适用于动态生成的输入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.");
        }
    }
});

但这确实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.");
        }
    }
});

答案 1 :(得分:0)

{{1}}

答案 2 :(得分:0)

您的事件处理程序实际上运行良好,问题是您的HTML中的id声明!

当您点击任何.repeat按钮时,您正在克隆当前的#repeatable并更改其ID,但您忘记更改.startLEDs和.endLEDs元素ID ,最终会重复,这就是当你点击第一个#repeatable下方的#repeatable方块时,选择器永远不会工作的原因,因为浏览器永远不会找到这些方形元素,而是在页面中找到第一个!

您可以将其他数据属性与“数据ID ”或可重复的内容相关联,而不是将ID与.startLEDs和.endLEDs元素相关联。

您还有另一个问题,因为您用于选择器的插件将选择器附加到单击的led a 元素) 且ID为' #picker_wrapper',当您克隆#repeatable时,您还要克隆选择器元素,因此出于同样的原因,即使将led id更改为data-id,克隆后第一个选择器下方的选择器将停止工作。要解决这个问题,我们首先应该在克隆之前销毁或删除上次使用的选择器。

这是一个可能的解决方案:

// 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>

<强>结论

- 切勿在HTML中使用重复的ID

PS: 我没有更改任何课程,因为您可能在某个项目中需要它们