You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2012/07/13 03:10:31 UTC
git commit: Inital pass at new pub/sub system ("stimulus" and
"response") - tests are coming!
Updated Branches:
refs/heads/5.4-js-rewrite 9c7194eea -> 83d6848ea
Inital pass at new pub/sub system ("stimulus" and "response")
- tests are coming!
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/83d6848e
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/83d6848e
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/83d6848e
Branch: refs/heads/5.4-js-rewrite
Commit: 83d6848eaa2ece668d6e1ce9aa7b61ad9a17e5c8
Parents: 9c7194e
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Thu Jul 12 18:10:15 2012 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Thu Jul 12 18:10:15 2012 -0700
----------------------------------------------------------------------
.../tapestry5/corelib/modulejs/pubsub.coffee | 150 +++++++++++++++
1 files changed, 150 insertions(+), 0 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/83d6848e/tapestry-core/src/main/coffeescript/org/apache/tapestry5/corelib/modulejs/pubsub.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/org/apache/tapestry5/corelib/modulejs/pubsub.coffee b/tapestry-core/src/main/coffeescript/org/apache/tapestry5/corelib/modulejs/pubsub.coffee
new file mode 100644
index 0000000..42b98bb
--- /dev/null
+++ b/tapestry-core/src/main/coffeescript/org/apache/tapestry5/corelib/modulejs/pubsub.coffee
@@ -0,0 +1,150 @@
+# Copyright 2012 The Apache Software Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http:#www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Framework/application publish and subscribe that is independent of
+# the DOM. Parts of this are modelled on how jQuery DOM events work.
+
+define ["_"], (_) ->
+
+ exports = {}
+
+ subscribers = { }
+
+ kullSubs = (name, namespaces, responder) ->
+ list = subscribers[name]
+ return if list is null
+
+ # Work backwards to avoid excessive copies
+ for i in [list.length - 1 .. 0]
+ listener = list[i]
+ if (responder is null or listener.fn is responder) and
+ # TODO: _.intersection is expensive
+ (namespaces.length == 0 or _.intersection(namespaces, listener.namespaces).length > 0)
+ if list.iterating
+ subscribers[name] = list = list[..]
+ list.splice i, 1
+
+ return
+
+ addSub = (stimulusName, addFirst, responder) ->
+ [simpleName, namespaces...] = _.split stimulusName, '.'
+
+ subscriber =
+ stimulus: simpleName
+ namespaces: namespaces
+ fn: responder
+
+ list = subscribers[simpleName]
+
+ if list is null
+ subscribers[simpleName] = [subscriber]
+ else
+ # If iterating the list (during a publish), then do a copy-on-write.
+ # This allows a clean way to have listeners unsubscribe one first notification, or
+ # otherwise change the subscriptions.
+ if list.iterating
+ subscribers[simpleName] = list = list.slice[..]
+
+ list[if addFirst then "unshift" else "push"] subscriber
+
+ return
+
+ # Adds a responder for a stimulus. The stimulus name consists of a simple topic name
+ # (used when publishing a message), and optional set of namespaces; each namespace
+ # is preceded by a '.'. The namespaces make it easier to identify specific responders
+ # later, such as when removing a responder.
+ # The ordering identifies where the listener will be placed.
+ # The listenerfn is a function to be invoked via the publisher. A topic publisher
+ # will publish a message with an application-specific memo. The listenerfn receives
+ # the memo parameter, and an event parameter. The event parameter allows the
+ # message to be terminated early.
+ # stimulus - name of stimulus to respond to, with namespaces appended
+ # responder - function to be invoked when the stimulus is fired. The responder
+ # is passed a memo object, and an event. The event can be used to cancel or
+ # pause the stimulus.
+ # Returns this module's exports, for easy chaining of calls.
+ exports.respondTo = exports.on = (stimulusName, responder) ->
+
+ addSub stimulusName, false, responder
+
+ return exports
+
+ # Adds a responder for a stimulus, but the responder is added first in the list.
+ # Otherwise, the same as respondsTo().
+ # Returns this module's exports, for easy chaining of calls.
+ exports.responderFirst = exports.first = (stimulusName, responder) ->
+ addSub stimulusName, true, responder
+
+ return exports
+
+ # Stops responding to a stimulus. The parameters identify zero or more responders
+ # that will no longer be triggered.
+ # Only previously added responders that match a specifically as possible will be removed.
+ # If a responder is provided, it must match exactly.
+ # If a stimulus name is provided, the name must match exactly.
+ # If any namespaces were provided, then at least ONE namespace must match a namespace provided when
+ # the responder was added.
+ # stimulusName - optional, identifies a stimulus and optional namespaces
+ # responder - optional, identifies a specific responder to remove
+ # Returns this modules exports, to support chaining.
+ exports.stopResponding = exports.off = (stimulusName = "", responder) ->
+ if _.isFunction stimulusName
+ responder = stimulusName
+ stimulusName = ""
+
+ [simpleName, namespaces...] = _.split stimulusName, '.'
+
+ if simpleName isnt ""
+ kullSubs simpleName, namespaces, responder
+ else
+ kullSubs name, namespaces, responder for name of subscribers
+
+ return exports
+
+
+ # Fires the stimulus, passing the memo, and an even, to each responder that was previously added.
+ # The event can be used to terminate the message (it has a stop() method).
+ # The context object defines the value of this for
+ # the invoked listener functions; it is often null (or omitted).
+ # stimulusName - simple name of stimulus to fire (it should not contain namespaces)
+ # memo - object to be passed to each responder (as the first parameter)
+ # context - context value (this) used when invoking responders
+ # Returns this modules exports, to support chaining.
+ exports.fire = (stimulusName, memo, context) ->
+ list = subscribers[stimulusName]
+
+ return exports if list is null
+
+ event =
+ running: true
+ stimulus: stimulusName
+ stop: -> running = false
+ # TODO: pause and resume
+
+ try
+ wasIterating = list.iterating
+ list.iterating = true
+
+ for subscriber in list when event.running
+ # Pass the memo and the event to the responder.
+ subscriber.fn.call context, memo, event
+
+ finally
+ list.iterating = wasIterating
+
+ return exports
+
+ # Result of define:
+ return exports
+