JQuery and human readable email addresses

JQuery No Comments »

Ive just started playing with the power that is Jquery and came up with this nice use for the Ajax functionality in Jquery.

You want to put your email address on your web site so people can contact you, but don’t want to put a mailto: anchor in the html, because it will be spidered and added to some morons Spam list.

Here is a simple and server independent solution:

Firstly, create a file on your site, it doesn’t have to have a html extension, e.g. email.me
In the content of the file, add the html snippet that you would like to display to the user as your email address (usually an anchor tag with a mailto: href). This is the html that will be inserted into your web page when the user clicks on the Show email address text.

e.g.
[code]
<a href=”mailto:someone@somewhere”>someone@somewhere</a>
[/code]
In your web pages, where you wish someone to be able to see your email address by clicking, enter a span with a class of email.

[code]
<span class=”email”>Click to see email</span>
[/code]

in the ready function for your document enter the following:

[code]
$(’.email’).click(function(el){
$(this).hide().load(’email.me’).fadeIn(1000);
});
[/code]

This will add a click function to all elements assigned the email class, that when clicked, will replace the current content with the content of the email.me file (faded in :) ). In this case your email mailto anchor. This principle can be used to display any content. Maybe you want to hide the comment form for your blog, until a display has been clicked, give it a try.

Script Hightlighter

JavaScript No Comments »

A nice script highlighter that I need to integrate at some point. It is written in javascript so does not rely on server side technologies which is quite nice and will highlight the following languages.

Language Aliases
C++ cpp, c, c++
C# c#, c-sharp, csharp
CSS css
Delphi delphi, pascal
Java java
Java Script js, jscript, javascript
PHP php
Python py, python
Ruby rb, ruby, rails, ror
Sql sql
VB vb, vb.net
XML/HTML xml, html, xhtml, xslt

Produces output that looks like this…

Javascript - Rails like pluralize function

JavaScript No Comments »

Found this on scripts.dzone.com blogged for reference.

/*
 * This script depends on no outside libraries.
 */

Inflector = {
    /*
     * The order of all these lists has been reversed from the way 
     * ActiveSupport had them to keep the correct priority.
     */
    Inflections: {
        plural: [
            [/(quiz)$/i,               "$1zes"  ],
            [/^(ox)$/i,                "$1en"   ],
            [/([m|l])ouse$/i,          "$1ice"  ],
            [/(matr|vert|ind)ix|ex$/i, "$1ices" ],
            [/(x|ch|ss|sh)$/i,         "$1es"   ],
            [/([^aeiouy]|qu)y$/i,      "$1ies"  ],
            [/(hive)$/i,               "$1s"    ],
            [/(?:([^f])fe|([lr])f)$/i, "$1$2ves"],
            [/sis$/i,                  "ses"    ],
            [/([ti])um$/i,             "$1a"    ],
            [/(buffal|tomat)o$/i,      "$1oes"  ],
            [/(bu)s$/i,                "$1ses"  ],
            [/(alias|status)$/i,       "$1es"   ],
            [/(octop|vir)us$/i,        "$1i"    ],
            [/(ax|test)is$/i,          "$1es"   ],
            [/s$/i,                    "s"      ],
            [/$/,                      "s"      ]
        ],
        singular: [
            [/(quiz)zes$/i,                                                    "$1"     ],
            [/(matr)ices$/i,                                                   "$1ix"   ],
            [/(vert|ind)ices$/i,                                               "$1ex"   ],
            [/^(ox)en/i,                                                       "$1"     ],
            [/(alias|status)es$/i,                                             "$1"     ],
            [/(octop|vir)i$/i,                                                 "$1us"   ],
            [/(cris|ax|test)es$/i,                                             "$1is"   ],
            [/(shoe)s$/i,                                                      "$1"     ],
            [/(o)es$/i,                                                        "$1"     ],
            [/(bus)es$/i,                                                      "$1"     ],
            [/([m|l])ice$/i,                                                   "$1ouse" ],
            [/(x|ch|ss|sh)es$/i,                                               "$1"     ],
            [/(m)ovies$/i,                                                     "$1ovie" ],
            [/(s)eries$/i,                                                     "$1eries"],
            [/([^aeiouy]|qu)ies$/i,                                            "$1y"    ],
            [/([lr])ves$/i,                                                    "$1f"    ],
            [/(tive)s$/i,                                                      "$1"     ],
            [/(hive)s$/i,                                                      "$1"     ],
            [/([^f])ves$/i,                                                    "$1fe"   ],
            [/(^analy)ses$/i,                                                  "$1sis"  ],
            [/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, "$1$2sis"],
            [/([ti])a$/i,                                                      "$1um"   ],
            [/(n)ews$/i,                                                       "$1ews"  ],
            [/s$/i,                                                            ""       ]
        ],
        irregular: [
            ['move',   'moves'   ],
            ['sex',    'sexes'   ],
            ['child',  'children'],
            ['man',    'men'     ],
            ['person', 'people'  ]
        ],
        uncountable: [
            "sheep",
            "fish",
            "series",
            "species",
            "money",
            "rice",
            "information",
            "equipment"
        ]
    },
    ordinalize: function(number) {
        if (11 <= parseInt(number) % 100 && parseInt(number) % 100 <= 13) {
            return number + "th";
        } else {
            switch (parseInt(number) % 10) {
                case  1: return number + "st";
                case  2: return number + "nd";
                case  3: return number + "rd";
                default: return number + "th";
            }
        }
    },
    pluralize: function(word) {
        for (var i = 0; i < Inflector.Inflections.uncountable.length; i++) {
            var uncountable = Inflector.Inflections.uncountable[i];
            if (word.toLowerCase() == uncountable) {
                return uncountable;
            }
        }
        for (var i = 0; i < Inflector.Inflections.irregular.length; i++) {
            var singular = Inflector.Inflections.irregular[i][0];
            var plural   = Inflector.Inflections.irregular[i][1];
            if ((word.toLowerCase() == singular) || (word == plural)) {
                return plural;
            }
        }
        for (var i = 0; i < Inflector.Inflections.plural.length; i++) {
            var regex          = Inflector.Inflections.plural[i][0];
            var replace_string = Inflector.Inflections.plural[i][1];
            if (regex.test(word)) {
                return word.replace(regex, replace_string);
            }
        }
    }
}

function ordinalize(number) {
    return Inflector.ordinalize(number);
}

/*
 * Javascript doesn't have optional parameters or overloading so I had to use
 * the ever popular pseudo options hash object technique.
 * required properties:
 *     count    Number of objects to pluralize
 *     singular Singular noun for the objects
 * optional property:
 *     plural   Plural (probably irregular) noun for the objects
 * examples:
 *      pluralize({ count: total_count, singular: "Issue" })
 *      pluralize({ count: total_count, singular: "Goose", plural: "Geese" })
 */
function pluralize(options) {
    return options.count + " " + (1 == parseInt(options.count) ?
        options.singular :
        options.plural || Inflector.pluralize(options.singular));
}

Oh my god, the future of Rich Internet Applications is here…

JavaScript 1 Comment »

In my opinion, there are key events that happen that shape the future of web development.  The move to Web 2.0 and ajax, was a little tremor compared by the Factor 10  on the Richter scale announcement of Aptana’s Jaxer server.  I have always found having to develop javascript client side, C# / PHP / ASP or some other technology server side annoying.  Having to replicate the same validation in different languages and having to write data conversion layers to get data in either json or xml format just so the client can use it annoying, a pain to maintain and a waste of development time.

Enter Jaxer, essentially server side javascript processing but on steroids.  With Jaxer, you can write in the single html page, javascript that can run on either the client, the server or both, server side code is never sent to the client browser enabling you to hide your intellectual property and the workings of you API.  Any javascript library that can run client side can be used server side as well and they have added server side libraries for writing to files, socket communications, database access and web based communication. The Client can even make callbacks to server side functions simply by setting function.name.proxy = true, and Jaxer will create an Ajaxy stub client side making the server side call available to the client.

It is implemented using the mozilla firefox 3 javascript and dom engine, and a large proportion of the interpreter is C++ code, so performance should be good.  I would love to see some performance stats that compare it against php / asp / etc , but haven’t come across any yet.  If Aptana have got the performance nail hit on the head, this really will be the future of Rich Internet application development.

Going loopy with JavaScript

JavaScript 2 Comments »

I am in the middle of writing a JavaScript tree that can handle 100s of thousands of nodes in the tree and needed to see if I can optimize the code.  Trying to optimize the loop iterations for array objects, I put together a test case to time the efficiency of various different types of loops in JavaScript.

The test

Create an array of 1 million numbers 0 to 1 million, for each of the loop tests, increment a counter then display it at the end of the iterations.

