Using jQuery in haXe

August 3rd, 2010  |  Published in Uncategorized

It is a kind of pain to code in JS without a proper library like jQuery. Using plain haXe in JS target is just as pain since haXe does not abstract most of the browser quirks, what it gives is only stricter typing and a little bit better core API (nothing DOM related…). When there is no solid haXe/JS targeted haxe library come out yet, we have to find some ways to use external JS libraries.

There is a jQuery wrapper appeared on haxelib last year, but I don’t really like its API, which is too different from the original one, and I’ve never used to having method names first letter capitalized… OK, it’s just personal taste :P Anyway I’ve written a jQuery extern to replace it, which provides API closer to jQuery and smaller compiled JS file (smaller because the haXe compiler does not generate codes for extern class).

Here I will illustrate a bit on how to use it, requiring you to have some experience on both haXe and jQuery.

Installing the jQuery extern

Since its put on haxelib, you can install it using the command:

haxelib install jQueryExtern

and then add “-lib jQueryExtern” in the hxml.

OR, you can download the cutting edge version from github: http://github.com/andyli/jQueryExternForHaxe, extract and place “JQuery.hx” (optionally with the “jQueryPlugins” folder) into your project source directory.

Using the jQuery classes

It should be better to illustrate with example. For a typical JS starting point with jQuery, you write:

$(function(){
	//do your magic
});

If you don’t know, it’s a short-hand that bind your magic codes to the document ready event, same as you write:

$(document).ready(function(){
	//do your magic
});

HaXe does not allow using “$” as a class name or a function name, but “$” is just a short-hand to “jQuery”. However, haXe requires all class names start with capital letter, so it is “JQuery” not “jQuery”. You start your haXe/JS codes using the jQuery extern as following:

import JQuery;
 
class Main {
	static public function main():Void {
		new JQuery(function():Void {
			//your magic codes
		});
	}
}

It seems to be a few lines more than JS, but you should already know, the extra lines are the same for all other haXe targets, its how haXe program starts. The main point is “new JQuery(…)” which is the same as “$(…)” in JS.

So, when you code in JS like:

	$("#myMightyDiv").hide();

now you do the same in haXe:

	new JQuery("#myMightyDiv").hide();

Simple.

Static functions

One thing to aware, that is the static methods of jQuery are placed to “JQueryS” in the extern. The reason is haXe does not allow using same name for both static and instance methods. For example in the original jQuery, there is “$.data()” and “$(…).data()”, they are now in the extern as “JQueryS.data()” and “new JQuery(…).data()”.

Extra methods in the jQuery extern

And there are some extra methods appears in the extern comparing to the original jQuery. For example, there is “cssSet()”, and it is just the same as “css()” but limiting you to really setting a css property and it is properly typed as returning a JQuery object, so you can happily chaining the methods with code completion and type checking. All the extra methods are like that and they are all set as “inline”, so that the haXe compiler will generate correct codes, that is “css()” not “cssSet()” in the compiled JS, because “cssSet()” is not really existing in jQuery. And because they are not really existing, don’t try to call the extra methods with Reflect.

Using plug-ins

I’ve included some jQuery plug-in externs. Currently there are jQuery Tools, jQuery media plug-in and jQuery UI (work-in-progress).

The plug-in architecture is a bit hard to deal with… To understand how it works, first of all you have to know there is a mighty “using” keyword in haXe, which inject methods into object instance. And the jQuery plug-in in my haXe extern is utilizing both “using” and “inline”.

Anyway, here is how you use the plug-ins. For example, when using jQuery Tools in JS, you just include its JS file in HTML and you can call the plug-in’s method on the jQuery object, that is:

$(".my_overlay_trigger").overlay({...}); //overlay is from jQuery Tools

In haXe, with my extern, you have to write:

import JQuery;
//there are several classes in Overlay.hx, we "using" only the "Overlay" class.
using jQueryPlugins.jQueryTools.Overlay.Overlay;
...
new JQuery(".my_overlay_trigger").overlay({...});
...

Because this implementation doesn’t deal with optional parameter very well, in most of the cases I made the optional parameters mandatory. If the method has a optional config parameter, but you just want to use the defaults, simply pass in “{}”.

And there are many cases some functions does not fit that well, I’ve wrap them into classes/methods with “inline”. You may have to look at the source file to fully understand how to use.

There will be more plug-ins to come when I need them. Feel free to integrate other plug-ins and let me put them into the extern.

Tags: , ,

CanvasBlock: a GM script to block canvas tag (should we…or can we?)

April 13th, 2010  |  Published in Uncategorized

HTML5 is believed to be the Flash killer and will replace Flash in the future. Eventually those Flash-haters will become canvas-haters, so a canvas-blocking GreaseMonkey script will be useful (at least they think it will be).

I myself was making it for fun. I don’t think we should block any HTML5 tags anytime since it is a part of the web, just like I do not agree people blocking Flash. What is interesting is, seems like we cannot effectively block the canvas tag, which will be discussed later in this post.

Features

