This article focuses on how to support SQLite (Web SQL) on the following platforms:
  • Android
  • iOS
  • Windows Phone

Why should a SQLite Plugin used in Cordova?

  • To follow the HTML5 Web SQL API as close as possible.
  • To support Web SQL on Windows Phone.
  • To deal with the same javascript functions on every platform.
  • Fail-safe nested transactions with batch processing optimisations.
  • Keeps sqlite database in a user data location that is known, can be reconfigured, and iOS will be backed up by iCloud.
  • Works with SQLCipher for encryption.

  Limitations of SQLite on Windows Phone

  • Drop table is not working, seems like a bug in the .NET or C# SQLite library. To work around this, empty the table instead of dropping it.
  • A high number of features in C# SQLite are disabled.
  • Missing failure-safe transaction mechanism.
  • Not (yet) working with SQLCipher for encryption.

What do I have to change in my existing applications?

Not much.

Just replace "window.openDatabase" with "window.sqlitePlugin.openDatabase".

Don't forget to take a look at the limitations of Windows Phone Plugin.

How to install the SQLite Plugin

There are so many SQL Plugins available. I choose "lite4cordova", because it supports Cordova 3.x, it is easy to install and it is still in development.
  • https://github.com/lite4cordova/Cordova-SQLitePlugin
  • https://github.com/lite4cordova/Cordova-SQLitePlugin-WP-2013.12
The second project is an extension of "Cordova-SQLitePlugin", because Windows Phone is not working on "Cordova-SQLitePlugin" yet.

Windows Phone 8

If you are starting to develop for Windows Phone, have a look at this article first.

To setup the project, type the following commands in the command line:
$ cordova create hello com.example.hello Hello
$ cd hello
$ cordova platform add wp8
$ cordova plugin add https://github.com/lite4cordova/Cordova-SQLitePlugin-WP-2013.12.git

Remove all files in "hello/www", except "config.xml".
Copy the testfile to "hello/www".

To build the project type the following commands in the command line:
$ cd hello
$ cordova build

Finish! Open and run the project, execute the testfile to see if all works fine.

Android and iOS

To setup the project, type the following commands in the command line:
$ cordova create hello com.example.hello Hello
$ cd hello
$ cordova platform add android
$ cordova platform add ios
$ cordova plugin add https://github.com/lite4cordova/Cordova-SQLitePlugin.git

Remove all files in "hello/www", except "config.xml".
Copy the testfile to "hello/www".

To build the project type the following commands in the command line:
$ cd hello
$ cordova build

Finish! Open and run the project, execute the testfile to see if all works fine.


In the early years of the Internet, it was possible to breach users security by using of JavaScript to exchange information from one website to another that has less reputation.

Therefore, all modern browsers implement the same origin policy that prevents attacks like cross-site scripting.

However, sometimes cross-origin HTTP request is a must-have requirement for a web application. This article will discuss about methods of how to deal with cross-origin HTTP requests. Lets start with some background information.

Origin policy

The algorithm used to calculate the "origin" of a URI (Uniform Resource Identifier) is specified in RFC 6454.

There are two different cases:
  1. Absolute URIs, the origin is the triple {protocol, host, port}
  2. If the URI does not use a hierarchical element as a naming authority (RFC 3986) or if the URI is not an absolute URI, then a globally unique identifier is used.
Two resources are considered to be of the same origin if and only if all these values are exactly the same.

The table below illustrates a check against the URL "http://www.example.com/pages/index.html":
URL to compare Result Why?
http://www.example.com/pages/index2.html ok Same host and protocol
http://www.example.com/pages2/index.html ok Same host and protocol
httpː//username:password@http://www.example.com/pages/index.html ok Same host and protocol
http://www.example.com:8080/pages2/index.html fail Same host and protocol, but different port
https://www.example.com/pages/index.html fail Different protocol
http://sub.example.com/pages/index.html fail Different host
http://example.com/pages/index.html fail Different host
http://www.example.com:80/pages/index.html - (Different port) Depends on the browser implementation


If the policy cannot be applied, the web browser will respond with an exception message, such as the following:

XMLHttpRequest cannot load ...
Cross origin requests are only supported for HTTP.
Uncaught NetworkError: A network error occurred.

Relaxing the same origin policy

Here are some techniques to relax with origin policy:
  • JSONP. If the requirement was to get only the data from a different domain, then a JSONP request is the best choice. JSONP includes external data via the <script> tag.
  • Cross origin resource sharing. This extends HTTP with a new origin request header and a new Access-Control-Allow-Origin response header. This article describes how to enable CORS.
  • Disable web security (for development mode only). If an application is under development, the web security can temporarily disabled for the web browser. While the web browser is in an unsecured mode, it is highly recommended not to surf on public Internet pages (since the browser is vulnerable for all cross site scripting attacks). See "Disable web security for a web browser".
  • Reverse Proxy. A reverse proxy (or gateway), by contrast, appears to the client just like an ordinary web server. No special configuration on the client is necessary. The client makes ordinary requests for content in the name-space of the reverse proxy. The reverse proxy then decides where to send those requests, and returns the content as if it was itself the origin. See "Setup a reverse proxy".
  • Whitelist (PhoneGap). If a web application is deployed to a mobile device with PhoneGap the domain can whitelisted (Whitelist Guide).

Disable web security for a web browser

For Google Chrome, the following command must executed in Terminal (browser must be closed):

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --disable-web-security

Setup a reverse proxy

Nowadays there are many http servers on the market, however this article focuses on how to configure a reverse proxy with XAMPP.

Install XAMPP

XAMPP is a free and open source cross-platform web server solution stack package, consisting mainly of the Apache HTTP Server, MySQL database, and interpreters for scripts written in the PHP and Perl programming languages.

You can download XAMPP here http://www.apachefriends.org/en/xampp.html.

Configure a virtual host

A virtual host gives you the possibility to run several name-based web applications on a single IP address.

Configuring the virtual host on your web server does not automatically cause DNS entries to be created for those host names. You can put entries in your hosts file for local testing.

Make a local host file entry

  1. Open your Terminal.
  2. Type: "sudo vi /private/etc/hosts" to open the host file.
  3. Add the following entry "127.0.0.1 local.app.com" to the end of this file. You can modify this domain name to your needs.
  4. Save the file and close it.

