getLabelByFor()

Hey, JavaScripters!

You know what kind of annoys me?

I mean, besides the post office?

If you want to make a super accessible form, with labels for every field, it’s a pain in the unowaht to access those labels with javascript. I thought, Wouldn’t it be nice if there was a way to access all the labels by their for attribute with a handy top-level object, much like you can access the fields in a form by their id and name attributes?

This is a handy little function to create a top-level object access all the labels by their for attribute. Stick these two functions somewhere in your script, and then then reference the label by document.getLabelByFor({the FOR attrib value}).

So, if you had: <label for="fieldid">Field</label>
<input name="fieldname" id="fieldid" type="text" value="field value" />
then document.getLabelByFor('fieldid') would return a reference to the label element.

Read on for the code snippets…

Put this somewhere in your script to use the function:

//make array of label ids, referenced by their FOR attribs
function loadLabels(){
  if(!document.getElementsByTagName)return;
  var l=document.getElementsByTagName('label');
  if(!l)return;
  if(!document.labels)document.labels=new Object;
  if(!document.labels)return;
  var baseId=String('labels'+
    Math.random()).replace(/\./,'');
  var theFor='';
  for(var i=l.length-1;i>-1;i--){
    if(l[i].htmlFor)theFor=l[i].htmlFor;
    else if(l[i].getAttribute(’for’))
      theFor=l[i].getAttribute(’for’);
    else if(l[i].getAttribute(’htmlFor’))
      theFor=l[i].getAttribute(’htmlFor’);
    else theFor=”;
    if(theFor){
      if(l[i].id==”)
        l[i].id=baseId+’_for_’+theFor;
      if(!document.labels[theFor])
        document.labels[theFor]=l[i].id;
    };
  };
};
document.getLabelByFor=function(strFor){
  if(!document.labels)loadLabels();
  if(!document.labels||!document.getElementById)return null;
  return document.getElementById(document.labels[strFor]);
};

Going a little further, if you create a special CSS class to hilight required values, you could have a few handy functions that set certain fields to required based on user input. Just send these functions the field element, and they’ll add/remove “required” and “disabled” classes to/from the associated label:

function requireField(lnk){
  unDisableField(lnk); //don't disable it if it's required!
  if(document.getLabelByFor(lnk.id))
    addClass(document.getLabelByFor(lnk.id),'required');
  addClass(lnk,'required');
};
function unRequireField(lnk){
  if(document.getLabelByFor(lnk.id))
    remClass(document.getLabelByFor(lnk.id),'required');
  remClass(lnk,'required');
};

function disableField(lnk){
  unRequireField(lnk); //don't require if it's disabled!
  if(document.getLabelByFor(lnk.id))
    addClass(document.getLabelByFor(lnk.id),'disabled');
  addClass(lnk,'disabled');
  lnk.disabled=true;
};
function unDisableField(lnk){
  if(document.getLabelByFor(lnk.id))
    remClass(document.getLabelByFor(lnk.id),'disabled');
  remClass(lnk,'disabled');
  lnk.disabled=false;
};

These functions are super-handy and I use them a lot. Basically just a quick little way to add or remove a class if you’re using several classes in a situation.

function addClass(lnk,cls) {
  if(!lnk)return;
  if(lnk.nodeType!=1)return;
  if(!lnk.className)lnk.className=cls;
  else if(lnk.className.indexOf(cls)!=-1)return;
  else lnk.className+=' '+cls;
};
function remClass(lnk,cls) {
  if(!lnk)return;
  if(lnk.nodeType!=1||!lnk.className)return;
  else if(!cls)lnk.className='';
  else if(lnk.className.indexOf(cls)!=-1)
    lnk.className=replace(lnk.className,cls,'');
};

This bit I picked up online, and have used a bajillion times since. Works like the old c and php str_replace(), and it’s flawless.

// by Real Gagnon
// http://www.rgagnon.com/jsdetails/js-0043.html
function replace(haystack,needle,replacement) {
  var i=haystack.indexOf(needle);
  r='';
  if(i==-1)return haystack;
  r+=haystack.substring(0,i)+replacement;
  if(i+needle.length<haystack.length)
    r+=replace(haystack.substring(i+needle.length,haystack.length),needle,replacement);
  return r;
};

Leave a Reply

Comments are moderated like crazy using a variety of plugins. There is a very high likelihood that your comment won't show up right away, especially if you have never commented here before, but it was not deleted.

Please be patient, and do not post your comment more than once. It will show up once it is approved.

You must be logged in to post a comment.