@@ -608,7 +608,7 @@ steal('jquery/class', 'jquery/lang/string', 'jquery/event/destroyed', function(
608
608
* default it is called with the element and options passed to the controller.
609
609
*/
610
610
setup : function ( element , options ) {
611
- var funcName , ready , cls = this . Class ;
611
+ var funcName , ready , cls = this [ STR_CONSTRUCTOR ] ;
612
612
613
613
//want the raw element here
614
614
element = element . jquery ? element [ 0 ] : element ;
@@ -622,8 +622,7 @@ steal('jquery/class', 'jquery/lang/string', 'jquery/event/destroyed', function(
622
622
//set in data
623
623
( data ( element ) || data ( element , { } ) ) [ pluginname ] = this ;
624
624
625
- //adds bindings
626
- this . _bindings = [ ] ;
625
+
627
626
/**
628
627
* @attribute options
629
628
* Options is [jQuery.Controller.static.defaults] merged with the 2nd argument
@@ -651,15 +650,7 @@ steal('jquery/class', 'jquery/lang/string', 'jquery/event/destroyed', function(
651
650
*/
652
651
this . options = extend ( extend ( true , { } , cls . defaults ) , options ) ;
653
652
654
- //go through the cached list of actions and use the processor to bind
655
- for ( funcName in cls . actions ) {
656
- if ( cls . actions . hasOwnProperty ( funcName ) ) {
657
- ready = cls . actions [ funcName ] || cls . _action ( funcName , this . options ) ;
658
- this . _bindings . push (
659
- ready . processor ( ready . delegate || element , ready . parts [ 2 ] , ready . parts [ 1 ] , funcName , this ) ) ;
660
- }
661
- }
662
-
653
+
663
654
664
655
/**
665
656
* @attribute called
@@ -669,13 +660,8 @@ steal('jquery/class', 'jquery/lang/string', 'jquery/event/destroyed', function(
669
660
*/
670
661
this . called = "init" ;
671
662
672
- //setup to be destroyed ... don't bind b/c we don't want to remove it
673
- var destroyCB = shifter ( this , "destroy" ) ;
674
- this . element . bind ( "destroyed" , destroyCB ) ;
675
- this . _bindings . push ( function ( el ) {
676
- //destroyCB.removed = true;
677
- $ ( element ) . unbind ( "destroyed" , destroyCB ) ;
678
- } ) ;
663
+ // bind all event handlers
664
+ this . bind ( ) ;
679
665
680
666
/**
681
667
* @attribute element
@@ -725,32 +711,70 @@ steal('jquery/class', 'jquery/lang/string', 'jquery/event/destroyed', function(
725
711
return this . element ;
726
712
} ,
727
713
/**
728
- * Bind attaches event handlers that will be removed when the controller is removed.
729
- * This is a good way to attach to an element not in the controller's element.
730
- * <br/>
731
- * <h3>Examples:</h3>
732
- * @codestart
733
- * init: function() {
734
- * // calls somethingClicked(el,ev)
735
- * this.bind('click','somethingClicked')
736
- *
737
- * // calls function when the window is clicked
738
- * this.bind(window, 'click', function(ev){
739
- * //do something
740
- * })
741
- * },
742
- * somethingClicked: function( el, ev ) {
743
- *
744
- * }
745
- * @codeend
746
- * @param {HTMLElement|jQuery.fn } [el=this.element] The element to be bound
714
+ * Bind attaches event handlers that will be
715
+ * removed when the controller is removed.
716
+ *
717
+ * This used to be a good way to listen to events outside the controller's
718
+ * [jQuery.Controller.prototype.element element]. However,
719
+ * using templated event listeners is now the prefered way of doing this.
720
+ *
721
+ * ### Example:
722
+ *
723
+ * init: function() {
724
+ * // calls somethingClicked(el,ev)
725
+ * this.bind('click','somethingClicked')
726
+ *
727
+ * // calls function when the window is clicked
728
+ * this.bind(window, 'click', function(ev){
729
+ * //do something
730
+ * })
731
+ * },
732
+ * somethingClicked: function( el, ev ) {
733
+ *
734
+ * }
735
+ *
736
+ * @param {HTMLElement|jQuery.fn|Object } [el=this.element]
737
+ * The element to be bound. If an eventName is provided,
738
+ * the controller's element is used instead.
739
+ *
747
740
* @param {String } eventName The event to listen for.
748
741
* @param {Function|String } func A callback function or the String name of a controller function. If a controller
749
742
* function name is given, the controller function is called back with the bound element and event as the first
750
743
* and second parameter. Otherwise the function is called back like a normal bind.
751
744
* @return {Integer } The id of the binding in this._bindings
752
745
*/
753
746
bind : function ( el , eventName , func ) {
747
+ if ( el === undefined ) {
748
+ //adds bindings
749
+ this . _bindings = [ ] ;
750
+ //go through the cached list of actions and use the processor to bind
751
+
752
+ var cls = this [ STR_CONSTRUCTOR ] ,
753
+ bindings = this . _bindings ,
754
+ actions = cls . actions ,
755
+ element = this . element ;
756
+
757
+ for ( funcName in actions ) {
758
+ if ( actions . hasOwnProperty ( funcName ) ) {
759
+ ready = actions [ funcName ] || cls . _action ( funcName , this . options ) ;
760
+ bindings . push (
761
+ ready . processor ( ready . delegate || element ,
762
+ ready . parts [ 2 ] ,
763
+ ready . parts [ 1 ] ,
764
+ funcName ,
765
+ this ) ) ;
766
+ }
767
+ }
768
+
769
+
770
+ //setup to be destroyed ... don't bind b/c we don't want to remove it
771
+ var destroyCB = shifter ( this , "destroy" ) ;
772
+ element . bind ( "destroyed" , destroyCB ) ;
773
+ bindings . push ( function ( el ) {
774
+ $ ( el ) . unbind ( "destroyed" , destroyCB ) ;
775
+ } ) ;
776
+ return bindings . length ;
777
+ }
754
778
if ( typeof el == 'string' ) {
755
779
func = eventName ;
756
780
eventName = el ;
@@ -765,6 +789,14 @@ steal('jquery/class', 'jquery/lang/string', 'jquery/event/destroyed', function(
765
789
this . _bindings . push ( binder ( el , eventName , func , selector ) ) ;
766
790
return this . _bindings . length ;
767
791
} ,
792
+ _unbind : function ( ) {
793
+ var el = this . element [ 0 ] ;
794
+ each ( this . _bindings , function ( key , value ) {
795
+ value ( el ) ;
796
+ } ) ;
797
+ //adds bindings
798
+ this . _bindings = [ ] ;
799
+ } ,
768
800
/**
769
801
* Delegate will delegate on an elememt and will be undelegated when the controller is removed.
770
802
* This is a good way to delegate on elements not in a controller's element.<br/>
@@ -793,11 +825,81 @@ steal('jquery/class', 'jquery/lang/string', 'jquery/event/destroyed', function(
793
825
return this . _binder ( element , eventName , func , selector ) ;
794
826
} ,
795
827
/**
796
- * Called if an controller's [jquery.controller.plugin jQuery helper] is
828
+ * Update extends [jQuery.Controller.prototype.options this.options]
829
+ * with the `options` argument and rebinds all events. It basically
830
+ * re-configures the controller.
831
+ *
832
+ * For example, the following controller wraps a recipe form. When the form
833
+ * is submitted, it creates the recipe on the server. When the recipe
834
+ * is `created`, it resets the form with a new instance.
835
+ *
836
+ * $.Controller('Creator',{
837
+ * "{recipe} created" : function(){
838
+ * this.update({recipe : new Recipe()});
839
+ * this.element[0].reset();
840
+ * this.find("[type=submit]").val("Create Recipe")
841
+ * },
842
+ * "submit" : function(el, ev){
843
+ * ev.preventDefault();
844
+ * var recipe = this.options.recipe;
845
+ * recipe.attrs( this.element.formParams() );
846
+ * this.find("[type=submit]").val("Saving...")
847
+ * recipe.save();
848
+ * }
849
+ * });
850
+ * $('#createRecipes').creator({recipe : new Recipe()})
851
+ *
852
+ *
853
+ * @demo jquery/controller/demo-update.html
854
+ *
855
+ * Update is called if a controller's [jquery.controller.plugin jQuery helper] is
797
856
* called on an element that already has a controller instance
798
- * of the same type. The base method
799
- * extends [jQuery.Controller.prototype.options this.options]
800
- * with the options passed in. If you overwrite this, you might want to call
857
+ * of the same type.
858
+ *
859
+ * For example, a widget that listens for model updates
860
+ * and updates it's html would look like.
861
+ *
862
+ * $.Controller('Updater',{
863
+ * // when the controller is created, update the html
864
+ * init : function(){
865
+ * this.updateView();
866
+ * },
867
+ *
868
+ * // update the html with a template
869
+ * updateView : function(){
870
+ * this.element.html( "content.ejs",
871
+ * this.options.model );
872
+ * },
873
+ *
874
+ * // if the model is updated
875
+ * "{model} updated" : function(){
876
+ * this.updateView();
877
+ * },
878
+ * update : function(options){
879
+ * // make sure you call super
880
+ * this._super(options);
881
+ *
882
+ * this.updateView();
883
+ * }
884
+ * })
885
+ *
886
+ * // create the controller
887
+ * // this calls init
888
+ * $('#item').updater({model: recipe1});
889
+ *
890
+ * // later, update that model
891
+ * // this calls "{model} updated"
892
+ * recipe1.update({name: "something new"});
893
+ *
894
+ * // later, update the controller with a new recipe
895
+ * // this calls update
896
+ * $('#item').updater({model: recipe2});
897
+ *
898
+ * // later, update the new model
899
+ * // this calls "{model} updated"
900
+ * recipe2.update({name: "something newer"});
901
+ *
902
+ * _NOTE:_ If you overwrite `update`, you probably need to call
801
903
* this._super.
802
904
*
803
905
* ### Example
@@ -814,10 +916,14 @@ steal('jquery/class', 'jquery/lang/string', 'jquery/event/destroyed', function(
814
916
* $('#myel').thing({prop : 'val1'}); // alerts init:val1
815
917
* $('#myel').thing({prop : 'val2'}); // alerts update:val2
816
918
*
817
- * @param {Object } options the object passed to the [jquery.controller.plugin jQuery helper function]
919
+ * @param {Object } options A list of options to merge with
920
+ * [jQuery.Controller.prototype.options this.options]. Often, this method
921
+ * is called by the [jquery.controller.plugin jQuery helper function].
818
922
*/
819
923
update : function ( options ) {
820
924
extend ( this . options , options ) ;
925
+ this . _unbind ( ) ;
926
+ this . bind ( ) ;
821
927
} ,
822
928
/**
823
929
* Destroy unbinds and undelegates all event handlers on this controller,
@@ -860,9 +966,7 @@ steal('jquery/class', 'jquery/lang/string', 'jquery/event/destroyed', function(
860
966
this . element . removeClass ( fname ) ;
861
967
862
968
// unbind bindings
863
- each ( this . _bindings , function ( key , value ) {
864
- value ( self . element [ 0 ] ) ;
865
- } ) ;
969
+ this . _unbind ( ) ;
866
970
// clean up
867
971
delete this . _actions ;
868
972
0 commit comments