Forum Moderators: open

Message Too Old, No Replies

Appending a <label/> to an Element not working in Internet explorer

Prototype

         

colorblind

7:22 pm on Jan 6, 2009 (gmt 0)

10+ Year Member



Hy all,

I have the following script, works perfectly in Firefox 2/3, but I’m having a problem with IE7 on WinXP. The text in the label tags remains visible next to each form field, and the labels within the form fields don’t appear at first — they show up only after tabbing through them (or adding, then removing input).

---------------------------------------------


var stereolabels = Class.create();

stereolabels.prototype = {
labels: [],

initialize: function(options) {
this.options = Object.extend({
className : 'inside'
}, options ¦¦ {});

this.labels = $$('label.'+this.options.className);
$A(this.labels).each(function(label) {
this.initLabel(label);
}.bind(this));

$A(document.forms).each(function(form) {
Event.observe(form, "submit", function() { this.uninit() }.bind(this))
}.bind(this));
},

// called on form submit
// - clear all labels so they don't accidentally get submitted to the server
// - WOULD CAUSE BUG IF FIELD CONTENTS WAS IN FACT MEANT TO EQUAL LABEL VALUE
uninit: function() {
$A(this.labels).each(function(label) {
var el = $(label.htmlFor);
if (el && el.value == el._labeltext) this.hide(el)
}.bind(this));
},

// initialize a single label.
// - only applicable to textarea and input[text] and input[password]
// - arrange for label_focused and label_blurred to be called for focus and blur
// - show the initial label
// - for other element types, show the default label
initLabel: function(label) {
try {
var input = $(label.htmlFor);
var inputTag = input.tagName.toLowerCase();
var inputType = input.type;
if (inputTag == "textarea" ¦¦ (inputType == "text" ¦¦ inputType == "password")) {
Element.setStyle(label, { position: 'absolute', visibility: 'hidden'});
Object.extend(input, {
_labeltext: label.childNodes[0].nodeValue,
_type: inputType
});
Event.observe(input, 'focus', this.focused.bind(this));
Event.observe(input, 'blur', this.blurred.bind(this));
this.blurred({target:input});
} else {
Element.setStyle(label, { position: 'static', visibility: 'visible' });
}
}
catch (e) {
Element.setStyle(label, { position: 'static', visibility: 'visible' });
}
},

focused: function(e) {
var el = Event.element(e);
if (el.value == el._labeltext) el = this.hide(el)
el.select();
},

blurred: function(e) {
var el = Event.element(e);
if (el.value == "") el = this.show(el);
},

hide: function(el) {
if (el._type == "password") el = this.setInputType(el, "password");
el.value = "";
Element.removeClassName(el, this.options.className);
return el;
},

show: function(el) {
if (el._type == "password") el = this.setInputType(el, "text");
Element.addClassName(el, this.options.className);
el.value = el._labeltext;
return el;
},

setInputType: function (el, type) {
try {
el.type = type;
return el;
}
catch (e) { //IE can't set the type parameter
var newEl = document.createElement("input");
newEl.type = type;
for (prop in el) {
try {
// crazy bug that still exists in ie 7 with width and heights, use class name if necessary instead!
if (prop != "type" && prop != "height" && prop != "width") {
newEl[prop] = el[prop];
}
}
catch(e) { }
}
Event.observe(newEl, 'focus', this.focused.bind(this));
Event.observe(newEl, 'blur', this.blurred.bind(this));
el.parentNode.replaceChild(newEl, el);
return newEl;
}
}
}

Event.observe(window, 'load', stereolabelsInit, false);

var myLabels = null;
function stereolabelsInit() {
myLabels = new stereolabels();
}


---------------------------------------------

The script uses Prototype framework. After some tests, i`ve discovered that with Prototype 1.5 works great on all browsers, but with Prototype 1.6.0.3 doesn`t work on IE. Can anyone help me with this ? :(

I forgot to tell you what this script`s for :)

Stereolabels: Form labels inside inputs with Prototype

stereolabels crawls the DOM for labels with the specified class name (default is ‘inside’) and places the label text inside the input field, and adds the class name to the input element. Upon clicking the field, the label is removed and the class name is removed from the input element. If the field is left blank when it loses focus, the label returns. This behavior is only applied to text, textarea, and password input fields.

coopster

2:52 pm on Jan 7, 2009 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



Welcome to WebmasterWorld, colorblind.

I'm wondering if your problem stems from an external stylesheet that you are including on this page?

colorblind

6:50 pm on Jan 7, 2009 (gmt 0)

10+ Year Member



Nope, i`ve erased all the stylesheet code, all the javascipt code, that i have in the <head> and still doesn`t solve the problem. I`ve only left the Prototype script and the script above (stereolabels).

Like i said, with Prototype 1.5 worked great, but if i put that, then my other elements such as accordion and dropdown menu won`t work anymore because of the old Prototype version.

I`m guessing that since the upgrade of the new Prototype version some functions have been changed, and the labels script work with the old functions. But if so, why is it working on FireFox 3 and Opera 9.6 ?

Here`s my Form :


<form name="comform" action="<?php echo get_option('siteurl'); ?>/wp-comments-post.php" method="post" id="commentform">

<label for="comment" class="inside">Type your comment here...</label>
<textarea name="comment" id="comment" rows="8" cols="10" class="jsrequired" ></textarea>

<label for="author" class="inside">Name (required)</label>
<input type="text" name="author" id="author" size="22" class="jsrequired jsvalidate_alpha"/>

<label for="email" class="inside">Email (gravatar enabled) (required)</label>
<input type="text" name="email" id="email" size="22" class="jsrequired jsvalidate_email"/>

<label for="url" class="inside">Website (optional)</label>
<input type="text" name="url" id="url" size="22" />

<input type="submit" name="submit" id="sub" value="Leave comment" />
<input type="hidden" name="comment_post_ID" id="hidden" value="<?php echo $id; ?>">

</form>

coopster

10:43 pm on Jan 7, 2009 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



But if so, why is it working on FireFox 3 and Opera 9.6 ?

They are much more compliant when it comes to standards and just flat out making things work. IE is slow to adapt and even slower to address issues.

whoisgregg

3:24 am on Jan 8, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'm having a bit of trouble understanding the code so I may be completely wrong about this. However, I believe your issue is probably with this line:

var newEl = document.createElement("input"); 

Prototype isn't going to automatically extend that new element, so you need to immediately follow that with:

var newEl = document.createElement("input");
Element.extend(newEl);

At least, something like that bit me with Prototype and IE a long time back.

P.S. Did you know you could write some of your Prototype calls just by chaining them to the element reference? Here's an example of code which has the identical effect:

Element.addClassName(el, this.options.className); 
el.addClassName(this.options.className); // same thing, less typing
 
// if you wrap the element handle with the dollar sign function
// then you guarantee the element will always be extended:
$(el).addClassName(this.options.className);

whoisgregg

3:27 am on Jan 8, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Oh you know what else I realized, if you are going from 1.5.x to 1.6.x then you need to know that the method for accessing Hash values has changed drastically.

Basically you can't directly call values anymore:

alert(this.options.somekey); // breaks

Instead you have to use a getter/setter function:

alert(this.options.get('somekey')); // breaks

Reference: [prototypejs.org...]

colorblind

4:39 pm on Jan 8, 2009 (gmt 0)

10+ Year Member



I`ve corrected some of the code like you said but still can`t get it to work on IE.
Here are some pictures :
<snip>

[edited by: eelixduppy at 3:40 am (utc) on Jan. 9, 2009]
[edit reason] no screenshots, please [/edit]