How to integrate qooxdoo and PubNub? - qooxdoo

PubNub works by calling callback functions you specify like this:
http://www.pubnub.com/account-javascript-api-include
How to integrate this properly with the Qooxdoo JS framework?
Qooxdoo application looks like this:
http://demo.qooxdoo.org/current/playground/#Hello%20World-ria
How do you load the external JS library and make the global "PUBNUB" available?

You could easily use the add-script config key, to load the pubnub-*.min.js before your app. Then add the PUBNUB.subscribe() call anywhere in your qooxdoo code where it suits you, e.g. in the main method of your main class or in an event handler of a GUI element like a button.
EDIT:
To add more details:
You add the add-script key in config.json, in the "jobs" section.
As you need the script in both the source and the build version, you should add it to the source-script and the build-script jobs, or you create a separate job for the key and extend source-script and build-script with it (that would I do).
The warning about the job shadowing is only to alert people that inadvertently use a pre-defined job name for self-defined job. But here this is exactly what you want, and you can silence the warning with the config-warnings key if you wish. But this doesn't affect the built app.
As for the definedness of PUBNUB you might run into a timing issue where your code using PUBNUB is already executed when the pubnub script file has not finished loading. In your running app, first check in the command line (e.g. Firebug or Chrome Developer Tools) if the PUBNUB symbol is known. If so, the loading was successful. In that case you might want to delay access to the PUBNUB symbol in your code, e.g. by placing it in an execute listener of a button.
Here is a fragment of the possible config.json entries:
...
"jobs" : {
"add-pubnub" : {
"add-script" : [
{
"uri": "http://cdn.pubnub.com/pubnub-3.3.min.js"
}
]
},
"source-script" : {
"extend" : ["add-pubnub"]
},
"build-script" : {
"extend" : ["add-pubnub"]
}
...

Related

Sencha - Conditionally adding namesapce in requires

I have a requirement that I want to add namespaces in requires conditionally.
e.g. In below example I want to add 'views.popupgrid' name space on specific condition. Currently it's always loaded.
requires: ['Ext.window.MessageBox','views.popupgrid','user.MyUser' ]
Conditional dependencies are not supported by the Sencha toolchain. While you would be able to write in a text editor of your choice
requires:[
(location.hash=='#test')?'testpopup':'normalpopup'
]
and this would work in the uncompiled version, Sencha Cmd would not be able to compile it correctly, and would throw errors.
Therefore, Sencha Architect does not support this syntax.
What you can do, while staying Standards-compliant: you can use Ext.Loader.loadScript, e.g. like this:
Ext.define('MyForm',{
extend: 'Ext.form.Panel'
initComponent:function() {
var me = this;
me.callParent(arguments);
if(x==3) Ext.Loader.loadScript({
url:'MyCustomFormComponent.js',
onLoad:function(){
me.add({
xtype:'mycustomformcomponent'
});
})
});
}
})
Please note that in this case you will always have to deliver MyCustomFormComponent.js alongside the minified app.js, because the dependency cannot be resolved by the toolchain. Also, depending on the connection, there may be a visible delay before the resource is loaded and the component is added to the form.
It is usually faster and smoother to always load the dependency, especially if you intend to deliver the app as a single minified javascript file (e.g. using Sencha Cmd).

Trigger Google Analytics pageview for Angular App while using Google Tag Manager