Configure XAMPP

  1. Open your Terminal.
  2. Open the XAMPP virtual host file. "sudo vi /Applications/XAMPP/etc/extra/httpd-vhosts.conf"
  3. Add the following virtual host entry to the end of this file:
<VirtualHost *:80>
  DocumentRoot "/Volumes/workspace/myHtml5App"
  ServerName local.app.com
  ProxyPass       /service.php       http://yourExternalHost.com/communication/service.php
</VirtualHost>

Short explanation:
  • "*:80" Listen for virtual host requests on all IP addresses.
  • "DocumentRoot" Destination of the web application on the filesystem.
  • "local.app.com" Server name, must be the same name as in the host file above.
  • "ProxyPass" Proxy path holds the service address.
Before you restart the server, make a quick check to the httpd.conf file. ("sudo vi /Applications/XAMPP/etc/httpd.conf").

Make sure that the following entries are not commented with a "#"
  • "Include /Applications/XAMPP/etc/extra/httpd-vhosts.conf"
  • LoadModule proxy_module modules/mod_proxy.so
  • LoadModule proxy_connect_module modules/mod_proxy_connect.so
If all is fine, restart your server.

If you call "local.app.com" in your browser, the web application should open. But you will still receive a cross origin policy exception, because your web application still sends the requests to "http://yourExternalHost.com/communication/service.php".

To fix this, replace the URL "http://yourExternalHost.com/communication/service.php" with "local.app.com/service.php" in your web application.


You might want to try to run Cordova with Windows Phone. The first thing that came up when I started with this project was, that the Cordova (PhoneGap) documentation is really lack of information. So I wrote this article to make it easier for you to make a successful and even quicker installation.



Note: This installation guide can be used for both, physical machine and Virtual Machine. There are a lot of Virtual Machine servers available on the market. I decided to focus on VMWare Fusion only, but it is also possible to use software like Parallels.

Before you start

It is very important that you have a 64 bit version of Windows 8 installed, otherwise it will not work.

The Windows Phone simulator relies on Hyper-V, which only comes with Windows 8 64 bit.

In case you did not installed, a evaluation ISO (Windows 8 64 bit) can downloaded at the evaluation center.

Configure the Window 8 installation for WP 8 simulator

The first thing you need to do is to prepare the Windows 8 installation for Windows Phone 8 simulator.

Choose your target system (Virtual Machine or Physical System):

Windows 8 installation on a VM

To make the required Virtual Machine settings, use the VMWare Fusion settings below:




Important:
  • Hyper-V requires at least two cores. Of course, for a better performance you can also set more.
  • You should use 2048mb RAM at the minimum, because not only Windows will consume RAM, also the simulator will consume another 256-512mb of RAM.
You also have to modify the "*.vmx" file. Add the lines below to the end of the vmx file:
  • hypervisor.cpuid.v0 = "FALSE"
  • mce.enable = "TRUE"
  • vhv.enable = "TRUE"
Make sure that you have no duplicate keys in this file.

Windows 8 installation on a physical machine

To be able to run the Windows Phone simulator on a physical Windows 8 machine, you have to enable hardware-assisted virtualisation in the BIOS. For more information, take a look at this article:

Install Microsoft Visual Studio

After the initial Windows 8 configuration you are ready to install Microsoft Visual Studio. Here you have to options:
  1. Using the Visual Studio Express 2012 for Windows Phone edition. This version is free of charge to you, but not recommended by PhoneGap (no templates can be used in the express edition). But since you are able to create PhoneGap projects via CLI, maybe this version is what you are looking for. Go to the Visual Studio Express products.
  2. Installing Visual Studio 2013 Pro / Premium / Ultimate (If you need templates)
In all cases the additional required Windows Phone 8 SDK is already included in the installation package.

Don't forget to enable the WP 8 SDK checkbox while you are installing Visual Studio.

Tip: If you are using VS 2013, Microsoft asks you to authenticate the product with a MS Account. But there is also a way to use the product key. Take a look at this article.

When the installation process of Visual Studio is finished, your computer will be restarted by the installation routine. After the restart, login again, but wait some seconds, the installation process will go on. Wait until you see the "Installation successful" message.

Add the .NET framework directory to the PATH system environment variable

Later on you need the "msbuild.exe" executable your PATH variable. In my case I have to add the following path:
C:\Windows\Microsoft.NET\Framework\v4.0.30319
The path may differ (different version of .NET), so make sure that it matches.

Test the WP 8 simulator

As soon as Visual Studio is completely installed you are able to test the simulator. Open Visual Studio and click on "File" > "New Project".

Go to your preferred language section and select a simple Windows Phone project.

If the project is created, just start the project. The simulator should come up. If the simulator open successfully, you can close Visual Studio. Otherwise follow the further instruction which VS will show to you.

Install Node.js

Those of you who are not familiar with Node.js, Node.js is a platform that is used to build scalable network applications. For more information click here. In this case we use Node.js to install Cordova (PhoneGap).

Just go to http://nodejs.org and install Node.js. The installation process is pretty clear (no custom settings required).
After you installed Node.js, RESTART your computer or Virtual Machine.

Install Cordova

To install Cordova, open "node.js command prompt" and type “npm install -g cordova”.

Fix broken Cordova 3.1.0 version

At the moment Cordova is really a mess. So if you installed the Cordova version above, you have two options: Installing a prior version of Cordova (3.0.x) or fixing the current one.

If you want to fix your current installation, you have to replace the two files in the Cordova installation directory:

~\AppData\Roaming\npm\node_modules\cordova\src\metadata\wp8_parser.js

with

https://github.com/sgrebnov/cordova-cli/blob/181aa1b7e8f3c8b2f7c4db12e1f79d64c26e8b42/src/metadata/wp8_parser.js

and

~\AppData\Roaming\npm\node_modules\cordova\src\platform.js

with

https://github.com/sgrebnov/cordova-cli/blob/181aa1b7e8f3c8b2f7c4db12e1f79d64c26e8b42/src/platform.js

Otherwise you'll receive the following error message when you are creating a Cordova project:

"Error: An error occured during creation of wp8 sub-project. The system cannot find the path specified."

Fix broken Cordova 3.2.0 version

Maybe this error message depends on your type of .NET installation, but with Cordova 3.2.0 I cannot add a WP8 project anymore. The following message is displayed:
The command `msbuild` failed. Make sure you have the latest Windows Phone SDKs installed, AND have the latest .NET framework added to your path (i.e C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319).

