[wp-trac] [WordPress Trac] #21170: JavaScript actions and filters

WordPress Trac wp-trac at lists.automattic.com
Sun Jul 15 12:05:18 UTC 2012


#21170: JavaScript actions and filters
----------------------------+--------------------------
 Reporter:  koopersmith     |       Owner:  koopersmith
     Type:  task (blessed)  |      Status:  new
 Priority:  normal          |   Milestone:  3.5
Component:  General         |     Version:  3.4
 Severity:  normal          |  Resolution:
 Keywords:                  |
----------------------------+--------------------------

Comment (by carldanley):

 Replying to [comment:31 azaozz]:

 > The .namespace/identifier bit would only be used to identify the
 callback, so each "leaf" on the "branch" would have a name and we would be
 able to easily remove anonymous "leaves" by branch name + leaf name

 So, as an example, when we use the action identifier
 'actionname.namespace.other.third', I was thinking that there were several
 identifiers for this particular action. The action being 'actionname' and
 then several tiers of identifiers: 'actionname.namespace',
 'actionname.namespace.other', 'actionname.namespace.other.third'. Each
 unique identifier tier would simply be it's own key in a flat array.
 Essentially, the callback passed lives in the
 'actionname.namespace.other.third' array key. However, the problem I see
 with this is as follows:[[br]][[br]]

 {{{
 addAction( 'foo.bar', callback1 );
 //Actions:
 //ACTIONS[ 'foo.bar' ] = [ callback1 ];

 addAction( 'foo.bar.test', callback2 );
 //Actions:
 //ACTIONS[ 'foo.bar' ] = [ callback1 ];
 //ACTIONS[ 'foo.bar.test' ] = [ callback2 ];

 addAction( 'foo.bar.test.foo', callback3 );
 //Actions:
 //ACTIONS[ 'foo.bar' ] = [ callback1 ];
 //ACTIONS[ 'foo.bar.test' ] = [ callback2 ];
 //ACTIONS[ 'foo.bar.test.foo' ] = [ callback3 ];
 }}}

 So when we doAction( 'foo.bar' ), we'd have to loop through each key in
 the flat array finding keys prefixed with 'foo.bar' and execute them. To
 me, this could get very heavy ( especially since we'd have to use for( var
 k in arr ) ) in different areas of a site with a lot of plugins installed.
 To combat this, I created the tree for easier access in calling the
 'children' identifiers. Meaning, if we called 'foo.bar' in this example,
 we would know that 'foo.bar' would have an array of callbacks that needed
 execution and to find the children, we know the object had a property
 called children where 'foo.bar.test' and 'foo.bar.test.foo' lived in the
 same manner that their ancestor, 'foo.bar', was created ( as an object
 with properties like 'callbacks' and 'children' ). I really like the flat
 array approach, I was just hesitant because of look-up speed for doing
 anything. You could also make the value of each unique array key an object
 with 2 properties ('callbacks' and 'siblings' where 'siblings' would store
 an array of values that could be used to find siblings when looking up for
 deletion/execution)[[br]][[br]]

 > If we create the nodes as instances of a small class, or even as simple
 objects, we can store the nodeType in each.

 Consider the following:
 {{{
 var appendHookToArray = function( arr, hookIdentifier, data ){
         var identifiers = hookIdentifier.split( '.' );
         var levels = [], identifier;

         for( var i = 1, len = identifiers.length; i <= len; i++ ){
                 identifier = identifiers.slice( 0, i ).join( '.' );
                 if( arr[ identifier ] === undefined ){
                         arr[ identifier ] = [];
                         if( i === len ){
                                 //just push it since we know it's a new
 identifier
                                 arr[ identifier ].push( data );
                         }
                 }
                 else if( i === len ){
                         //insert the callback now
                         arr[ identifier ] = insertHookByPriority( arr[
 identifier ], data );
                 }
         }

         return arr;
 };

 }}}

 So then, when addAction is called all it does is this:
 {{{
 SELF.addAction = function( action, callback, priority ){
         if( typeof callback !== 'function' ){
                 return SELF;
         }

         ACTIONS = appendHookToArray( ACTIONS, action, {
                 'callback' : callback,
                 'priority' : ( priority || 10 )
         } );
         return SELF;
 };
 }}}

 With 'ACTIONS' being a private class property ( 'FILTERS' would also exist
 as something separately. ) ACTIONS/FILTERS will def. need to be kept
 separate but I think that adding a 'nodeType' property to the object
 created is a little bit of an unnecessary waste, if i'm understanding
 correctly, meaning: I don't think it's necessary to specify nodeType of
 'action' for 100+ different actions, as an example. We already know that
 it's an action because we have to access the 'ACTIONS' variable and, for
 this example, storing a 'nodeType' for each ACTION of value 'action' would
 mean making the array 600+ bytes heavier at run-time. I would use the same
 new 'object' class for both actions and filters. Thoughts?

 > Yeah, chaining is definitely handy. The question is whether it's better
 to support chaining or to return true/false on success/failure when adding
 or removing actions and filter.

 You're also making me sway on chaining vs. true/false. It would
 interesting to hear other opinions as well.

 > Perhaps if we get it right, it can also be released as a stand-alone JS
 class.
 That's what I'm shooting for! :)

-- 
Ticket URL: <http://core.trac.wordpress.org/ticket/21170#comment:32>
WordPress Trac <http://core.trac.wordpress.org/>
WordPress blogging software


More information about the wp-trac mailing list