【问题标题】:Custom Event for HTML formHTML 表单的自定义事件
【发布时间】:2015-05-04 08:50:26
【问题描述】:

假设我有两个隐藏的表单字段输入:

<input id="val1" name="val1" value="0"/>
<input id="val2" name="val2" value="0"/>

假设我有一个警告 DIV,如果这两个输入的值都为“1”,我想显示一条消息

<div id="myWarningDiv" style="display: none;" class="clswhatever">
    You have done something wrong comrade!
</div>

现在假设有很多方法可以触发更改这些隐藏字段值中的一个或两个。我不想做的是更改每个触发器上的代码以检查这两个值是否都是“1”。有没有办法我可以添加一个自定义事件来监听这件事的发生,而不使用 setInterval 或类似的东西?

这是一个简单的例子。我真正要寻找的不是将事件附加到单个 DOM 元素的方法,而是创建可能跨越多个 DOM 对象的自定义条件,但在触发时会调用事件处理函数。下面是一些伪代码:

public Boolean onBothTrue() {
   if (document.getElementById("val1").value == "1" && document.getElementById("val2").value == "1") {
       return true;
   }
   else {
       return false;
   }
}
document.addEventListener('onBothTrue',myEventHandler);
function myEventHandler() {
    var elem = document.getElementById("myWarningDiv");
    elem.style.display = "block";
} 

【问题讨论】:

  • 你能展示你这样做的尝试吗?
  • 虽然我在 javascript 方面有不错的经验,但我在自定义事件方面没有很多经验,所以我不知道从哪里开始。
  • 大家好!感谢您的输入。我现在在想我想使用 CustomEvent 并将其附加到表单中。还认为应该在表单更改而不是 Window.SetInterval 时调度它。认为我可以随时使用 setter 函数,代码会更新值 abd 也会触发自定义事件。这个解决方案对每个人都有一点影响。这听起来对吗?如果是这样,有人可以发布一个全面的答案,以便我知道将赏金奖励给谁吗?我不知道如何分配赏金。
  • 我添加了另一个应该可以解决问题的示例。

标签: javascript jquery html


【解决方案1】:

我会这样做:

var input1 = document.getElementById('val1');
var input2 = document.getElementById('val2');
var div = document.getElementById('myWarningDiv');

input1.addEventListener('change', check);

input2.addEventListener('change', check);

function check() {
    if (parseInt(input1.value, 10) === 1 && parseInt(input2.value, 10) === 1) {
        div.style.display = 'block';
    } else {
        div.style.display = 'none';
    }
}

编辑

表单将从其子表单接收更改事件,在这种情况下,我会将更改事件侦听器附加到父表单并在任何输入更改时执行检查,例如:

var form = document.getElementById('form1');
var inputs = form.getElementsByTagName('input');

form.addEventListener('change', check);

function check(event) {
    var element = event.target;
    //convert nodeList to Array
    var inputArray = Array.prototype.slice.call(inputs);
    var conditionMet = true;

    // check all inputs checked
    inputArray.forEach(function (el, index) {
        if (!el.checked) {
            conditionMet = false;   
        }
    });

    // OR 

    // check all inputs with a class "required" are checked
    inputArray.forEach(function (el, index) {
        if (el.className.indexOf('required') !== -1) {
            if(!el.checked) {
                conditionMet = false;
            }
        }
    });

    if (conditionMet) {
        showWarningDiv();
    }
}

function showWarningDiv() {
    // show div
    console.log('show warning');
}

Fiddle

【讨论】:

  • 我希望可以在 BODY 或 FORM 中添加一个监听器。在我的示例中,我绝对可以使用您的示例,但我的示例非常简单。如果它更复杂(例如 - 我有 10 个输入,如果其中任何 3 个的值小于 5)怎么办?我必须将侦听器添加到所有 10 个输入,对吗?顺便说一句 - 如果隐藏字段的值被代码更改,会触发 onchange 事件吗?
  • 也许您的问题缺乏细节或太板而无法回答?人们会尽其所能回答,这符合所提出的问题。如果您想扩展问题,那么也许您应该在发布问题之前考虑一下您的问题?举一个真实的例子或展示你的尝试,也许人们会有值得合作的东西。
  • 我在我的问题中添加了一些伪代码,以便更清楚地了解我的目标。
  • 关于您编辑的答案 - 如果输入的值之一被代码而不是用户输入更改,是否会触发表单更改事件?或者我需要按照 Prathik Rajendran 的建议设置一个二传手吗?
  • 不,当以编程方式更改元素时,JS 中的更改事件不会触发。如果你要走 jQuery 路线,那么 $.trigger 就足够了,如果你想坚持使用 vanilla JS,那么你需要查看 createEvent,初始化事件,然后在元素上调度事件。在这个答案中可以看到一个很好的例子。 stackoverflow.com/a/25083394/4571952