To fix this, open "c:\Users\%user%\.cordova\lib\wp\cordova\3.2.0\wp8\bin\check_reqs.js":
Replace:
var msversion = output.match(/Microsoft\s\(R\)\s+Build\sEngine\s[a-z]+\s4\.0\.30319/i);

with:
var msversion = output.match(/\.NET\sFramework\,\sversion\s4\.0/i);
or simply set "var msversion = true;" if you have the right version of "msbuild.exe" in your path variable.

Create the final Cordova project

At this point you are able to build the final Cordova project. As mentioned earlier, I use the CLI of Cordova to create the project, not the Visual Studio templates.
  1. Open the command line and type: "cordova create hello com.example.hello HelloWorld". The first argument specifies a hello directory to be generated for your project. The other two arguments are optional: the com.example.hello argument provides your project with a reverse domain-style identifier, and the HelloWorld provides the application's display text. You can edit both of these values later in the config.xml file.
  2. Open the "hello" folder ("cd hello") which you created above.
  3. Add a WP 8 platform to the current Cordova project. Type "cordova platform add wp8"
  4. Open the Windows Explorer and go to hello/platforms/wp8 and double click on the solution file "*.sln". Microsoft Visual Studio will open with your selected project. Just click the "Run Button" to show up the simulator.

It is a bit tricky to deploy a HTML5 application on a Windows Phone, but I hope this article helps...


Most cookies are disabled by default on Windows Phone. However, here is one workaround to allow cookies. Open Internet Explorer and follow the images below:








After I came back from my last vacation, the first thing I did was updating my system to Mavericks. Of course, I read some recommendations before if it is worse to update or not, but after some researches I thought nothing can go wrong :)

The OS X update itself worked for me like a charm without having any problems, but there was one thing I mentioned first: Java is no more included in OS X 10.9 Mavericks. Ok this was easy to fix. The real problem started after I wanted to build my Sencha Touch application via Sencha CMD.

When I started the Sencha CMD build I received a message, that not the right Ruby version is installed on my system.
[ERR] Detected ruby version 2.0.0 was not less than 2.0. Please install ruby 1.8 or 1.9
After some researches on the web, I found the following information:

  • Ext JS themes use Sass variables whose value are set to "null !default".
  • Sass changed the behavior of such things and broke those themes.
  • Sencha Cmd embeds a version of Sass that is known compatible with Ext JS themes.
  • Ruby 2 changed some API and broke that version of Sass.
So the only solution for my problem was going back to Ruby 1.9 to make my Sencha CMD build working again.

There are a lot of ways to downgrade Ruby, but a very straight forward and easy way by using RVM is described in the following article: http://moduscreate.com/sencha-cmd-not-working-in-os-x-10-9-mavericks/


You've experienced unusual problems trying to share your screen on a MacBook Pro with Retina display? A black screen with a moving mouse cursor is shared?

In this case your current display resolution settings are too high for screen sharing.

To change the resolution of your display, you can use a tool like "Display Menu".

https://itunes.apple.com/gb/app/display-menu/id549083868?mt=12&ls=1

After you changed the resolution, you may have to restart your screen sharing session.


Chrome has a new flex layout support since version 29.0.1547.57, this cause a broken layout in Sencha Touch 2.2.1.

Fix this issue by changing the rule order of the st-box mixin.

Open resources/themes/stylesheets/sencha-touch/base/mixins/_Class.scss in a text editor and replace the mixin st-box with the following:

@mixin st-box($important: no) {
    @if $important == important {
        display: flex !important;
        display: -webkit-box !important;
        display: -ms-flexbox !important;
    } @else {
        display: flex;
        display: -webkit-box;
        display: -ms-flexbox;
    }
}
After re-compiling your css, your application layout should look as nice as in prior Chrome versions.
During the last view days I was evaluating the Sencha Architect (Version 2.2.2). Most of the things that I wanted to implement were not a problem. But then I wanted to add a custom property in the controller section.
config: {
        /**
         * @private
         */
        viewCache: []
}
At first I thought no problem, that is easy. But in the end it has taken some time to find this out. So here comes the trick:

Go to the "Project Inspector". Type the name of your custom property in the search field of the config pane then click the "add" button or hit your enter key. After that you can change the type. See below:


Eclipse is one of the most popular development environment for developers all over the world. Me personally have been using Eclipse for nearly 10 years for many projects. Lately, while working with an intern, I noticed that the performance of his Eclipse is quite slow.

Of course there are many factors that could influence the speed of Eclipse such as the use of poorly written plugins or the wrong user settings. Even the standard installation of Eclipse itself has performance issues.

For years I have been trying to optimise Eclipse performance in many ways. I would like to share with you one trick that I've always do when my Eclipse starts running like an 80 years old man.

Eclipse stores all the changes in a local history. When this history gets bigger, it obviously has some effect on the performance.

In this case, we should release some old entries from the history. The local history can be found at: ".metadata/.plugins/org.eclipse.core.resources/.history".

However, instead of deleting the history entries manually, there is an option to limit the size of the history file. In the "Settings" of  Eclipse, from "Preferences > General > Workspace > Local history" the number of items and days can be set.

Sencha Touch includes some notable features. The function Ext.Function.createThrottled is one of them.

This function prevents multiple function execution. The interval on which the passed function is executed can defined additionally.

Ok, let's take a look into the code:
// The function to execute at a regular time interval.
var fn = function () {

console.log('fired');
};

// The intervall in milliseconds on which 
// the passed function is executed.
var intervall = 5000; // 5 seconds

var myFunc = Ext.Function.createThrottled(fn, intervall, this);

// Excecuted immediately
myFunc();

// No matter how often myFunc() is called,
// it is only executed once and after 5 seconds
myFunc();
myFunc();
myFunc();
myFunc();
myFunc();
myFunc();
Tip: The function can be assigned to a class variable that is initialized via a constructor or init().
Meanwhile, there are many tools on the market for remote debugging, but remote debugging is still damn tricky.

In this post I'd like to introduce http://jsconsole.com in combination with a Sencha Touch application to you.
jsconsole is a simple JavaScript command line tool. However, it also provides the ability to bridge across to other browser windows to remotely control and debug that window - be it in another browser or another device altogether.
First we need to create a new ID for the device that we want to debug. Jump to http://jsconsole.com and enter the following command in the console:
:listen
After the command ":listen" is entered, the following output appear:
As can be seen in the output, a new ID is generated.

