如何确定元素是否是动态创建的

时间:2016-06-13 13:59:39

标签: javascript jquery twitter-bootstrap backbone.js

我有一个使用jQuery构建的现有系统,Backbone.js和一个用C#编写的REST-ish后端。该应用程序是一个SPA,其中包含填写和导航的表单。我的工作是构建一个“导航拦截器”来连接应用程序,以便系统检测当前视图中是否修改了一个字段,这样当用户导航时,他将被警告字段被修改并被请求保存或取消变化。

我设计它的方式是使用jQuery。为简短起见,我在inputselect等上使用选择器,并将更改事件绑定到它。然后我在链接和按钮上使用选择器,取消绑定所有单击事件,绑定我的“拦截器”(如果字段已更改,在导航之前询问),然后在我的拦截器之后重新绑定所有单击事件。我使用stopImmediatePropagation()来取消常规导航事件,从而产生一种围绕事件的包装。

通过这样做,我有两个问题:

  1. 在字段上调用.val()不会触发更改事件,因为我会动态填充字段。问题是引导日期选择器似乎没有使用.val()设置值,导致所有日期字段在初始化时具有“已更改”状态。

  2. 动态创建的元素(例如:在页面加载后创建的折叠面板中的字段)不接受导致表单未触发导航拦截器的更改事件的事件。

  3. 我的问题是关于以上两个要素:

    1. 有没有办法确定特定字段是否是日期选择器并在该字段上绑定更改事件,以便在我填充它时,更改事件不会触发,但是当用户执行时,它会(我尝试过)绑定changeDate事件,但setDate方法似乎也触发了changeDate事件?
    2. 有没有办法确定元素是否是动态创建的(例如:$(''))?问题是我没有单个字段的特定选择器,所以我认为我不能使用委托($(document).on('change', 'someFieldSelectorICannotKnow', function () {});)。我所拥有的只是jQuery元素的句柄($(this)迭代中的.each(fn))。
    3. #2使用所有字段上的事件委派解决并在字段不是表单字段时跳过处理程序

      #2的解决方案:

      NavigationInterceptor.prototype.bindChangeEventOnAllEditableFields = function () {
          var self = this;
      
          var fieldsSelector = $(this.configuration.selectors.formFields.join(', '));
          $(fieldsSelector).each(function () {
              var isFormField = !self.searchClassFromArrayInElement(self.configuration.classes.nonFormFieldClasses, $(this));
      
              if (isFormField && self.configuration.debug.highlight.fields.unchanged && $(this).attr('type') === 'radio') {
                  $(this).parent().css('background-color', self.configuration.debug.highlight.fields.unchanged);
              } else if (isFormField && self.configuration.debug.highlight.fields.unchanged) {
                  $(this).css('background-color', self.configuration.debug.highlight.fields.unchanged);
              }
          });
      
          $(document).on('change', fieldsSelector, function (event) {
              var field = $(event.target);
              var isFormField = !self.searchClassFromArrayInElement(self.configuration.classes.nonFormFieldClasses, field);
      
              if (isFormField) {
                  self.hasFieldChanged = true;
      
                  if (self.configuration.debug.highlight.fields.changed) {
                      if (field.attr('type') === 'radio') {
                          field.parent().css('background-color', self.configuration.debug.highlight.fields.changed);
                      } else {
                          field.css('background-color', self.configuration.debug.highlight.fields.changed);
                      }
                  }
              }
          });
      
      
          return this;
      }
      

4 个答案:

答案 0 :(得分:1)

var unchangeable_classes = ['decorative', 'constant'];
$(document).on('change', 'input,select,textarea', function () {
    var $this=$(this); 
    for(var i =0;i<unchangeable_classes.length;++i){
       if($this.hasClass(unchangeable_classes[i]))
           return;
    } 
    global_changed = true;
});

为什么这不起作用呢? (编辑回应评论。)

答案 1 :(得分:0)

我的想法&gt;&gt;

1)在调用setDate()之后停止调用changeDate()的方法,你可以调用event.stopPropogation(),它会阻止事件冒泡

2)在创建动态元素时,您可以添加任何属性。例如

var iDiv = document.createElement('div');
iDiv.isDynamic = true;

然后在迭代元素时,检查isDynamic属性

答案 2 :(得分:0)

为什么不在元素中添加良性类标记

$('#foo').addClass('bar');

然后您可以检查班级是否已创建

if ($('#foo').hasClass('bar'))
    alert('was created');

请注意,添加元素时,必须重新附加事件。因此,如果您有一个全局文档事件,然后添加一个元素,那么除非您明确附加新元素,否则不会包含该元素。

答案 3 :(得分:0)

我正在为我的问题#1发布答案。

我所做的是修改bootstrap的源代码。如此调用setDate

$('#myDateInput').datepicker('setDate', new Date());

代码遍历调用setDatesupdate的函数setValue,第一个函数导致日期在datepicker本身中设置,第二个函数仅设置值输入文本字段。我所做的是删除对'change'的调用,该调用触发字段上的change事件并离开自定义事件'dateChange'。这导致我的代码在调用setDate时未触发更改事件,但在用户使用选择器本身设置日期时调用它。