Skip to content

Commit 982b752

Browse files
committed
Merge branch 'widget-delegation'
2 parents 61caba7 + 0ff3396 commit 982b752

File tree

3 files changed

+80
-53
lines changed

3 files changed

+80
-53
lines changed

tests/unit/widget/widget_core.js

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ test( "jQuery usage", function() {
8989
"parameter passed via .pluginName(methodName, param)" );
9090
equals( param2, "value2",
9191
"multiple parameters passed via .pluginName(methodName, param, param)" );
92-
92+
9393
return this;
9494
},
9595
getterSetterMethod: function( val ) {
@@ -153,17 +153,17 @@ test( "direct usage", function() {
153153
}
154154
}
155155
});
156-
156+
157157
var elem = $( "<div>" )[ 0 ];
158-
158+
159159
shouldCreate = true;
160160
var instance = new $.ui.testWidget( {}, elem );
161161
shouldCreate = false;
162162

163163
equals( $( elem ).data( "testWidget" ), instance,
164164
"instance stored in .data(pluginName)" );
165165
equals( instance.element[ 0 ], elem, "element stored on widget" );
166-
166+
167167
var ret = instance.methodWithParams( "value1", "value2" );
168168
equals( ret, instance, "plugin returned from method call" );
169169

@@ -193,7 +193,7 @@ test( "error handling", function() {
193193
equal( msg, "no such method '_privateMethod' for testWidget widget instance",
194194
"invalid method call on widget instance" );
195195
};
196-
$( "<div>" ).testWidget().testWidget( "_privateMethod" );
196+
$( "<div>" ).testWidget().testWidget( "_privateMethod" );
197197
$.error = error;
198198
});
199199

@@ -463,7 +463,7 @@ test( ".option() - delegate to ._setOptions()", function() {
463463
calls = [];
464464
div.testWidget( "option", "foo", "bar" );
465465
same( calls, [{ foo: "bar" }], "_setOptions called for single option" );
466-
466+
467467
calls = [];
468468
div.testWidget( "option", {
469469
bar: "qux",
@@ -490,7 +490,7 @@ test( ".option() - delegate to ._setOption()", function() {
490490
div.testWidget( "option", "foo", "bar" );
491491
same( calls, [{ key: "foo", val: "bar" }],
492492
"_setOption called for single option" );
493-
493+
494494
calls = [];
495495
div.testWidget( "option", {
496496
bar: "qux",
@@ -666,6 +666,39 @@ test( "._bind() to descendent", function() {
666666
.trigger( "keydown" );
667667
});
668668

669+
test( "_bind() with delegate", function() {
670+
expect( 8 );
671+
$.widget( "ui.testWidget", {
672+
_create: function() {
673+
this.element = {
674+
bind: function( event, handler ) {
675+
equal( event, "click.testWidget" );
676+
ok( $.isFunction(handler) );
677+
},
678+
delegate: function( selector, event, handler ) {
679+
equal( selector, "a" );
680+
equal( event, "click.testWidget" );
681+
ok( $.isFunction(handler) );
682+
},
683+
trigger: $.noop
684+
};
685+
this._bind({
686+
"click": "handler",
687+
"click a": "handler",
688+
});
689+
this.element.delegate = function( selector, event, handler ) {
690+
equal( selector, "form fieldset > input" );
691+
equal( event, "change.testWidget" );
692+
ok( $.isFunction(handler) );
693+
};
694+
this._bind({
695+
"change form fieldset > input": "handler"
696+
});
697+
}
698+
});
699+
$.ui.testWidget();
700+
});
701+
669702
test( "._hoverable()", function() {
670703
$.widget( "ui.testWidget", {
671704
_create: function() {
@@ -703,14 +736,14 @@ test( "._focusable()", function() {
703736
this._focusable( this.element.children() );
704737
}
705738
});
706-
739+
707740
var div = $( "#widget" ).testWidget().children();
708741
ok( !div.hasClass( "ui-state-focus" ), "not focused on init" );
709742
div.trigger( "focusin" );
710743
ok( div.hasClass( "ui-state-focus" ), "focused after explicit focus" );
711744
div.trigger( "focusout" );
712745
ok( !div.hasClass( "ui-state-focus" ), "not focused after blur" );
713-
746+
714747
div.trigger( "focusin" );
715748
ok( div.hasClass( "ui-state-focus" ), "focused after explicit focus" );
716749
$( "#widget" ).testWidget( "disable" );
@@ -719,7 +752,7 @@ test( "._focusable()", function() {
719752
ok( !div.hasClass( "ui-state-focus" ), "can't focus while disabled" );
720753
$( "#widget" ).testWidget( "enable" );
721754
ok( !div.hasClass( "ui-state-focus" ), "enabling doesn't reset focus" );
722-
755+
723756
div.trigger( "focusin" );
724757
ok( div.hasClass( "ui-state-focus" ), "focused after explicit focus" );
725758
$( "#widget" ).testWidget( "destroy" );

ui/jquery.ui.menu.js

Lines changed: 26 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -38,52 +38,37 @@ $.widget( "ui.menu", {
3838
id: this.menuId,
3939
role: "menu"
4040
})
41+
// need to catch all clicks on disabled menu
42+
// not possible through _bind
4143
.bind( "click.menu", function( event ) {
42-
var item = $( event.target ).closest( ".ui-menu-item:has(a)" );
4344
if ( self.options.disabled ) {
44-
return false;
45-
}
46-
if ( !item.length ) {
47-
return;
45+
event.preventDefault();
4846
}
47+
});
48+
this._bind({
49+
"click .ui-menu-item:has(a)": function( event ) {
50+
event.stopImmediatePropagation();
51+
var target = $( event.currentTarget );
4952
// it's possible to click an item without hovering it (#7085)
50-
if ( !self.active || ( self.active[ 0 ] !== item[ 0 ] ) ) {
51-
self.focus( event, item );
52-
}
53-
self.select( event );
54-
})
55-
.bind( "mouseover.menu", function( event ) {
56-
if ( self.options.disabled ) {
57-
return;
58-
}
59-
var target = $( event.target ).closest( ".ui-menu-item" );
60-
if ( target.length ) {
61-
//Remove ui-state-active class from siblings of the newly focused menu item to avoid a jump caused by adjacent elements both having a class with a border
62-
target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" );
63-
self.focus( event, target );
64-
}
65-
})
66-
.bind( "mouseout.menu", function( event ) {
67-
if ( self.options.disabled ) {
68-
return;
69-
}
70-
var target = $( event.target ).closest( ".ui-menu-item" );
71-
if ( target.length ) {
72-
self.blur( event );
53+
if ( !this.active || ( this.active[ 0 ] !== target[ 0 ] ) ) {
54+
this.focus( event, target );
7355
}
74-
})
75-
.bind( "focus.menu", function( event ) {
76-
if ( self.options.disabled ) {
77-
return;
78-
}
79-
self.focus( event, $( event.target ).children( ".ui-menu-item:first" ) );
80-
})
81-
.bind( "blur.menu", function( event ) {
82-
if ( self.options.disabled ) {
83-
return;
84-
}
85-
self.collapseAll( event );
86-
});
56+
this.select( event );
57+
},
58+
"mouseover .ui-menu-item": function( event ) {
59+
event.stopImmediatePropagation();
60+
var target = $( event.currentTarget );
61+
// Remove ui-state-active class from siblings of the newly focused menu item to avoid a jump caused by adjacent elements both having a class with a border
62+
target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" );
63+
this.focus( event, target );
64+
},
65+
"mouseout .ui-menu-item": "blur",
66+
"focus": function( event ) {
67+
this.focus( event, $( event.target ).children( ".ui-menu-item:first" ) );
68+
},
69+
"blur": "collapseAll"
70+
});
71+
8772
this.refresh();
8873

8974
this.element.attr( "tabIndex", 0 ).bind( "keydown.menu", function( event ) {

ui/jquery.ui.widget.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,10 @@ $.Widget.prototype = {
305305
element = $( element );
306306
this.bindings = this.bindings.add( element );
307307
}
308+
308309
var instance = this;
309310
$.each( handlers, function( event, handler ) {
310-
element.bind( event + "." + instance.widgetName, function() {
311+
function handlerProxy() {
311312
// allow widgets to customize the disabled handling
312313
// - disabled as an array instead of boolean
313314
// - disabled class as method for disabling individual parts
@@ -317,7 +318,15 @@ $.Widget.prototype = {
317318
}
318319
return ( typeof handler === "string" ? instance[ handler ] : handler )
319320
.apply( instance, arguments );
320-
});
321+
}
322+
var match = event.match( /^(\w+)\s*(.*)$/ ),
323+
eventName = match[1] + "." + instance.widgetName,
324+
selector = match[2];
325+
if ( selector ) {
326+
element.delegate( selector, eventName, handlerProxy );
327+
} else {
328+
element.bind( eventName, handlerProxy );
329+
}
321330
});
322331
},
323332

0 commit comments

Comments
 (0)