homepage Welcome to WebmasterWorld Guest from 54.166.148.189
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member

Home / Forums Index / Code, Content, and Presentation / JavaScript and AJAX
Forum Library, Charter, Moderator: open

JavaScript and AJAX Forum

    
Variable scope and functions
this is doing my head in
le_gber




msg:3909508
 3:11 pm on May 8, 2009 (gmt 0)

Hi all,

The goal: I have a form with different default fields values (name, surname, email). I want to empty the field onfocus and put the default value back onblur if the field is empty.

I am trying to be clever and do the whole form in one js function (I know how to do it if I create a function for each individual field).

I've got an issue on the following:

window.onload = function(){
if(document.getElementById('myform')){
ffields = document.getElementById('myform').getElementsByTagName('input');
for(f in ffields){
ffields[i].onclick = function(){ alert(i); }
}
}
}

at the moment I get 'namedItem' in my alert box. I tried

ffields[i].onclick = function(){ alert(i); }

but that doesn't work either it alerts '[object MouseEvent]'

Basically I need somebody to tell me how to pass 'i' inside the function, and I'd be forever grateful to them - I've been trying to do this for the entire afternoon :(

I promise to share the finished file :)

 

whoisgregg




msg:3909560
 4:00 pm on May 8, 2009 (gmt 0)

If I understand you're trying to get a reference to the <input> element itself? One of these should do the trick:

ffields[i].onclick = function(){ alert(this); }

ffields[i].onclick = function(evt){ alert(evt.target); }

le_gber




msg:3909581
 4:41 pm on May 8, 2009 (gmt 0)

whoisgregg thanks for your reply.

I needed i because part of my function also checks the form default value array against it.

a more complete version of the function would be:
window.onload = function(){
if(document.getElementById('myform')){
ffields = document.getElementById('myform').getElementsByTagName('input');
var formDefaultVal = new Array("name", "surname","email");
for(f in ffields){
ffields[i].onclick = function(){ if(this.value==smallFormVal[i]){ this.value=''; }}
ffields[i].onblur= function(){ if(this.value==''){ this.value=smallFormVal[i]; }}
}
}
}

if(this.value==''){ this.value=smallFormVal[f]; }

astupidname




msg:3909783
 8:59 pm on May 8, 2009 (gmt 0)

window.onload = function(){
if(document.getElementById('myform')){
ffields = document.getElementById('myform').getElementsByTagName('input');
var formDefaultVal = new Array("name", "surname","email");
for(f in ffields){
ffields[i].onclick = function(){ if(this.value==smallFormVal[i]){ this.value=''; }}
ffields[i].onblur= function(){ if(this.value==''){ this.value=smallFormVal[i]; }}
}
}
}

One problem I see, is that I don't even see the variable i's value defined anywhere's in there ( although even if you do define i you will still have roughly the same problem ). The variable i within the onclick and onblur functions being defined will be evaluated at the time those functions are invoked, not within the loop. So when the functions are actually invoked i's value will be whatever it is at the end of the loop. The way to fix it is to force i to be evaluated at the time it is installed into the onclick or onblur function by feeding i to another function which returns the function that will be the event handler (note I don't see smallFormVal defined anywhere's either, am assuming you intended to use formDefaultVal instead?):

window.onload = function(){
if(document.getElementById('myform')){
var ffields = document.getElementById('myform').getElementsByTagName('input');
var formDefaultVal = ["name", "surname","email"]; //new Array declaration not needed, just use []
for (var i = 0; i < ffields.length; i++){
ffields[i].onclick = (function(val){
return function () {
if(this.value==val){
this.value='';
}
};
})(formDefaultVal[i]); //outer anonymous function is invoked
//and formDefaultVal[i] is passed in as an argument to val,
//the outer anonymous function returns the inner anonymous function
//which becomes the event handler

ffields[i].onblur= (function(val){
return function () {
if(this.value==''){
this.value=val;
}
};
})(formDefaultVal[i]);
}
}
};

The above is the best way to fix the problem, it is entirely similar to the below (although this is not really desirable, usually), just for demo to show what is happening when the onclick and onblur's are set above:


function returnOnClickFunction(val) {
return function () {
if (this.value == val) {
this.value = '';
}
};
}

function returnOnBlurFunction(val) {
return function () {
if (this.value == '') {
this.value = val;
}
};
}

