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

How to determine if an Element was created dynamically

我有一个使用 jQuery、Backbone.js 和用 C# 编写的 REST-ish 后端构建的现有系统。该应用程序是一个 SPA,具有要填写和导航的表单。我的工作是构建一个 "Navigation Interceptor" 来连接应用程序,以便系统检测当前视图中的字段是否被修改,以便当用户导航时,他将被警告字段被修改并被要求保存或取消更改。

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

这样做,我遇到了两个问题:

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

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

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

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

#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;
}

我的想法>>

1)调用setDate()后停止调用changeDate()的方法,直接调用event.stopPropogation(),可以防止事件冒泡

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

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

然后在遍历元素时,检查 isDynamic 属性

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

为什么这不起作用,它应该? (根据评论进行编辑。)

为什么不给元素添加一个良性的 class 标签

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

然后您可以检查 class 以查看它是否已创建

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

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

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

我所做的是修改bootstrap的来源。像这样调用 setDate 时:

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

代码通过调用 updatesetValue 的函数 setDates,第一个导致在日期选择器本身中设置日期,第二个仅设置输入文本字段中的值。我所做的是删除对 'change' 的调用,该调用会触发字段上的更改事件并保留自定义事件 'dateChange'。这导致我的代码在我调用 setDate 时未触发更改事件,而是在用户使用选择器本身设置日期时调用它。