coder and technology lover
Posts tagged javascript
Debugging PhoneGap applications using Xcode console
Jan 12th
When I started to play whit PhoneGap, my greatest issue was: “how can I debug my code?”, I use often tools such FireBug and JavaScript debugger included in Internet Explorer 8 (which is the first good thing IE has to offers!) but write and test my code on iPhone simulator is completely different. Fortunately PhoneGap offers a way to access to Xcode console and print messages by choosing among three different levels: log, warn and error. In order to print a message, we have to use the debug object, which has scope window (it is a global object), in this way:
1 2 3 4 5 | debug.log("my log message"); // or debug.warn("my warning message"); // or debug.error("my error message"); |
To open Xcode console you have to choose “Run -> Console” from the toolbar (or CMD+SHIFT+R) and after a “Build and Run” (CMD+Enter), you will see your message appear in the console.
Testing applications while developing using PhoneGap and Xcode, is an intense activity, because errors are not automatically notified (like in FireBug or similar), so it’s really important to make use of try/catch/finally blocks and logging calls:
1 2 3 4 5 6 7 8 9 10 11 12 13 | try { mycommand.execute(); } catch (e) { debug.error("Error using mycommand: " + e.message); } finally { // do something smart here :^) } |
Finally, in order to avoid problems related to Xcode cache, I suggest to always clean the cache by running “Build -> Clean” from the toolbar (or CMD+SHIFT+K) before doing a new build and eventually remove the application folder under “/Users/{your-name}/Library/Application Support/iPhone Simulator/User/Applications/{app-number}”.
How to solve CSS conflicts using jQTouch
Jan 2nd
In these days I’m developing my first iPhone application, using frameworks like PhoneGap and jQTouch. This aims to be a powerful app, not a mere widget, so I’m writing a lot of code and I’m using several libraries and components in order to create a really native-like application.
Unfortunately, due to a bad CSS approach, I faced an issue with the excellent SpinningWheel component which won’t never be displayed unless you open and modify jQTouch CSS. The fact is that, jQTouch takes the body and use it as main container to hold all application’s pages and components and by default it hides all nodes inside the body except the current displayed content (active page/section) and this is a problem, because SpinningWheel create the ui object into the body and it won’t be displayed.
Fortunately the solution is simple, we just need a wrapper, an html element which will holds all jQTouch stuff in place of body, so in my html I wrapped all inside this:
1 2 3 4 5 | <body> <div id="jqtouch-wrapper"> <!-- content --> </div> </body> |
Then I changed all jQTouch CSS, to reflect this approach (you can see the wrapper as a sandbox):
1 2 3 4 5 6 7 8 9 10 11 | div#jqtouch-wrapper > * { -webkit-backface-visibility: hidden; -webkit-box-sizing: border-box; display: none; position: absolute; left: 0; width: 100%; -webkit-transform: translate3d(0,0,0) rotate(0) scale(1); min-height: 420px !important; } /* ...and so on*/ |
…and finally I changed jQuery selectors inside JavaScript code:
1 2 | $body = $('#jqtouch-wrapper'); // ...and so on |
It’s also possible to solve the conflict by changing SpinningWheel code in order to put the dom node inside active jQTouch pages, but the problem of potential incompatibilities will remains. A CSS declaration, except reset statements and other rare cases, should NEVER refers directly to a whole set of nodes (ie: ul { color: red; }), but to a node type contained by a wrapper/sandbox (ie: #foo ul {color: red; }), thus conflicts will be avoided.
Google Closure’s idiocies: Ajax can’t be synchronous :(
Dec 31st
While I love Closure tools and the possibility to write a better organized and OOP based JavaScript, I’m facing some weakness and inexplicable choices in the library. The last discover is that is impossible to make synchronous ajax call using the provided classes, since I didn’t find nothing about synch/asynch options by reading API reference, I took a look to the source (xhrio.js), and I noticed this:
1 | this.xhr_.open(method, url, true); // Always async! |
that true should be a parametric value which developers can set to true or false. Why forcing it to true???
I’m really disappointed :(
“Not authorized” error due to Safari “private browsing” mode! :P
Dec 27th
This is just a quick post to share my misadventure with Safari and the “private
browsing” mode. I’m working on a small JavaScript library which has the goal to abstract SQLite database api and allow users to create table, insert, update and delete
records easily… my code seems to work very well, but this morning during some
tests, I got the “not authorized” exception (error code n°1) on every
transaction. After hours of debugging I realized that my code was ok, but I forgot
to disable the “private browsing” mode in Safari!
So, bear in mind, if you want to play with database api and other client-related store capabilities (such cookies), remember to disable that option in Safari ;)
Extending Eclipse using JavaScript and Monkey Script engine
Dec 16th
I was wondering how to wrap a string with quotes in Eclipse by using a shortcut, then I realized that there is not such command, so I started thinking for a solution and initially I created an Aptana’s snippet, but I was not satisfied, because I want to have an handy shortcut to invoke my snippet. By googling, I discovered Eclipse Monkey Script engine, that is an extremely powerful tool for every JavaScript developer who wants to extend Eclipse features by writing few lines of JavaScript code. In order to use the js engine, you must have the package org.eclipse.eclipsemonkey (which is installed by default by Aptana) installed. Unfortunately I can’t find a complete and exhaustive reference for this project, which seems forgotten by authors, so I learnt what I know reading different posts.
Basically, Monkey Script allow developers to access editor’s instance, get selected test, get document content, edit it and update it. Moreover is possible to print text to consol, read and create files on the filesystem… and finally the scripts created will be accessible from Eclipse menu (under “Scripts”) and invokable through user defined shortcut… really nice!
So, backing to my experiment, I created this monkey script:
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 | /* * Key: M1+M2+C * Menu: Custom Scripts > Wrap with double quotes * DOM: http://download.eclipse.org/technology/dash/update/org.eclipse.eclipsemonkey.lang.javascript * Kudos: Davide Zanotti */ function main() { // no editor... exit if (typeof editors.activeEditor == "undefined") { return alert("No active editor"); } // get a reference to the editor in use var editor = editors.activeEditor; // beginning of text selection var startOffset = editor.selectionRange.startingOffset; // end of text selection var endOffset = editor.selectionRange.endingOffset; // selected text var selection = editor.source.substring(startOffset, endOffset); try { // surround selection with quotes editor.applyEdit(startOffset, endOffset - startOffset, '"' + selection + '"'); } catch (e) { alert("Error " + e.code + ": " + e.message); } }; |
It’s important to notice some points, first you MUST write an “header” using the comment syntax “/* */” into which you MUST declare at least 2 parameter: the “Menu” path (you can nest several menu items by writing several “>”) and the “DOM” package (which allows you to access specific objects like “editors“). You can write several js functions, but you must provide a main() function, which is called automatically by Eclipse once you launch your script, otherwise you can call the main function as you like but you must then provide the “OnLoad” param in the header, specifying which function will be called.
To define a shortcut you can use the “Key” parameter and define your own keys combination by choosing among the four modifiers: M1, M2, M3, M4, that are a platform-independent way of representing keys (these stand for ALT, COMMAND, CTRL, and SHIFT). The strange (at least to me) parameter “Kudos” is used to declare the author of the monkey script.
To test my little script or create your own, you have simply to create a new project into Eclipse by calling it as you like (ie: “custom-extensions”), then create a “scripts” folder into which you will save your .js files… that’s all, try yourself and enjoy :)
This is how it looks:
eclipse monkey script menu
ps: I’m going to explore the Monkey Script API in order to write more complex and useful extensions :P
.cjs (Compiled JavaScript): an idea for a new file extension
Dec 10th
Due to the growing diffusion of tools to compress and optimize JavaScript files (such Google Closure), I feel the need of an introduction of a standard way to identify and differentiate them (compiled files) from other uncompressed files. Basically, I would adopt a different file extension like CJS (which stands for compiled/compressed JavaScript). In this way it would be easy to browse a directory of hundreds of js files and identify those which are ready to be used in our project because already compressed and optimized.
What do you think about?
Custom JavaScript classes and packages using goog.provide() and goog.require()
Dec 1st
I will repeat it until the dead, the real power of Goolge Closure is the mechanism and the tools behind it, not the classes and methods written for you, but the possibility to write your own better JavaScript code! Today I’m gonna show you how to create and use your custom JavaScript classes and to take the benefits of goog.provide() and goog.require() methods.
Ok, let’s suppose we are working on a funny and exciting project, like an online JavaScript game called “Js Monsters Battle” and let’s suppose the domain will be www.jsmonstersbattle.com. We love OOP, we love write js code, we love to have a well organized and document code, so we will begin by creating our packages, following the standard which establishes that the root of a package must be the reversed domain name, so in our example we will create this folders structure “/com/jsmonstersbattle/” and inside we will put our classes (and subpackages).
Since our game is a game about monsters, we will create the core package “monsters” in that directory and we will write the first base class called Monster. We will got the following: “/com/jsmonstersbattle/monsters/monster.js”, three folders and one js file. Yes, one JavaScript file for class, forget those huge files containing millions of functions, we are going to write better JavaScript code and thinking more like a Java developer. If you are concerning about file size and performances, don’t worry about it, the compiler will reduce and optimize the code for you (just before release the project). Ok, let’s take a look inside the Monster class (monster.js):
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 | goog.provide("com.jsmonstersbattle.monsters.Monster"); /** * A common Monster * @constructor * @param {String} name * @param {String} age * @param {Number} level */ com.jsmonstersbattle.monsters.Monster = function(name, age, level) { /** @private */ this._name = name; /** @private */ this._age = age; /** @private */ this._level = level; } /** * Returns an amount of damage points * @return {Number} */ com.jsmonstersbattle.monsters.Monster.prototype.attack = function() { return Math.round(this._level + this._age / 100) * 2000; } |
In the code above I defined a basic class called Monster, which is available under the package (namespace) com.jsmonstersbattle.monsters, declared using goog.provide(), then I created a constructor (by using the special jsDoc notation /** @constructor */) which receives three arguments and sets three private Monster’s variable (/** @private */), finally I defined a method attack which returns a number of damage points. Ok, by following the Monster’s example, we can now create as many classes and packages as we like, interfaces (using /** @interface */ and /** @impements */) and subcalsses (using the method goog.inherits()), let’s see briefly these implementation:
Extending a class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /** * @constructor * @extends com.jsmonstersbattle.monsters.Monster */ com.jsmonstersbattle.monsters.UglyMonster = function(name, age, level, uglyness) { // call to Super com.jsmonstersbattle.monsters.Monster.call(this, name, age, level); /** @private */ this._uglyness = uglyness; }; // you can read the following as: "UglyMonster extends Monster" goog.inherits(com.jsmonstersbattle.monsters.UglyMonster, com.jsmonstersbattle.monsters.Monster); |
Creating and implementing an interface:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /** * Evil interface. * @interface */ function IEvil() {}; IEvil.prototype.doEvil = function() {}; /** * @constructor * @implements {IEvil} */ com.jsmonstersbattle.monsters.EvilMonster = function(name, age, level) { // some code here }; com.jsmonstersbattle.monsters.EvilMonster.prototype.doEvil = function() { // IEvil implementation } |
Once we created all the necessary classes, we will put our “com” folder under “closure” folder. Then we will create a main js file which will includes all the code required to initialize and run the application, I called it “application.js” for convenience. This file will requires all the classes it needs by using goog.require():
1 2 | goog.require("com.jsmonstersbattle.monsters.EvilMonster"); // ...and so on! |
After the import we will be able to use the classes, by referring them with the full qualified class name (“com.jsmonstersbattle.monsters.EvilMonster”), however since this means to write long strings, we can create references as the following:
1 2 3 4 5 6 7 | goog.require("com.jsmonstersbattle.monsters.EvilMonster"); var EvilMonster = com.jsmonstersbattle.monsters.EvilMonster; // then... var monster = new EvilMonster(); |
or use the JavaScript with operator:
1 2 3 4 5 6 7 | goog.require("com.jsmonstersbattle.monsters.EvilMonster"); with (com.jsmonstersbattle.monsters) { var monster = new EvilMonster(); } |
…and this is all today, I hope you enjoyed my post ;^)
UPDATE:
Don’t use the with operator nor take reference to fully qualified class name, otherwise you will get several errors if you use advanced compilation!
goog.i18n.NumberFormat: Formatting numbers to localized strings
Nov 26th
By using Closure’s NumberFormat class (located under goog.i18n package) is relatively easy to format numbers and print readable strings. All we have to import is goog.i18n.NumberFormat:
1 2 3 | <script type="text/javascript"> goog.require("goog.i18n.NumberFormat"); </script> |
Then, we have to create an instance of that class and specify the type of format to apply, by choosing among: CURRENCY, DECIMAL, SCIENTIFIC and PERCENT. Assuming we have to display a budget, we will write a similar statement:
1 2 3 4 5 | // create a new formatter var formatter = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.CURRENCY); // test the output console.log(formatter.format(15650.579)); |
The code above, by using the default locale, will print: $15,650.58. Is possible to localize the output by assigning a different symbols set to goog.i18n.NumberFormatSymbols. The code below will set an italian format:
1 2 3 4 5 6 7 8 | // symbols setting goog.i18n.NumberFormatSymbols = goog.i18n.NumberFormatSymbols_it_IT; // redefine formatter (in order to use new symbols set) formatter = new goog.i18n.NumberFormat(goog.i18n.NumberFormat.Format.CURRENCY); // see the differences console.log(formatter.format(15650.579)); |
This time the output will be: € 15.650,58.
Automatically compile JavaScript applications using Google Closure and Ant
Nov 23rd
As I said on insideRIA, the power of Google Closure is represented by the additional tools provided by Google: the Java compiler (which compress and optimize your javascript files) and the python script (which calculates dependencies). This tools however are not so user friendly, because you have to rely on the terminal and invoke them through command lines, a pretty annoying procedure that can scare people which usually rely only on visual tools.
Fortunately is relatively easy to automatize this compilation, by using Ant (a Java-based build tool). Ant is included by default in Eclipse standard platform (anyway some stand alone Eclipse-based ide such Aptana don’t include it… it’s time to use such programs as Eclipse plugins!) and can be configured and used by simply writing an xml file formally named “build.xml“. A build file contains one root node “project” and at least one “target” node containing tasks to execute, tasks are a series of different operations that can be executed by Ant, such create/delete files and folders, zip/unzip a file, running scripts and more. To automatize the deployment of our JavaScript application, we will invoke the calcdeps.py and the compiler.jar from Ant in a single statement, and we will print the result to a specific file.
To invoke a script, we have to use the exec tag and specify at least the param “executable“, which indicates the location of the script to execute, then by setting the parameter “output” the result returned from the script will be redirect to the specified file. Finally, to avoid undesired output in the file, such debug information and errors, we have to specify also a file which will receive this type of data by using the “error” parameter.
Since, paths to scripts and other files can be very long, we can create custom variables to hold these information and then reusing them in our script invocations. This is as simple as use the “property” tag and specify a “name” and a “value” attributes.
The following is an example of how a build.xml will looks like:
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 | <?xml version="1.0" encoding="utf-8"?> <project name="Google Closure Ant Test" basedir="." > <!-- Full path of the current project --> <property name="projectPath" value="/Users/davidezanotti/Documents/workspace/GoogleClosure" /> <!-- Full path to Closure library --> <property name="closurePath" value="${projectPath}/closure" /> <!-- List of javascript files to compile --> <property name="filesToCompile" value="${projectPath}/my-closure-app.js" /> <!-- Full path to the compiler jar --> <property name="compilerPath" value="/Users/davidezanotti/Documents/closure-compiler/compiler.jar" /> <!-- Full path to the compiled file (created if not defined) --> <property name="outputPath" value="${projectPath}/ant-generation.js" /> <!-- Full path to the file which will contains debug output and errors --> <property name="logPath" value="${projectPath}/closure-compiler.log" /> <!-- Compilation level --> <property name="compilation" value="WHITESPACE_ONLY" /> <target name="JavaScript Compilation"> <exec error="${logPath}" output="${outputPath}" executable="${closurePath}/bin/calcdeps.py"> <arg line="-i ${filesToCompile} -p ${closurePath} -o compiled -c ${compilerPath} -f '--compilation_level=${compilation}'" /> </exec> </target> </project> |
The build.xml above will first gathering all the necessary Closure files (dependencies) and then will compile the resulting js using a WHITESPACE_ONLY compilation. The result will be printed to the file “ant-generation.js” and the debug to “closure-compiler.log”.
To run the Ant process: right click on the build.xml and choose Run as Ant Build. This procedure can be also configured in order to execute all the task each time a file in the project is saved, but it’s not a great idea because the process can takes several seconds to complete.
If you want to learn more about Ant (I have to learn a lot too, since I never used it before :P), check the reference here: http://ant.apache.org
goog.net.XhrIo: make simple ajax calls with Google Closure
Nov 17th
Closure has a consistent package called goog.net, which contains a lot of classes to work with ajax and remote http requests. In this post I want to show how to create a basic xhr object to make get/post calls, listen for related ajax events and send data to server. Once imported the main js file (base.js), we will require the following:
1 2 3 4 | goog.require("goog.dom"); goog.require("goog.net.XhrIo"); goog.require("goog.structs.Map"); goog.require("goog.Uri.QueryData"); |
The most important import is goog.net.XhrIo, which represents the object wrapping the XmlHttpRequest and allows us to retrieve and send information to/from the server. This class is a pretty low level api, which means that several tasks are not as simple and automatic as they would in jQuery or such libraries, but on the other hand this offers us more control and consciousness of what we are going to do.
The first step is instantiate an object of type goog.net.XhrIo and take a reference to it:
Recent comments