window.onload = function(){
if(document.getElementById('myform')){
var ffields = document.getElementById('myform').getElementsByTagName('input');
var formDefaultVal = ["name", "surname","email"];
for (var i = 0; i < ffields.length; i++){
ffields[i].onclick = returnOnClickFunction(formDefaultVal[i]);
ffields[i].onblur = returnOnBlurFunction(formDefaultVal[i]);
}
}
};


daveVk




msg:3909895
 1:46 am on May 9, 2009 (gmt 0)

An alternative is to index the array smallFormVal by the the name is each input element so smallFormVal[i] becomes smallFormVal[this.name], removing need for "i", initialization
of smallFormVal becomes

smallFormVal['email'] = "..."
instead of
smallFormVal[2] = "..."

le_gber




msg:3909979
 7:39 am on May 9, 2009 (gmt 0)

astupidname, my mistake

for(f in ffields){
should have been
for(i in ffields){

You were also correct in smallFormVal[i] = formDefaultVal[i]

I'll give your first example a try although I don't get everything :)

le_gber




msg:3909982
 7:55 am on May 9, 2009 (gmt 0)

whoa, ok this works EXACTLY as intended, that is some heavy piece of js you gave me there - THANK YOU astupidname.

As I said I don't get everything you did, and I don't get the ; right after the } either, but I'll try to break it down - and also will buy the DOM scripting book

astupidname




msg:3910010
 9:13 am on May 9, 2009 (gmt 0)

You are going to like this even better!

An alternative

I had the thought also that another way around it is to give the input object it's own special property that is the value of formDefaultVal[i] (or [f], whatever), such as: ffields[i].ownSpecialProperty = formDefaultVal[i]; and then you can have the onclick or onblur function compare to the input element's ownSpecialProperty.

I then realized also, that form input's of the following types: text, radio, checkbox, password and file type input's have already got a DOM property named: defaultValue which you can use (instead of defining your ownSpecialProperty for the input). And you don't even have to set it, it is whatever the input's value was when the page loaded. An example of this (note we don't even need formDefaultVal array):

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Some Title</title>
<script type="text/javascript">

window.onload = function(){
if(document.getElementById('myform')){
var ffields = document.getElementById('myform').getElementsByTagName('input');
for (var i = 0; i < ffields.length; i++){
//left this if statement out before also, should really check that the
//current input is of the correct type, and check that it has a defaultValue
if (ffields[i].type == 'text' && ffields[i].defaultValue) {
ffields[i].onclick = function () {
if(this.value == this.defaultValue){
this.value='';
}
};
ffields[i].onblur= function () {
if(this.value==''){
this.value = this.defaultValue;
}
};
//I kinda like this too,
//don't even have to click the input, can just start typing
ffields[i].onmouseover = function () {
this.select();
};
}
}
}
};

</script>
</head>
<body>
<div>
<form action="submission.php" method="post" name="myform" id="myform">
<input type="text" name="nameField" value="name"><br>
<input type="text" name="surnameField" value="surname"><br>
<input type="text" name="emailField" value="email"><br>
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>


astupidname




msg:3910011
 9:17 am on May 9, 2009 (gmt 0)

and I don't get the ; right after the } either,

The reason for that is, it is proper syntax when ending an assignment statement (defining a value).
Such as:
var a = 3;
or:
var f = function () { return a/7; }; //<---- a value was assigned to f, just happens to be a function

le_gber




msg:3910021
 10:08 am on May 9, 2009 (gmt 0)

I use onfocus instead of onclick here --> ffields[i].onclick = function () {

The reason for that is, it is proper syntax when ending an assignment statement (defining a value).
Such as:
var a = 3;
or:
var f = function () { return a/7; }; //<---- a value was assigned to f, just happens to be a function

makes sense, cheers

le_gber




msg:3910035
 10:33 am on May 9, 2009 (gmt 0)

defaultValue IS what I was looking for haaaaaaaargh - THANK YOU

this is my final code :), thanks once again astupidname and you were quite right, I do love this solution (it seems to be faster to remove/reinstate the value as well)
if(document.getElementById('smform')){
var ffields = document.getElementById('smform').getElementsByTagName('input');
for (f in ffields){
ffields[f].onfocus = function () { if(this.value == this.defaultValue){ this.value=''; }};
ffields[f].onblur = function () { if(this.value.replace(/\s+/g,"") == ''){ this.value=this.defaultValue; }};
}
}

no need to check the input == "text" in my particular situation. Have added a triming space function to the onblur as well :)

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / JavaScript and AJAX
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved