[wp-trac] [WordPress Trac] #21170: JavaScript actions and filters
WordPress Trac
wp-trac at lists.automattic.com
Mon Jul 16 00:21:30 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 azaozz):
Replying to [comment:32 carldanley]:
> I understand what you're saying now. The only question I have is how do
we traverse the array to find simulated 'parents' and 'children'.
Yes, that's exactly the thing. This is modelled after the PHP actions API
that has been in WP for years and works quite well. There aren't any sub-
divisions / sub-branches / children and grandchildren in an action. That
keeps things simple. Each action is a single branch that only has leaves
(callbacks). It also matches the DOM events API, there's no 'click.one',
click.other', etc. When 'click' is triggered, everything attached to it is
fired.
> If doAction( 'some.action' ) was called and we know there were several
actions that existed such as 'some.action.a' and 'some.action.b', would we
first find 'some.action' and then maybe look to a 'family' property that
will indicate who the parent/children are? I don't think traversing each
key in this flat array and determining who is prefixed with the correct
action/identifier is the safest way, especially using for( var in ) to
iterate. Thoughts?
If we stick to the current model,
{{{
doAction( 'some.action' )
doAction( 'some.action.a' )
doAction( 'some.other' )
}}}
will not be supported. The action for all these would be
{{{
doAction( 'some' )
}}}
and all callbacks that were registered with
{{{
addAction( 'some.thing', function(){...} )
addAction( 'some.action', function(){...} )
addAction( 'some.identifier', function(){...} )
}}}
would be fired. So in `addAction()` the identifier only applies to the
callback and has nothing to do with the action itself.
On the other hand, as I said in [#comment:29 comment:29], perhaps we could
support "true" namespacing for the actions. That would open some advanced
possibilities to additionally "filter" which callbacks are called.
In this case each action would be a container of many actions that start
with the same name, and each child action can also be a container for even
more actions (grandchildren), and so on. So an action would contain both
callbacks and other actions. This would complicate the API quite a bit
even if we limit the depth to, lets say 3 levels.
Perhaps we should consider all pros and cons. For example, lets say we
have an action 'init' with several namespaces/children: 'init.some',
'init.some.more', 'init.other'.
- Firing 'init' would fire all callbacks registered directly under 'init',
plus all callbacks registered under 'init.some', plus all callbacks
registered under 'init.some.more', plus all callbacks registered under
'init.other', plus... etc. Exactly the same thing can be achieved by
firing several actions: 'init', 'init_some', 'init_some_more',
'init_other', etc. one after the other.
So with namespaced actions we only need:
{{{
doAction( 'init' );
}}}
without namespaces we need:
{{{
doAction( 'init' );
doAction( 'init_some' );
doAction( 'init_some_more' );
doAction( 'init_other' );
}}}
and we have control over which action is fired first, second, etc.
Advantage of namespacing: shorter code, disadvantage: no control over
firing order.
- Setting a namespace first then firing the action. Lets say we can set
the namespace to '.some'. Firing 'init' should fire only callbacks under
'init.some' and 'init.some.more'. That's still exactly the same as firing
'init_some' and 'init_some_more' as separate actions.
With namespaced actions we need:
{{{
setNamespace( 'some' );
doAction( 'init' );
setNamespace( '' ); // depends on whether we reset the namespace after
each action
}}}
without namespaces we need:
{{{
doAction( 'init_some' );
doAction( 'init_some_more' );
}}}
and we can choose to do 'init_some_more' before 'init_some'. Advantage:
none, disadvantage: same as above.
- Firing directly 'init.some' should fire callbacks under 'init.some' and
'init.some.more'. Still the same as firing the callbacks in 'init_some'
and 'init_some_more' separately with the same advantages and
disadvantages.
- Setting the namespace to 'other' or firing directly 'init.other' should
fire the callbacks registered under 'init.other'. That's exactly the same
as simply firing 'init_other'.
So the advantage of using namespaced vs. "flat" actions is a bit shorter
code, the disadvantages are: more complex API, different than the PHP
actions (that's a big one), no control of child actions firing order.
Another possibility is to add namespacing support in the API and never use
it in core. Usually the core code does `doAction` and `applyFilters`, and
plugins do `addAction` and `addFilter`, so if core never uses action
namespaces, the plugins wouldn't need to deal with the differences from
the PHP API.
> I agree in saying that we should keep the actions/filters in separate
containers.
Yes, they either have to be in separate containers or we can have a flag
in each object, perhaps something like `isFilter: true/false`. Both would
work well and require about the same amount of code.
--
Ticket URL: <http://core.trac.wordpress.org/ticket/21170#comment:33>
WordPress Trac <http://core.trac.wordpress.org/>
WordPress blogging software
More information about the wp-trac
mailing list