Hint: It is also possible to listen to a predefined device. Just type: ":listen <ID>".

The next thing we have to do is to include the script in our application. The script can be integrated as follows in the "app.json":
  "js": [
    {
      "path": "http://jsconsole.com/remote.js?AE61E3FB-7B1B-4367-8DEC-AD476FC9CA5F",
      "update": "full",
      "remote": true
    },
Now any calls to console.log from your application will display the result in the jsconsole session that is listening to your ID.

It is also possible to inject code into the remote application. As a simple example, write "alert ('test');" in jconsole. On the remote application, a message box with the text "test" should appear. Of course it can also be injected much more complex code.
For this reason, this script should never be used in a production environment!

More information about jconsole is available here.


I would like to take this opportunity to explain a few pitfalls that arise when in development with Sencha. This article is designed to help develop Sencha applications faster and more robust.

If you should find that something important is missing or something is wrong, do not hesitate to contact me.

Loading Sencha Framework and external Resources

It is recommended that the Sencha framework is loaded via the Microloader.

The "index.html" should be kept as lightweight as possible to avoid negative side effects. It seems Sencha has problems, for example, when trying to place child elements within the body region.

Below is an example of linking against the Sencha Touch framework:
<!DOCTYPE HTML>
<html manifest="" lang="en-US">
<head>
    <meta charset="UTF-8">
    <title>Your Application</title>
    <script id="microloader" type="text/javascript" src="touch/microloader/development.js"></script>
</head>
<body></body>
</html>
If additional JavaScript files required, these should not be included in the "index.html". Additional JavaScript files and CSS should always defined in the file "app.json".

The defintion of the files in the "app.json ' has the following advantages:
  • Included files are automatically compressed during the Sencha Build process. 
  • Included files can be loaded depending on the target platform. 
  • The application loads faster. 
  • index.html is lightweight.

Styling your Application

When it comes to styling your application, Sencha has a few ways to do this directly in JavaScript. However, this should be avoided. All style information should be defined via CSS or better SASS.
This results in the following advantages:
  • The actual source code is lightweight. 
  • All style information are defined centrally. 
  • The application can be easily edit at the same time by several developers. 
  • The design can be flexibly adapted at any time.

The app.js File

All changes to this file should be as minimal as possible. The reason for this, as soon as a Sencha update is performed, this file must be manually merged with the update.

Using Ext.getCmp()

The use of the function Ext.getCmp() should be largely avoided. The use of this function makes the source code hard to read and maintainable. By using the MVC principle, the function should no longer be needed.
See also MVC in depth Part 1 and MVC in depth Part 2.

In short, if Ext.getCmp() is used, the developer has missed the object-oriented approach.

In many applications, this function is still used to prototype faster or because the programmer does not know better.
When using Ext.getCmp() is essential to make sure that the object exists. I.e. the object must not be 'undefined' when its function is called. Otherwise, the interpreter throws an exception.

Using Ext.Viewport.removeAll() to destroy components

In the life cycle of an application it often happens that components are no longer needed. A good example to log out in an application. It is tempting to destroy all components on the Viewport with the Ext.Viewport.removeAll (http://docs.sencha.com/touch/2.2.1/#!/api/Ext.Container-method-removeAll) command:
Ext.Viewport.removeAll(true, true);
At first glance, all components were destroyed which were located on the Viewport. But what happens if the user now wants to re-login? Furthermore, we assume that the user enters his password incorrectly, and we show via Ext.Msg an error message.
Unfortunately, the following error message is displayed instead Ext.Msg:
Uncaught TypeError: Cannot read property 'dom' of null
Ext.Msg is a singleton instance of Ext.MessageBox. When you do the removeAll(true, true) the second argument is to destroy everything, inner items, docked items and floating items. Ext.Msg is a floating item so you have destroyed Ext.Msg, but you are then trying to use it. Now, if the component is destroyed it ends with the error message above.
It is recommended to destroy all the components separately. Not with "Ext.Viewport.remove" but directly through "myObj.destroy();"

Naming Model, Store and View

In the naming of models, views, and stores should pay attention to the following:
Basically, the name always begins with a capital letter, all the following words also with a capital letter.
  • Model, in the singular. Example: "TrainStation.js" 
  • Store in the plural. Example: "TrainStations.js" 
  • View, in the singular. Example: "TrainStation.js" 
Following this convention, the structure of the application is easier to read and quicker to learn.

JavaScript === versus == (Comparison Operators)

The identity "===" operator behaves identically to the equality "==" operator except no type conversion is done, and the types must be the same to be considered equal.

If values ​​are compared with each other it is recommended to use "===" instead of "==". This makes the program less error prone.

This is also the case for "!==" and "!=".

See also http://www.c-point.com/javascript_tutorial/jsgrpComparison.htm

Stop over nesting the View

When creating new views, make sure that they are as lightweight as possible. I.e. you should not go deeper than it is absolutely necessary in the structure. The use of unnecessary panels is a prime example of this. Is a view nested too deeply, it will have a negative impact on the performance of the application.

Is a view defined with "Ext.View", the view should not contain any action listener. These are defined in the relevant controller. This has the advantage that the view is more legible.

In short, in the view there is no business logic! All business logic should always be to find in the respective controller.

Code Completion

If the application is developed in Eclipse there are two ways to obtain a code completion. The first way is to use Spket. How this works can be found here. The second alternative is to purchase Sencha Complete. This version includes the necessary Eclipse plugins.

JSLINT for better source code

For the development of JavaScript applications, it is recommended to use JSLint. Who JSLint does not know yet, thus it is possible to validate your code against best practices. How to configure Eclipse with JSLint is described here.

Icon fonts instead of the classic icons

One element of themes in Sencha Touch 2.2 is the new use of icons as fonts. This is an awesome feature, because this offers the following new features:
  • size can be easily changed. 
  • color can be easily changed. 
  • shadow can be easily added to their shape. 
  • transparency nearly everywhere, unlike transparent png's in ie6. 
  • smaller in file size 
  • infinitely scaleable (because vector)
The goal of using icon fonts is to replace the need to render icons on a web page using images.

Click here to continue...

Using ComponentQueries instead of Id Config

Avoid using the id config, let ComponentQuery resolve the component using xtype with a property.

For those who are not familiar with ComponentQueries yet, they are used to retrieve pointers to one or many components in the application using a syntax similar to that of CSS selectors.

Let‘s compare the following cases. With Id Config, we define the following Sencha controller:
Ext.define('MyApp.controller.Main', {
    extend: 'Ext.app.Controller',

    config: {
        refs: {
            myButton: '#buttonId'
        },
        control: {
            myButton: {
                tap: 'onButtonTap',
                change: 'onButtonChange'
            }
        }
    },
});

As seen in the above example, we refer to the button with "#buttonId". The code would work for now. But what happens if we destroy the view with the button on it and then re-create the view?

The result is, the "tap" handler fires, but not the "change" listener. The controller reference do not point to the button anymore. The reason being is, the button has been referenced via the config id. As you can clearly see Id Config is lack of flexibility.

Here is the same case, but using the ComponentQuery:

Ext.define('MyApp.controller.Main', {
    extend: 'Ext.app.Controller',

    config: {
        refs: {
            myButton: 'button[id=buttonId]'
        },
        control: {
            myButton: {
                tap: 'onButtonTap',
                change: 'onButtonChange'
            }
        }
    },
});
There is no difference between quoted and unquoted references. myButton and also "myButton" are valid references. 

More about ComponentQueries

ComponentQueries can be built with: 
  • The XTYPE-property
  • Attributes in brackets, i.E. 'button[action=submitForm]' 
  • Functions which return true/false values in curly braces '{isValid()}'
  • The itemId property '#itemId'
  • The 'not' operator. Used to retrieve all components that are not the pointed component. I.E. 'not textfields'
  • Like in css '>' can used for parent and child relationships ('panel > button'). 
  • Multiple queries can be separated by using ','. I.E. 'button, textfield'

Testing ComponentQueries

ComponentQueries are mostly defined in controllers (ref section), but it is also possible to use the singleton object Ext.ComponentQuery (http://docs.sencha.com/touch/2.2.1/#!/api/Ext.ComponentQuery). To run and test a ComponentQuery,  there is a handy option in the JavaScript console. I.E Ext.ComponentQuery.query('panel > button')

Using itemId instead of id

I recommend you not to use the "id" attribute for the identification of components. The problem is that the "id" must be unique throughout the entire application. Replace "id" with "itemId" will avoid this conflict. The itemId property requires uniqueness of value only among child components of a container.

Caution: If the itemId used in a ComponentQuery, the itemId must either pre-qualified via a parent item and/or you could put its xtype#myItemId.

Short example. We  define a button with the itemId="navButton" and the parent container of our button has the xtype="navigation". So our config could look like this:
Ext.define('MyApp.controller.Main', {
    extend: 'Ext.app.Controller',

    config: {
        refs: {
            myButton: 'button#navButton'
        },
        control: {
            myButton: {
                tap: ...
            }
        }
    },
});

While itemIds are not unique throughout the entire application, it is a good advice to put the xtype into the query too. So instead of 'button#navButton' we use the following query: 'xtype button#navButton' to gain more precision:
Ext.define('MyApp.controller.Main', {
    extend: 'Ext.app.Controller',

    config: {
        refs: {
            myButton: 'navigation button#navButton'
        },
        control: {
            myButton: {
                tap: ...
            }
        }
    },
});

Using GLOBAL Variables

It is generally advised not to use global variables. First problem, there is no namespace for these variables. Second problem, the debugging of these variables often proves to be very difficult.
messageText = 'My message text.';
timeout = 5000;
In the above example, the variable "messageText" and "timeout" was defined as global. A better solution is to define these variables in a separate class.
Ext.define('MyApp.util.Config', {
    singleton : true,
    alternateClassName : ['Config'],

    config : {
        app : {
            messageText = 'My message text.'
            //...
        },
        services : {
            timeout = 5000;
            //....
        }
    },
    constructor: function () {
        return this.config;
    }
});
The new class "Config" is included in the "app.js" file via require:
Ext.application({
    name : 'MyApp',

    requires: [
        'MyApp.util.Config'
        //...
    ],
    //...
});
Access to the variables is done with:
Config.app.messageText
Config.services.timeout
Alternatively setter and getter functions can be automatically generated by Sencha. The Config class looks like this:
Ext.define('MyApp.util.Config', {
    singleton : true,
    alternateClassName : ['Config'],
    config: {
        messageText = 'My message text.',
        timeout = 5000
    },

    constructor: function(config) {
        this.initConfig(config);
    }
});
Access to the variables is done with:
Config.getTimeout();
Config.getMessageText();


One element of themes in Sencha Touch 2.2 is the new use of icons as fonts. This is an awesome feature, because this offers the following new features:
  • size can be easily changed. 
  • color can be easily changed. 
  • shadow can be easily added to their shape. 
  • transparency nearly everywhere, unlike transparent png's in ie6. 
  • smaller in file size 
  • infinitely scaleable (because vector) 
The goal of using icon fonts is to replace the need to render icons on a web page using images.

Requirements

To use this new feature it is mandatory to setup your project with SASS. If your project not yet including SASS, take a look at this article "Theming Sencha Touch with SASS".

Out-of-the-box icons

The lightweight Sencha Touch 2.2 default theme already includes some basic icons. It is shipped with 27 icons in total.

The default icon set includes:
action, add, arrow_down, arrow_left, arrow_right, arrow_up, bookmarks, compose, delete, download, favorites, home, info, locate, maps, more, organize, refresh, reply, search, settings, star, team, time, trash and user.
Use the default icons above by typing:
{  xtype: 'button',  iconCls: 'user',  title: 'User'  }

Extend the Out-of-the-box icons

Sencha Touch 2.2 is now using the http://www.pictos.cc/font/ library. When you checkout this website, you'll find out that they have more to offer in terms of icons.

At the first glance, the icon collections on the website might be a little bit confusing. You might ask yourself how does the mapping works between the "iconCls" and the pictos.

Well, when you take a look inside the framework of Sencha Touch 2.2, you will find the following mapping in "Sencha Touch SDK/resources/themes/stylesheets/sencha-touch/base/mixins/_Class.scss":
@function icon-character-for-name($name) {
    // http://pictos.cc/font/

    // Row 1
    @if ($name == "anchor") { @return "a"; }
    @else if ($name == "box") { @return "b"; }
    @else if ($name == "upload") { @return "c"; }
    @else if ($name == "forbidden") { @return "d"; }
    @else if ($name == "lightning") { @return "e"; }
    @else if ($name == "rss") { @return "f"; }
    @else if ($name == "team") { @return "g"; }
    @else if ($name == "help") { @return "h"; }
    @else if ($name == "info") { @return "i"; }
    @else if ($name == "attachment") { @return "j"; }
    @else if ($name == "heart") { @return "k"; }
    @else if ($name == "list") { @return "l"; }
    @else if ($name == "music") { @return "m"; }
    @else if ($name == "table") { @return "n"; }
    @else if ($name == "folder") { @return "o"; }
    @else if ($name == "pencil") { @return "p"; }
    @else if ($name == "chat2") { @return "q"; }
    @else if ($name == "retweet") { @return "r"; }
    @else if ($name == "search") { @return "s"; }
    @else if ($name == "time") { @return "t"; }
    @else if ($name == "switch") { @return "u"; }
    @else if ($name == "camera") { @return "v"; }
    @else if ($name == "chat") { @return "w"; }
    @else if ($name == "settings2") { @return "x"; }
    @else if ($name == "settings") { @return "y"; }
    @else if ($name == "tags") { @return "z"; }

    // Row 2
    @else if ($name == "attachment2") { @return "A"; }
    @else if ($name == "bird") { @return "B"; }
    @else if ($name == "cloud") { @return "C"; }
    @else if ($name == "delete_black1") { @return "D"; }
    @else if ($name == "eye") { @return "E"; }
    @else if ($name == "file") { @return "F"; }
    @else if ($name == "browser") { @return "G"; }
    @else if ($name == "home") { @return "H"; }
    @else if ($name == "inbox") { @return "I"; }
    @else if ($name == "network") { @return "J"; }
    @else if ($name == "key") { @return "K"; }
    @else if ($name == "radio") { @return "L"; }
    @else if ($name == "mail") { @return "M"; }
    @else if ($name == "news") { @return "N"; }
    @else if ($name == "case") { @return "O"; }
    @else if ($name == "photos") { @return "P"; }
    @else if ($name == "power") { @return "Q"; }
    @else if ($name == "action") { @return "R"; }
    @else if ($name == "favorites") { @return "S"; }
    @else if ($name == "plane") { @return "T"; }
    @else if ($name == "user") { @return "U"; }
    @else if ($name == "video") { @return "V"; }
    @else if ($name == "compose") { @return "W"; }
    @else if ($name == "truck") { @return "X"; }
    @else if ($name == "chart2") { @return "Y"; }
    @else if ($name == "chart") { @return "Z"; }

    // Row 3
    @else if ($name == "expand") { @return "`"; }
    @else if ($name == "refresh") { @return "1"; }
    @else if ($name == "check") { @return "2"; }
    @else if ($name == "check2") { @return "3"; }
    @else if ($name == "play") { @return "4"; }
    @else if ($name == "pause") { @return "5"; }
    @else if ($name == "stop") { @return "6"; }
    @else if ($name == "forward") { @return "7"; }
    @else if ($name == "rewind") { @return "8"; }
    @else if ($name == "play2") { @return "9"; }
    @else if ($name == "refresh2") { @return "0"; }
    @else if ($name == "minus") { @return "-"; }
    @else if ($name == "battery") { @return "="; }
    @else if ($name == "left") { @return "["; }
    @else if ($name == "right") { @return "]"; }
    @else if ($name == "calendar") { @return "\005C"; }
    @else if ($name == "shuffle") { @return ";"; }
    @else if ($name == "wireless") { @return "'"; }
    @else if ($name == "speedometer") { @return ","; }
    @else if ($name == "more") { @return "."; }
    @else if ($name == "print") { @return "/"; }


    // Row 4
    @else if ($name == "download") { @return "~"; }
    @else if ($name == "warning_black") { @return "!"; }
    @else if ($name == "locate") { @return "@"; }
    @else if ($name == "trash") { @return "#"; }
    @else if ($name == "cart") { @return "$"; }
    @else if ($name == "bank") { @return "%"; }
    @else if ($name == "flag") { @return "^"; }
    @else if ($name == "add") { @return "&"; }
    @else if ($name == "delete") { @return "*"; }
    @else if ($name == "lock") { @return "("; }
    @else if ($name == "unlock") { @return ")"; }
    @else if ($name == "minus2") { @return "_"; }
    @else if ($name == "add2") { @return "+"; }
    @else if ($name == "up") { @return "{"; }
    @else if ($name == "down") { @return "}"; }
    @else if ($name == "screens") { @return "|"; }
    @else if ($name == "bell") { @return ":"; }
    @else if ($name == "quote") { @return "\""; }
    @else if ($name == "volume_mute") { @return "<"; }
    @else if ($name == "volume") { @return ">"; }
    @else if ($name == "help") { @return "?"; }

    // Backwards compat; icons that are not in the font
    @else if ($name == "arrow_left") { @return "["; }
    @else if ($name == "arrow_right") { @return "]"; }
    @else if ($name == "arrow_up") { @return "{"; }
    @else if ($name == "arrow_down") { @return "}"; }
    @else if ($name == "organize") { @return "I"; }
    @else if ($name == "bookmarks") { @return "I"; }
    @else if ($name == "loop2") { @return "r"; }
    @else if ($name == "star") { @return "S"; }
    @else if ($name == "maps") { @return "@"; }
    @else if ($name == "reply") { @return "R"; }

    @else {
        @return null;
    }
}
Ok, lets try this:
{  xtype: 'button',  iconCls: 'speedometer',  title: 'Speedometer'  }
But as you see in the result, the icon is still missing! This is because we did not included the icon in our "*.scss" file yet (because it is not in the range of the default icon set). To do this, add the following line to your "*.scss" file:
@include icon('speedometer');

Change the color or size of an icon

Changing the color of an icon is easier now than ever. All you need to do is adding the following line to your "*.scss" file:
.x-button-icon {
    color: #fff;
}
Now the color of your icon should change to white.

In case you want to change the size of the icon:
.x-button-icon {
    font-size: 50px;
}
Pretty simple, isn't it?

Add a icon to Ext.List

If you want to add a icon to Ext.List you need to define your own css class, because Ext.List do not have the iconCls config attribute.

In this example we add an user icon to Ext.List.

Open your "*.scss" file and add the following lines:
.userCls:before {
    font-family: "Pictos";
    content: "U";
    font-size: 1.5em;
}
Using the ":before" selector in CSS you can insert the user icon before the anchor text. Similarly, you can also use the :after selector to insert the icon after the text.

Ext.List item:
xtype : 'list',
store : 'your store',
itemTpl : new Ext.XTemplate(
 '<span class="userCls"></span>',
 '<span>{name}</span>',
 ...

Add more custom Icon-Fonts

If you need more icons, you can also attach icons from http://icomoon.io/app/ or checkout more icon collections.

The way to add custom Icon-Fonts is explained in this video: http://vimeo.com/66191690

Conclusion

Well, I hope this article helps. If you have any question, please contact me. In the mean time - let's keep developing apps guys.
Today at work I faced an interesting issue, I spent so much time looking for an instruction of how to implement the Ext.Logger in Sencha Touch application. Unfortunately, there is no information about this in the official documentation. Therefore, just to save you some time I would like to explain some details that I found out during my research.

First of all, the described technique for implementing the Ext.Logger works for Debug-Mode only, which means, the created Log messages are not visible when you use one of the following build-modes:
  • testing 
  • production 
  • native 
  • package 
The initial Logger setup is done, by putting the following lines to your app.js file:
    //<debug>
    logger: {
        enabled: true,
        xclass: 'Ext.log.Logger',
        minPriority: 'verbose',
        writers: {
            console: {
                xclass: 'Ext.log.writer.Console',
                throwOnErrors: true,
                formatter: {
                    xclass: 'Ext.log.formatter.Default'
                }
            }
        }
    },
    //</debug>

Pay attention that you put these lines between the //<debug> comment tags. Anything between //<debug> and //</debug> will be removed after you do a build with Sencha Cmd. If you are not putting your Logger setup between these lines, you won't be able to build your application with Sencha Cmd again.

For further information also checkout src/log/writter. There you can see how to Log in browsers document title or how to do a remote Log.

After the main configuration is done, the Log messages can be implemented like:
    //<debug>
    Ext.Logger.info('Hello World!');
    //</debug>
Take also a look at http://docs.sencha.com/touch/2.2.1/#!/api/Ext.Logger for a complete list of the Ext.Logger methods.

While Sencha Cmd is removing all code between //debug, your application should also run a little bit faster after building it. At least when you are using a huge amount of logging information.
Happy Logging...



Go to Terminal and open the bash_profile:
vi ~/.bash_profile
Press "i" to insert and copy the following line to the bash_profile script (Make sure that the path matches your XAMPP installation):
export PATH=/Applications/XAMPP/xamppfiles/bin:$PATH
Commit the current changes while pressing ESC and writing :wq + ENTER 

To apply your changes to the current Terminal session, type:
source ~/.bash_profile
or just close and open the Terminal again.


When you want to display your launch screen longer as normal you can do this by simply adding a sleep() in the AppDelegate implementation:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Time in seconds
    sleep(5);
    
    // Override point for customization after application launch.
    return YES;
}
When you want to remove all provisioning profiles from Xcode, close Xcode and run the following commands from terminal:

rm -r ~/Library/MobileDevice/Provisioning\ Profiles/
rm  ~/Library/Developer/Xcode/connect1.apple.com\ 4.6.1.db

Xcode quit unexpectedly.

Click Reopen to open the application again. Click Report to see more detailed information and send a report to Apple.



When you received the message above while refreshing provisioning profiles, close Xcode, go to terminal and delete the "connect1.apple.com 4.6.1.db" file:
rm  ~/Library/Developer/Xcode/connect1.apple.com\ 4.6.1.db
After deleting the database file you should be able to refresh provisioning profiles in Xcode again.
The following code shows how-to pre select your list items in Sencha Touch:

var itemsToSelect = ["soccer", "baseball"];
var index = -1;
var myList = getMyList();

itemsToSelect.forEach(function(itemToSelect) {

   index = myList.getStore().find('fieldName', itemToSelect);
   myList.select(index,true,false); 
});
While in the process of implementing a JSONP proxy writter the following message will pop up when running the code:
Error: [ERROR][Ext.data.proxy.Server#create] JsonP proxies can only be used to read data.
There is nothing in the Sencha Touch documentation, that tells me that a proxy writer can not be used.

After looking at the framework code it was clear to me, that the source code had not been implemented.

With that, you really do need a JSONP writer, otherwise you have to implement the logic yourself or switch back to an AJAX proxy.

There is nothing in the release notes to Sencha Touch 2.2.0 beta 1 that leads me to believe, that any updates on the subject are forthcoming.
Maybe you received  the following error while building a Sencha Architect application:

Error: The package command has moved to 'sencha app package'

This error is thrown because Sencha Architect 2.1 only works with Sencha Cmd 3.0.0 version.

To fix this you have to download and refer one of the following Sencha Cmd 3.0.0 versions:

http://cdn.sencha.com/senchacmd/SenchaCmd-3.0.0.250-linux-x64.run.zip
http://cdn.sencha.com/senchacmd/SenchaCmd-3.0.0.250-linux.run.zip
http://cdn.sencha.com/senchacmd/SenchaCmd-3.0.0.250-osx.app.zip
http://cdn.sencha.com/senchacmd/SenchaCmd-3.0.0.250-windows.exe.zip


Short overview where Google Chrome browser stores the Web SQL databases:

Mac OS X (In case you cannot see the Library folder in Mac Finder > make it visible)
~/Library/Application Support/Google/Chrome/Default/databases
Linux
~/.config/google-chrome/Default/databases
Windows Vista/7
\Users\_username_\AppData\Local\Google\Chrome\User Data\Default\databases
Windows XP
\Documents and Settings\_username_\Local Settings\Application Data\Google\Chrome\User Data\Default\databases
You can use free tools like Lita to access your Web SQL databases.


If you bought a German version of Photoshop CS6, you may want to switch back to English. In this post I will show you a trick to do this without taking use of a language pack.

The main problem is, that Adobe disallows us to switch the language in Photoshop directly, as you can see at the following screen:


Ok, here comes the trick (I am quite sure this will work on other language versions too).
  1. Make sure that Photoshop is closed!
  2. Open the Finder: /Applications/Adobe Photoshop CS6/Locales/de_DE/Support Files
  3. In the "Supported Files" directory you will find a file named "tw10428.dat"
  4. Rename "tw10428.dat" to "tw10428.bak"*
  5. Start Photoshop (GUI language should be English now)
  6. Done! :)

* To rename "tw10428.dat" > Right click on "tw10428.dat" file > Select "Get Info" > Goto the "Name & Extension" label > In the textfield you type "tw10428.bak".

After closing the current dialog don't forget to confirm the changes with "Use .bak".




There are many ways to clear the localStorage of your web browser.

In a common dev toolbar just type:
localStorage.clear();
If you are using jQuery:
$.storage('clear');
If you are using Sencha:
// proxy
var store = Ext.getStore('YourStore');
store.getProxy().clear();
store.data.clear();
store.sync();

// no proxy
var store = Ext.getStore('YourStore');
store.removeAll();
store.sync();
You can also delete the localStorage via a bookmark. Just add the following snippet as new bookmark:
javascript:(function(){localStorage.clear()})();
Today my phone has been eating my battery life like crazy. After some google searches I came arround that it is might be caused by a bad file or corrupted sd-card. I also unmounted my sd-card, but so far this was not the solution for my problem...


A quick hack for this problem is to kill the media service via a script.

If your phone is rooted, you can install a program that can run shell scripts like Script Manager - SManager on your phone.

Then run the following script to kill the media service:
#!/system/bin/sh
killall -9 android.process.media
killall -9 mediaserver

Baaaaam! :)

If you have any idea how I find out what file or error is causing my media service to crash, don't hesitate to contact me.


You have an iPhone storyboard and want to support the iPad too? This can be done in a quick way:

  1. Open Xcode
  2. Duplicate the existing storyboard.
  3. Rename them to "MainStoryboard_iPhone.storyboard" and "MainStoryboard_iPad.storyboard"
  4. Right click on the "MainStoryboard_iPad.storyboard" file > "Open as" > "Source code" 
  5. Search & Replace:
    targetRuntime="iOS.CocoaTouch"
    with:
    targetRuntime="iOS.CocoaTouch.iPad"
  6. Done!
You are developing with Sencha Touch and Eclipse? You want to have code completion and outline? ... Here I'll show you how to do it at no charge to you.
This tutorial works also for ExtJS developer, at least I tested it with ExtJS 4.x before. But actually I don't know if the required *.jsb3 file is still included their archives. May someone can confirm this?

Requirements:
  • Working installation of Eclipse with Aptana Studio Plug-in (tested with Eclipse Juno Service Release 2 and Aptana Studio 3.4.0)
  • Unzipped Sencha Touch 2.x.x (tested with Sencha Touch 2.2.1)
  • *.jsb3 file *
* Since .jsb3 file is no more included in the Sencha Touch 2.2.1 archive (I guess they wanna sell you the Sencha Architect instead), you can download it here directly:
Download Sencha Touch .jsb3

For the case you are new to Aptana, I can suggest you to watch the following video tutorial first.

In the next steps I will show you how to install and configure your Spket IDE:
  1. Download and copy the *.jsb3 file into the root directory of your extracted Sencha Touch archive (as a sibling of src)
  2. Start Eclipse.
  3. Goto Help > Install New Software
  4. Click the "add" button
    1. Name: Spket IDE
    2. Location: http://www.agpad.com/update/
  5. Select the Spket IDE Node and click the "Next" button (See Image1). Follow the installation steps.
  6. Restart Eclipse.
  7. In Eclipse, Windows > Preferences or just press  + ,
  8. Select "Spket" > "JavaScript Profile preference" page to display the installed JavaScript Profiles.
  9. Click the "New.." button. In the Name field, type "Sencha Touch" as the name for the new profile. Click "OK".
  10. Click the "Add Library" button. From the Library drop-down list, select "ExtJS". Click "OK".
  11. Click the "Add File" button, choose the *.jsb3 file, which you copied to the Sencha Touch root folder before (See step 1).
  12. Check all the available select boxes in the created profile.
  13. Select the Ext profile created in step 9, click the "Default" button. This makes it to the default profile for all your project.
  14. Click "OK" to save the preferences.
  15. Open your javascript file with the Spket JavaScript Editor. You can set Spket JavaScript Editor as the default editor. "Windows" > "Preferences" or just press  + ,"General" > "Editors" > "File Associations". Select the filetype "*.js". In associated editors select the Spket JavaScript Editor and press the "Default" button. See Image2.
  16. When you type "Ext.de" and press STRTG + SPACE your code should get completed.
  17. Done.



Mac OS X offers you a smart built-in solution to secure your files and folders. It is possible to create an encrypted disk image, it is like a regular disk image but requieres a password to become mounted. How this works, I'd like to show you in the following steps:
  1. Open Disk Utility (press + SPACE and type disk utility).
  2. File > New > Blank Disk Image.
  3. Type a name in the Save As field. This name will be used for the disk image.
  4. Choose a preferred location to save the *.dmg file.
  5. Select a size for the disk image.
  6. Choose as volume format the default Mac OS X Extended (Journaled)
  7. Use "sparse disk image" for a disk image that only uses as much space as it needs, rather than a set amount of space.
  8. Choose 128-bit AES encryption (or 256-bit AES in Mac OS X v10.5 or later, but slower). I would suggest 128-bit AES encryption. 
  9. Click on "Create" button.
  10. Enter a strong password and don't forget to deselect "Remember password (add to keychain)" if you don't want it saved. Because if you do, your created disk image is less secure.




Okay nothing new here, but maybe it inspires you to use "hot" keys more often  :)
  1. CRTL + Q goto last edit location
  2. CRTL + SPACE completes everything
  3. + S removes current line or selected lines
  4. + L goto line number
  5. + ALT + copies current line or selected lines to below
  6. + ALT + copies current line or selected lines to above
  7. ALT + moves current line or selected lines to below
  8. ALT + moves current line or selected lines to above
  9. + SHIFT + 7 Toggle comment*
  10. + goto the beginning of a line
  11. + goto the end of a line
  12. + SHIFT + L brings up a List of shortcut keys
Something missed? - See Windows -> Preference -> General -> Keys.

* You may have to disable the OS X hotkey (  + SHIFT + 7 brings up the help menu).