监听同一元素上的多个事件以触发
Listen to multiple events on the same element to fire
我需要你的帮助,因为我已经束手无策了。我正在尝试等待表单元素上的多个事件。为了向您展示我的意思,这里有一个例子:
var el = this,
conditions = $( this ).data( 'conditions' ),
promises = [];
$( conditions ).each( function () {
var def = new $.Deferred(),
condition = this;
$( el ).hide();
$( this.listener ).on( 'change', function () {
if ( $( '#' + condition.target ).is( ':checked' ) ) {
def.resolve( 'show' );
} else {
def.resolve( 'hide' );
}
promises.push( def );
} );
} );
$.when.apply( undefined, promises ).done( function ( res ) {
console.log( res );
} );
这背后的想法是,我可以收听 select 元素并检查用户 selected 的值。如果条件验证为真,则显示另一个元素。
现在的问题是:如果我在同一元素上有另一个条件,两个侦听器都会执行,一个验证为真,另一个为假。
所以我用 deferred 试了一下。上面的例子第一次正常工作。如果用户再次发出事件,则延迟不会第二次得到解决。我很期待这个,因为一个承诺只能解决一次。
另一种方式是,如果我只使用纯 jQuery 侦听器,它们都会被触发,最后附加的侦听器会显示或隐藏元素。但我需要一次评估所有听众。
我现在的问题是,我该如何解决这个问题?有人可以给我一个关于如何实施的提示吗?
感谢@jfriend00 给我提示。
这是我最终得到的示例:
var el = $( '#formfield-3' ),
conditions = $( el ).data( 'conditions' ),
targetConditions = {};
$( el ).on( 'condition.check', function () {
var show = false;
$.each( targetConditions, function ( key, target ) {
switch ( key ) {
case 'show':
$.each( target, function ( key, value ) {
if ( ! show ) {
show = value.indexOf( true ) !== - 1;
}
} );
break;
}
} );
if ( show ) {
$( el ).parent( '.forminput-group' ).show();
} else {
$( el ).parent( '.forminput-group' ).hide();
}
} );
$( conditions ).each( function () {
var condition = this;
if ( ! targetConditions[this.type] ) {
targetConditions[this.type] = {};
}
if ( ! targetConditions[this.type][this.target] ) {
targetConditions[this.type][this.target] = [];
}
if ( ! targetConditions[this.type][this.target][this.id] ) {
targetConditions[this.type][this.target][this.id] = false;
}
$( el ).hide();
$( this.listener ).on( 'change', function () {
targetConditions[condition.type][condition.target][condition.id] = false;
switch ( condition.condition ) {
case 'selected':
if ( $( '#' + condition.target ).is( ':checked' ) ) {
targetConditions[condition.type][condition.target][condition.id] = true;
}
break;
}
$( el ).trigger( 'condition.check' );
} );
} );
这是我用来测试的有效表单元素标签:
<input id="formfield-1" name="sample" type="radio" value="1">
<input id="formfield-2" name="sample" type="radio" value="2">
<select id="formfield-3" data-conditions="[{"id":1,"target":"formfield-1","listener":"input[name=sample]:radio","type":"show","condition":"selected","value":null,"element":"select"},{"id":2,"target":"formfield-2","listener":"input[name=sample]:radio","type":"show","condition":"selected","value":null,"element":"select"}]">
<option>Please select</option>
<option>Sample Value</option>
</select>
这将在无线电组上创建两个听众,无论 select 编辑什么,都会显示 select 框。
这只是一个很小的演示,但我希望如果其他人有这样的问题,我可以帮助解决这个问题:)
非常感谢
我需要你的帮助,因为我已经束手无策了。我正在尝试等待表单元素上的多个事件。为了向您展示我的意思,这里有一个例子:
var el = this,
conditions = $( this ).data( 'conditions' ),
promises = [];
$( conditions ).each( function () {
var def = new $.Deferred(),
condition = this;
$( el ).hide();
$( this.listener ).on( 'change', function () {
if ( $( '#' + condition.target ).is( ':checked' ) ) {
def.resolve( 'show' );
} else {
def.resolve( 'hide' );
}
promises.push( def );
} );
} );
$.when.apply( undefined, promises ).done( function ( res ) {
console.log( res );
} );
这背后的想法是,我可以收听 select 元素并检查用户 selected 的值。如果条件验证为真,则显示另一个元素。
现在的问题是:如果我在同一元素上有另一个条件,两个侦听器都会执行,一个验证为真,另一个为假。
所以我用 deferred 试了一下。上面的例子第一次正常工作。如果用户再次发出事件,则延迟不会第二次得到解决。我很期待这个,因为一个承诺只能解决一次。
另一种方式是,如果我只使用纯 jQuery 侦听器,它们都会被触发,最后附加的侦听器会显示或隐藏元素。但我需要一次评估所有听众。
我现在的问题是,我该如何解决这个问题?有人可以给我一个关于如何实施的提示吗?
感谢@jfriend00 给我提示。
这是我最终得到的示例:
var el = $( '#formfield-3' ),
conditions = $( el ).data( 'conditions' ),
targetConditions = {};
$( el ).on( 'condition.check', function () {
var show = false;
$.each( targetConditions, function ( key, target ) {
switch ( key ) {
case 'show':
$.each( target, function ( key, value ) {
if ( ! show ) {
show = value.indexOf( true ) !== - 1;
}
} );
break;
}
} );
if ( show ) {
$( el ).parent( '.forminput-group' ).show();
} else {
$( el ).parent( '.forminput-group' ).hide();
}
} );
$( conditions ).each( function () {
var condition = this;
if ( ! targetConditions[this.type] ) {
targetConditions[this.type] = {};
}
if ( ! targetConditions[this.type][this.target] ) {
targetConditions[this.type][this.target] = [];
}
if ( ! targetConditions[this.type][this.target][this.id] ) {
targetConditions[this.type][this.target][this.id] = false;
}
$( el ).hide();
$( this.listener ).on( 'change', function () {
targetConditions[condition.type][condition.target][condition.id] = false;
switch ( condition.condition ) {
case 'selected':
if ( $( '#' + condition.target ).is( ':checked' ) ) {
targetConditions[condition.type][condition.target][condition.id] = true;
}
break;
}
$( el ).trigger( 'condition.check' );
} );
} );
这是我用来测试的有效表单元素标签:
<input id="formfield-1" name="sample" type="radio" value="1">
<input id="formfield-2" name="sample" type="radio" value="2">
<select id="formfield-3" data-conditions="[{"id":1,"target":"formfield-1","listener":"input[name=sample]:radio","type":"show","condition":"selected","value":null,"element":"select"},{"id":2,"target":"formfield-2","listener":"input[name=sample]:radio","type":"show","condition":"selected","value":null,"element":"select"}]">
<option>Please select</option>
<option>Sample Value</option>
</select>
这将在无线电组上创建两个听众,无论 select 编辑什么,都会显示 select 框。
这只是一个很小的演示,但我希望如果其他人有这样的问题,我可以帮助解决这个问题:)
非常感谢