I'm trying to make labels toggle on and off when their respective inputs are clicked. However my code just turns off the last label in the form. I know jQuery would be the best solution, but I'm trying to get to grips with Javascript. I would greatly appreciate any help. Many thanks! :)
<html>
<head>
<script type="text/javascript">
window.onload=foo;
function foo(){
function ToggleLabels(form){
var oForm = document.forms[form];
// this function will add events to objects.
function addEvent(object,eType,eWindowsType,func,bubble){
if(window.addEventListener){
object.addEventListener(eType,func,bubble);
}
if(window.attachEvent){
object.attachEvent(eWindowsType,func);
}
}
//toggles the display of the labels
function toggle(input,label){
alert(label.innerHTML)
if(input.value == ''){
if(label.style.display == 'none'){
label.style.display = 'inline';
}
else{
label.style.display = 'none';
}
}
else{
label.style.display = 'none';
}
}
// Loop through all text inputs in the form and add the toggle functionality
for(var i=0; i < oForm.length; i++){
if(oForm.elements[i].type == '开发者_如何学Pythontext'){
var oInput = oForm.elements[i];
var oLabel = oInput.previousSibling;
addEvent(oInput,'click','onclick',function(){toggle(oInput,oLabel)},false);
}
}
}
new ToggleLabels(0);
}
</script>
</head>
<body>
<form>
<label for="name" id="nameL">Name: </label><input id="name" type="text" name="name"/>
<label for="age">Age: </label><input type="text" name="age"/>
<label for="gender">Gender: </label><input type="text" name="gender"/>
</form>
</body>
</html>
This simple change on your code will do the trick:
// Loop through all text inputs in the form and add the toggle functionality
for(var i=0; i < oForm.length; i++){
if(oForm.elements[i].type == 'text'){
var oInput = oForm.elements[i];
addEvent(oInput,'click','onclick',function(){toggle(this,this.previousSibling)},false);
}
}
You make the typical mistake of creating functions in a loop. JavaScript has only function scope, not block scope. Thus doing
for(...) {
var value = "something";
}
is the same as
var value;
for(...) {
value = "something";
}
That means every of the anonymous functions refer to the same oInput
and oLabel
. And those will have the value of the last iteration of the loop.
You have to introduce a new scope, e.g. with an immediate function:
for(var i=0; i < oForm.length; i++){
if(oForm.elements[i].type == 'text'){
addEvent(oInput,'click','onclick',(function(oInput, oLabel) {
return function(){toggle(oInput,oLabel)},false);
}(oForm.elements[i], oInput.previousSibling)));
}
}
but more readable would be to create a dedicated function:
function getHandler(oInput, oLabel) {
return function(){toggle(oInput,oLabel)},false);
}
// later
for(var i=0; i < oForm.length; i++){
if(oForm.elements[i].type == 'text'){
addEvent(oInput,'click','onclick',getHandler(oForm.elements[i], oInput.previousSibling));
}
:) the previous 2 answers about closures explain what you did wrong.
I changed your toggle method to accept an element as it's input (instead of the 2 elements that you were attempting to pass in).
I then changed your toggle method to retrieve all of the Label elements in the parent node of the element passed into the method (using the getElementsByTagName method). I then retrieved the ID of the element that was passed in and compared it to each of the label elements retrieved. If the ID of the element matched the For property of the label, I set the label's style to "display:none"...otherwise I set the label's style to "display:inline".
OH yeah, one last thing I changed...I gave your inputs "ids" :)
<html>
<head>
<script type="text/javascript">
window.onload=foo;
function foo(){
function ToggleLabels(form){
var oForm = document.forms[form];
// this function will add events to objects.
function addEvent(object,eType,eWindowsType,func,bubble){
if(window.addEventListener){
object.addEventListener(eType,func,bubble);
}
if(window.attachEvent){
object.attachEvent(eWindowsType,func);
}
}
//toggles the display of the labels
function toggle(element){
var labels= element.parentNode.getElementsByTagName("label");
var elementName = String(element.id);
for(i=0; i<labels.length; i++)
{
var labelFor = String(labels[i].htmlFor);
if(labelFor == elementName )
{ hideLabel(labels[i])
}else{
displayLabel(labels[i]);
}
}
}
function displayLabel(label){
if(label != undefined){
label.style.display = 'inline';
}
}
function hideLabel(label){
if(label != undefined){
label.style.display = 'none';
}
}
// Loop through all text inputs in the form and add the toggle functionality
for(var i=0; i < oForm.length; i++){
if(oForm.elements[i].type == 'text'){
var oInput = oForm.elements[i];
var oLabel = oInput.previousSibling;
addEvent(oInput,'click','onclick',function(){toggle(this)},false);
}
}
}
new ToggleLabels(0);
}
</script>
</head>
<body>
<form>
<label for="name">Name: </label><input id="name" type="text" name="name"/>
<label for="age">Age: </label><input type="text" id="age" name="age"/>
<label for="gender">Gender: </label><input type="text" id="gender" name="gender"/>
</form>
</body>
</html>
-Frinny
精彩评论