I'm trying to get Sencha Touch to listen to the events phonegap gives off, any help I can find online only points to sencha events. I've also tried setting up listeners and " .on " but it doesn't seem to work on outside events.
I'm not talking about any specific event, just any event like 'resume', or 'batterystatus'.
Please don't reply with a reference to Ext.device because Sencha support for Ext.device is limited and outdated as it always has been when one company tries to provide a wrapper around a different company, I'd like to take full advantage of all the features the most up-to-date phonegap version offers.
You should be able to add PhoneGap-specific listeners like this:
document.addEventListener("deviceready", function() {
document.addEventListener("backbutton", MyApp.backButtonListener, false);
document.addEventListener("menubutton", MyApp.menuButtonListener, false);
}, false);
MyApp.backButtonListener = function(e) {
e.preventDefault();
//do other stuff here...
}
MyApp.menuButtonListener = function(e) {
e.preventDefault();
//do other stuff here...
}
You can do something like this, I have tested it and it's working!
Ext.application({
name: 'TestApp',
...
launch: function() {
// Hook up events of PhoneGap here
document.addEventListener("pause", this.onPause, false);
document.addEventListener("resume", this.onResume, false);
// Destroy the #appLoadingIndicator element
Ext.fly('appLoadingIndicator').destroy();
// Initialize the main view
Ext.Viewport.add(Ext.create('TestApp.view.Main'));
},
onPause: function() {
// this code is fine but using 'this' here is not safe
console.log("onPause");
},
onResume: function() {
console.log("onResume");
}
...
});
Edited:
Turn out it's not a very good idea to put the handler in the app.js file (although it will still work anw). Because if you upgrade sencha, it expects this file not to be modified much.
So you should instead put it in your launch function of a main controller. Controllers' launch function are executed after Application's launch function.
Ext.define('TestApp.controller.Main', {
extend: 'Ext.app.Controller',
...
launch: function() {
// Hook up events of PhoneGap here
document.addEventListener("pause", this.onPause, false);
document.addEventListener("resume", this.onResume, false);
},
onPause: function() {
// this code is fine but using 'this' here is not safe
console.log("onPause");
},
onResume: function() {
console.log("onResume");
}
...
});
Related
The magiczoom documentation describes callbacks that will execute at given times, but it's unclear how to use or assign those callbacks.
For example, how would I print a console message onZoomReady?
The closest I've found is a MagicZoom.defaults.onready property, but it's unclear how to set it via javascript (my attempts aren't working as expected).
The callbacks are configured via mzOptions, for example:
var mzOptions = {
onZoomReady: function() { … } }
;
Or:
var mzOptions = {};
mzOptions.onZoomReady = function() { … };
You can do something like this:
MagicZoom.registerCallback('onUpdate',
function() {
console.log('onUpdated', arguments[0], arguments[1], arguments[2]);
});
That will log stuff in the console like this:
onUpdated (id-of-mz-wraper) (html of old element) (html of new element)
Other options that you can use are as per the documentation:
MagicZoom.registerCallback('onZoomReady', function() {
console.log('onReady', arguments[0]);
});
MagicZoom.registerCallback('onZoomIn', function() {
console.log('onZoomIn', arguments[0]);
});
MagicZoom.registerCallback('onZoomOut', function() {
console.log('onZoomOut', arguments[0]);
});
Following is a minimal casper script that does a Google query. I've added casper.on('click' ...) prior to running the script, but it doesn't appear to get triggered.
What am I missing?
// File: google_click_test.js
"use strict";
var casper = require('casper').create();
casper.on('click', function(css) {
casper.echo('casper.on received click event ' + css);
});
// ================================================================
// agenda starts here
casper.start('https://google.com', function g01() {
casper.echo('seeking main page');
});
casper.then(function a02() {
casper.waitForSelector(
'form[action="/search"]',
function() {
casper.echo("found search form");
},
function() {
casper.echo("failed to find search form");
casper.exit();
});
});
casper.then(function a03() {
casper.fillSelectors('form[action="/search"]', {
'input[title="Google Search"]' : 'casperjs'
}, false);
});
casper.then(function a04() {
casper.click('form[action="/search"] input[name="btnG"]')
casper.echo('clicked search button');
});
casper.run();
Output:
Here's the output. I would expect to see casper.on received click event somewhere, but it seems that it didn't get triggered:
$ casperjs --ignore-ssl-errors=true --web-security=no google_click_test.js
seeking main page
found search form
clicked search button
$
Although your example runs fine for me using casperjs 1.1.0-beta3 and phantomjs 1.9.8, I've been having similar issues in the last few months with casperjs. Sadly it seems that the author has stopped maintaining the project. More information here:
https://github.com/n1k0/casperjs/issues/1299
I would suggest moving to a different testing framework. In my case I chose a combination of mocha + chai + nightmarejs. This gist is a good starting point:
https://gist.github.com/MikaelSoderstrom/4842a97ec399aae1e024
deftjs looks really promising as it adds exactly the necessary things I missed in the MVC implementation of ExtJs.
What I actually miss is a functionality that makes routing possible/ easy. Extjs has a Ext.ux.Router functionality but I formerly used code like this with help of this lib:
initRoutes: function () {
var me = this;
Log.debug('Books.controller.App: initRoutes');
//use PATH.JS library until ExtJs supports routing as Sencha Touch 2.0 does. (see utils\Path)
Path.map("#/home").to(function () {
me.getController('Home').index();
});
Path.map("#/trackingsheet").to(function () {
me.getController('TrackingSheet').index();
});
Path.root('#/home');
Path.listen();
}
As the procedure of creating the crucial parts in deftjs is now exactly the other way around (view creates the controller) I certainly cannot refer to a controller's method and instantiate the view and make it the visible one. I have a pretty simple card layout here - what means only one view can be visible at a time, it is not necessary to go any deeper like this (e.g. make a task pane visible or the like).
What is the preferred way to do it?
I can think of making the Viewport a view factory having some methods like the controller before.
Thanks,
da5id
I solved this problem by using Ext.util.History class in a history context class that can raise an event when the hash changes:
Ext.define('myApp.context.HistoryContext', {
mixins: {
observable: 'Ext.util.Observable'
},
constructor: function(config) {
var me = this;
if (config == null) {
config = {};
}
this.initConfig(config);
Ext.util.History.add('home');
//init Ext.util.History; if there is a hash in the url,
//controller will fire the event
Ext.util.History.init(function(){
var hash = document.location.hash;
me.fireEvent('tokenChange', hash.replace('#', ''));
});
//add change handler for Ext.util.History; when a change in the token occurs,
//this will fire controller's event to load the appropriate content
Ext.util.History.on('change', function(token){
me.fireEvent('tokenChange', token);
});
this.mixins.observable.constructor.call(this);
this.addEvents('tokenChange');
return this.callParent(arguments);
}
});
Then you can inject this context in to your controller, and observe the token change, and implement the action in dispatch method:
Ext.define('myApp.controller.HomeController', {
extend: 'Deft.mvc.ViewController',
inject: [
'historyContext'
],
control: {
appContainer: {},
home: {
click: 'addHistory'
},
about: {
click: 'addHistory'
}
},
observe: {
historyContext: {
tokenChange: "dispatch"
}
},
init: function() {
return this.callParent(arguments);
},
switchView: function(view) {
//change this to get the cards for your card layout
this.getAppContainer().add(Ext.ComponentMgr.create({
xtype : view,
flex : 1
}));
},
addHistory: function(btn) {
var token = btn.itemId;
Ext.util.History.add(token);
},
dispatch: function(token) {
// switch on token to determine which content to load
switch(token) {
case 'home':
this.switchView('view-home-Index');
break;
case 'about':
this.switchView('view-about-Index');
break;
default:
break;
}
}
});
This should be ok for the first level routing (#home, #about), but you need to implement your own mechanism to fetch the token for the second and third level routes. (#home:tab1:subtab1) You can possibly create a service class that can handle fetching the hash and inject the service to each controllers to dispatch.
For further discussion in this topic, go to https://github.com/deftjs/DeftJS/issues/44
I have an app with a carousel. On all of the carousel pages there are elements such as buttons and datepickers. I would like to handle the tapStart event on each of these elements using Sencha Touch but I haven't been able to find anything to allow me to do this.
Does anyone have an idea?
UPDATE
I asked this question on the Sencha Forums as well. Here is the link to the Sencha Forum thread: http://www.sencha.com/forum/showthread.php?262804-Handle-tapStart-Event-on-a-button&p=963782#post963782
You can try using touchstart which can be bound to any element including button
I figured out a solution to my problem with help from the Sencha Touch Forums.
First I used the initConfig function to initialize my configuration of my container.
Ext.define('MyApp.view.ViewName', {
...
// Very Important, this is what I use in the controller to handle the events
xtype: 'myxtype',
...
initConfig: function () {
var me = this;
this.config = {
...
items: {
...
{
xtype: 'button',
...
listeners: {
element: 'element',
// This is where my code handles the tapstart
// (touchstart) event
touchstart: function () {
// Fire an event on the controller (me)
me.fireEvent('buttondown');
}
}
},
...
}
}
this.callParent([this.config]); // Very Important when using initConfig
}
});
Then, in my controller I added this code:
Ext.define('MyApp.controller.MainController', {
...
config: {
views: [
'ViewName',
...
],
...
},
...
init: function () {
this.control({
'myxtype': {
buttondown: this.myFunction
}
})
},
myFunction: function () {
// Do something
}
});
I made this jQuery plugin called removable when you click the objects button it slides up and should trigger a custom event like onDone.
Here's what I did (The codeing format is based on jQuery's http://docs.jquery.com/Plugins/Authoring):
init: function(){
return this.each(function(){
$('a', this).click(function(){
$(this).parent().slideUp(function(){
// Somehow trigger the onDone method
})
});
})
},
onDone: function(){
// Default action
},
and this is what I've done when calling the plugin
$('li').removable({
onDone: function(){
// Overwrite default action
},
})
How can this be done?
If all you need is to call it at the end of the animation, just pass it as the second argument to slideUp or even just call it with $(foo).MyPlugin.onDone() inside the callback function.
otherwise look at trigger and bind jQuery functions - you can use any string you want for those event types so you can trigger and bind a MyPluginDone event
EDIT: based on comments you want something simpler -
As it states in the article you quoted, the best way to provide override-able defaults to options is to have your plugin accept an options object, then to get the combined defaults+overrides you do:
var combinedOpts = $.extend({},defaults,overrides);
and get all the values to use from there...
Try this one.
(function($){
jQuery.fn.extend({
removable: function(options) {
var defaults = {
onDone: function(){alert('default action');}
};
var options = $.extend(defaults, options);
return this.each(function() {
$('a', this).click(function(){
$(this).parent().slideUp(function(){
options.onDone.call();
});
});
});
}
});
})(jQuery);
$('li').removable({
onDone: function(){
alert('Overwrite default action');
},
})