Archive for category Web development

Programatically fire crossbrowser click event with JavaScript

The following function triggers a mouseclick event on the DOM-node you pass to it.
I’ve tested it with Internet Explorer 6, 7, 8 and 9, Firefox 3.x and 11 nightly. Chrome 17-dev, Opera 10 and 11, webkit on iOS 5 iPhone 4, webkit on Android 2.3.4, Safari 4.0.5 on Windows. If you need it on another browser/version/os, please test it and post the result as a comment here.

function fireClick(node){
	if ( document.createEvent ) {
		var evt = document.createEvent('MouseEvents');
		evt.initEvent('click', true, false);
		node.dispatchEvent(evt);	
	} else if( document.createEventObject ) {
		node.fireEvent('onclick') ;	
	} else if (typeof node.onclick == 'function' ) {
		node.onclick();	
	}
}

Example usage:

//assumes <a href="http://www.nonobtrusive.com" id="myLink">Click me</a>
var theNode = document.getElementById('myLink');
theNode.onclick = function(){ alert("You clicked a link with href:" + this.href); };
fireClick(theNode);

26 Comments

Lightweight JSONP javascript library

This can now be found at github: https://github.com/IntoMethod/Lightweight-JSONP

Are you one of those that include jQuery or any other library only to be able to use some JSONP in your website? In that case this might be the code for you to read and try to understand. I won’t post any detailed explainations right now but feel free to comment if you wonder anything. I’ve also included a minified version in the bottom.

Update (2012-04-10) Fixed issues/suggestions found by Zach, Gabriel and Pamela (see comments). These updates and fixes can be found on github

Update (2011-06-08) Fixed delete/setting to null as pointed out by Bryan Smith (see comment)

Update (2011-04-29) Added encodeURIComponent as suggested by yched (see comment)

Update: Fixed scoping problem as found by Damon Oehlman (see comment)

Feel free to use this script for anything that you like, commercial or non-commercial, but please keep the comment and link to this site.

Oh and by the way, the script has been tested successfully in the following browsers:
Chrome 4,5,6
Firefox 3.x
Internet Explorer 6,7,8
Opera 9.6+10
Androids webkit-based browser
Symbian S60 browser

First an example of how to use it, to show the simplicity, then the actual code.

JSONP.get( 'someUrl.php', {param1:'123', param2:'456'}, function(data){
        //do something with data, which is the JSON object you output from someUrl.php
        //into the callback javascript method specified by the "callback" value in the querystring
});

A simple example of the someUrl.php (please observe this example does not include any security checks what so ever, just to show the principle):

$myData = fetchSomeData();
 
echo $_GET['callback'];
echo "(";
echo json_encode($myData);
echo ")";

See github link above for current code and examples, the code below is old

The actual code for the Lightweight JSONP functionality.
Around 1.1kb without gzip.

//Lightweight JSONP fetcher - www.nonobtrusive.com
var JSONP = (function(){
	var counter = 0, head, query, key, window = this;
	function load(url) {
		var script = document.createElement('script'),
			done = false;
		script.src = url;
		script.async = true;
 
		script.onload = script.onreadystatechange = function() {
			if ( !done && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") ) {
				done = true;
				script.onload = script.onreadystatechange = null;
				if ( script && script.parentNode ) {
					script.parentNode.removeChild( script );
				}
			}
		};
		if ( !head ) {
			head = document.getElementsByTagName('head')[0];
		}
		head.appendChild( script );
	}
	function jsonp(url, params, callback) {
		query = "?";
		params = params || {};
		for ( key in params ) {
			if ( params.hasOwnProperty(key) ) {
				query += encodeURIComponent(key) + "=" + encodeURIComponent(params[key]) + "&";
			}
		}
		var jsonp = "json" + (++counter);
		window[ jsonp ] = function(data){
			callback(data);
			try {
				delete window[ jsonp ];
			} catch (e) {}
			window[ jsonp ] = null;
		};
 
		load(url + query + "callback=" + jsonp);
		return jsonp;
	}
	return {
		get:jsonp
	};
}());

