[ close ]
Help Upgrade the Web: Download Firefox 3.6

JavaScript


2
Feb 10

How to insert a SWF file in an ASDoc API documentation ?

ASDoc with inline SWF file

ASDoc API documentation is well designed for developers but remain difficult to read for others. Some of my co-workers are web designer. They code a bit but they want API to be simple and they want usage examples. In the past days I developed some image filters and effects for them. The resulting API has very few meaning without a real example of code and a way to test it. Thus, I wanted them to be able to access the code examples as well as being able to test the result of each effects, inline, in the ASDoc documentation. Click the image below to see the rendering SWF tester.

Effect tester

Code examples are easy to integrate using the @example and @includeExample (Flex 4), but there is no default way of inserting SWF files directly (as far as I know).

In order to insert a SWF file in a generated ASDoc API documentation, one needs to understand the process of generating documentation with ASDoc. On one side there are packages and classes, on the other side ASDoc templates files. Generating documentation consists for the asdoc.exe application of parsing the classes for any special comments and injecting what has been found in the templates. The result is output in a directory and is made of a bunch of HTML, CSS, JavaScript files…

The type of special comments the ASDoc process is looking for looks like that :

/**
 * Apply an RGB distortion effect on a DisplayObject
 *
 * @param target The DisplayObject on which to apply the effect
 */

override public function apply(target : DisplayObject):void{
    ...
}

Special tags starting with an @ can be used in these comments and will be interpreted by the ASDoc process. Fortunately HTML tags can be used as well inside these comments and will be output unchanged. I make use of this feature to insert SWF files inside the documentation.

Step 1 : adding the required JavaScript libraries to the ASDoc templates

Note : in the following section you have to download several components to make it works. I packaged all of them in a zip file.

ASDoc templates are located in a Flex SDK sub-directory by default : FLEX_SDK_DIR\asdoc\templates
To keep unmodified the original templates you can copy this folder outside the Flex directory. In this case to make the ASDoc process being aware of this change use the command parameter -templates-path ‘path/to/your/new/template_folder’
Full ASDoc documentation is located on Adobe Web site

In the template folder locate the file asdoc-util.xsl and in there search for those lines :

<script language="javascript" type="text/javascript">
    <xsl:attribute name="src">
        <xsl:value-of select="$baseRef"/>
        <xsl:text>asdoc.js</xsl:text>
    </xsl:attribute>
</script>

insert the following lines just before the previous ones :

<script language="javascript" type="text/javascript">
   <xsl:attribute name="src">
        <xsl:value-of select="$baseRef"/>
         <xsl:text>jquery.min.js</xsl:text>
    </xsl:attribute>
</script>
<script language="javascript" type="text/javascript">
   <xsl:attribute name="src">
        <xsl:value-of select="$baseRef"/>
         <xsl:text>swfobject.js</xsl:text>
    </xsl:attribute>
</script>
<script language="javascript" type="text/javascript">
   <xsl:attribute name="src">
        <xsl:value-of select="$baseRef"/>
         <xsl:text>swf-loader.js</xsl:text>
    </xsl:attribute>
</script>

As you may guess we will use jQuery and SWFObject to achieve our goal. Download jQuery and SWFObject and put the files in the templates directory (rename the files to match the previous lines). From the SWFObject download ZIP file, extracts the expressInstall.swf file in the templates directory as well.

The third file is made by myself and will help substitute special HTML tags in the documentation by SWF files. Save the following code in the file templates/swf-loader.js

$(document).ready(function(){
    var idBase = "swfLoader";
    var idNum = 0;
    var width, height;
    var params = {
        quality: "high",
        scale: "noscale",
        allowscriptaccess: "always",
        bgcolor: "#FFFFFF"
    };
    var flashvars = {};

    $("div[src]").each(function(){
        $(this).attr("id",idBase + idNum);
        width = $(this).attr('width') || "100%";
        height = $(this).attr('height') || "100%";
       
        var flasvarsString = $(this).attr("flashvars");
        var flashvarsArray = flasvarsString.split("&");
        for ( var i = 0; i < flashvarsArray.length; i++) {
            var flasvar = flashvarsArray[i].split(":");
            flashvars[flasvar[0]] = flasvar[1];
        }
        swfobject.embedSWF(
                $(this).attr("src"),
                idBase + idNum,
                width,
                height,
                "10.0.0",
                "expressInstall.swf",
                flashvars,
                params,
                {}
        );
   
        idNum++;
    });
});

Step 2 : adding special HTML Tag in ASDoc classes comments

Now that the files are in place it’s possible to add special HTML tags in comments to insert SWF files :

/**
 * Creates an RGB distortion effect (Timed effect).
 * <div src='../../../swf/effectTester.swf'
 *   width='780px' height='550px' flashvars='form:mosaicForm'></div>
 */

The div tag will be replaced by the SWF files located at ‘../../../swf/effectTester.swf’ passing width, height and flashvars parameters.
Flashvars must be of the following form :
var1:value1&var2:value2&var3:value3.