The test covers the following loops:

  1. ForLoop - standard for loop accessing the length of the array in the iterator
  2. ForLoopLocalCount - standard for loop, accessing the length of the array stored in a local variable before the iterator
  3. ForLoopLocalCountAndIterator - standard for loop accessing the count and the iterator from local variables
  4. ForInLoop - standard For In loop
  5. ForInLoopLocalItem - standard For In Loop, but declaring the iterator variable locally first.
  6. WhileLoop - While loop iterator accessing the length at each iteration
  7. WhileLoopCountFirst - while loop but storing the length of the array in a local variable before the iterator.

 

var loopTest = {
    itemCount : 1000000,
    items : [],
    
    initArray : function()
    {
        for(var x=0; x < this.itemCount; x++)
        {
            this.items.push(x);
        }
        console.log(this.items.length);
    },
    
    forLoop : function()
    {
        var total=0;
        for(var i=0;i < this.items.length; i++)
        {
            total ++;
        }
        console.log(total );
    },
    
    forLoopLocalCount : function()
    {
        var total=0;
        var count = this.items.length;
        for(var i=0;i < count; i++)
        {
            total ++;
        }
        console.log(total );
    },
    
    forLoopLocalCountAndIterator : function()
    {
        var total=0;
        var count = this.items.length;
        var i = 0;
        for(i=0;i < count; i++)
        {
            total ++;
        }
        console.log(total );
    },
    
    forInLoop : function()
    {
        var total=0;
        for(item in this.items)
        {
            total ++;
        }
        console.log(total);
    },
    
    forInLoopLocalItem : function()
    {
        var total=0;
        var item = null;
        for(item in this.items)
        {
            total ++;
        }
        console.log(total);
    },
    
    whileLoop : function()
    {
        var total=0;
        var i = 0;
        while(i<this.items.length)
        {
            total ++;
            i++;
        }
        console.log(total );
    },
    
    whileLoopCountFirst : function()
    {
        var total=0;
        var i = 0;
        var count = this.items.length;
        while(i<count)
        {
            total ++;
            i++;
        }
        console.log(total );
    },
    
    runTests : function()
    {
        this.initArray();
        this.forLoop();
        this.forLoopLocalCount();
        this.forLoopLocalCountAndIterator();
        this.forInLoop();
        this.forInLoopLocalItem();
        this.whileLoop();
        this.whileLoopCountFirst();
        console.log("Complete.");
    }
}

 

The test was profiled using the firebug profile option and run in Firefox 2.0.0.4 on a Dual Core Pentium 3.2Ghz machine with 3Gb of ram.

 

Results & Conclusion

The test results are shown in the table to the right. So what can we conclude from the results?

  • Don’t use a For In loop.  There is a small increase in performance if you allocate the item variable outside of the loop, but it is still up to 31 times slower than using a for or while loop.
  • Always ensure that the count (used in the loop exit test) is stored in a temporary variable outside of the iterator i.e. rather than calling array.length in the iterator exit test.
  • When local variables are used to store the iterator and count, a for loop performs the same as a while loop.  One would assume that the JavaScript.
  • In a For loop, declaring the iterator variable outside of the loop actually slows the iteration down! This I did not expect.

Firebug - Console options

JavaScript 1 Comment »

Firebug, the ultimate javascript debugger for firefox, automatically creates a “console” object that has various methods that can be used to aid in debugging your javascript apps.

Full Documentation is here http://www.getfirebug.com/console.html

console.log() is the most used, with the ability to pass parameters and a formatted string.

One of the nice things is, if you log an object it displays all the objects properties as well.

For performance testing console.time(id) and console.timeEnd(id) are very useful.

consolt.trace() will even dump the full stack at the point it is called.

 

If you haven’t got firebug, it’s a must if you are developing with firefox.  Go get it here

101 of Memory Leak causes in JavaScript

JavaScript 1 Comment »

Really nice article explaining some of the gotcha’s that can cause memory leaks in JavaScript

http://www-128.ibm.com/developerworks/web/library/wa-memleak/

Ext.Format extension for thousands separator formatting

Ext General, JavaScript No Comments »

A simple function, the basis of was in the public domain (see comments) to format a number with thousand separators.

 