, ,

46 Comments

How to prevent setting dynamic fields in your PHP classes

One problem that could arise when multiple coders are working on the same project is that everyone might not work with the same editors, and therefore everyone might not have intellisense / autocompletion. What could this cause? Alot of things 🙂 But we’ll talk about one of them below.

Well all PHP classes are by nature dynamic, which means that it’s possible to set variables that havn’t been declared. One would believe that setting the class to “final” would automatically fix this, but this is not the case.

Simple example:

class SimpleStructure 
{
	public $name;
	public function __construct( $name ) {
		$this->name = $name;
	}
}
 
$simple = new SimpleStructure("nonobtrusive");
$simple->myName = "dynamic_value";	//allowed
 
echo $simple->name, " - ", $simple->myName;

The above code will output:

nonobtrusive - dynamic_value

So, how can we prevent this if it’s an unwanted behaviour ?
The answer is simple, use the magic method __set.

class SimpleStructure 
{
	public $name;
 
	public function __construct( $name ) {
		$this->name = $name;
	}
 
	public function __set( $key, $value ) {
		throw new Exception( "Not allowed to assign undefined variable : " . $key );
	}
}
 
$simple = new SimpleStructure("nonobtrusive");
$simple->myName = "dynamic_value";	//allowed
 
echo $simple->name, " - ", $simple->myName;

The above code would throw the error:

Fatal error: Uncaught exception 'Exception' with message 'Not allowed to assign undefined variable : myName'

To wrap this up we could also create our own UndefinedFieldException class and throw an instance of it to easier catch that specific error.

class UndefinedFieldException extends Exception
{
	public function __construct( $key ) {
		$this->message = "Not allowed to assign undefined field : " . $key;
	}
}
 
//then we can throw the exception like this instead
throw new UndefinedFieldException( $key );
 
//which in the above example would show as
Fatal error: Uncaught exception 'UndefinedFieldException' with message 'Not allowed to assign undefined field : myName'

, , , , ,

1 Comment

Wan’t to get rid of your traces to trace? (Flex)

Update: to clearify I want to mention already here that this post regards using the Flex SDK, since the Adobe CS have an “Omit traces” checkbox which totally removes all traces in the bytecode as well.

I noticed a high FPS-loss in one of my applications when testing some Z-sorting in the Flash 10 3D functionality which I hadn’t been seing before. This even when using release mode when compiling! I had to use the profiler through Flash Builder 4 beta to track it down to a trace in the Z-ordering algorithm (just using a regular Painters Algorithm based on the actual Z-value compared to the root). /Update

What’s up with that trace draining performance even when compiling in release mode?

Believe it or not, but the bytecode regarding traces look identically no matter if you use release or debug compilation mode, it’s just up to the flashplayer itself to actually make something with the call to trace depending on the release mode.

So here’s the proof, and solution:

A normal constructor for a Main class:

public function Main():void 
{
	trace("Test");
}

So, you’re running your little flash-application in debug mode while developing, of course because you want to see the trace messages. But what happens behind the scene?
This is what the ABC2 byte-code looks like for the above Main constructor, notice the trace with 13, 15 and 17 in front (which by the way is the sum of instructions for the AVM2 engine).

function Main():void	/* disp_id -1*/
{
	// local_count=1 max_scope=1 max_stack=2 code_len=24
	0       debugfile     	"E:\temp\TraceTest\src;;Main.as"
	2       debugline     	13
	4       getlocal0     	
	5       pushscope     	
	6       debugline     	13
	8       getlocal0     	
	9       constructsuper	(0)
	11      debugline     	15
	13      findpropstrict	trace //find the trace function
	15      pushstring    	"Test" //the string to trace
	17      callproperty  	trace (1) //call the function
	20      pop           	          //end - start of next, 20-13 = 7 instructions for the AVM2 engine
	21      debugline     	16
	23      returnvoid    	
}