I am building a SPA using Angular.js. We use Google Tag Manager to load in most of our analytics/marketing scripts, which includes Google Analytics. I am also using ui-router to manage states/views.
I would like to send pageview events off to Google Analytics whenever a user browses to a different state in my app. Part of the complexity in doing this with GTM is that GTM creates a named tracker. That means that all GA events need be prepended with the tracker name. That would usually look like this:
ga('trackerName.send', 'pageview', {page: '/a/path/', title: 'A Title'});
GTM uses a randomly generated tracker name, so the tracker name needs to be grabbed at runtime. That can be done fairly simply with GA's getAll function. If you want to send the pageview event to all trackers, you would simply do:
var allTrackers = ga.getAll();
for(var i=0; i<allTrackers.length; i++) {
ga.send(allTrackers[i].getName()+".send", "pageview", {page: '/a/path', title: 'A Title'});
}
This works great for most of my pageview events. However, there is a race condition between when ui-router fires the initial view's $stateChangeSuccess (which is where I trigger the GA pageview), and when analytics.js is loaded.
Prior to analytics.js being loaded, Google Analytic's snippet creates a faux ga object, that you can send events to. This faux object does not have the rest of the ga functions on it, so you can not run getAll. Without the getAll function, I cannot get the tracker name and I cannot send pageview events.
As far as I can tell, Google Analytics does not provide any callbacks or events for when analytics.js is finished loading, so there is no way to tell when I will be able to start sending events. Right now I am using an $interval to check for the existence of ga.getAll, but that is not a very performant or ideal solution. This is what I've got:
gaCheckInterval = setInterval(function() {
if(typeof(ga) !== 'undefined' && typeof(ga.getAll) == 'function') {
clearInterval(gaCheckInterval);
sendBackloggedEvents();
}
}, 200);
Is there any other way to recognize when analytics.js has finished loading? Or any other way to send events to a named tracker, without having access to getAll?
Attempting to configure and trigger individual trackers circumvents the purpose of using a tag manager. Instead do:
dataLayer.push({event:'spa.pageView', page:..., title:...});
Where:
dataLayer is optionally renamed in the gtm snippet
spa is a handy abbreviation for your app/project/company/whatever in case you need to distinguish its actions later.
page and title can be whatever you like, you will reference them by adding dataLayer macros in your GTM container.
Then, in the tag manager you configure:
rule of {{event}} ends with pageView.
dataLayer macros for the page, title you are pushing into the dataLayer.
UA Tag (and later whatever else) to fire (1) and use the macros in (2) for the TAG parameters they override.
Repeat (3) as many times as you like for different UA properties with additional blocking rules, alternate macros or more granular firing rules as necessary.
Now you can configure the specifics and add other tag types that reuse the rules and macros without modifying the application for each change.

Sencha AlternateClassName do not work in compiled version

I'm working in a Sencha application.
I've created a couple of Utilities classes as singleton components (helpers, services, etc).
I'm using alternateClassName to have a shorter name for those classes.
It works perfect, but stop working after compiling for production.
I don't know why, and need help to get this working!
Looks to the following example:
I've created a demo application using sencha cmd for simplicity. The application is "Demo".
The whole application is as default, but I've added a util folder inside app, with a single file Helper.js. This is the code:
Ext.define('Demo.util.Helper', {
singleton: true,
alternateClassName: 'Helper',
test: function () {
alert('It works !');
}
});
Then, I just need to update app.js to require this new file, and update the launch function to call test method after add the main view. So here is the code to use in app.js:
requires: [
'Ext.MessageBox',
'Demo.util.Helper'
],
The launch function:
launch: function () {
// Destroy the #appLoadingIndicator element
Ext.fly('appLoadingIndicator').destroy();
// Initialize the main view
Ext.Viewport.add(Ext.create('Demo.view.Main'));
Helper.test();
},
Now, if I try the example, after load the app, an alert msg is shown successfully.
But after compile it using sencha cmd
sencha app build production
I get this error:
I know the problem is with alternate class name, because if I use the full name (instead of alternate class name), it works anyway. But I want to use alternate class name, otherwise it doesn't make any sense.
Any idea on what's wrong with compiled version ?
TIA!
Milton
After some time, we realized that Sencha has a bug when compiles singleton classes for production (works on testing also).
The solution was to remove the singleton flag, and create application variable for all of the singleton classes, in the launch method.
For example:
Demo.Helper = Ext.create('Helper');
Hope this help!
UPDATE
Last version of Sencha Cmd is full of freaking bugs!
I found a lot of other issues after fixing this ones, and finally, I found this link http://www.sencha.com/forum/showthread.php?288972-MyAppName.app-not-working-on-build-production&p=1064635

Angular translate extend existing translations

I am trying to have external modules change my $translateProvider.translation on the main module. see this as a "tranlation plugin" for my app.
it seems like changing translations from the $translate service is not possible.
mymodule.service('MyService', function ($translateProvider) {
var lib = function () {
//EDITED FOR BREVITY
this._registerTranslations = function (ctrl) {
if (!ctrl.i18n) return;
for (var name in ctrl.i18n) {
/////////////////////////////
// THIS IS THE PLACE, OBVIOUSLY PROVIDER IS NOT AVAILABLE!!!!
$translateProvider.translations(name, ctrl.i18n[name]);
//////////////////////////////
}
};
//EDITED FOR BREVITY
};
return new lib();
});
anyone with a bright idea?
So, to answer your question: there's no way to extend existing translations during runtime with $translate service without using asynchronous loading. I wonder why you want to do that anyway, because adding translations in such a way means that they are already there (otherwise you would obviously use asynchronous loading).
Have a look at the Asynchronous loading page. You can create a factory that will load a translation from wherever you want.
I created an Angular constant to hold new translations. If I want to add a new translation, I add it to the constant. Then in my custom loader, I first check the constant to see if the translation exists (either a new one, or an updated one). If so, I load it from the constant. If not, I load it from a .json file (or wherever you load your initial translations from). Use $translate.refresh() to force translations to be reloaded and reevaluated.
Demo here
The demo is pretty simple. You would need to do a little more work if you wanted to just change a subset of the translations, but you get the general idea.
From the AngularJS docs (https://docs.angularjs.org/guide/providers):
You should use the Provider recipe only when you want to expose an API for application-wide configuration that must be made before the application starts. This is usually interesting only for reusable services whose behavior might need to vary slightly between applications.
Providers are to be used with the application's .config function. $translateProvider for configuration, $translate for other services and controllers.

UI testing an ExtJS webapp using CasperJS/PhantomJS

I'm working on UI testing an ExtJS web-app, and I'm a beginner.
I am trying to test the ExtJS widgets by using CasperJS/PhantomJS tool.
Also, I generate the required CasperJs script using Resurrectio and by making necessary changes to it.
Since ExtJs generates unique ids dynamically for the DOM elements that it creates, I want to know how to provide those ids in CasperJs script for testing.
For example, The following Casper Script was generated by Resurrectio:
casper.waitForSelector("#ext-gen1142 .x-tree-icon.x-tree-icon-parent",
function success() {
test.assertExists("#ext-gen1142 .x-tree-icon.x-tree-icon-parent");
this.click("#ext-gen1142 .x-tree-icon.x-tree-icon-parent");
},
function fail() {
test.assertExists("#ext-gen1142 .x-tree-icon.x-tree-icon-parent");
});
casper.waitForSelector("#gridview-1038",
function success() {
test.assertExists("#gridview-1038");
this.click("#gridview-1038");
},
function fail() {
test.assertExists("#gridview-1038");
});
Here #ext-gen1142 and #gridview-1038 are the ids dynamically created. How should one provide data in the tests? Is there any stub or mocking tools which works with ExtJs in the code to provide these ids at runtime during tests?
I came across SinonJS. Can it be used or Do I need to used CSS or XPath Locators as mentioned in this answer? How reliable it is to use CSS or Xpath Locators?
Thanks in advance!
Not so easy to answer this, but here a few thoughts...
Don't rely on generated IDs. Never. They'll change in moments you won't like and if you have luck very much earlier.
Your best friends will probably be pseudo CSS classes you attach to your components. You could also use IDs, but this is only reasonable when you have elements which occur only once in your page. If that is the case, they are very good anchors to start with selections/queries.
XPath with ExtJS is possible, but you have to carefully choose the elements. ExtJS is so verbose in generating little things so your paths can be quite complicated. And when Sencha drops support for problematic browsers (IE < 8) maybe they change their templates and your XPath doesn't find anything.
SinonJS is great. But it won't help you much in DOM problems. But sure you can use it in your tests. I suppose it will payoff most in testing parts of your controllers or non-trivial models.
Model your test components after your real UI components and screen sections. Don't just record a script. Test code should be engineered like production code. If you create reusable components of test code and logic, you don't have to fear changes. In the best case the changes in one component will only touch the testing code of that particular component.
I know you have ExtJS. But take some time to look at AngularJS and see how easy it can be to test all parts of a JavaScript web application. I'm not saying you should switch to AngularJS, but you can learn a lot. Have a look at Deft JS as it has many concepts which enhance testability of ExtJS applications.
I use Siesta for my ExtJs testing. It works amazingly good for all JavaScript (jQuery based and others), but is specifically designed for ExtJS/Sencha Touch.
It has the feature to combine CSSquery and ComponentQuery to select your elements I think that will fix a lot of problems for you.
In the paid version there is even a test recorder to record scenario's and use them for your tests.
Here's a demo
Here's some sample code:
StartTest(function(t) {
t.chain(
{ waitFor : 'CQ', args : 'gridpanel' },
function(next, grids) {
var userGrid = grids[0];
t.willFireNTimes(userGrid.store, 'write', 1);
next();
},
{ waitFor : 'rowsVisible', args : 'gridpanel' },
{ action : 'doubleclick', target : 'gridpanel => .x-grid-cell' },
// waiting for popup window to appear
{ waitFor : 'CQ', args : 'useredit' },
// When using target, >> specifies a Component Query
{ action : 'click', target : '>>field[name=firstname]'},
function(next) {
// Manually clear text field
t.cq1('field[name=firstname]').setValue();
next();
},
{ action : 'type', target : '>>field[name=firstname]', text : 'foo' },
{ action : 'click', target : '>>useredit button[text=Save]'},
function(next) {
t.matchGridCellContent(t.cq1('gridpanel'), 0, 0, 'foo Spencer', 'Updated name found in grid');
}
);
})

Resources