From 2d1b9b391eadc979fb0988a76055ab5397e8b55f Mon Sep 17 00:00:00 2001 From: Jörn Zaefferer Date: Wed, 8 Jun 2011 22:14:37 +0200 Subject: Widget delegation: First draft --- ui/jquery.ui.widget.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 00bc07c4f..1c01ef7c9 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -301,9 +301,10 @@ $.Widget.prototype = { element = $( element ); this.bindings = this.bindings.add( element ); } + var instance = this; $.each( handlers, function( event, handler ) { - element.bind( event + "." + instance.widgetName, function() { + function handlerProxy() { // allow widgets to customize the disabled handling // - disabled as an array instead of boolean // - disabled class as method for disabling individual parts @@ -313,7 +314,15 @@ $.Widget.prototype = { } return ( typeof handler === "string" ? instance[ handler ] : handler ) .apply( instance, arguments ); - }); + } + var match = key.match( /^(\w+)\s*(.*)$/ ); + var eventName = match[1] + "." + instance.widgetName, + selector = match[2]; + if (selector === '') { + element.bind( eventName, handlerProxy ); + } else { + element.delegate( selector, eventName, handlerProxy ); + } }); }, -- cgit v1.2.3 From 391282a9aeb4e5bb6ba6655d7f1d5d125f93155a Mon Sep 17 00:00:00 2001 From: Jörn Zaefferer Date: Sun, 19 Jun 2011 14:42:15 +0200 Subject: Whitespace --- tests/unit/widget/widget_core.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index b1c27b104..892336c50 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -89,7 +89,7 @@ test( "jQuery usage", function() { "parameter passed via .pluginName(methodName, param)" ); equals( param2, "value2", "multiple parameters passed via .pluginName(methodName, param, param)" ); - + return this; }, getterSetterMethod: function( val ) { @@ -153,9 +153,9 @@ test( "direct usage", function() { } } }); - + var elem = $( "
" )[ 0 ]; - + shouldCreate = true; var instance = new $.ui.testWidget( {}, elem ); shouldCreate = false; @@ -163,7 +163,7 @@ test( "direct usage", function() { equals( $( elem ).data( "testWidget" ), instance, "instance stored in .data(pluginName)" ); equals( instance.element[ 0 ], elem, "element stored on widget" ); - + var ret = instance.methodWithParams( "value1", "value2" ); equals( ret, instance, "plugin returned from method call" ); @@ -193,7 +193,7 @@ test( "error handling", function() { equal( msg, "no such method '_privateMethod' for testWidget widget instance", "invalid method call on widget instance" ); }; - $( "
" ).testWidget().testWidget( "_privateMethod" ); + $( "
" ).testWidget().testWidget( "_privateMethod" ); $.error = error; }); @@ -444,7 +444,7 @@ test( ".option() - delegate to ._setOptions()", function() { calls = []; div.testWidget( "option", "foo", "bar" ); same( calls, [{ foo: "bar" }], "_setOptions called for single option" ); - + calls = []; div.testWidget( "option", { bar: "qux", @@ -471,7 +471,7 @@ test( ".option() - delegate to ._setOption()", function() { div.testWidget( "option", "foo", "bar" ); same( calls, [{ key: "foo", val: "bar" }], "_setOption called for single option" ); - + calls = []; div.testWidget( "option", { bar: "qux", @@ -684,14 +684,14 @@ test( "._focusable()", function() { this._focusable( this.element.children() ); } }); - + var div = $( "#widget" ).testWidget().children(); ok( !div.hasClass( "ui-state-focus" ), "not focused on init" ); div.trigger( "focusin" ); ok( div.hasClass( "ui-state-focus" ), "focused after explicit focus" ); div.trigger( "focusout" ); ok( !div.hasClass( "ui-state-focus" ), "not focused after blur" ); - + div.trigger( "focusin" ); ok( div.hasClass( "ui-state-focus" ), "focused after explicit focus" ); $( "#widget" ).testWidget( "disable" ); @@ -700,7 +700,7 @@ test( "._focusable()", function() { ok( !div.hasClass( "ui-state-focus" ), "can't focus while disabled" ); $( "#widget" ).testWidget( "enable" ); ok( !div.hasClass( "ui-state-focus" ), "enabling doesn't reset focus" ); - + div.trigger( "focusin" ); ok( div.hasClass( "ui-state-focus" ), "focused after explicit focus" ); $( "#widget" ).testWidget( "destroy" ); -- cgit v1.2.3 From 8b14b35dc72afce16b544b011a04d1e5ea1b7344 Mon Sep 17 00:00:00 2001 From: Jörn Zaefferer Date: Sun, 19 Jun 2011 14:59:18 +0200 Subject: Widget delegation: Fix impl and add basisc test --- tests/unit/widget/widget_core.js | 34 ++++++++++++++++++++++++++++++++++ ui/jquery.ui.widget.js | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index bb21b74ea..c73f7284c 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -666,6 +666,40 @@ test( "._bind() to descendent", function() { .trigger( "keydown" ); }); +test( "_bind() with delegate", function() { + expect( 8 ); + $.widget( "ui.testWidget", { + _create: function() { + var that = this; + this.element = { + bind: function( event, handler ) { + equal( event, "click.testWidget" ); + ok( $.isFunction(handler) ); + }, + delegate: function( selector, event, handler ) { + equal( selector, "a" ); + equal( event, "click.testWidget" ); + ok( $.isFunction(handler) ); + }, + trigger: $.noop + } + this._bind({ + "click": "handler", + "click a": "handler", + }); + this.element.delegate = function( selector, event, handler ) { + equal( selector, "form fieldset > input" ); + equal( event, "change.testWidget" ); + ok( $.isFunction(handler) ); + }; + this._bind({ + "change form fieldset > input": "handler" + }); + } + }); + $.ui.testWidget(); +}) + test( "._hoverable()", function() { $.widget( "ui.testWidget", { _create: function() { diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index cf138f774..0e5695d97 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -319,7 +319,7 @@ $.Widget.prototype = { return ( typeof handler === "string" ? instance[ handler ] : handler ) .apply( instance, arguments ); } - var match = key.match( /^(\w+)\s*(.*)$/ ); + var match = event.match( /^(\w+)\s*(.*)$/ ); var eventName = match[1] + "." + instance.widgetName, selector = match[2]; if (selector === '') { -- cgit v1.2.3 From 5297b7bc4250462213b05ad2763fe99d0f8dedec Mon Sep 17 00:00:00 2001 From: Jörn Zaefferer Date: Mon, 20 Jun 2011 22:31:28 +0200 Subject: Whitespace cleanup --- ui/jquery.ui.widget.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index 0e5695d97..d154185d5 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -319,14 +319,14 @@ $.Widget.prototype = { return ( typeof handler === "string" ? instance[ handler ] : handler ) .apply( instance, arguments ); } - var match = event.match( /^(\w+)\s*(.*)$/ ); - var eventName = match[1] + "." + instance.widgetName, + var match = event.match( /^(\w+)\s*(.*)$/ ), + eventName = match[1] + "." + instance.widgetName, selector = match[2]; - if (selector === '') { - element.bind( eventName, handlerProxy ); - } else { - element.delegate( selector, eventName, handlerProxy ); - } + if ( selector === '' ) { + element.bind( eventName, handlerProxy ); + } else { + element.delegate( selector, eventName, handlerProxy ); + } }); }, -- cgit v1.2.3 From 02aad7b0ae8c752eb24f99d7a6a06aeeb5d17367 Mon Sep 17 00:00:00 2001 From: Jörn Zaefferer Date: Thu, 28 Jul 2011 15:47:32 +0200 Subject: Widget delegation: Update menu to use _bind with delegation. Clean up test. --- tests/unit/widget/widget_core.js | 5 ++- ui/jquery.ui.menu.js | 77 +++++++++++++++++----------------------- 2 files changed, 34 insertions(+), 48 deletions(-) diff --git a/tests/unit/widget/widget_core.js b/tests/unit/widget/widget_core.js index c73f7284c..b08de27c7 100644 --- a/tests/unit/widget/widget_core.js +++ b/tests/unit/widget/widget_core.js @@ -670,7 +670,6 @@ test( "_bind() with delegate", function() { expect( 8 ); $.widget( "ui.testWidget", { _create: function() { - var that = this; this.element = { bind: function( event, handler ) { equal( event, "click.testWidget" ); @@ -682,7 +681,7 @@ test( "_bind() with delegate", function() { ok( $.isFunction(handler) ); }, trigger: $.noop - } + }; this._bind({ "click": "handler", "click a": "handler", @@ -698,7 +697,7 @@ test( "_bind() with delegate", function() { } }); $.ui.testWidget(); -}) +}); test( "._hoverable()", function() { $.widget( "ui.testWidget", { diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index c55ae75c9..7cfa61f86 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -37,53 +37,40 @@ $.widget( "ui.menu", { .attr({ id: this.menuId, role: "menu" - }) - .bind( "click.menu", function( event ) { - var item = $( event.target ).closest( ".ui-menu-item:has(a)" ); - if ( self.options.disabled ) { - return false; - } - if ( !item.length ) { - return; - } + }); + this.element.bind("click.menu", function( event ) { + if ( self.options.disabled ) { + event.preventDefault(); + } + }); + this._bind({ + "click .ui-menu-item:has(a)": function( event ) { + event.stopImmediatePropagation(); + var target = $( event.currentTarget ); // it's possible to click an item without hovering it (#7085) - if ( !self.active || ( self.active[ 0 ] !== item[ 0 ] ) ) { - self.focus( event, item ); - } - self.select( event ); - }) - .bind( "mouseover.menu", function( event ) { - if ( self.options.disabled ) { - return; - } - var target = $( event.target ).closest( ".ui-menu-item" ); - if ( target.length ) { - //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 - target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" ); - self.focus( event, target ); + if ( !this.active || ( this.active[ 0 ] !== target[ 0 ] ) ) { + this.focus( event, target ); } - }) - .bind( "mouseout.menu", function( event ) { - if ( self.options.disabled ) { - return; - } - var target = $( event.target ).closest( ".ui-menu-item" ); - if ( target.length ) { - self.blur( event ); - } - }) - .bind( "focus.menu", function( event ) { - if ( self.options.disabled ) { - return; - } - self.focus( event, $( event.target ).children( ".ui-menu-item:first" ) ); - }) - .bind( "blur.menu", function( event ) { - if ( self.options.disabled ) { - return; - } - self.collapseAll( event ); - }); + this.select( event ); + }, + "mouseover .ui-menu-item": function( event ) { + event.stopImmediatePropagation(); + var target = $( event.currentTarget ); + // 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 + target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" ); + this.focus( event, target ); + }, + "mouseout .ui-menu-item": function( event ) { + this.blur( event ); + }, + "focus": function( event ) { + this.focus( event, $( event.target ).children( ".ui-menu-item:first" ) ); + }, + "blur": function( event ) { + this.collapseAll( event ); + } + }); + this.refresh(); this.element.attr( "tabIndex", 0 ).bind( "keydown.menu", function( event ) { -- cgit v1.2.3 From 9e2efe95b2f130778a43a441e157c6ecf5197c1a Mon Sep 17 00:00:00 2001 From: Jörn Zaefferer Date: Thu, 28 Jul 2011 15:52:52 +0200 Subject: Widget delegation: Further simplify menu code --- ui/jquery.ui.menu.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 7cfa61f86..17f8db2f5 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -60,9 +60,7 @@ $.widget( "ui.menu", { target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" ); this.focus( event, target ); }, - "mouseout .ui-menu-item": function( event ) { - this.blur( event ); - }, + "mouseout .ui-menu-item": "blur", "focus": function( event ) { this.focus( event, $( event.target ).children( ".ui-menu-item:first" ) ); }, -- cgit v1.2.3 From 5b45d618dc208af58f968922fd799a7a8d8b1fac Mon Sep 17 00:00:00 2001 From: Jörn Zaefferer Date: Thu, 28 Jul 2011 15:53:55 +0200 Subject: Widget delegation: Further simplify menu code, blur handler also doesn't do anything --- ui/jquery.ui.menu.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index 17f8db2f5..b8affd168 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -64,9 +64,7 @@ $.widget( "ui.menu", { "focus": function( event ) { this.focus( event, $( event.target ).children( ".ui-menu-item:first" ) ); }, - "blur": function( event ) { - this.collapseAll( event ); - } + "blur": "collapseAll" }); this.refresh(); -- cgit v1.2.3 From 5e35a0c55b9dd7070cda7b5fb6fc1f031e04ae3e Mon Sep 17 00:00:00 2001 From: Jörn Zaefferer Date: Thu, 28 Jul 2011 15:55:56 +0200 Subject: Widget delegation: Put back the simple click event handler where it was. --- ui/jquery.ui.menu.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index b8affd168..c2890502c 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -37,12 +37,14 @@ $.widget( "ui.menu", { .attr({ id: this.menuId, role: "menu" + }) + // need to catch all clicks on disabled menu + // not possible through _bind + .bind("click.menu", function( event ) { + if ( self.options.disabled ) { + event.preventDefault(); + } }); - this.element.bind("click.menu", function( event ) { - if ( self.options.disabled ) { - event.preventDefault(); - } - }); this._bind({ "click .ui-menu-item:has(a)": function( event ) { event.stopImmediatePropagation(); -- cgit v1.2.3 From a57c43525786712207f8067df68045c2c33c1e04 Mon Sep 17 00:00:00 2001 From: Jörn Zaefferer Date: Thu, 28 Jul 2011 15:56:57 +0200 Subject: Whitespace --- ui/jquery.ui.menu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js index c2890502c..27e76d909 100644 --- a/ui/jquery.ui.menu.js +++ b/ui/jquery.ui.menu.js @@ -40,7 +40,7 @@ $.widget( "ui.menu", { }) // need to catch all clicks on disabled menu // not possible through _bind - .bind("click.menu", function( event ) { + .bind( "click.menu", function( event ) { if ( self.options.disabled ) { event.preventDefault(); } -- cgit v1.2.3 From 0ff3396e8853d1858db56e4ad7552f87c09e5504 Mon Sep 17 00:00:00 2001 From: Jörn Zaefferer Date: Thu, 28 Jul 2011 21:55:38 +0200 Subject: Widget delegation: Small if-simplify refactoring --- ui/jquery.ui.widget.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js index d154185d5..a66b8a54a 100644 --- a/ui/jquery.ui.widget.js +++ b/ui/jquery.ui.widget.js @@ -322,10 +322,10 @@ $.Widget.prototype = { var match = event.match( /^(\w+)\s*(.*)$/ ), eventName = match[1] + "." + instance.widgetName, selector = match[2]; - if ( selector === '' ) { - element.bind( eventName, handlerProxy ); - } else { + if ( selector ) { element.delegate( selector, eventName, handlerProxy ); + } else { + element.bind( eventName, handlerProxy ); } }); }, -- cgit v1.2.3