【解决方案2】:

所提供的答案很好地说明了使用或不使用 jQuery 的人。要回答您关于自定义事件的问题,您可以注册它,但它就像您写的那样,但它不会触发(因为它怎么知道什么时候)。所以这样做的唯一方法是:

window.setInterval(function(){
    if (parseInt(input1.value, 10) === 1 && parseInt(input2.value, 10) === 1) {
        // Create the event
        var event = new CustomEvent("bothTrue", { "detail": "Both elements are true which indicates an error" });

        // Dispatch/Trigger/Fire the event
        document.dispatchEvent(event);
    }
}, 500);

这里还有其他帖子讨论原生 JS 中的事件处理(即How to trigger event in JavaScript?

使用自定义事件和更改处理程序更新:

var input1 = document.getElementById('val1');
var input2 = document.getElementById('val2');
var warningDiv = document.getElementById('myWarningDiv');

function customCondition() {
    if (parseInt(input1.value, 10) === 1 && parseInt(input2.value, 10) === 1) {
        // Create the event
        var event = new CustomEvent("bothTrue", { "detail": "Both elements are true which indicates an error" });
        // Dispatch/Trigger/Fire the event
       document.dispatchEvent(event);
}

input1.addEventListener('change', customCondition);
input2.addEventListener('change', customCondition);

document.addEventListener('bothTrue', function(e){
    warningDiv.style.display = 'block';
});

【讨论】:

  • 所以没有办法告诉文档只是在不使用 setInterval 的情况下监听某个条件的发生?
  • 不,监听器就是事件触发后执行的。但是缺少的是传递条件或类似条件的能力,因此唯一真正有意义的解决方法是使用setInterval,条件不太复杂,并且设置合理的间隔。这就是大多数提供此类功能的框架的方式,AFAIK 也是如此。
  • 太糟糕了。是否曾将其作为新标准提出?我真的很喜欢事件驱动架构的概念,但是如果你不能告诉浏览器在不执行 setInterval(基本上是一个计时器)的情况下引发它们,那么 javascript 中自定义事件的整个想法似乎有点牵强。
  • 如果我没有听到更好的消息,我会在今天晚些时候奖励你 +50。
【解决方案3】:

我将采用相同的示例,使用 JQuery 可以通过将 css 类附加到每个元素(基本上是输入)来实现。

<input id="val1" name="val1" class="listen"value="0"/>  
<input id="val2" name="val2" class="listen" value="0"/>

jQuery

$(".listen").each(function() {
   $(this).on('change', function(){
   var val=$(this).val();
   alert(val);
   });
});

【讨论】:

  • 我发现您的解决方案(使用类)是最优雅的。但是,它仍然对属于此类的元素使用内置的“更改”事件。我希望构建自己的自定义事件,该事件仅在我的某些条件为真时触发。如果我所追求的是不可能的,请告诉我。
  • 这是一个如何构建自己的自定义事件的示例,How to Create Custom Events in JavaScript to Program with HTML
【解决方案4】:

使用 jQuery

$("#val1,#val2").change(function() {
 var other = ($(this).get(0).id==="val1")?$("#val2"):$("#val1");
 if($(this).val() == 1 && $(other).val() == 1) {
   $("#myWarningDiv").show();
 } else {
   $("#myWarningDiv").hide();
 }
});

这是一个小提琴

https://jsfiddle.net/sx0mg8k1/

设置器确保每次更改值时都会触发更改事件。

$.fn.setVal = function(val) {
    $(this).val(val);
    $(this).trigger('change');
}

任何时候你想改变这个值,你都可以使用$("#val1").setVal(0);

【讨论】:

  • 如果另一个 javascript 函数改变了 #val1 或 #val2 的值(而不是用户输入),你的函数会工作吗?
  • 用户输入会触发更改,但我不确定代码输入是否会。您可以编写自定义设置器以确保它会触发更改事件。使用会触发更改事件的 jQuery 设置器更新答案。
【解决方案5】:

试试

var input = $("input"), message = $("#myWarningDiv"), arr = [], n = 1;
input.each(function(i, el) {
  return $(el).on("input", function(e) {
    arr[i] = Number($(this).val());
    var res = arr.length === input.length ? arr.every(function(value) {
      return value === n
    }) : false;
    return res ? message.show() : message.hide()
  })
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<input id="val1" name="val1" value="0"/>
<input id="val2" name="val2" value="0"/>
<!-- Lets say I have a warning DIV with a message that I want to display 
     if both of these inputs have a value of "1" -->

<div id="myWarningDiv" style="display: none;" class="clswhatever">
    You have done something wrong comrade!
</div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    • 2014-09-24
    • 2014-05-11
    • 2023-04-04
    • 2014-08-30
    • 1970-01-01
    相关资源
    最近更新 更多