eu.extjs.desktop.**
it would receive message with subject eu.extjs.desktop.wallpaper.set
but it wouldn’t receive message eu.extjs.taskbar.hide
.
So this plugin was born.
Ext.ux.MsgBus fits in any component that is descendant of Ext.util.Observable and it does not need any other changes/overrides. You would stick it only into the components that must participate in bus messaging. It adds subscribe
and publish
methods to the component.
Usage example:
1 2 3 4 5 6 7 8 |
var p = new Ext.Panel({ plugins:['msgbus'] ,onWallpaper:function(subject, message) { // do something } // the rest of config }); p.subscribe('eu.extjs.desktop.wallpaper.**', {fn:p.onWallpaper, single:true}); |
1 |
p.publish('eu.extjs.this.panel.move', {oldx:100, oldy:200, x:300, y:400}); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
// vim: sw=4:ts=4:nu:nospell:fdc=4 /** * Message Bus Plugin * * @author Ing. Jozef Sakáloš * @copyright (c) 2009, by Ing. Jozef Sakáloš * @date 19. September 2009 * @version $Id: Ext.ux.MsgBus.js 29 2009-09-23 09:51:55Z jozo $ * * @license Ext.ux.MsgBus.js is licensed under the terms of the Open Source * LGPL 3.0 license. Commercial use is permitted to the extent that the * code/component(s) do NOT become part of another Open Source or Commercially * licensed development library or toolkit without explicit permission. * * License details: http://www.gnu.org/licenses/lgpl.html */ /*global Ext,window */ /** * @class Ext.ux.MsgBus * * Creates new Ext.ux.MsgBus object * @constructor * @param {Object} config The config object */ Ext.ux.MsgBus = function(config) { Ext.apply(this, config, { }); }; // eo constructor Ext.override(Ext.ux.MsgBus, { /** * @cfg {String} busName Name of the global Observable instance */ busName:'Ext.ux.Bus' /** * @private */ ,bus:false /** * Initializes the plugin and component * @private */ ,init:function(cmp) { this.cmp = cmp; cmp.bus = this.getBus(); cmp.bus.addEvents('message'); cmp.subs = {}; this.applyConfig(); } // eo function init // {{{ /** * Returns or creates the global Observable instance * @private */ ,getBus:function() { var bus = window; var a = this.busName.split('.'); var last = a.pop(); Ext.each(a, function(n) { if(!Ext.isObject(bus[n])) { bus = false; return false; } else { bus = bus[n]; } }, this); if(false === bus) { Ext.ns(this.busName); return this.getBus(); } if(!(bus[last] instanceof Ext.util.Observable)) { bus[last] = new Ext.util.Observable(); } return bus[last]; } // eo function getBus // }}} // {{{ /** * Creates RegExp for message filtering. * Override it if you need another logic. * @param {String} subject The message subject * @return {RegExp} RegExp used for message filtering */ ,getFilterRe:function(subject) { var a = subject.split('.'); var last = a.length - 1; a[last] = '**' === a[last] ? '.*' : a[last]; var re = /^w+$/; Ext.each(a, function(token, i) { if(!re.test(token) && '*' !== token && '.*' !== token) { throw 'Invalid subject: ' + subject; } if('*' === token) { a[i] = '\w+'; } }); return new RegExp('^' + a.join('\.') + '$'); } // eo function getFilter // }}} // {{{ /** * Applies new methods to the component * @private */ ,applyConfig:function() { Ext.applyIf(this.cmp, { /** * Subscribes to messages (parent component method) * @param {String} subject Dotted notation subject with wildcards. * See http://www.openajax.org/member/wiki/OpenAjax_Hub_2.0_Specification_Topic_Names * @param {Object} config Same as addListener config object * @return {Boolean} success true on success, false on failure (subscription exists) */ subscribe:function(subject, config) { var sub = this.subs[subject]; if(sub) { return false; } config = config || {}; config.filter = this.getFilterRe(subject); this.subs[subject] = {config:config, fn:this.filterMessage.createDelegate(this, [config], true)}; this.bus.on('message', this.subs[subject].fn, config.scope || this, config); return true; } /** * Unsubscribes from messages (parent component method) * @param {String} subject Dotted notation subject with wildcards. * @return {Boolean} success true on success, false on failure (nonexistent subscription) */ ,unsubscribe:function(subject) { var sub = this.subs[subject]; if(!sub) { return false; } this.bus.un('message', sub.fn, sub.scope || this, sub.config); delete this.subs[subject]; sub = null; return true; } // eo function unsubscribe /** * Publishes the message (parent component method) * @param {String} subject Message subject * @param {Mixed} message Message body, most likely an object */ ,publish:function(subject, message) { this.getFilterRe(subject); this.bus.fireEvent('message', subject, message); } // eo function publish /** * Returns current subscriptions * @return {Object} subscriptions */ ,getSubscriptions:function() { return this.subs; } // eo function /** * @private */ ,getFilterRe:this.getFilterRe /** * Filters incoming messages * @private */ ,filterMessage:function(subject, message, config) { if(config.filter.test(subject)) { (config.fn || this.onMessage).call(config.scope || this, subject, message); } } // eo function filterMessage /** * Default message processing function * @param {String} subject The message subject * @param {Mixed} message The message body */ ,onMessage:Ext.emptyFn }); } // eo function applyConfig // }}} }); // eo override // register ptype Ext.preg('msgbus', Ext.ux.MsgBus); // eof |
Latest posts by saki (see all)
- Ext, Angular, React, and Vue - June 27, 2019
- The Site Resurgence - February 11, 2018
- Configuring ViewModel Hierarchy - June 19, 2015
re: Konstantin
I think that is a limitation of Ext, since direct Observable descendents to not take the “plugin” property. tried it on a RowSelectionModel instance and it failed as well.
Very useful stuff indeed. My approach of what I started today before i found your blog post was an event broker component that would pool all events that are relayed to it. Although I do prefer your solution of a message bus.
However, my approach was hooking the necessary code right into Ext.util.Observable, so that all objects that are descendants of Observable could communicate (right now anything thats not of the Component class won’t accept plugins). However, I failed to override Ext.util.Observable properly, my skillz are not at leet 😉
I’d love to any pointers by anyone on how to override Ext.util.Observable properly, since it seems to be quite different to overriding Component, to fit the code into the override and have the messagebus be accessible by any descendant of Observable.
Take a look at forum and/or learn section of http://sencha.com/learn Hint: override constructor.
Very nice idea. I’m gonna use this for my current project as to reduce the coupling.
I am little confused about how the actual filtering is performed. Because the subscription is always done for ‘message’ and the publish always fires the ‘message’ event. Is the filtering used in the publish method?
I am trying to get this to work on ExtJs4..it works allright..but Its basically working by creating a listener for message and firing an event on it. No subject filtering as expected. What am I doing wrong?
Can you write the example by using msgbus plugin in Object Oriented manner ?
Why because if components are there in a single page it is nicely working.. But i want in object oriented manner i dont’t know how to do it in OOP style ?
If multiple component are in the same page then it is working fine ..but if in the object oriented manner how can i use publish/subscribe methods and most importantly where i use these methods in the component –
for Ex- component 1(Ext.panel) having button and on button click i want to open a component 2 (Ext.panel) then how & where i need to put publish and subscribe by using message bus plugins …… please give me suggestion because of this i am not able to use correctly the message bus functionality .
Hello, Saki!
First of all, thanks so much for all of your superb work – you seem to be everywhere (ExtJs is) ! 🙂
Secondly, I wanted to ask you a question about the MsgBus. It probably is a broader question about the JavaScript scope and area of visibility.
If I have 2 segments of JavaScript code within my HTML page code (that is 2 … chunks, separated by other HTML), each of the chunks rendering some UI, is it possible to use a MsgBus instance to communicate between the 2 interfaces?
Thanks.
Saki, it would be nice to see a syntax highlighter in your blog to be able to read easily code!
It shortly stopped to work after port. Syntax highlighter should be now up and running.
Hello,
I cannot get http://examples.learnfromsaki.com/?ex=msgbus example.
Is it available yet?
Jean-Marc
Yeah it doesn’t work for some reason. I’m now away but I’ll take a look in a week or so.