3 module( "widget factory", {
6 delete $.ui.testWidget;
7 delete $.fn.testWidget;
12 TestHelpers.testJshint( "widget" );
14 test( "widget creation", function() {
19 equal( method, "_create", "create function is copied over" );
21 creationTest: function() {
22 equal( method, "creationTest", "random function is copied over" );
26 $.widget( "ui.testWidget", myPrototype );
27 ok( $.isFunction( $.ui.testWidget ), "constructor was created" );
28 equal( typeof $.ui.testWidget.prototype, "object", "prototype was created" );
30 $.ui.testWidget.prototype._create();
31 method = "creationTest";
32 $.ui.testWidget.prototype.creationTest();
33 equal( $.ui.testWidget.prototype.option, $.Widget.prototype.option,
34 "option method copied over from base widget" );
37 test( "element normalization", function() {
40 $.widget( "ui.testWidget", {} );
42 $.ui.testWidget.prototype._create = function() {
43 // workaround for core ticket #8381
44 this.element.appendTo( "#qunit-fixture" );
45 ok( this.element.is( "div" ), "generated div" );
46 deepEqual( this.element.data( "ui-testWidget" ), this, "instance stored in .data()" );
50 $.ui.testWidget.prototype.defaultElement = "<span data-test='pass'></span>";
51 $.ui.testWidget.prototype._create = function() {
52 ok( this.element.is( "span[data-test=pass]" ), "generated span with properties" );
53 deepEqual( this.element.data( "ui-testWidget" ), this, "instace stored in .data()" );
57 elem = $( "<input>" );
58 $.ui.testWidget.prototype._create = function() {
59 deepEqual( this.element[ 0 ], elem[ 0 ], "from element" );
60 deepEqual( elem.data( "ui-testWidget" ), this, "instace stored in .data()" );
62 $.ui.testWidget( {}, elem[ 0 ] );
65 $.ui.testWidget.prototype._create = function() {
66 deepEqual( this.element[ 0 ], elem[ 0 ], "from jQuery object" );
67 deepEqual( elem.data( "ui-testWidget" ), this, "instace stored in .data()" );
69 $.ui.testWidget( {}, elem );
71 elem = $( "<div id='element-normalization-selector'></div>" )
72 .appendTo( "#qunit-fixture" );
73 $.ui.testWidget.prototype._create = function() {
74 deepEqual( this.element[ 0 ], elem[ 0 ], "from selector" );
75 deepEqual( elem.data( "ui-testWidget" ), this, "instace stored in .data()" );
77 $.ui.testWidget( {}, "#element-normalization-selector" );
79 $.ui.testWidget.prototype.defaultElement = null;
80 $.ui.testWidget.prototype._create = function() {
81 // using strictEqual throws an error (Maximum call stack size exceeded)
82 ok( this.element[ 0 ] === this, "instance as element" );
87 test( "custom selector expression", function() {
89 var elem = $( "<div>" ).appendTo( "#qunit-fixture" );
90 $.widget( "ui.testWidget", {} );
92 deepEqual( $( ":ui-testwidget" )[0], elem[0] );
93 elem.testWidget( "destroy" );
96 test( "jQuery usage", function() {
99 var elem, instance, ret,
100 shouldCreate = false;
102 $.widget( "ui.testWidget", {
104 _create: function() {
105 ok( shouldCreate, "create called on instantiation" );
107 methodWithParams: function( param1, param2 ) {
108 ok( true, "method called via .pluginName(methodName)" );
109 equal( param1, "value1",
110 "parameter passed via .pluginName(methodName, param)" );
111 equal( param2, "value2",
112 "multiple parameters passed via .pluginName(methodName, param, param)" );
116 getterSetterMethod: function( val ) {
118 this.getterSetterVal = val;
120 return this.getterSetterVal;
123 jQueryObject: function() {
130 .bind( "testwidgetcreate", function() {
131 ok( shouldCreate, "create event triggered on instantiation" );
134 shouldCreate = false;
136 instance = elem.data( "ui-testWidget" );
137 equal( typeof instance, "object", "instance stored in .data(pluginName)" );
138 equal( instance.element[0], elem[0], "element stored on widget" );
139 ret = elem.testWidget( "methodWithParams", "value1", "value2" );
140 equal( ret, elem, "jQuery object returned from method call" );
142 ret = elem.testWidget( "getterSetterMethod" );
143 equal( ret, 5, "getter/setter can act as getter" );
144 ret = elem.testWidget( "getterSetterMethod", 30 );
145 equal( ret, elem, "getter/setter method can be chainable" );
146 equal( instance.getterSetterVal, 30, "getter/setter can act as setter" );
147 ret = elem.testWidget( "jQueryObject" );
148 equal( ret[ 0 ], document.body, "returned jQuery object" );
149 equal( ret.end(), elem, "stack preserved" );
151 elem.testWidget( "destroy" );
152 equal( elem.data( "ui-testWidget" ), null );
155 test( "direct usage", function() {
158 var elem, instance, ret,
159 shouldCreate = false;
161 $.widget( "ui.testWidget", {
163 _create: function() {
164 ok( shouldCreate, "create called on instantiation" );
166 methodWithParams: function( param1, param2 ) {
167 ok( true, "method called dirctly" );
168 equal( param1, "value1", "parameter passed via direct call" );
169 equal( param2, "value2", "multiple parameters passed via direct call" );
173 getterSetterMethod: function( val ) {
175 this.getterSetterVal = val;
177 return this.getterSetterVal;
182 elem = $( "<div>" )[ 0 ];
185 instance = new $.ui.testWidget( {}, elem );
186 shouldCreate = false;
188 equal( $( elem ).data( "ui-testWidget" ), instance,
189 "instance stored in .data(pluginName)" );
190 equal( instance.element[ 0 ], elem, "element stored on widget" );
192 ret = instance.methodWithParams( "value1", "value2" );
193 equal( ret, instance, "plugin returned from method call" );
195 ret = instance.getterSetterMethod();
196 equal( ret, 5, "getter/setter can act as getter" );
197 instance.getterSetterMethod( 30 );
198 equal( instance.getterSetterVal, 30, "getter/setter can act as setter" );
201 test( "error handling", function() {
204 $.widget( "ui.testWidget", {
205 _privateMethod: function () {}
207 $.error = function( msg ) {
208 equal( msg, "cannot call methods on testWidget prior to initialization; " +
209 "attempted to call method 'missing'", "method call before init" );
211 $( "<div>" ).testWidget( "missing" );
212 $.error = function( msg ) {
213 equal( msg, "no such method 'missing' for testWidget widget instance",
214 "invalid method call on widget instance" );
216 $( "<div>" ).testWidget().testWidget( "missing" );
217 $.error = function ( msg ) {
218 equal( msg, "no such method '_privateMethod' for testWidget widget instance",
219 "invalid method call on widget instance" );
221 $( "<div>" ).testWidget().testWidget( "_privateMethod" );
225 test( "merge multiple option arguments", function() {
227 $.widget( "ui.testWidget", {
228 _create: function() {
229 deepEqual( this.options, {
242 $( "<div>" ).testWidget({
262 test( "._getCreateOptions()", function() {
264 $.widget( "ui.testWidget", {
270 _getCreateOptions: function() {
272 option1: "override1",
276 _create: function() {
277 deepEqual( this.options, {
280 option1: "override1",
286 $( "<div>" ).testWidget({ option2: "value2" });
289 test( "._getCreateEventData()", function() {
291 var data = { foo: "bar" };
292 $.widget( "ui.testWidget", {
293 _getCreateEventData: function() {
297 $( "<div>" ).testWidget({
298 create: function( event, ui ) {
299 strictEqual( ui, data, "event data" );
304 test( "re-init", function() {
306 var div = $( "<div>" ),
309 $.widget( "ui.testWidget", {
310 _create: function() {
311 actions.push( "create" );
314 actions.push( "init" );
316 _setOption: function( key ) {
317 actions.push( "option" + key );
322 div.testWidget({ foo: "bar" });
323 deepEqual( actions, [ "create", "init" ], "correct methods called on init" );
327 deepEqual( actions, [ "init" ], "correct methods call on re-init" );
330 div.testWidget({ foo: "bar" });
331 deepEqual( actions, [ "optionfoo", "init" ], "correct methods called on re-init with options" );
334 test( "inheritance", function() {
336 // #5830 - Widget: Using inheritance overwrites the base classes options
337 $.widget( "ui.testWidgetBase", {
347 $.widget( "ui.testWidgetExtension", $.ui.testWidgetBase, {
352 arr: [ "alpha", "beta" ]
356 equal( $.ui.testWidgetBase.prototype.widgetEventPrefix, "testWidgetBase",
357 "base class event prefix" );
358 deepEqual( $.ui.testWidgetBase.prototype.options.obj, {
361 }, "base class option object not overridden");
362 deepEqual( $.ui.testWidgetBase.prototype.options.arr, [ "testing" ],
363 "base class option array not overridden");
365 equal( $.ui.testWidgetExtension.prototype.widgetEventPrefix, "testWidgetExtension",
366 "extension class event prefix" );
367 deepEqual( $.ui.testWidgetExtension.prototype.options.obj, {
370 }, "extension class option object extends base");
371 deepEqual( $.ui.testWidgetExtension.prototype.options.arr, [ "alpha", "beta" ],
372 "extension class option array overwrites base");
374 delete $.ui.testWidgetBase;
375 delete $.ui.testWidgetExtension;
378 test( "._super()", function() {
381 $.widget( "ui.testWidget", {
382 method: function( a, b ) {
383 deepEqual( this, instance, "this is correct in testWidget" );
384 deepEqual( a, 5, "parameter passed to testWidget" );
385 deepEqual( b, 20, "second parameter passed to testWidget" );
390 $.widget( "ui.testWidget2", $.ui.testWidget, {
391 method: function( a, b ) {
392 deepEqual( this, instance, "this is correct in testWidget2" );
393 deepEqual( a, 5, "parameter passed to testWidget2" );
394 deepEqual( b, 10, "parameter passed to testWidget2" );
395 return this._super( a, b*2 );
399 $.widget( "ui.testWidget3", $.ui.testWidget2, {
400 method: function( a ) {
401 deepEqual( this, instance, "this is correct in testWidget3" );
402 deepEqual( a, 5, "parameter passed to testWidget3" );
403 var ret = this._super( a, a*2 );
404 deepEqual( ret, 25, "super returned value" );
408 instance = $( "<div>" ).testWidget3().data( "ui-testWidget3" );
409 instance.method( 5 );
410 delete $.ui.testWidget3;
411 delete $.ui.testWidget2;
414 test( "._superApply()", function() {
417 $.widget( "ui.testWidget", {
418 method: function( a, b ) {
419 deepEqual( this, instance, "this is correct in testWidget" );
420 deepEqual( a, 5, "parameter passed to testWidget" );
421 deepEqual( b, 10, "second parameter passed to testWidget" );
426 $.widget( "ui.testWidget2", $.ui.testWidget, {
427 method: function( a, b ) {
428 deepEqual( this, instance, "this is correct in testWidget2" );
429 deepEqual( a, 5, "parameter passed to testWidget2" );
430 deepEqual( b, 10, "second parameter passed to testWidget2" );
431 return this._superApply( arguments );
435 $.widget( "ui.testWidget3", $.ui.testWidget2, {
436 method: function( a, b ) {
437 deepEqual( this, instance, "this is correct in testWidget3" );
438 deepEqual( a, 5, "parameter passed to testWidget3" );
439 deepEqual( b, 10, "second parameter passed to testWidget3" );
440 var ret = this._superApply( arguments );
441 deepEqual( ret, 15, "super returned value" );
445 instance = $( "<div>" ).testWidget3().data( "ui-testWidget3" );
446 instance.method( 5, 10 );
447 delete $.ui.testWidget3;
448 delete $.ui.testWidget2;
451 test( ".option() - getter", function() {
453 $.widget( "ui.testWidget", {
454 _create: function() {}
458 div = $( "<div>" ).testWidget({
461 qux: [ "quux", "quuux" ]
464 deepEqual( div.testWidget( "option", "x" ), null, "non-existent option" );
465 deepEqual( div.testWidget( "option", "foo"), "bar", "single option - string" );
466 deepEqual( div.testWidget( "option", "baz"), 5, "single option - number" );
467 deepEqual( div.testWidget( "option", "qux"), [ "quux", "quuux" ],
468 "single option - array" );
470 options = div.testWidget( "option" );
471 deepEqual( options, {
476 qux: [ "quux", "quuux" ]
477 }, "full options hash returned" );
478 options.foo = "notbar";
479 deepEqual( div.testWidget( "option", "foo"), "bar",
480 "modifying returned options hash does not modify plugin instance" );
483 test( ".option() - deep option getter", function() {
485 $.widget( "ui.testWidget", {} );
486 var div = $( "<div>" ).testWidget({
494 equal( div.testWidget( "option", "foo.bar" ), "baz", "one level deep - string" );
495 deepEqual( div.testWidget( "option", "foo.qux" ), { quux: "xyzzy" },
496 "one level deep - object" );
497 equal( div.testWidget( "option", "foo.qux.quux" ), "xyzzy", "two levels deep - string" );
498 equal( div.testWidget( "option", "x.y" ), null, "top level non-existent" );
499 equal( div.testWidget( "option", "foo.x.y" ), null, "one level deep - non-existent" );
502 test( ".option() - delegate to ._setOptions()", function() {
506 $.widget( "ui.testWidget", {
507 _create: function() {},
508 _setOptions: function( options ) {
509 calls.push( options );
512 div = $( "<div>" ).testWidget();
515 div.testWidget( "option", "foo", "bar" );
516 deepEqual( calls, [{ foo: "bar" }], "_setOptions called for single option" );
519 div.testWidget( "option", {
523 deepEqual( calls, [{ bar: "qux", quux: "quuux" }],
524 "_setOptions called with multiple options" );
527 test( ".option() - delegate to ._setOption()", function() {
531 $.widget( "ui.testWidget", {
532 _create: function() {},
533 _setOption: function( key, val ) {
540 div = $( "<div>" ).testWidget();
543 div.testWidget( "option", "foo", "bar" );
544 deepEqual( calls, [{ key: "foo", val: "bar" }],
545 "_setOption called for single option" );
548 div.testWidget( "option", {
553 { key: "bar", val: "qux" },
554 { key: "quux", val: "quuux" }
555 ], "_setOption called with multiple options" );
558 test( ".option() - deep option setter", function() {
560 $.widget( "ui.testWidget", {} );
561 var div = $( "<div>" ).testWidget();
562 function deepOption( from, to, msg ) {
563 div.data( "ui-testWidget" ).options.foo = from;
564 $.ui.testWidget.prototype._setOption = function( key, value ) {
565 deepEqual( key, "foo", msg + ": key" );
566 deepEqual( value, to, msg + ": value" );
570 deepOption( { bar: "baz" }, { bar: "qux" }, "one deep" );
571 div.testWidget( "option", "foo.bar", "qux" );
573 deepOption( null, { bar: "baz" }, "null" );
574 div.testWidget( "option", "foo.bar", "baz" );
577 { bar: "baz", qux: { quux: "quuux" } },
578 { bar: "baz", qux: { quux: "quuux", newOpt: "newVal" } },
580 div.testWidget( "option", "foo.qux.newOpt", "newVal" );
583 test( ".enable()", function() {
585 $.widget( "ui.testWidget", {
586 _create: function() {},
587 _setOption: function( key, val ) {
588 deepEqual( key, "disabled", "_setOption called with disabled option" );
589 deepEqual( val, false, "disabled set to false" );
592 $( "<div>" ).testWidget().testWidget( "enable" );
595 test( ".disable()", function() {
597 $.widget( "ui.testWidget", {
598 _create: function() {},
599 _setOption: function( key, val ) {
600 deepEqual( key, "disabled", "_setOption called with disabled option" );
601 deepEqual( val, true, "disabled set to true" );
604 $( "<div>" ).testWidget().testWidget( "disable" );
607 test( ".widget() - base", function() {
609 $.widget( "ui.testWidget", {
610 _create: function() {}
612 var div = $( "<div>" ).testWidget();
613 deepEqual( div[0], div.testWidget( "widget" )[0]);
616 test( ".widget() - overriden", function() {
618 var wrapper = $( "<div>" );
619 $.widget( "ui.testWidget", {
620 _create: function() {},
625 deepEqual( wrapper[0], $( "<div>" ).testWidget().testWidget( "widget" )[0] );
628 test( "._on() to element (default)", function() {
631 $.widget( "ui.testWidget", {
632 _create: function() {
639 keyup: function( event ) {
641 equal( that.element[0], event.currentTarget );
642 equal( "keyup", event.type );
644 keydown: function( event ) {
646 equal( that.element[0], event.currentTarget );
647 equal( "keydown", event.type );
650 widget = $( "<div></div>" )
653 .trigger( "keydown" );
655 .testWidget( "disable" )
657 .trigger( "keydown" );
659 .testWidget( "enable" )
661 .trigger( "keydown" );
663 .testWidget( "destroy" )
665 .trigger( "keydown" );
668 test( "._on() to element with suppressDisabledCheck", function() {
671 $.widget( "ui.testWidget", {
672 _create: function() {
679 keyup: function( event ) {
681 equal( that.element[0], event.currentTarget );
682 equal( "keyup", event.type );
684 keydown: function( event ) {
686 equal( that.element[0], event.currentTarget );
687 equal( "keydown", event.type );
690 widget = $( "<div></div>" )
693 .trigger( "keydown" );
695 .testWidget( "disable" )
697 .trigger( "keydown" );
699 .testWidget( "enable" )
701 .trigger( "keydown" );
703 .testWidget( "destroy" )
705 .trigger( "keydown" );
708 test( "._on() to descendent", function() {
710 var that, widget, descendant;
711 $.widget( "ui.testWidget", {
712 _create: function() {
714 this._on( this.element.find( "strong" ), {
719 keyup: function( event ) {
721 equal( that.element.find( "strong" )[0], event.currentTarget );
722 equal( "keyup", event.type );
724 keydown: function(event) {
726 equal( that.element.find( "strong" )[0], event.currentTarget );
727 equal( "keydown", event.type );
730 // trigger events on both widget and descendent to ensure that only descendent receives them
731 widget = $( "<div><p><strong>hello</strong> world</p></div>" )
734 .trigger( "keydown" );
735 descendant = widget.find( "strong" )
737 .trigger( "keydown" );
739 .testWidget( "disable" )
741 .trigger( "keydown" );
744 .trigger( "keydown" );
746 .testWidget( "enable" )
748 .trigger( "keydown" );
751 .trigger( "keydown" );
753 .addClass( "ui-state-disabled" )
755 .trigger( "keydown" );
757 .testWidget( "destroy" )
759 .trigger( "keydown" );
762 .trigger( "keydown" );
765 test( "_on() with delegate", function() {
767 $.widget( "ui.testWidget", {
768 _create: function() {
769 var uuid = this.uuid;
771 bind: function( event, handler ) {
772 equal( event, "click.testWidget" + uuid );
773 ok( $.isFunction(handler) );
777 this.widget = function() {
779 delegate: function( selector, event, handler ) {
780 equal( selector, "a" );
781 equal( event, "click.testWidget" + uuid );
782 ok( $.isFunction(handler) );
790 this.widget = function() {
792 delegate: function( selector, event, handler ) {
793 equal( selector, "form fieldset > input" );
794 equal( event, "change.testWidget" + uuid );
795 ok( $.isFunction(handler) );
800 "change form fieldset > input": "handler"
807 test( "_on() with delegate to descendent", function() {
809 $.widget( "ui.testWidget", {
810 _create: function() {
811 this.target = $( "<p><strong>hello</strong> world</p>" );
812 this.child = this.target.children();
813 this._on( this.target, {
814 "keyup": "handlerDirect",
815 "keyup strong": "handlerDelegated"
817 this.child.trigger( "keyup" );
819 handlerDirect: function( event ) {
820 deepEqual( event.currentTarget, this.target[ 0 ] );
821 deepEqual( event.target, this.child[ 0 ] );
823 handlerDelegated: function( event ) {
824 deepEqual( event.currentTarget, this.child[ 0 ] );
825 deepEqual( event.target, this.child[ 0 ] );
831 test( "_on() to common element", function() {
833 $.widget( "ui.testWidget", {
834 _create: function() {
835 this._on( this.document, {
836 "customevent": "_handler"
839 _handler: function() {
840 ok( true, "handler triggered" );
843 var widget = $( "#widget" ).testWidget().data( "ui-testWidget" );
844 $( "#widget-wrapper" ).testWidget();
846 $( document ).trigger( "customevent" );
849 test( "_off() - single event", function() {
852 $.widget( "ui.testWidget", {} );
853 var shouldTriggerWidget, shouldTriggerOther,
854 element = $( "#widget" ),
855 widget = element.testWidget().data( "ui-testWidget" );
856 widget._on( element, { foo: function() {
857 ok( shouldTriggerWidget, "foo called from _on" );
859 element.bind( "foo", function() {
860 ok( shouldTriggerOther, "foo called from bind" );
862 shouldTriggerWidget = true;
863 shouldTriggerOther = true;
864 element.trigger( "foo" );
865 shouldTriggerWidget = false;
866 widget._off( element, "foo" );
867 element.trigger( "foo" );
870 test( "_off() - multiple events", function() {
873 $.widget( "ui.testWidget", {} );
874 var shouldTriggerWidget, shouldTriggerOther,
875 element = $( "#widget" ),
876 widget = element.testWidget().data( "ui-testWidget" );
877 widget._on( element, {
879 ok( shouldTriggerWidget, "foo called from _on" );
882 ok( shouldTriggerWidget, "bar called from _on" );
885 element.bind( "foo bar", function( event ) {
886 ok( shouldTriggerOther, event.type + " called from bind" );
888 shouldTriggerWidget = true;
889 shouldTriggerOther = true;
890 element.trigger( "foo" );
891 element.trigger( "bar" );
892 shouldTriggerWidget = false;
893 widget._off( element, "foo bar" );
894 element.trigger( "foo" );
895 element.trigger( "bar" );
898 test( "_off() - all events", function() {
901 $.widget( "ui.testWidget", {} );
902 var shouldTriggerWidget, shouldTriggerOther,
903 element = $( "#widget" ),
904 widget = element.testWidget().data( "ui-testWidget" );
905 widget._on( element, {
907 ok( shouldTriggerWidget, "foo called from _on" );
910 ok( shouldTriggerWidget, "bar called from _on" );
913 element.bind( "foo bar", function( event ) {
914 ok( shouldTriggerOther, event.type + " called from bind" );
916 shouldTriggerWidget = true;
917 shouldTriggerOther = true;
918 element.trigger( "foo" );
919 element.trigger( "bar" );
920 shouldTriggerWidget = false;
921 widget._off( element );
922 element.trigger( "foo" );
923 element.trigger( "bar" );
926 test( "._hoverable()", function() {
928 $.widget( "ui.testWidget", {
929 _create: function() {
930 this._hoverable( this.element.children() );
934 var div = $( "#widget" ).testWidget().children();
935 ok( !div.hasClass( "ui-state-hover" ), "not hovered on init" );
936 div.trigger( "mouseenter" );
937 ok( div.hasClass( "ui-state-hover" ), "hovered after mouseenter" );
938 div.trigger( "mouseleave" );
939 ok( !div.hasClass( "ui-state-hover" ), "not hovered after mouseleave" );
941 div.trigger( "mouseenter" );
942 ok( div.hasClass( "ui-state-hover" ), "hovered after mouseenter" );
943 $( "#widget" ).testWidget( "disable" );
944 ok( !div.hasClass( "ui-state-hover" ), "not hovered while disabled" );
945 div.trigger( "mouseenter" );
946 ok( !div.hasClass( "ui-state-hover" ), "can't hover while disabled" );
947 $( "#widget" ).testWidget( "enable" );
948 ok( !div.hasClass( "ui-state-hover" ), "enabling doesn't reset hover" );
950 div.trigger( "mouseenter" );
951 ok( div.hasClass( "ui-state-hover" ), "hovered after mouseenter" );
952 $( "#widget" ).testWidget( "destroy" );
953 ok( !div.hasClass( "ui-state-hover" ), "not hovered after destroy" );
954 div.trigger( "mouseenter" );
955 ok( !div.hasClass( "ui-state-hover" ), "event handler removed on destroy" );
958 test( "._focusable()", function() {
960 $.widget( "ui.testWidget", {
961 _create: function() {
962 this._focusable( this.element.children() );
966 var div = $( "#widget" ).testWidget().children();
967 ok( !div.hasClass( "ui-state-focus" ), "not focused on init" );
968 div.trigger( "focusin" );
969 ok( div.hasClass( "ui-state-focus" ), "focused after explicit focus" );
970 div.trigger( "focusout" );
971 ok( !div.hasClass( "ui-state-focus" ), "not focused after blur" );
973 div.trigger( "focusin" );
974 ok( div.hasClass( "ui-state-focus" ), "focused after explicit focus" );
975 $( "#widget" ).testWidget( "disable" );
976 ok( !div.hasClass( "ui-state-focus" ), "not focused while disabled" );
977 div.trigger( "focusin" );
978 ok( !div.hasClass( "ui-state-focus" ), "can't focus while disabled" );
979 $( "#widget" ).testWidget( "enable" );
980 ok( !div.hasClass( "ui-state-focus" ), "enabling doesn't reset focus" );
982 div.trigger( "focusin" );
983 ok( div.hasClass( "ui-state-focus" ), "focused after explicit focus" );
984 $( "#widget" ).testWidget( "destroy" );
985 ok( !div.hasClass( "ui-state-focus" ), "not focused after destroy" );
986 div.trigger( "focusin" );
987 ok( !div.hasClass( "ui-state-focus" ), "event handler removed on destroy" );
990 test( "._trigger() - no event, no ui", function() {
994 $.widget( "ui.testWidget", {
995 _create: function() {}
998 $( "#widget" ).testWidget({
999 foo: function( event, ui ) {
1000 deepEqual( event.type, "testwidgetfoo", "correct event type in callback" );
1001 deepEqual( ui, {}, "empty ui hash passed" );
1002 handlers.push( "callback" );
1005 $( document ).add( "#widget-wrapper" ).add( "#widget" )
1006 .bind( "testwidgetfoo", function( event, ui ) {
1007 deepEqual( ui, {}, "empty ui hash passed" );
1008 handlers.push( this );
1010 deepEqual( $( "#widget" ).data( "ui-testWidget" )._trigger( "foo" ), true,
1011 "_trigger returns true when event is not cancelled" );
1012 deepEqual( handlers, [
1013 $( "#widget" )[ 0 ],
1014 $( "#widget-wrapper" )[ 0 ],
1017 ], "event bubbles and then invokes callback" );
1019 $( document ).unbind( "testwidgetfoo" );
1022 test( "._trigger() - cancelled event", function() {
1025 $.widget( "ui.testWidget", {
1026 _create: function() {}
1029 $( "#widget" ).testWidget({
1031 ok( true, "callback invoked even if event is cancelled" );
1034 .bind( "testwidgetfoo", function() {
1035 ok( true, "event was triggered" );
1038 deepEqual( $( "#widget" ).data( "ui-testWidget" )._trigger( "foo" ), false,
1039 "_trigger returns false when event is cancelled" );
1042 test( "._trigger() - cancelled callback", function() {
1044 $.widget( "ui.testWidget", {
1045 _create: function() {}
1048 $( "#widget" ).testWidget({
1053 deepEqual( $( "#widget" ).data( "ui-testWidget" )._trigger( "foo" ), false,
1054 "_trigger returns false when callback returns false" );
1057 test( "._trigger() - provide event and ui", function() {
1060 var originalEvent = $.Event( "originalTest" );
1061 $.widget( "ui.testWidget", {
1062 _create: function() {},
1063 testEvent: function() {
1071 this._trigger( "foo", originalEvent, ui );
1078 }, "ui object modified" );
1081 $( "#widget" ).bind( "testwidgetfoo", function( event, ui ) {
1082 equal( event.originalEvent, originalEvent, "original event object passed" );
1089 }, "ui hash passed" );
1092 $( "#widget-wrapper" ).bind( "testwidgetfoo", function( event, ui ) {
1093 equal( event.originalEvent, originalEvent, "original event object passed" );
1100 }, "modified ui hash passed" );
1103 $( "#widget" ).testWidget({
1104 foo: function( event, ui ) {
1105 equal( event.originalEvent, originalEvent, "original event object passed" );
1112 }, "modified ui hash passed" );
1113 ui.baz.quux = "jQuery";
1116 .testWidget( "testEvent" );
1119 test( "._trigger() - array as ui", function() {
1120 // #6795 - Widget: handle array arguments to _trigger consistently
1123 $.widget( "ui.testWidget", {
1124 _create: function() {},
1125 testEvent: function() {
1136 this._trigger( "foo", null, [ ui, extra ] );
1139 $( "#widget" ).bind( "testwidgetfoo", function( event, ui, extra ) {
1146 }, "event: ui hash passed" );
1149 }, "event: extra argument passed" );
1151 $( "#widget" ).testWidget({
1152 foo: function( event, ui, extra ) {
1159 }, "callback: ui hash passed" );
1162 }, "callback: extra argument passed" );
1165 .testWidget( "testEvent" );
1168 test( "._trigger() - instance as element", function() {
1170 $.widget( "ui.testWidget", {
1171 defaultElement: null,
1172 testEvent: function() {
1173 this._trigger( "foo", null, { foo: "bar" } );
1176 var instance = $.ui.testWidget({
1177 foo: function( event, ui ) {
1178 equal( event.type, "testwidgetfoo", "event object passed to callback" );
1179 deepEqual( ui, { foo: "bar" }, "ui object passed to callback" );
1182 $( instance ).bind( "testwidgetfoo", function( event, ui ) {
1183 equal( event.type, "testwidgetfoo", "event object passed to event handler" );
1184 deepEqual( ui, { foo: "bar" }, "ui object passed to event handler" );
1186 instance.testEvent();
1190 function shouldDestroy( expected, callback ) {
1192 var destroyed = false;
1193 $.widget( "ui.testWidget", {
1194 _create: function() {},
1195 destroy: function() {
1200 equal( destroyed, expected );
1203 test( "auto-destroy - .remove()", function() {
1204 shouldDestroy( true, function() {
1205 $( "#widget" ).testWidget().remove();
1209 test( "auto-destroy - .remove() when disabled", function() {
1210 shouldDestroy( true, function() {
1211 $( "#widget" ).testWidget({ disabled: true }).remove();
1215 test( "auto-destroy - .remove() on parent", function() {
1216 shouldDestroy( true, function() {
1217 $( "#widget" ).testWidget().parent().remove();
1221 test( "auto-destroy - .remove() on child", function() {
1222 shouldDestroy( false, function() {
1223 $( "#widget" ).testWidget().children().remove();
1227 test( "auto-destroy - .empty()", function() {
1228 shouldDestroy( false, function() {
1229 $( "#widget" ).testWidget().empty();
1233 test( "auto-destroy - .empty() on parent", function() {
1234 shouldDestroy( true, function() {
1235 $( "#widget" ).testWidget().parent().empty();
1239 test( "auto-destroy - .detach()", function() {
1240 shouldDestroy( false, function() {
1241 $( "#widget" ).testWidget().detach();
1245 test( "destroy - remove event bubbling", function() {
1246 shouldDestroy( false, function() {
1247 $( "<div>child</div>" ).appendTo( $( "#widget" ).testWidget() )
1248 .trigger( "remove" );
1253 test( "redefine", function() {
1255 $.widget( "ui.testWidget", {
1256 method: function( str ) {
1257 strictEqual( this, instance, "original invoked with correct this" );
1258 equal( str, "bar", "original invoked with correct parameter" );
1261 $.ui.testWidget.foo = "bar";
1262 $.widget( "ui.testWidget", $.ui.testWidget, {
1263 method: function( str ) {
1264 equal( str, "foo", "new invoked with correct parameter" );
1265 this._super( "bar" );
1269 var instance = new $.ui.testWidget({});
1270 instance.method( "foo" );
1271 equal( $.ui.testWidget.foo, "bar", "static properties remain" );
1274 test( "redefine deep prototype chain", function() {
1276 $.widget( "ui.testWidget", {
1277 method: function( str ) {
1278 strictEqual( this, instance, "original invoked with correct this" );
1279 equal( str, "level 4", "original invoked with correct parameter" );
1282 $.widget( "ui.testWidget2", $.ui.testWidget, {
1283 method: function( str ) {
1284 strictEqual( this, instance, "testWidget2 invoked with correct this" );
1285 equal( str, "level 2", "testWidget2 invoked with correct parameter" );
1286 this._super( "level 3" );
1289 $.widget( "ui.testWidget3", $.ui.testWidget2, {
1290 method: function( str ) {
1291 strictEqual( this, instance, "testWidget3 invoked with correct this" );
1292 equal( str, "level 1", "testWidget3 invoked with correct parameter" );
1293 this._super( "level 2" );
1296 // redefine testWidget after other widgets have inherited from it
1297 // this tests whether the inheriting widgets get updated prototype chains
1298 $.widget( "ui.testWidget", $.ui.testWidget, {
1299 method: function( str ) {
1300 strictEqual( this, instance, "new invoked with correct this" );
1301 equal( str, "level 3", "new invoked with correct parameter" );
1302 this._super( "level 4" );
1305 // redefine testWidget3 after it has been automatically redefined
1306 // this tests whether we properly handle _super() when the topmost prototype
1307 // doesn't have the method defined
1308 $.widget( "ui.testWidget3", $.ui.testWidget3, {} );
1310 var instance = new $.ui.testWidget3({});
1311 instance.method( "level 1" );
1313 delete $.ui.testWidget3;
1314 delete $.ui.testWidget2;
1317 test( "redefine - widgetEventPrefix", function() {
1320 $.widget( "ui.testWidget", {
1321 widgetEventPrefix: "test"
1323 equal( $.ui.testWidget.prototype.widgetEventPrefix, "test",
1324 "cusotm prefix in original" );
1326 $.widget( "ui.testWidget", $.ui.testWidget, {} );
1327 equal( $.ui.testWidget.prototype.widgetEventPrefix, "test",
1328 "cusotm prefix in extension" );
1332 test( "mixins", function() {
1336 method: function() {
1337 return "mixed " + this._super();
1341 $.widget( "ui.testWidget1", {
1342 method: function() {
1343 return "testWidget1";
1346 $.widget( "ui.testWidget2", {
1347 method: function() {
1348 return "testWidget2";
1351 $.widget( "ui.testWidget1", $.ui.testWidget1, mixin );
1352 $.widget( "ui.testWidget2", $.ui.testWidget2, mixin );
1354 equal( $( "<div>" ).testWidget1().testWidget1( "method" ),
1355 "mixed testWidget1", "testWidget1 mixin successful" );
1356 equal( $( "<div>" ).testWidget2().testWidget2( "method" ),
1357 "mixed testWidget2", "testWidget2 mixin successful" );
1360 asyncTest( "_delay", function() {
1364 $.widget( "ui.testWidget", {
1365 defaultElement: null,
1366 _create: function() {
1368 var timer = this._delay(function() {
1369 strictEqual( this, that );
1373 ok( timer !== undefined );
1374 timer = this._delay("callback");
1375 ok( timer !== undefined );
1377 callback: function() {
1378 strictEqual( this, that );
1383 $( "#widget" ).testWidget();
1386 test( "$.widget.bridge()", function() {
1390 elem = $( "<div>" );
1392 function TestWidget( options, element ) {
1393 deepEqual( options, { foo: "bar" }, "options passed" );
1394 strictEqual( element, elem[ 0 ], "element passed" );
1397 $.extend( TestWidget.prototype, {
1398 method: function( param ) {
1399 ok( true, "method called via .pluginName(methodName)" );
1400 equal( param, "value1",
1401 "parameter passed via .pluginName(methodName, param)" );
1403 getter: function() {
1408 $.widget.bridge( "testWidget", TestWidget );
1410 ok( $.isFunction( $.fn.testWidget ), "jQuery plugin was created" );
1412 strictEqual( elem.testWidget({ foo: "bar" }), elem, "plugin returns original jQuery object" );
1413 instance = elem.data( "testWidget" );
1414 equal( typeof instance, "object", "instance stored in .data(pluginName)" );
1416 ret = elem.testWidget( "method", "value1" );
1417 equal( ret, elem, "jQuery object returned from method call" );
1419 ret = elem.testWidget( "getter" );
1420 equal( ret, "qux", "getter returns value" );
1423 test( "$.widget.bridge() - widgetFullName", function() {
1427 elem = $( "<div>" );
1429 function TestWidget() {}
1430 TestWidget.prototype.widgetFullName = "custom-widget";
1431 $.widget.bridge( "testWidget", TestWidget );
1434 instance = elem.data( "custom-widget" );
1435 equal( typeof instance, "object", "instance stored in .data(widgetFullName)" );