SitePoint Sponsor

User Tag List

Results 1 to 3 of 3

Hybrid View

  1. #1
    SitePoint Zealot
    Join Date
    Nov 2005
    Posts
    181
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Simple unobtrusive js works in FF but not IE

    Hi. I'm working on a simple script that takes the value of a <label> and put's it in to the associated <input>. The code isn't commented very well but it's pretty straightforward.

    So the method I use is
    1. Find all labels
    2. Use the contents of the for attribute to find the input element (via getElementById)
    3. Looks for the classname that flags this behaviour
    4. Create a new attribute for later use with type=password
    5. Hide the label with CSS through dom
    6. Set the onfocus event on the input to empty it if the string is == the label text
    7. Set the onblur event to replace an empty input with the label text


    So like I said this is pretty straightforward.

    I'm no hero javascript programmer so I guess there might be a better method but for starters I'd like to get this working under IE.

    Feel free comment on my coding too if you don't mind.

    Notice that I use innerHTML to get the <label> content - know a better idea?

    Also notice that for each onblur onfocus event I need to loop through the labels until I find the label associated with the input to get the labels content.

    I tried to avoid that by using an array that's set when I initialize the script like so:

    var labelText = new Array();

    and then set the variable when I loop by doing var labelText[i] = label[i].innerHTML; but I always got an error.


    labels.js
    Code JavaScript:
    function labelsInit() {
     
    	var label = document.getElementsByTagName('label');
     
    	for(var i=0;i<label.length;i++) {
     
     
    	// Get the input element
    	var labelText = label[i].innerHTML;
    	var input = document.getElementById(label[i].getAttribute("for"));
     
    	// Only touch the elements flagged with a class
    	if(input.className.match('labelslabels')) {	
     
    		if(input.type == 'password') { 
    			input.type = 'text';
    			input.setAttribute('labelspassword', 'true')
    		 }
     
    		input.value = labelText;
    		if(input.getAttribute('title') == null) { input.setAttribute('title', labelText); }
     
    		// Hide the label
    		label[i].style.display = 'none';
     
    		input.onfocus = function() {
    			var labels = document.getElementsByTagName('label');
    			var labelText;
     
    			for(i=0;i<labels.length;i++)
    			{
    				if(labels[i].getAttribute("for") == this.id)
    				{
    					labelText = labels[i].innerHTML;
    					break;
    				}
     
    			}
     
    			if(this.value.match(labelText))  { this.value = ''; }
     
    			if(this.getAttribute('labelspassword').match('true')) {
    				this.type = 'password';
    			}
     
    		}
     
    		input.onblur = function() {
    			var labels = document.getElementsByTagName('label');
    			var labelText;
     
    			for(i=0;i<labels.length;i++)
    			{
    				if(labels[i].getAttribute("for") == this.id)
    				{
    					labelText = labels[i].innerHTML;
    					break;
    				}
     
    			}
     
    			if(!this.value) { 
    				this.value = labelText;
    				if(this.getAttribute('labelspassword').match('true')) { this.type = 'text'; }
    			 }
    		}
    	}
    }
     
     
    }

    labels.html
    HTML Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    		"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html>
    <head>
    <title>Labels.js example</title>
    <script src="labels.js"></script>
    </head>
    <body onload="labelsInit()">
    <form>
    
    <label for="username">Username: </label>
    <input type="text" id="username" name="username" class="labelslabels"  /><br/>
    
    <label for="password">Password: </label>
    <input type="password" id="password" name="password" class="labelslabels" /><br> 
    
    </form>
    </body>
    </html>
    So do you think you can help me? I intent to give the code to the public domain when I'm done with it.

  2. #2
    SitePoint Evangelist hexburner's Avatar
    Join Date
    Jan 2007
    Location
    Belgium
    Posts
    591
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Internet Explorer uses htmlFor instead of for in JS.
    So: var input = document.getElementById(label[i].getAttribute("for"));
    Would become: var input = document.getElementById(label[i].getAttribute("for")||label[i].getAttribute("htmlFor"));

    But there's one major problem: you can't change the type of an input-tag that has type password... If you could, that wouldn't be secure, right?
    If you're planning to do so, you'll find out that'll remain buggy after all.

    I wouldn't advise it anyways...
    Maybe you can use JS to replace the input with [parent].replaceChild([textInput], [passwordInput]).
    FOR SALE: 1 set of morals, never used, will sell cheap

  3. #3
    SitePoint Enthusiast
    Join Date
    Jan 2006
    Posts
    28
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    An approach from the different end..

    I'm also only learning Javascript, but I think I can offer an alternative solution for the problem. Since you cannot create new input elements and set or change their type attribute value in any way in IE why not write some extra markup in the HTML and swap the password element for a text input and the other way around when needed? Then in the end you may want to errase the extra fileds, or process the form data on the server side accordingly..

    Here is the HTML:

    ------------------------------------------------------------------------
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html>
    <head>
    <style>
    .password
    {
    position:static;
    }
    .shadow
    {
    position:absolute;
    left:-1000px;
    top:0;
    }

    .error
    {
    background:red;
    color:#000;
    }

    </style>
    <title>Labels.js example</title>
    <script src="labels.js"></script>
    </head>
    <body>
    <form>
    <label for="username">Username: </label>
    <input type="text" id="username" name="username" class="labelslabels" /><br/>

    <label for="password">Password: </label>
    <input type="password" id="password" name="password" class="password" /><br>
    <input type="text" id="password_alias" value='' class=" password shadow"/>
    </form>
    </body>
    </html>
    --------------------------------------------------------------------------
    extra helper tags are identified by the "whatever_alias" id and class="shadow"
    puts them off screen initially.
    ---------------------------------------------------------------------------
    I use some of the utility functions I learned from: The Javascript Antology. This is far the best book on this topic I have ever read!
    --------------------------------------------------------------------------
    all javascript functions are in: labels.js

    function labelsInit()
    {
    /*called at onload to find the label tags, the input elements
    blonging to them and the helper input elements (_alias).
    Then sends them to setEventHandlers();
    */
    var labels = document.getElementsByTagName('label');
    var myId,labelText,input;
    for(var i=0;i<labels.length;i++)
    {
    labelText=getInnerText(labels[i]);
    if(labels[i].getAttribute('for') || labels[i].getAttribute('htmlFor'))
    {
    myId=labels[i].htmlFor;
    input= document.getElementById(myId);
    }
    input.myLabel=labels[i];
    input.pass = (input.type.toLowerCase()=="password")? true: false;

    /*Then save references to all important info and elements I need later for easy use
    */
    input.labelText=labelText;
    if(input.type.toLowerCase()=="password")
    {
    var id=myId + "_alias";
    var replacement= document.getElementById(id);
    input.sibl=replacement;
    replacement.sibl=input;
    replacement.value=labelText;
    shuffle(input);
    input.title= (input.title==null)? labelText: input.title + labelText;
    replacement.title=(replacement.title==null)? labelText: replacement.title + labelText;
    }
    else
    {
    input.value=labelText;
    input.title= (input.title==null)? labelText: input.title + labelText;
    }

    setEventHandlers(input);
    }


    }

    function setEventHandlers(input)
    {
    /*Sets event handlers on the input elements
    uses the above set element properties and dom scripting to achieve the goal
    */

    if(input.sibl)
    //if this is the input password element
    {
    var sibl= input.sibl;
    //sibl= the text input belonging to the password input
    sibl.onfocus= function(e)
    {
    var target= findTarget(e);
    while(target.nodeName.toLowerCase()!="input"){target= target.parentNode;}
    target.value='';
    shuffle(target);
    //change place with the input password element
    target.sibl.focus();
    }

    input.onblur= function(e)
    {
    var target= findTarget(e);
    while(target.nodeName.toLowerCase()!="input"){target=target.parentNode;}
    if(target.value=='')
    {
    shuffle(target);
    //bring back the text input field belonging to the password and set its different style values to indicate error
    target.sibl.className+=" error";
    target.sibl.value=target.labelText;

    }
    }
    }

    else
    {
    input.onfocus= function(e)
    //this is the text input (username). Empty it.
    {
    var target= findTarget(e);
    while(target.nodeName.toLowerCase()!="input"){target= target.parentNode;}
    target.value='';
    target.className=target.className.replace(/( |^)error( |$)/gi,'');
    }


    input.onblur= function(e)
    {
    var target= findTarget(e);
    while(target.nodeName.toLowerCase()!="input"){target= target.parentNode;}
    if(target.value=='')
    {
    target.className+=" error";
    target.value=target.labelText;
    }
    }


    }

    }


    -------------------------------------------------------------------------
    ------------------------------------------------------------------------
    UTILITIES
    --------------------------------------------------------------------------

    function findTarget(e)
    {
    var target = e? e.target : window.event.srcElement;
    return target;
    }

    function shuffle(elem)
    {
    var sibl= elem.sibl;
    sibl.className=sibl.className.replace(/( |^)shadow( |$)/gi,'');
    //change the sibling element's position to static
    elem.className+=(elem.className=='')? "shadow": " shadow";
    //make the element get beyond the screen
    elem.parentNode.replaceChild(sibl,elem);
    //replace the element in the dom tree with its sibling
    return true;
    }

    function getInnerText(elem)
    {
    var allText='';
    if(elem.nodeType==3 && elem.nodeValue!='')
    {
    return elem.nodeValue;
    }
    else
    {
    var c= elem.childNodes;
    if(c.length >0)
    {
    for(var i=0; i<c.length;i++)
    {
    allText+=getInnerText(c[i]);
    }
    }
    }
    return allText;
    }

    function addLoadListener(fn)
    {
    if(typeof window.addEventListener !="undefined")
    {
    window.addEventListener("load",fn,false);
    }
    else if(typeof document.addEventListener!="undefined")
    {
    document.addEventListener("load",fn,false);
    }
    else if(typeof window.attachEvent !="undefined")
    {
    window.attachEvent("onload",fn);
    }
    else
    {
    if(typeof window["onload"]=="function")
    {
    var oldListener= window["onload"];

    window["onload"]= function()
    {
    oldListener();
    fn();
    }
    }
    }
    }


    addLoadListener(labelsInit);


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •