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
 }
})()