Step 3 : where to put the SWF files

Put the SWF files in the doc_output_directory/swf.

  • Share/Bookmark

16
Nov 09

Array.sort() should not be used to shuffle an array

When a developer searches the web for an algorithm to shuffle an array in JavaScript or ActionScript, he will surely find a way to achieve that using the Array.sort() method (see references : JavaScript, ActionScript 3). While this method is intended to sort an array, it can also be used to randomize it (!). In general, here and there, the following algorithm comes forth :

/**
 * Add a randomize method to the Array object prototype
 * Usage :
 *  var tmpArray = ["a", "b", "c", "d", "e"];
 *  tmpArray.randomize();
 */

Array.prototype.randomize = function (){
    this.sort(
        function(a,b) {
            return Math.round( Math.random() * 2 ) - 1;
        }
    );
};

The principle of this implementation is simple. It takes advantage of the comparison Function that can be passed to the Array.sort() method. This function defines the sort order. It will be passed two objects (from the array) a and b, compare them and return -1, 0 or 1 whether a is less, equal or greater than b. The idea, to shuffle an array, is to randomly output -1, 0 or 1. This is the purpose of the expression Math.round( Math.random() * 2 ) – 1. This idea is bad.

Shuffling an array with Array.sort() results in… a not so shuffled array

Implementing a shuffle function on arrays, this way, is bad. At first glance it seems to produce well randomized arrays, but the random distribution is not uniform. I will illustrate this in a minute. Before that, give a look at the table below. It’s interactive. When you click start, it will run the following process :

  1. Create an array with ten letters in alphabetical orders from A to J

    var simpleArray = ["A","B","C","D","E","F","G","H","I","J"];
  2. Copy this array in a second array
  3. Run a shuffle algorithm against the second array
  4. Look where the letters are in the second array and record their position in the table columns
  5. Return to the step 2 and start the process again until a certain number of iterations has been reached

This repetitive process is pretty simple. It is not intended to give a mathematical evidence of the problem but to illustrate the consequences of a badly implemented shuffle algorithm. Note that the copy at step 2 is always made from the original array (not from the last shuffled array).

In this first example and to make sure you understand how this table work, step 3 is bypassed. Thus the copied array is always exactly the same as the original one. Click on Start button will launch the process (The number of iterations can be changed).

Normally, at the end of the process, you should see a table full of zeros with only the diagonal (top-left / bottom-right) filled with the number of iterations. It means that, at every steps, letters in the second array are at the same position than in the first one. This is what was expected because there is no shuffle.

Let’s do the same thing but now step 3 uses the shuffle algorithm we have seen before.

The result is interesting, isn’t it ? The position of letters has well been set randomly over iterations. Almost every cells in the table are filled with numbers. Let’s give a closer look. Actually, the nearer a cell is from the diagonal (top-left / bottom-right) the higher its number. Moreover there are still zeros in some cells far from this diagonal. Obviously, it means letters are more likely to be near their original position, after a shuffle.

How to better shuffle an array with Array.sort() ?

We said the comparison function returned randomly either -1, 0 or 1. What exactly happens in each case ? Let’s quote the Mozilla developer Center for the Array.sort() comparison function description

If compareFunction is supplied, the array elements are sorted according to the return value of the compare function. If a and b are two elements being compared, then:

  • If compareFunction(a, b) is less than 0, sort a to a lower index than b.
  • If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.
  • If compareFunction(a, b) is greater than 0, sort b to a lower index than a.

The Array.sort() method uses a Bubble Sort algorithm. Roughly, it steps through array elements and compare each one with its next adjacent element. It swaps the elements when the comparison function return 1. What does it do when the comparison function return 0 or -1 ? Actually nothing and here is the issue ! As the comparison function randomly generate -1, 0 or 1, each of those numbers has the same chance to arise. Unfortunately a letter can change its position only if 1 arises. It means that a letter has twice the chance not to move than to move !

So to resolve the issue the comparison function must not generate 3 numbers randomly but only two : 0 or 1. Thus a letter has the same chance to move than to stay in place. Below is the new implementation (Note that it is simpler than the previous one).

/**
 * Add a randomize method to the Array object prototype
 * Usage :
 *  var tmpArray = ["a", "b", "c", "d", "e"];
 *  tmpArray.randomize2();
 */

Array.prototype.randomize2 = function (){
    this.sort(
        function(a,b) {
            return  Math.round( Math.random() );;
        }
    );
};

The following table shows the result of this new implementation :

This result seems much more random than the previous one. There are much less zeros filling the table, however we can still see a kind of diagonal pattern where higher numbers seem much more on the diagonal. It is less obvious than before but still there. The reason for this can be found in the Bubble Sort algorithm and its implementation. Think about if A < B and B < C then not need to compare A and C.Thus, some comparisons are not done and optimization in code results in a greater efficiency to sort but an issue when shuffle.

Update : it seems there are differences between browsers. Notably, the method explained here is more accurate in Firefox but less in IE. Both gives bad uniform random, though. Not tested in other browsers

