Archive for category JavaScript
Programatically fire crossbrowser click event with JavaScript
Posted by Erik Karlsson in JavaScript, Web development on November 29, 2011
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); |
Lightweight JSONP javascript library
Posted by Erik Karlsson in JavaScript, PHP, Web development on May 20, 2010
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 }; }()); |
Array clone in javascript ?
Posted by Erik Karlsson in JavaScript, Web development on October 20, 2009
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. |
“Keeping” calling-context with setTimeout/setInterval
Posted by Erik Karlsson in JavaScript, Web development on September 12, 2009
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(); |
Just a general note, you can’t delete everything
Posted by Erik Karlsson in JavaScript, Web development on July 31, 2009
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 })(); |
Dispatcher followup : A more compact way of writing prototypes + module pattern + test
Posted by Erik Karlsson in JavaScript, Web development on July 27, 2009
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
Custom events in javascript by making your own Dispatcher class.
Posted by Erik Karlsson in JavaScript, Web development on July 24, 2009
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(); |
Count the number of javascript eventhandlers in the DOM-tree.
Posted by Erik Karlsson in JavaScript, Web development on July 23, 2009
Sometimes I’ve wanted to find out how many eventhandlers there are attached to the DOM-tree I’m working with, but I’ve never found a good tool for doing this. I decided to write a simple javascript snippet that traverses the tree and finds the fact for me and it looks like its working pretty good too.
Please don’t hesitate to comment if you find this useful or have any improvement suggestions
/** * @author Erik Karlsson, www.nonobtrusive.com **/ function countEventHandlers(){ var elements = document.getElementsByTagName("*"), len = elements.length, counter = 0, countermap = [], /* fill up with more events if needed or just use those you want to look for */ events = ['onmousedown', 'onmouseup', 'onmouseover', 'onmouseout', 'onclick', 'onmousemove', 'ondblclick', 'onerror', 'onresize', 'onscroll', 'onkeydown', 'onkeyup', 'onkeypress', 'onchange', 'onsubmit'], eventlen = events.length; for ( var i = eventlen-1; i >= 0; --i ) { countermap[events[i]] = 0; //reset the map } while ( len-- ) { //go through all DOM-nodes var element = elements[len], tmp = eventlen; while ( tmp-- ) { //go through all events defined above for each node and see if it exists. if ( element[events[tmp]] ) { counter++; countermap[events[tmp]]++; } } } var someStats = counter + " events found in total\n\n"; for ( var o in countermap ) { someStats += o + " was found " + countermap[o] + " times\n"; } alert(someStats); } |
So you think you’re writing effiecent jQuery selectors?
Posted by Erik Karlsson in JavaScript, jQuery, Web development on July 18, 2009
Think again if you’re writing selectors such as
$("div#myId") |
When selecting against the DOM ID the fastest way to get the node is to use only the id:
$("#myId") //will translate into document.getElementById("myId") internally |
otherwise jQuery will first get all DIV-nodes then manually iterate over them looking for an attribute id that’s equal to “myId”. In a case with a large DOM-tree this could be a large performance-hit making your site unusable on slower computers if you’re using selectors like this everywhere.
On the other hand when selecting against CSS-classes it’s faster to use
$("div.myClass") |
than just
$(".myClass") |
How to get the amount of days in an arbitrary month with leapyear in consideration
Posted by Erik Karlsson in JavaScript, Web development on July 18, 2009
function daysInMonth( month, year ) { var now = new Date(); month = month || now.getMonth()+1; //this month as default year = year || now.getFullYear(); //this year as default return new Date(year, month, 0).getDate(); } //consider January as month 1, February as month 2 ... December 12 daysInMonth( 2, 2003 ); //returns 28, not leap-year daysInMonth( 2, 2004 ); //returns 29, leap-year daysInMonth( 7, 2009 ); //returns 31 daysInMonth( ); //returns the amount of days in the current month |