Ext.apply(Ext.util.Format,{
 
    decimalSeparator : '.',
    thousandSeparator : ',',
        
    /* Adapted from http://www.mredkj.com/javascript/nfbasic.html, 
     * Public Domain, without copyright, and can be used without restriction: 
     * see http://www.mredkj.com/legal.html
     */    
    asThousands : function(value)
    {
        value = parseInt(value,10) + '';
        var x = value.split(this.decimalSeparator);
        var x1 = x[0];
        var x2 = x.length > 1 ? this.decimalSeparator + x[1] : '';
        var rgx = /(\d+)(\d{3})/;
        while (rgx.test(x1)) {
            x1 = x1.replace(rgx, '$1' + this.thousandSeparator + '$2');
        }
        return x1 + x2;
    }
});

Ext.util.SpriteManager

Ext Components, JavaScript 3 Comments »

One of the ways of improving web page performance (especially in RIA - Rich Internet Applications) where there are lots of small images that need to be displayed, e.g. on a toolbar, is to create a compound image and then use css to select a section of the image to display.  In the javascript world this is known as using sprites.  In the world of C#/vb/Delphi this is well known and there have always been ImageList components that store images in this form.

So instead of creating single images :    we create a composite image e.g. (have added a second row as well)

To make the process of assigning the correct css style to select on of the images to display, I have created a SpriteManager addition to Ext JS as follows:

 

 
Ext.namespace('Ext', 'Ext.util');
 
Ext.util.SpriteManager = function(config){
        Ext.apply(this,config,{
                spriteSource:true,
                spriteWidth:1,
                spriteHeight:1,
                spriteColumns:1,
                spriteRows:1
                });
};
 
 
Ext.util.SpriteManager.prototype = {
 
    /**
     * Gets the CSS Style for the appropriate image
     * @param {Object...} spriteLocation Expects an object with an X and Y location of the sprite to display
     * @return {String} returns the CSS style string enclosed in braces {}
     */
    getSpriteCSS : function(spriteLocation){
            var locationX = spriteLocation.x-1 || 0;
            var locationY = spriteLocation.y-1 || 0;
            var spriteCss = ['{'];
            var spriteW = this.spriteWidth / this.spriteColumns;
            var spriteH = this.spriteHeight / this.spriteRows;
            var spriteXPos = locationX * spriteW;
            var spriteYPos = locationY * spriteH;
                         
            if(!typeof this.spriteSource =="boolean")
            {            
                spriteCss.push('background:url(' + this.spriteSource +');');
            }
            spriteCss.push('height:' + spriteH + 'px;');
            spriteCss.push('width:' + spriteW + 'px;');
            spriteCss.push('background-position:-' + spriteXPos + 'px -' + spriteYPos + 'px;');
            spriteCss.push('}');
            return spriteCss.join("");
    },
        
    /**
     * Applies the CSS Style for the appropriate sprite image to an element
     * @param {element} Ext.Element to apply the sprite style to.
     * @param {Object...} spriteLocation Expects an object with an X and Y location of the sprite to display
     */
        applySpriteCss : function(el, spriteLocation)
        {
            var css = this.getSpriteCSS(spriteLocation);
            el.applyStyles(css);
        }
};

Here is an example of the usage:

<script type="text/javascript">
var spriteManager = new Ext.util.SpriteManager({
            spriteSource:"sprites.png",
            spriteWidth:64,
            spriteHeight:34,
            spriteColumns:4,
            spriteRows:2
            });
</script>
 
...
 
<img id="test" src="images/default/s.gif" /> 
<a href="javascript:spriteManager.applySpriteCss(Ext.get('test'),{x:1,y:1});">Image 1,1</a>
<a href="javascript:spriteManager.applySpriteCss(Ext.get('test'),{x:2,y:1});">Image 2,1</a>
<a href="javascript:spriteManager.applySpriteCss(Ext.get('test'),{x:1,y:2});">Image 1,2</a>
<a href="javascript:spriteManager.applySpriteCss(Ext.get('test'),{x:2,y:2});">Image 2,2</a>

  ** Updated 2/5/2007 - spriteSource does not now need to be supplied if the element already has a css style specifying the background image.

Non-record based Json calls across Domains with Ext

Ext General 1 Comment »

From a forum question I posted at Ext: http://extjs.com/forum/showthread.php?t=5430

I am trying to make a call to a webpage that returns a json object that is hierarchical in nature and not record based so as far as I am aware, jsonreader / datareader are not suitable.

The Server returns something looking like this:

   1: (
   2:     { 
   3:     children: [
   4:         { 
   5:         id : "1", 
   6:         name : "Dim Item 1", 
   7:         children : [