Shuffle arrays the good way

Fortunately it is not required to use Array.sort() to shuffle an array. Implement a shuffle function using Fisher-Yates algorithm is better and still easy.

Below is the code implementing a shuffle function using the Fisher-Yates algorithm. This algorithm provides uniform random.

/*
 * Add a shuffle function to Array object prototype
 * Usage :
 *  var tmpArray = ["a", "b", "c", "d", "e"];
 *  tmpArray.shuffle();
 */

Array.prototype.shuffle = function (){
    var i = this.length, j, temp;
    if ( i == 0 ) return;
    while ( --i ) {
        j = Math.floor( Math.random() * ( i + 1 ) );
        temp = this[i];
        this[i] = this[j];
        this[j] = temp;
    }
};

To prove the superiority of Fisher-Yates algorithm in Array.sort() implementation play with the table below.

With these results, it is obvious that this algorithm is far more efficient in distributing uniformly the letters in the array over iterations than Array.sort() style algorithms. Distribution is much more the same across cells.

  • Share/Bookmark

3
Oct 09

HTML 5 support workarounds and fallbacks

Last update Thursday, October 8, 2009

HTML 5 is a kind of revolution in Web development nowadays, but is not well supported still. I put together here a list of workarounds and fallbacks you can use to start coding HTML5 while keeping a good cross browsers support. If you have suggestions just drop a comment !

HTML5 tags and IE

IE will fail to style tags it does not recognize, especially the new HTML5 semantic tags like section, article, aside… The workaround is to help it identify those tags by using this small piece of JavaScript :

document.createElement("section");

Several JavaScript libraries help to detect http://www.modernizr.com/ or even to fix http://code.google.com/p/html5shiv/ HTML5 support in IE.

Source : http://blog.whatwg.org/supporting-new-elements-in-ie

Audio

A JavaScript exists which tests the audio element and the Audio() object support :
http://www.happyworm.com/jquery/jplayer/HTML5.Audio.Support/

Canvas

A JavaScript library exists to simulate canvas tag in Internet Explorer : http://code.google.com/p/explorercanvas/

SVG

Google has developped a JavaScript library to simulate SVG in browser that does not support it http://code.google.com/p/svgweb/

Video

There are several support levels of the HTML 5 video tag. Internet Explorer does not support it at all. Firefox, Safari and Chrome, in there last release, support it but with different codecs. As a result the best way to use the video tag is : first, by providing sources with different codecs, second by providing a Flash fallback :

<video controls>
<source src="zombie.ogg" type="video/ogg"/>
<source src="zombie.mp4" type="video/mp4"/>
<embed src="http://blip.tv/play/AYGLzBmU8hw"
   type="application/x-shockwave-flash"
   width="500" height="396"
   allowscriptaccess="always"
   allowfullscreen="true"/>
</video>

This fallback should be supported by all the major browsers. If you require more support for iPhone, Quicktime… you should give a look at other solutions like : Video for everybody

Sources :
http://hacks.mozilla.org/2009/06/html5-video-fallbacks-markup/
https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox

Web Forms 2.0

A JavaScript library exists to emulate Web Forms 2.0 : http://code.google.com/p/webforms2/.
More information on Web Forms 2.0 emulation can be found here : http://wiki.whatwg.org/wiki/Implementations_in_Web_browsers

Web workers

The ability to do JavaScript threading is partially emulated by a JavaScript library : http://code.google.com/p/fakeworker-js/

  • Share/Bookmark

11
Jul 09

jQuery Twitter API plugin

I have released a simple Twitter public API for jQuery. Code and examples are open source and can be download here : http://code.google.com/p/jquery-twitter-api/.

NB : informations requiring authentication are not accessible to JavaScript inside classical Web pages because of the same origin policy restriction. Thus this plugin is only intended to access publicly available data.

  • Share/Bookmark

8
Jun 09

Mozilla Hacks

Mozilla Hacks

Mozilla Hacks

Firefox 3.5 is going to be released in a few weeks. To highlight some of the new features, Mozilla launched a new website.

http://hacks.mozilla.org/

Mozilla Hacks presents articles and demos, either from core Mozilla hackers or from Web Developer like me. I’m very proud that the Mozilla Team chose as first demo the one I made at Pims Labs “Content Aware Image Resizing implemented with JavaScript“.

The post is here http://hacks.mozilla.org/2009/06/content-aware-image-resizing/

I would like to thanks all Mozilla team for that !

Update : two Chinese translations have been posted here (zh-CN) 内容感知的图片大小调整 and here (zh-TW) 內容感知式圖片縮小法。

  • Share/Bookmark

2
Jun 09

A JavaScript implementation of the Content Aware Image Resizing algorithm

http://labs.pimsworld.org/2009/05/a-javascript-implementation-of-the-content-aware-image-resizing-algorithm/

  • Share/Bookmark

2
Jun 09

Firefox Native Content Aware Image Resizing

http://labs.pimsworld.org/2009/04/firefox-native-content-aware-image-resizing/

  • Share/Bookmark