I made the script blocks not only canvas tag but also video tag and audio tag. It is because Flash is going to be replaced by all the three tags but not only canvas. Video and audio can be as annoying as canvas.

Like those Flash-blockers, the blocked contents are replaced by a line of text, “Click to show xxxx”. You may click on it to get back the blocked content.

CanvasBlock is tested on FireFox 3.6 on Mac, FireFox 3.5 on Ubuntu and Chrome on Ubuntu. Other platforms should works too.

Implementing the script

I used haXe instead of writing pure JS. No big reason here, just to see if it is possible. Turn out there is no big difference from using JS, you just need to copy all the meta data to the compiled JS file. And the events listener need to be assigned by “addEventListener” instead of something like “onclick = function …”.

Detecting HTML5 tags is easier than detecting Flash objects. Firstly, the tags are standardized meaning you can simply use “getElementsByTagName”. For Flash objects you need to check the params of the “object” and the “embed” tags, which is a bit troublesome. Secondly, currently no one (at least not much ppl) is creating canvas tags on the fly, unlike for Flash the standard way is to use swfobject. So I can detect the tags once the DOM is ready, no need to wait for the execution of the page’s JS.

Replacing the tags and saving them for later retrieval is easy too. Using normal JS method will work.

The tags are blocked but…

The script is functional and I went to do some more testing. Blocking video and audio seems ok, but there is some problem of blocking canvas.

Possibility of Freezing/Crashing

I went to ChromeExperiments and randomly picked one. You know what? The browser freezed.

So, look like after I blocked the canvas, the JS on the page which is used to draw thing on the canvas originally, is still there trying to work on the canvas. And this become a big problem since I don’t know exactly which JS function is going to work on canvas, because different web page have different functions, so no way I can work on that. You can completely disable JS, but this is not a CanvasBlock should do.

Browser freezed and an timeout message was shown after blocking canvas.

However, I have tested some more web page and they are ok with the blocking script. So maybe only some complex JS will have this problem. But anyway the possibility of freezing a browser is not a good thing.

No significant reduction on CPU usage

The remaining JS script  problem reminded me to test on the CPU usage. And the result is, blocking canvas does not bring significant reduction on CPU usage. See the following screenshots, which is using another Chrome experiment:

Page opened, canvas blocked. However CPU usage still rise to a very high level.

Clicked to show back the canvas. CPU usage rose even higher, but not much difference.

So what’s that mean? Again if I want to block the real CPU hog, I should block the JS with the canvas. But again, stated above, it is not possible to block the right function without blocking all JS.

Conclusion

Blocking canvas can only introduce little benefit on CPU usage but give you possibility of freezing/crashing!

Let’s look at Flash again. Flash can be blocked easily because ActionScript is included in the swf. Removing the swf from the page automatically removes the associated scripts. Also, usually JS does not control a Flash object so it is pretty safe to kick Flash out without dealing with the remained JS. From this point of view, seems that Flash is more user friendly than canvas, and HTML5 ads will be more annoying than Flash ads…

If you want to try, you may install the script from CanvasBlock’s page on userscripts.org.

You’re also welcome to get the haXe source from CanvasBlock’s github repo.

Tags: , , ,

AS3/JS string concatenation methods performace test

October 9th, 2009  |  Published in Uncategorized

When writing BrainFlash, I was thinking if the string concatenations for program output will slow down the whole interpreter. That is because I was once hit that a year ago when dealing with XML.

I asked for better handling methods over StackOverflow. It is interesting that some of the answers shown that using “+=” is already the fastest. But I still want to know more about that, so I wrote my own simple testing program, which is below:

ActionScript version

http://get.adobe.com/flashplayer

source code

Methods used are:

  1. str += concateString;
  2. str = str.concat(concateString);
  3. array.push(concateString); … str = array.join(“”);
  4. vector.push(concateString); … str = vector.join(“”);
  5. byteArray.writeUTFBytes(concateString); … str = byteArray.readUTFBytes(byteArray.length);
  6. byteArray.writeMultiByte(concateString,”us-ascii”); … str = byteArray.readMultiByte(str.length,”us-ascii”);

The result shows that fastest method is using “+=”, but using Array/Vector is still very close to it. Using ByteArray is slow and with ASCII instead of UTF-8 is even slower…

And all the methods are performed reasonably fast, what is slow is when showing the resulting string on TextArea… It takes a few seconds! But when it is drawn, run it again and it will become normal speed, maybe there is some caching?

JavaScript version

I coded a JavaScript port too. See it here.

Methods used are:

  1. str += concateString;
  2. str = str.concat(concateString);
  3. array.push(concateString); … str = array.join(“”);

Interesting enough, the result is very similar to AS3. It is the opposite of what we believe using the Array trick will let it performs faster. “+=” is the fastest in most cases, if not, that’s not much difference.

I’ve only tested in IE8(Win), Firefox 3 (Win/Mac), Safari 4 (Win/Mac), Chrome 3 (Win). The really really really interesting part is in Chrome 3, using the concat method of String is x7000 SLOWER than the other two!! What are your results?

Tags: , ,