Okay, nothing weird here since its compiled with debug, but what really happens when we switch to release mode?
Well, mainly the compiler will remove the debugline, telling what line in the actual source-code (.AS files) the flashplayer executes the code for. This is the information shown in unhandled exceptions that gets thrown so you easily can find the broken code.

But, what about that trace?

This is the exact same code, only switched to release mode:

function Main():void	/* disp_id -1*/
{
	// local_count=1 max_scope=1 max_stack=2 code_len=13
	0       getlocal0     	
	1       pushscope     	
	2       getlocal0     	
	3       constructsuper	(0)
	5       findpropstrict	trace //Didn't I just tell you to go away by switching to release mode?
	7       pushstring    	"Test" //Even the strings are left intact
	9       callpropvoid  	trace (1) //And also the function call.... sigh
	12      returnvoid    	     //still adding upp to 12-5 = 7 instructions as well since it's the exact same code
}

But how can we solve this?
One solution could be to add a global flag in the main class and then use it as condition when to use the trace

private const DEBUG:Boolean = false;  //change to true when developing

But this would only make the release build to evaluate that flag to see if we want to trace or not,
so how about removing all traces by hand ? Not too funny when we want to continue to develop again.

The solution is called conditional compilation and is supported by the Flex compiler.
See Adobes reference here: http://livedocs.adobe.com/flex/3/html/help.html?content=compilers_21.html

The solution for this example:

public function Main():void 
{
	IFDEF::DEBUG {
		trace("Test");
	}
}

And by passing this to the compiler:

-define=IFDEF::DEBUG,false
//or
-define=IFDEF::DEBUG,true

we simply make the compiler remove the whole block of code within the { } when IFDEF:DEBUG is set to false

This produces the ABC2 byte-code as follows, nice and clean from the trace:

function Main():void	/* disp_id -1*/
{
	// local_count=1 max_scope=1 max_stack=1 code_len=6
	0       getlocal0     	
	1       pushscope     	
	2       getlocal0     	
	3       constructsuper	(0)
	5       returnvoid    	
}

, , , , , ,

8 Comments

Array clone in javascript ?

There’s no such thing unfortunately, but it’s easy to replicate the same behaviour since we’ve got a handy cross-browser method called slice.
So what does the slice method do ? It allows up to two parameters to be passed in, start index and end index. If none are sent in the slice method will return a COPY of the original array, which allows us to use it as if it were a clone method. If only the first parameter is specified it will assume the full length of the array as secondary parameter. Not specifying a value will as earlier mentioned behave the same as this:

var copiedArray = theArray.slice( 0, theArray.length );
 
//this results in the same
var copiedArray = theArray.slice();

Examples:

var sourceArray = [1,2,3,4,5],
     clonedArray = sourceArray.slice();
 
alert(sourceArray.slice(1));  //will return & alert a copied array with the values 2,3,4,5 at indexes 1,2,3,4
 
alert(sourceArray.slice(1,2));  //will return & alert a copied array with the value 2 at index 0
 
sourceArray = sourceArray.slice(1,4);  //sourceArray will now contain 2,3,4
 
alert(clonedArray);  //will still alert 1,2,3,4,5 since it's a copy of the original array and not a reference.

1 Comment

“Keeping” calling-context with setTimeout/setInterval

The javascript setTimeout function allows to pass some code or function to be called after a specifiec timeout in milliseconds. But since the callback is handled by the Window object it’ll loose the “this” from whatever it was called from. There’s two possible solutions to this, the first and most common is to use something like

var self = this;
setTimeout( function(){
     self.someValue = ........;
     self.someFunction();
     etc....
}, 500 );

But one other option is to execute the anonymous function which then returns another function as the code below shows.

function Foo(){
	setTimeout( (function(self){
		return function(){
			alert(this);	//Window
			alert(self);	//Foo
		}
	})(this), 2500 );
}
Foo.prototype.toString = function(){
	return "[object Foo]";
}
new Foo();

