Skip to content

Commit ff39bed

Browse files
committed
Widget: Added _off() for removing event handlers. Fixes #7795 - Widget: _on and _off.
1 parent 00d4beb commit ff39bed

File tree

8 files changed

+108
-27
lines changed

8 files changed

+108
-27
lines changed

tests/unit/widget/widget_core.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,83 @@ test( "_on() to common element", function() {
767767
$( document ).trigger( "customevent" );
768768
});
769769

770+
test( "_off() - single event", function() {
771+
expect( 3 );
772+
773+
$.widget( "ui.testWidget", {} );
774+
var shouldTriggerWidget, shouldTriggerOther,
775+
element = $( "#widget" ),
776+
widget = element.testWidget().data( "testWidget" );
777+
widget._on( element, { foo: function() {
778+
ok( shouldTriggerWidget, "foo called from _on" );
779+
}});
780+
element.bind( "foo", function() {
781+
ok( shouldTriggerOther, "foo called from bind" );
782+
});
783+
shouldTriggerWidget = true;
784+
shouldTriggerOther = true;
785+
element.trigger( "foo" );
786+
shouldTriggerWidget = false;
787+
widget._off( element, "foo" );
788+
element.trigger( "foo" );
789+
});
790+
791+
test( "_off() - multiple events", function() {
792+
expect( 6 );
793+
794+
$.widget( "ui.testWidget", {} );
795+
var shouldTriggerWidget, shouldTriggerOther,
796+
element = $( "#widget" ),
797+
widget = element.testWidget().data( "testWidget" );
798+
widget._on( element, {
799+
foo: function() {
800+
ok( shouldTriggerWidget, "foo called from _on" );
801+
},
802+
bar: function() {
803+
ok( shouldTriggerWidget, "bar called from _on" );
804+
}
805+
});
806+
element.bind( "foo bar", function( event ) {
807+
ok( shouldTriggerOther, event.type + " called from bind" );
808+
});
809+
shouldTriggerWidget = true;
810+
shouldTriggerOther = true;
811+
element.trigger( "foo" );
812+
element.trigger( "bar" );
813+
shouldTriggerWidget = false;
814+
widget._off( element, "foo bar" );
815+
element.trigger( "foo" );
816+
element.trigger( "bar" );
817+
});
818+
819+
test( "_off() - all events", function() {
820+
expect( 6 );
821+
822+
$.widget( "ui.testWidget", {} );
823+
var shouldTriggerWidget, shouldTriggerOther,
824+
element = $( "#widget" ),
825+
widget = element.testWidget().data( "testWidget" );
826+
widget._on( element, {
827+
foo: function() {
828+
ok( shouldTriggerWidget, "foo called from _on" );
829+
},
830+
bar: function() {
831+
ok( shouldTriggerWidget, "bar called from _on" );
832+
}
833+
});
834+
element.bind( "foo bar", function( event ) {
835+
ok( shouldTriggerOther, event.type + " called from bind" );
836+
});
837+
shouldTriggerWidget = true;
838+
shouldTriggerOther = true;
839+
element.trigger( "foo" );
840+
element.trigger( "bar" );
841+
shouldTriggerWidget = false;
842+
widget._off( element );
843+
element.trigger( "foo" );
844+
element.trigger( "bar" );
845+
});
846+
770847
test( "._hoverable()", function() {
771848
$.widget( "ui.testWidget", {
772849
_create: function() {

ui/jquery.ui.accordion.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,7 @@ $.widget( "ui.accordion", {
219219

220220
if ( key === "event" ) {
221221
if ( this.options.event ) {
222-
this.headers.unbind(
223-
this.options.event.split( " " ).join( ".accordion " ) + ".accordion" );
222+
this._off( this.headers, this.options.event );
224223
}
225224
this._setupEvents( value );
226225
}

ui/jquery.ui.button.js

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ $.widget( "ui.button", {
5454
},
5555
_create: function() {
5656
this.element.closest( "form" )
57-
.unbind( "reset.button" )
58-
.bind( "reset.button", formResetHandler );
57+
.unbind( "reset" + this.eventNamespace )
58+
.bind( "reset" + this.eventNamespace, formResetHandler );
5959

6060
if ( typeof this.options.disabled !== "boolean" ) {
6161
this.options.disabled = !!this.element.prop( "disabled" );
@@ -79,7 +79,7 @@ $.widget( "ui.button", {
7979
this.buttonElement
8080
.addClass( baseClasses )
8181
.attr( "role", "button" )
82-
.bind( "mouseenter.button", function() {
82+
.bind( "mouseenter" + this.eventNamespace, function() {
8383
if ( options.disabled ) {
8484
return;
8585
}
@@ -88,30 +88,30 @@ $.widget( "ui.button", {
8888
$( this ).addClass( "ui-state-active" );
8989
}
9090
})
91-
.bind( "mouseleave.button", function() {
91+
.bind( "mouseleave" + this.eventNamespace, function() {
9292
if ( options.disabled ) {
9393
return;
9494
}
9595
$( this ).removeClass( hoverClass );
9696
})
97-
.bind( "click.button", function( event ) {
97+
.bind( "click" + this.eventNamespace, function( event ) {
9898
if ( options.disabled ) {
9999
event.preventDefault();
100100
event.stopImmediatePropagation();
101101
}
102102
});
103103

104104
this.element
105-
.bind( "focus.button", function() {
105+
.bind( "focus" + this.eventNamespace, function() {
106106
// no need to check disabled, focus won't be triggered anyway
107107
that.buttonElement.addClass( focusClass );
108108
})
109-
.bind( "blur.button", function() {
109+
.bind( "blur" + this.eventNamespace, function() {
110110
that.buttonElement.removeClass( focusClass );
111111
});
112112

113113
if ( toggleButton ) {
114-
this.element.bind( "change.button", function() {
114+
this.element.bind( "change" + this.eventNamespace, function() {
115115
if ( clickDragged ) {
116116
return;
117117
}
@@ -121,15 +121,15 @@ $.widget( "ui.button", {
121121
// prevents issue where button state changes but checkbox/radio checked state
122122
// does not in Firefox (see ticket #6970)
123123
this.buttonElement
124-
.bind( "mousedown.button", function( event ) {
124+
.bind( "mousedown" + this.eventNamespace, function( event ) {
125125
if ( options.disabled ) {
126126
return;
127127
}
128128
clickDragged = false;
129129
startXPos = event.pageX;
130130
startYPos = event.pageY;
131131
})
132-
.bind( "mouseup.button", function( event ) {
132+
.bind( "mouseup" + this.eventNamespace, function( event ) {
133133
if ( options.disabled ) {
134134
return;
135135
}
@@ -140,15 +140,15 @@ $.widget( "ui.button", {
140140
}
141141

142142
if ( this.type === "checkbox" ) {
143-
this.buttonElement.bind( "click.button", function() {
143+
this.buttonElement.bind( "click" + this.eventNamespace, function() {
144144
if ( options.disabled || clickDragged ) {
145145
return false;
146146
}
147147
$( this ).toggleClass( "ui-state-active" );
148148
that.buttonElement.attr( "aria-pressed", that.element[0].checked );
149149
});
150150
} else if ( this.type === "radio" ) {
151-
this.buttonElement.bind( "click.button", function() {
151+
this.buttonElement.bind( "click" + this.eventNamespace, function() {
152152
if ( options.disabled || clickDragged ) {
153153
return false;
154154
}
@@ -166,7 +166,7 @@ $.widget( "ui.button", {
166166
});
167167
} else {
168168
this.buttonElement
169-
.bind( "mousedown.button", function() {
169+
.bind( "mousedown" + this.eventNamespace, function() {
170170
if ( options.disabled ) {
171171
return false;
172172
}
@@ -176,21 +176,21 @@ $.widget( "ui.button", {
176176
lastActive = null;
177177
});
178178
})
179-
.bind( "mouseup.button", function() {
179+
.bind( "mouseup" + this.eventNamespace, function() {
180180
if ( options.disabled ) {
181181
return false;
182182
}
183183
$( this ).removeClass( "ui-state-active" );
184184
})
185-
.bind( "keydown.button", function(event) {
185+
.bind( "keydown" + this.eventNamespace, function(event) {
186186
if ( options.disabled ) {
187187
return false;
188188
}
189189
if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
190190
$( this ).addClass( "ui-state-active" );
191191
}
192192
})
193-
.bind( "keyup.button", function() {
193+
.bind( "keyup" + this.eventNamespace, function() {
194194
$( this ).removeClass( "ui-state-active" );
195195
});
196196

ui/jquery.ui.dialog.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ $.widget("ui.dialog", {
224224
if ( this.overlay ) {
225225
this.overlay.destroy();
226226
}
227-
this.uiDialog.unbind( "keypress.ui-dialog" );
227+
this._off( this.uiDialog, "keypress" );
228228

229229
if ( this.options.hide ) {
230230
this.uiDialog.hide( this.options.hide, function() {
@@ -310,7 +310,7 @@ $.widget("ui.dialog", {
310310

311311
// prevent tabbing out of modal dialogs
312312
if ( options.modal ) {
313-
uiDialog.bind( "keydown.ui-dialog", function( event ) {
313+
this._on( uiDialog, { keydown: function( event ) {
314314
if ( event.keyCode !== $.ui.keyCode.TAB ) {
315315
return;
316316
}
@@ -326,7 +326,7 @@ $.widget("ui.dialog", {
326326
last.focus( 1 );
327327
return false;
328328
}
329-
});
329+
}});
330330
}
331331

332332
// set focus to the first tabbable element in the content area or the first button

ui/jquery.ui.menu.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ $.widget( "ui.menu", {
4444
})
4545
// need to catch all clicks on disabled menu
4646
// not possible through _on
47-
.bind( "click.menu", $.proxy(function( event ) {
47+
.bind( "click" + this.eventNamespace, $.proxy(function( event ) {
4848
if ( this.options.disabled ) {
4949
event.preventDefault();
5050
}
@@ -168,7 +168,7 @@ $.widget( "ui.menu", {
168168
this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
169169

170170
// unbind currentEventTarget click event handler
171-
$( currentEventTarget ).unbind( "click.menu" );
171+
this._off( $( currentEventTarget ), "click" );
172172
},
173173

174174
_keydown: function( event ) {

ui/jquery.ui.tabs.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ $.widget( "ui.tabs", {
5858
.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
5959
.toggleClass( "ui-tabs-collapsible", options.collapsible )
6060
// Prevent users from focusing disabled tabs via click
61-
.delegate( ".ui-tabs-nav > li", "mousedown.tabs", function( event ) {
61+
.delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
6262
if ( $( this ).is( ".ui-state-disabled" ) ) {
6363
event.preventDefault();
6464
}
@@ -69,7 +69,7 @@ $.widget( "ui.tabs", {
6969
// We don't have to worry about focusing the previously focused
7070
// element since clicking on a non-focusable element should focus
7171
// the body anyway.
72-
.delegate( ".ui-tabs-anchor", "focus.tabs", function() {
72+
.delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
7373
if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
7474
this.blur();
7575
}
@@ -480,7 +480,7 @@ $.widget( "ui.tabs", {
480480
});
481481
}
482482

483-
this.anchors.add( this.tabs ).add( this.panels ).unbind( ".tabs" );
483+
this._off( this.anchors.add( this.tabs ).add( this.panels ) );
484484
this._on( this.anchors, events );
485485
this._on( this.tabs, { keydown: "_tabKeydown" } );
486486
this._on( this.panels, { keydown: "_panelKeydown" } );

ui/jquery.ui.tooltip.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ $.widget( "ui.tooltip", {
233233
});
234234

235235
target.removeData( "tooltip-open" );
236-
target.unbind( "mouseleave.tooltip focusout.tooltip keyup.tooltip" );
236+
this._off( target, "mouseleave focusout keyup" );
237237

238238
this.closing = true;
239239
this._trigger( "close", event, { tooltip: tooltip } );

ui/jquery.ui.widget.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,11 @@ $.Widget.prototype = {
387387
});
388388
},
389389

390+
_off: function( element, eventName ) {
391+
eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
392+
element.unbind( eventName ).undelegate( eventName );
393+
},
394+
390395
_delay: function( handler, delay ) {
391396
function handlerProxy() {
392397
return ( typeof handler === "string" ? instance[ handler ] : handler )

0 commit comments

Comments
 (0)