- Its extremely handy for short and snappy stuff
- Everything under the sun is available in CPAN but figuring out which is best suited for your needs is a bitch
- While developing webapps with CGI not knowing
use Carp::qw(fatalsToBrowser);is the last thing you want to do (coz I did that) - Why ? Oh why do warnings and
use strict;exist if you can write stuff faster without it :((
Sunday, January 08, 2006
PERL update
After almost 4 months of PERL this is what I have to say.
addEvent()
A lots been said and done here. Here's my take if attachEvent does not give you access to the "this" pointer don't use it, instead use the age old method supported by most browsers :)
<html>
<head>
<title>Javascript Test Page</title>
<script type="text/javascript">
/*****************************************************************************
* Helper Functions
*****************************************************************************/
var onlyUnique = true; // default
function registerListener(target, event, listener) {
if ( target[event + "Count"] ) {
target[event + "Count"] = parseInt(target[event + "Count"]) + 1;
} else {
// first handler so add default event handler
target[event + "Count"] = 1;
target.defaultHandler = defaultHandler;
target["on" + event] = function(evt) {
evt = window.event ? window.event : evt;
target.defaultHandler(event, evt);
};
}
var currCount = parseInt(target[event + "Count"]) - 1;
if ( onlyUnique ) {
for ( var i = 0; i < currCount; i++ ) {
if ( target[event + i] == listener ) {
target[event + "Count"] = currCount;
return false;
}
} // endfor i
} // endif onlyUnique
target[event + currCount] = listener;
return true;
}
function unRegisterListener(target, event, listener) {
if ( target[event + "Count"] ) {
var currCount = parseInt(target[event + "Count"]);
for ( var i = 0; i < currCount; i++ ) {
if ( target[event + i] == listener ) {
target[event + i] = null;
currCount--; // removed one
break;
}
} // endfor i
for ( var j = i; j < currCount; j++ ) {
target[event + j] = target[event + (j + 1)];
} // endfor j
if ( currCount < 1 ) {
// cleanup default event handler
target["on" + event] = null;
}
target[event + "Count"] = currCount;
}
}
function defaultHandler(eventName, evt) {
if ( this[eventName + "Count"] ) {
var currCount = parseInt(this[eventName + "Count"]);
for ( var i = 0; i < currCount; i++ ) {
this[eventName + i](evt);
} // endfor i
}
}
/*****************************************************************************
* Event Handler Functions
*****************************************************************************/
function addEvent(target, event, func) {
if ( target.addEventListener ) {
target.addEventListener(event, func, false);
} else {
registerListener(target, event, func)
}
}
function removeEvent(target, event, func) {
if ( target.removeEventListener ) {
target.removeEventListener(event, func, false);
} else {
unRegisterListener(target, event, func)
}
}
/*****************************************************************************/
function gel(idName) {
return document.getElementById ? document.getElementById(idName) : false;
}
addEvent(window, "load", one);
addEvent(window, "load", two);
addEvent(window, "load", initialize);
var oneCount = 0;
function one() {
var text = "[one][" + oneCount + "]" + this.id;
oneCount++;
var div = document.createElement("div");
div.appendChild(document.createTextNode(text));
gel("oneDiv").appendChild(div);
}
var twoCount = 0;
function two(evt) {
var text = "[two][" + twoCount + "]" + evt.type;
twoCount++;
var div = document.createElement("div");
div.appendChild(document.createTextNode(text));
gel("twoDiv").appendChild(div);
}
function initialize() {
alert("[initialize]");
alert("adding one");
add1();
alert("adding two");
add2();
alert("done");
addEvent(gel("remove1"), "click", remove1);
addEvent(gel("remove2"), "click", remove2);
addEvent(gel("add1"), "click", add1);
addEvent(gel("add2"), "click", add2);
}
function remove1() {
for ( var i = 0; i < 10; i++ ) {
remove(one);
}
alert(gel("anchor").clickCount + " handler(s) left");
}
function remove2() {
for ( var i = 0; i < 10; i++ ) {
remove(two);
}
alert(gel("anchor").clickCount + " handler(s) left");
}
function remove(which) {
removeEvent(gel("anchor"), "click", which);
}
function add1() {
for ( var i = 0; i < 10; i++ ) {
add(one);
}
alert(gel("anchor").clickCount + " handler(s) present");
}
function add2() {
for ( var i = 0; i < 10; i++ ) {
add(two);
}
alert(gel("anchor").clickCount + " handler(s) present");
}
function add(which) {
addEvent(gel("anchor"), "click", which);
}
</script>
</head>
<body>
<a id="anchor" href="#">[Test]</a>
<a id="remove1" href="#">[Remove 1]</a>
<a id="remove2" href="#">[Remove 2]</a>
<a id="add1" href="#">[Add 1]</a>
<a id="add2" href="#">[Add 2]</a>
<div id="test"></div>
<table>
<tr>
<td valign="top">
<div id="oneDiv"></div>
</td>
<td valign="top">
<div id="twoDiv"></div>
</td>
</tr>
</table>
</body>
</html>
Saturday, July 23, 2005
PERL
Have been messing around a lot with PERL recently. Got involved in a project where only PERL can be used due to hosting environment restrictions enforced by the client. PERL seems a lot like shell scripting without the hassle of strict spacing considerations. Adding $/@/% before each variable occassionaly bugs me though it has its advantages. Hoping to become a professional perl programmer soon :)
Wednesday, July 06, 2005
Dynamic Select
Sometime ago in QuirksBlog came across this post which lead to the this link which provides an elegant solution to dynamic select boxes.
This set my refactoring mind rolling :) and I figured instead of using an existing attribute why not use the name/id of the controlling select-box !! That done my lazy mind decided one was not enough and so I decided my dynamic select script must control multiple select-boxes. The HTML form for such a thing looks somewhat like this
<form name="testForm">
<select name="regionId">
<option value="_select_"> - Select - </option>
<option value="1">England</option>
<option value="2">France</option>
</select>
<select name="businessId">
<option value="_select_"> - Select - </option>
<option regionId="1" value="1">Cards</option>
<option regionId="1" value="2">Loans</option>
<option regionId="2" value="2">Loans</option>
</select>
<select name="productId">
<option value="_select_"> - Select - </option>
<option regionId="1" businessId="1" value="1">GoldCard</option>
<option regionId="1" businessId="2" value="4">HomeLoan</option>
<option regionId="2" businessId="2" value="4">HomeLoan</option>
<option regionId="1" businessId="2" value="2">PersonalLoan</option>
<option regionId="2" businessId="2" value="2">PersonalLoan</option>
</select>
</form>
The javascript for achieving this is below
function addID(tags) {
if ( tags && document.getElementsByTagName ) {
for ( i = 0; i < tags.length; i++ ) {
var elements = document.getElementsByTagName(tags[i]);
for ( j = 0; j < elements.length; j++ ) {
var elementName = elements[j].getAttribute("name");
if ( elementName ) {
elements[j].setAttribute("id", elementName);
}
} // enfor j
} // endfor i
} // endif
}
function gel(eName) {
if ( document.getElementById ) {
return document.getElementById(eName);
}
return null;
}
function addHandler(target, eventName, eventHandler) {
if ( target ) {
if ( target.addEventListener ) {
target.addEventListener(eventName, eventHandler, true);
return true;
} else if ( target.attachEvent ) {
target.attachEvent("on" + eventName, eventHandler);
return true;
}
}
return false;
}
function addChainedSelect(sourceSelect, targetSelects) {
var numTargets = targetSelects.length;
var originalTargets = new Array(numTargets);
for ( i = 0; i < targetSelects.length; i++ ) {
if ( targetSelects[i] && targetSelects[i].cloneNode ) {
originalTargets[i] = targetSelects[i].cloneNode(true);
if ( targetSelects[i].getAttribute("chainedSelect") ) {
var chainedSelects = targetSelects[i].getAttribute("chainedSelect");
chainedSelects += "," + sourceSelect.name;
targetSelects[i].setAttribute("chainedSelect", chainedSelects);
} else {
targetSelects[i].setAttribute("chainedSelect", sourceSelect.name);
}
}
}
addHandler(sourceSelect, "change", function() {
refreshSelect(sourceSelect, targetSelects, originalTargets);
});
}
function refreshSelect(sourceSelect, targetSelects, originalTargets) {
var curValue = sourceSelect.value;
var srcName = sourceSelect.getAttribute("name");
for ( i = 0; i < targetSelects.length; i++ ) {
clearSelect(targetSelects[i]);
var option = originalTargets[i].getElementsByTagName("option");
var regEx = new RegExp(curValue);
for ( j = 0; j < option.length; j++ ) {
if ( /_select_/.test(option[j].value) || regEx.test(option[j].getAttribute(srcName)) ) {
targetSelects[i].appendChild(option[j].cloneNode(true));
}
} // endfor j
if ( targetSelects[i].getAttribute("chainedSelect") ) {
var chainedSelects = targetSelects[i].getAttribute("chainedSelect").split(",");
for ( j = 0; j < chainedSelects.length; j++ ) {
var chainName = chainedSelects[j];
var chainValue = document.getElementById(chainName).value;
var regEx = new RegExp(chainValue);
var option = targetSelects[i].getElementsByTagName("option");
for ( k = 0; k < option.length; k++ ) {
if ( !/_select_/.test(option[k].value) && !regEx.test(option[k].getAttribute(chainName)) ) {
targetSelects[i].removeChild(option[k]);
}
} // endfor k
} // endfor j
} // endif additional chainedSelects
} // endfor i
}
function clearSelect(selectBox) {
if ( selectBox ) {
var option = selectBox.getElementsByTagName("option");
while ( option[0] ) {
selectBox.removeChild(option[0]);
}
}
}
And the onload calls to initate it all :)
window.onload = function() {
addID(["input", "select", "div", "a"]);
if ( document.getElementById ) {
addChainedSelect(gel("regionId"), [gel("businessId"), gel("productId")]);
addChainedSelect(gel("businessId"), [gel("productId")]);
} // endif gEBI
} // end winload
Have tested it out only in Firefox and that too not extensively so watchout for those bugs ;)
Greasemonkey
I recently discovered Greasemonkey which is a really cool idea. Imagine you have the power to pick and choose the content that a website is throwing at you. If you have used the Web Developer you will know a little of what I'm talking about. What basically "Web Developer" allows you to do is control the various aspects of the page that is currently being displayed. For example you can turn off all the images, view response headers and a lot of cool stuff. But, "Web Developer" is limited that you have to manually go use its toolbar.(Like for example every time I have to login into Yahoo Mail I'll go to the "Web Developer" toolbar "Forms->Enable Auto Completion" so that I don't have to type in my email id because Yahoo disables autocompletion on the sign-in form)
Now with a "Greasemonkey" user-script which will automatically run whenever I go to Yahoo Mail I'm saved the arduos task of typing in my emailid :). I got so excited that I wrote a few in myself :). Here they are...
// ==UserScript==
// @name Yahoo Autocomplete
// @include http://mail.yahoo.com/*
// @include http://mail.yahoo.com
// @exclude
// @author fc
// @namespace http://fc-unleashed.blogspot.com/
// @description Enable autocomplete in Yahoo's login page
// ==/UserScript==
(function() {
var login = document.login_form;
login.setAttribute("autocomplete", "on");
})()
All you've got to do is put this into a file called YahooMail.user.js. You need the .user.js for Greaskmonkey to know that its our special user-script. Then write up a simple HTML page with a hyperlink to YahooMail.user.js (like <a href="YahooMail.user.js">Yahoo Mail</a>). Now, all you have to do is open up this HTML file in Firefox and right-click on the link (if you have installed Greasemonkey) the first item is "Install User Script...", select that and you are done. Now visit Yahoo Mail so that you'll never again have to type out your yahoo id :).
Here's another that tries to disable all the targets and javascript popups :)
// ==UserScript==
// @name Disable targets and javascript popups
// @include *
// @exclude
// @author fc
// @namespace http://fc-unleashed.blogspot.com/
// @description General disable targets and javascript popups
// ==/UserScript==
(function() {
if ( document.getElementsByTagName ) {
var anchors = document.getElementsByTagName("a");
for ( i = 0; i < anchors.length; i++ ) {
var targetVal = anchors[i].getAttribute("target");
var hrefVal = anchors[i].getAttribute("href");
if ( targetVal ) {
if ( targetVal.match(/^_[bB][lL][aA][nN][kK]$/) || targetVal.match(/^_[nN][eE][wW]$/) ) {
out = anchors[i].removeAttribute("target");
}
}
if ( hrefVal ) {
var myRegex = new RegExp("^javascript:[^(]+\\(['\"]([hH][tT][tT][pP]://[^'\"]+)['\"]\\).*");
if ( hrefVal.match(myRegex) ) {
var newVal = hrefVal.replace(myRegex, "$1");
anchors[i].setAttribute("href", newVal);
}
}
} // endfor i
}
})()
Wednesday, June 09, 2004
AJAX
I've been working a lot lately with AJAX and when I'm trying to explain how great it is for developing intutive UI's to non-programmers I'm at a fix. Its not a radical idea because callback functions have been in existence for a long time. It is not a framework/template/engine. It is actually more of a new cool object that is available with the browser which can be accesed and made to do a lot of cool stuff with javascript. Javascript is a real pain to write and debug but the end result is always worth the pain.
Learn more...
Learn more...
Subscribe to:
Posts (Atom)