, ,

No Comments

Simple Actionscript 3.0 Flash VideoPlayer in < 40 lines of code

So.. you want a flash videoplayer but don’t want to purchase an expensive player, or use the great multi-i-can-play-everything-player which is 30kb+ in swf size?

Lets check this out how easy it could be to really create a tiny videoplayer, the following code does compile into roughly 1kb swf which should be small enough for everyone to use, let the user spend his bandwidth on downloading the actual video instead of the player itself!
Set the flashvar videoUrl to specify which video to play.

See the player in action here

package 
{
	import flash.display.*;
	import flash.media.*;
	import flash.events.*;
	import flash.net.*;
	/**
	 * @author Erik Karlsson, www.nonobtrusive.com
	 */
	public class Main extends Sprite 
	{
		public function Main() 
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			var connection:NetConnection = new NetConnection();
			connection.connect(null);			
			var stream:NetStream = new NetStream(connection);
			stream.addEventListener(NetStatusEvent.NET_STATUS, onEvent );
			stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onEvent );
			stream.addEventListener(IOErrorEvent.IO_ERROR, onEvent );
			stream.client = this;     //for onMetaData and onCuePoint
			var video:Video = new Video(stage.stageWidth, stage.stageHeight);
			video.attachNetStream( stream );
			stream.play( stage.loaderInfo.parameters["videoUrl"] );  //pass the url to video as videoUrl flashvar
			addChild(video);
		}
		private function onEvent(event:Event):void {
			trace( event.toString() );		//handle this as you wish
		}
		public function onMetaData(info:Object):void {
			trace( info.duration + " - " + info.width + " - " + info.height + " - " + info.framerate ); //handle this as you wish
		}
		public function onCuePoint(info:Object):void {
			trace( info.time + " - " + info.name + " - " + info.type ); //handle this as you wish
		}
		public function onXMPData(data:Object):void {
                        //used in flash10+
			trace( data ); //handle this as you wish
		}
	}
}

, , ,

71 Comments

Just a general note, you can’t delete everything

I’ve had this discussion a couple of times now with several people and maybe It’s about time to make a post for it here 🙂

The delete operator in ECMAScript-262 can only be used to delete dynamically created variables/properties. Having that said heres a code sample:

var foo = "test"; //executing this in the global window-scope will actually create window.foo and it's being considered as a  dynamically created property on the window object.
delete foo;  //will return true, success
alert(foo); //throws a javascript exception since foo is deleted, thus being undefined

On the other hand…

(function(){
var foo ="test";  //local to the anonymous function, could as well be in a named function.
delete foo;  //will return false, failure to delete
alert(foo);  //will alert "test", delete had no affect
})();

1 Comment

Dispatcher followup : A more compact way of writing prototypes + module pattern + test

The previous post I added some prototype methods to the Dispatcher class, but It could has well been written on the following syntax instead

function Dispatcher(){}
Dispatcher.prototype = {
     addEventlistener : function(event, callback){
        //code here
     },
     removeEventlistener : function(event, callback){
        //code here
     }
     //add more methods here... don't forget to comma-separate them and do not add a comma last!
}

So how about writing up this with the module pattern on the same time. I’ll also show a simple way to write an automatic unit-alike test for this.

