|
|||||||
![]() |
|
|
Thread Tools |
|
#1
|
|||
|
|||
|
There is just one thing that keeps me from being able to wipe out all my references to YAHOO.util.CustomEvent, and that is that I can't figure out from the Ext reference how to create & fire events that are not tied to Elements. Everything I can find on EventObject and EventManager and Observable seems to be focused on "user-object interaction events" (e.g. "click" an object) and not "application-UI interaction."
Let me give a description of what I mean, and then hopefully someone can say, "Boris, you дурак, it's simple to implement that using Ext as ________________, which you would know if you had read the documentation more carefully." My application uses "message queues" based on YAHOO.util.CustomEvent to keep application components notified of state changes. For example, when a response from the server indicates that the "Current Organization" has changed, the response handler adds a "Current Organization Changed" message (i.e. event) to the application message queue. It does not keep track of which components need to know when the current organization has changed. Instead, any component which needs to perform some action when the current organization changes--maybe change the text in a panel, or enable certain buttons, whatever--subscribes to the application message queue and listens for "Current Organization Changed" messages. Currently, the MessageQueue has two methods, sendMessage(queueName, message) and subscribe(queueName, messageHandler). A snippet from the sendMessage method: if (!queueName) return false;
if(!queues[queueName])
{
queues[queueName] = new YAHOO.util.CustomEvent(queueName, this);
}
message.queueName = queueName;
queues[queueName].fire(message);
("this" being the MessageQueue object which exposes the sendMessage method)
queues[queueName].subscribe(messageHandler) MessageQueue.sendMessage("Application Events", "Current Organization Changed")
MessageQueue.subscribe("Application Events", currentOrganizationChanged)
|
|
#2
|
|||
|
|||
|
Just thinking off the top of my head, but this might give you some direction. You can derive your object from Observable and add any events you want - they don't have to be UI related. You could look at Store as an example - it defines load and beforeload events that can be fired by code.
__________________
Tim Ryan - Ext JS Support Team Read BEFORE posting a question / BEFORE posting a Bug Use Google to Search - API / Forum API Doc (3.x | 2.x | 1.x) / FAQ / Wiki / Tutorials / 1.x->2.0 Migration Guide |
|
#3
|
|||
|
|||
|
That's a great place to start, thanks for pointing me there, Tim. And just to be clear, it sounds like you're suggesting that the internal queues[queueName] object is the one that would derive from Observable, right? Something like the air code
queues[queueName] = new function {...}
Ext.extend(queues[queueName], Ext.util.Observable);
|
|
#4
|
|||
|
|||
|
You'd probably want to kick it around a little as to whether individual queue elements are derived from Observable, or the queue itself does. In that case a queue might just contain a MixedCollection of it's objects. Kind of depends on whether the queue can delegate the events to the right object, or the objects have to do things themselves. The less events you have to create the better of you'll be performance wise
Going the Observable route means you get to use same syntax as the rest of Ext and don't have to code to the YAHOO API, and if you ever need to switch adapters, it's transparent.
__________________
Tim Ryan - Ext JS Support Team Read BEFORE posting a question / BEFORE posting a Bug Use Google to Search - API / Forum API Doc (3.x | 2.x | 1.x) / FAQ / Wiki / Tutorials / 1.x->2.0 Migration Guide |
|
#5
|
|||
|
|||
|
Thanks again, Tim. I did play with both an Observable MessageQueue manager object and Observable queues. With the Observable MessageQueue, the queue name becomes the event name, and so broadcasting a message means calling this.fireEvent(queueName, message) to notify all subscribers. In this case, the global MessageQueue can be defined like this:
examplenamespace.MessageQueue = function()
{
var _messageQueue = function()
{
this.SendMessage = function(message, queueName)
{
// optional queueName parameter allows easy re-sending
// of a message on a different queue, overriding the
// original queue.
if (queueName)
{
message.queueName = queueName;
}
else
{
queueName = message.queueName;
}
if (!queueName) return false;
var queue = {events: {}};
queue.events[queueName] = true;
this.addEvents(queue);
this.fireEvent(queueName, message);
return true;
}
this.Subscribe = function(subscription, callback, subscriberArgs)
{
var subscriptionInfo = {};
// The subscription can be created by passing an object with
// subscription properties, or can be created with a shortcut
// in the form of "Query Name:Message Name:Message Content"
// (where Message Name and Message Content are both optional)
if (typeof(subscription)=='string')
{
subscription = subscription.split(':');
subscriptionInfo.queueName = subscription[0];
subscriptionInfo.name = subscription[1];
subscriptionInfo.content = subscription[2];
}
else
{
subscriptionInfo = subscription;
}
subscriptionInfo.subscriberArgs = subscriberArgs;
var queueName = subscriptionInfo.queueName;
if (!queueName || !callback) return false;
var queue = {events: {}};
queue.events[queueName] = true;
this.addEvents(queue);
this.on
(
queueName,
function(message, subscriptionInfo)
{
// A subscriber can listen to the whole message queue, or
// to messages on the queue with specific properties.
// Here we look at the subscription properties to see
// whether the message matches the subscription.
var subscriptionMatched = true;
for (var filterItem in subscriptionInfo)
{
if(subscriptionInfo[filterItem] && (filterItem != 'subscriberArgs'))
{
subscriptionMatched = (subscriptionMatched && (subscriptionInfo[filterItem] == message[filterItem]));
if (!subscriptionMatched) break;
}
}
if (subscriptionMatched)
{
callback(message, subscriptionInfo.subscriberArgs);
}
}.createDelegate(this, subscriptionInfo, true)
)
}
}
Ext.extend(_messageQueue, Ext.util.Observable);
return new _messageQueue();
}();
examplenamespace.MessageQueue = function()
{
var queues = {};
messageQueue = function(queueName)
{
this.name = queueName;
this.events = {"MessageSent": true};
}
Ext.extend(messageQueue, Ext.util.Observable);
return {
SendMessage: function(message, queueName)
{
// optional queueName parameter allows easy re-sending
// of a message on a different queue, overriding the
// original queue.
if (queueName)
{
message.queueName = queueName;
}
else
{
queueName = message.queueName;
}
if (!queueName) return false;
if(!queues[queueName])
{
queues[queueName] = new messageQueue(queueName);
}
queues[queueName].fireEvent("MessageSent", message);
return true;
}
,
Subscribe: function(subscription, callback, subscriberArgs)
{
var subscriptionInfo = {};
// The subscription can be created by passing an object with
// subscription properties, or can be created with a shortcut
// in the form of "Query Name:Message Name:Message Content"
// (where Message Name and Message Content are both optional)
if (typeof(subscription)=='string')
{
subscription = subscription.split(':');
subscriptionInfo.queueName = subscription[0];
subscriptionInfo.name = subscription[1];
subscriptionInfo.content = subscription[2];
}
else
{
subscriptionInfo = subscription;
}
subscriptionInfo.subscriberArgs = subscriberArgs;
var queueName = subscriptionInfo.queueName;
if (!queueName || !callback) return false;
if(!queues[queueName])
{
queues[queueName] = new messageQueue(queueName);
}
queues[queueName].on
(
"MessageSent",
function(message, subscriptionInfo)
{
// A subscriber can listen to the whole message queue, or
// to messages on the queue with specific properties.
// Here we look at the subscription properties to see
// whether the message matches the subscription.
var subscriptionMatched = true;
for (var filterItem in subscriptionInfo)
{
if(subscriptionInfo[filterItem] && (filterItem != 'subscriberArgs'))
{
subscriptionMatched = (subscriptionMatched && (subscriptionInfo[filterItem] == message[filterItem]));
if (!subscriptionMatched) break;
}
}
if (subscriptionMatched)
{
callback(message, subscriptionInfo.subscriberArgs);
}
}.createDelegate(this, subscriptionInfo, true)
)
}
}
}();
| var queue = {events: {}}; | queue.events[queueName] = true; looks too... um, hacked, which it is. Looking at the internals of EventManager, I think I could also have made that work for me instead of a MessageQueue; however, updating the MessageQueue meant fewer changes to the rest of the application's code. And since I very much believe in sharing the pieces I can, I wanted to post these two examples in case someone else is using a similar design pattern. To make the code complete, for either version of the MessageQueue I've got a Message class examplenamespace.MessageQueue.Message = function(queueName, messageName, messageContent, messageSource)
{
this.queueName = queueName;
this.name = messageName;
this.content = messageContent;
this.source = messageSource;
};
examplenamespace.MessageQueue.Subscribe
(
"Application Events",
function(message)
{
alert("An application event occured")
}
);
examplenamespace.MessageQueue.Subscribe
(
"Application Events:Organization Changed",
function(message, args)
{
alert(message.name + " changed to " + message.content + " by " + args)
},
"Joe Schmoe"
);
MessageQueue.SendMessage
(
new MessageQueue.Message("Application Events", "Organization Changed", 1097, this)
)
P.S. I know that there's no Unsubscribe method... so far, there hasn't been a need for one in this project. You may find that you need to write one. |
|
#6
|
|||
|
|||
|
This is just the topic i needed to discuss...
I'm looking to create a message queue so i can produce a UI of loosely coupled components. These eventing topics are pretty standard in a Swing type application and I'd like to apply the same good practices to my apps in Ext. My key obective is to have a central global event loop that components can attach themselves to and broker all global activity. BorisNikolaevich - Are my objectives anything like yours with this thread? If so, have you found a neat way to get IFrames to communicate neatly? I wish i had found this thread before i created one just yesterday ![]() |
|
#7
|
||||
|
||||
|
I'm so glad I found this post!
![]() Just my 2 cents, but it would be nice if this pattern of element-agnostic message queues was built-in in Ext 2.x core, it helps avoid unnecessary coupling. It is specially useful for large, dynamic apps where the components that are going to be load is not necessary known,or new components are deleted/updated frequently. |
|
#8
|
||||
|
||||
|
Quote:
It exposes frame messaging via standard Ext Events.
__________________
Doug Hendricks Maintaining ux: ManagedIFrame, MIF2 (FAQ, Wiki), ux.Media/Flash, AudioEvents, ux.Chart[Fusion,OFC,amChart], ext-basex.js/$JIT, Documentation Site, donate. |
|
#9
|
|||
|
|||
|
Hi Guys,
I saw the discussion is around implementing custom events. I am also having hard time in implementing some custom event on GridPanel. I noticed that there is NO OnRowOver and OnRowOut functionality attached to the Grid Panel so I thought to implement on my own but am without luck. Here is the things I implemented. I declared a GridPanel just a basic one. Now I am initializing yahoo's custom events just like this. and attaching it to the grid.
But this doesn't seem to be working. Am I doing something wrong? Can we attach any custom event to ext's component like this?? Help and replies are appreciated. Thanks Anshu |
![]() |
| Thread Tools | |
|
|