/**
* @author: Erik Karlsson, www.nonobtrusive.com
**/
var nonobtrusive = nonobtrusive ||{}; //create the "namespace" like object if it doesnt exist
nonobtrusive.events = nonobtrusive.events || {}; //create the sub-namespace events where we'll place our Dispatcher class
nonobtrusive.events.Dispatcher = (function(){
	var undefined; //speed up references to undefined + allows munging
    function Dispatcher(){
         this.events=[];
    }
    Dispatcher.prototype = {
		addEventlistener : function(event, callback){
			if ( event == undefined || callback == undefined ) return false;	//verify that we have parameters sent in
			var listeners = this.events[event] = this.events[event] || [];		//create a new array to hold listeners if first time
			listeners[listeners.length]=callback;
		},
		removeEventlistener : function(event, callback){
			if ( event == undefined || callback == undefined ) return false;	//verify that we have parameters sent in
			var listeners = this.events[event];
			if ( listeners ) {
				for ( var i = listeners.length-1; i>=0; --i ){	//go through all listeners for this specific event
					if ( listeners[i] === callback ) {
						listeners.splice( i, 1 );	//remove the eventcallback if we found it
						return true;
					}
				}
			}
			return false;
		},
		dispatch : function(event){
			if ( event == undefined ) return false;
			if ( this.events[event] ) {
				var listeners = this.events[event], len = listeners.length;
				while ( len-- ) {
					listeners[len](this);	//callback with self
				}		
			}
		}
		//add more methods here... don't forget to comma-separate them and do not add a comma last!
   }
 
   return Dispatcher;
})();
 
 
function DispatcherTest(){
	nonobtrusive.events.Dispatcher.call(this);
 
	//Some internal variables to keep track of the test-process.
	var	dispatchOk = false,
		afterRemovalOk = false;
 
	this.dispatchCallback = function(){
		dispatchOk = !dispatchOk;
	}
 
	this.setup = function(){
		this.addEventlistener("TestEvent", this.dispatchCallback);
	}
 
	this.run = function(){
		this.dispatch("TestEvent");
		afterRemovalOk = this.removeEventlistener("TestEvent", this.dispatchCallback);
		this.dispatch("TestEvent");	//nothing should happen since we're not listening to this event anymore.
		if ( dispatchOk && afterRemovalOk ) {
			alert("DispatcherTest was ok!");
		}
	}
}
DispatcherTest.prototype = new nonobtrusive.events.Dispatcher();
 
//Run the test
var test = new DispatcherTest();
test.setup();
test.run();

If you want to use this class, download the minified script here :
http://www.nonobtrusive.com/wp-content/uploads/2009/07/nonobtrusive.events.Dispatcher-min.js
or try out the test yourself by visiting this page :
http://www.nonobtrusive.com/wp-content/uploads/2009/07/dispatcher-test.html

, , , , ,

1 Comment

Custom events in javascript by making your own Dispatcher class.

Don’t have the time to comment the code and explain right now, but I will update the post later on 🙂
I wrote this in about 2minutes to help out a guy just before going to bed so I’ve only tested the addEventListener and dispatch functionality (not removeEventListener), but it actually worked in IE7, IE8, Firefox 3.5, Chrome2 and Stainless (Webkit based browser under osx) on the first try.

Feel free to comment if you find this useful

/**
* @author Erik Karlsson, www.nonobtrusive.com
*/
function Dispatcher(){
	this.events=[];
}
Dispatcher.prototype.addEventlistener=function(event,callback){
	this.events[event] = this.events[event] || [];
	if ( this.events[event] ) {
		this.events[event].push(callback);
	}
}
Dispatcher.prototype.removeEventlistener=function(event,callback){
	if ( this.events[event] ) {
		var listeners = this.events[event];
		for ( var i = listeners.length-1; i>=0; --i ){
			if ( listeners[i] === callback ) {
				listeners.splice( i, 1 );
				return true;
			}
		}
	}
	return false;
}
Dispatcher.prototype.dispatch=function(event){
	if ( this.events[event] ) {
		var listeners = this.events[event], len = listeners.length;
		while ( len-- ) {
			listeners[len](this);	//callback with self
		}		
	}
}
 
 
/** Below is some test-code to verify the most basic functionality **/
function SomeClass(){
	Dispatcher.call(this);
}
SomeClass.prototype = new Dispatcher();
 
SomeClass.prototype.sendSomeEvent=function(){
	this.dispatch("test");
}
 
var foo = new SomeClass();
foo.addEventlistener( "test", function(){ alert("bah"); } )
foo.sendSomeEvent();

, ,

17 Comments