PDA

View Full Version : Cursor wrong placement in IE



Rain Lover
04-19-2011, 04:21 PM
Hi,

Would you please try the following in IE:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript" src="http://dev.jquery.com/view/trunk/plugins/validate/jquery.validate.js"></script>
<style type="text/css">
* { font-family: Verdana; font-size: 96%; }
label { width: 10em; float: left; }
label.error { float: none; color: red; padding-left: .5em; vertical-align: top; }
p { clear: both; }
.submit { margin-left: 12em; }
em { font-weight: bold; padding-right: 1em; vertical-align: top; }
</style>
<script>
$(document).ready(function(){
$("#curl").focus(function(){
if( this.value == this.defaultValue ) {
$(this).val("http://");
}
});
$("#commentForm").validate();
});
</script>

</head>
<body>


<form class="cmxform" id="commentForm" method="get" action="">
<fieldset>
<legend>A simple comment form with submit validation and default messages</legend>
<p>
<input id="cname" name="name" size="25" class="required" value="Name" />
</p>
<p>
<input id="cemail" name="email" size="25" class="required email" value="Email" />
</p>
<p>
<input id="curl" name="url" size="25" class="url" value="URL" />
</p>
<p>
<textarea id="ccomment" name="comment" cols="22" class="required">Comment</textarea>
</p>
<p>
<input class="submit" type="submit" value="Submit"/>
</p>
</fieldset>
</form>
</body>
</html>

As you see the cursor goes back to the beginning of the field if you focus on the URL field. It works with no problem in other browsers. How can it be corrected?

Thanks for any help!

jscheuer1
04-20-2011, 03:27 PM
There is a way to create a text range or something like that in IE that could perhaps be used to place the cursor at the end of the field. However, I've seen this sort of thing before, and even with that, it can be intractable.

Here's a sort of workaround:


$("#curl").focus(function(){
if( this.value == this.defaultValue ) {
$(this).val("http://");
if($.browser.msie){
this.select();
this.blur();
}
}
});

What this does is highlight and blur the new value, pretty much forcing the user to focus on it again, which will remove the highlight, and in most cases place the cursor at the end. Most folks will get the idea.

Getting back to this text range thing. It was in a thread in PHP of all places that dealt with that, started out being a PHP RegExp question. See:

http://www.dynamicdrive.com/forums/showthread.php?p=215793#post215793

I played with it:


$("#curl").focus(function(){
if( this.value == this.defaultValue ) {
if($.browser.msie){
this.select();
var rng = document.selection.createRange();
rng.text = "http://";
this.blur();
this.focus();
} else {
$(this).val("http://");
}
}
});

But no real luck. The above was about the best. There may be other available commands for the created range though. If so, perhaps one of those would move the cursor.

Rain Lover
04-20-2011, 06:16 PM
Just found this:


$('#curl').focus(function() {
$(this).val('http://');
window.o = this;
if (o.setSelectionRange) /* DOM */
setTimeout('o.setSelectionRange(o.value.length,o.value.length)', 2);
else if (o.createTextRange) /* IE */
{
var r = o.createTextRange();
r.moveStart('character', o.value.length);
r.select();
}
});

How do you evaluate the code? Is it valid?

jscheuer1
04-21-2011, 05:12 AM
Looks OK to me, seems work. One thing I see is that it's overkill for other browsers since simply setting the value is sufficient for them. Also, it no longer detects/checks for the default value. And it looks like it unnecessarily exposes o as a global variable.

Anyways, I was just playing with it and this looks real good to me:


<script>
$(document).ready(function(){
$("#curl").focus(function(){
if( this.value == this.defaultValue ) {
if($.browser.msie){
var el = this, rng;
el.value = '';
rng = document.selection.createRange();
document.selection.empty();
rng.text = "http://";
setTimeout(function(){
el.blur();
$(el).removeClass('error').next('label').remove();
el.focus();
}, 0);
} else {
$(this).val("http://");
}
}
});
$("#commentForm").validate();
});
</script>

It interacts very well with the validation script.

Using the method for IE in your post would probably be better:


<script type="text/javascript">
jQuery(document).ready(function($){
$('#curl').focus(function() {
if(this.value === this.defaultValue){
this.value = 'http://';
if($.browser.msie && this.createTextRange){ // IE
var r = this.createTextRange();
r.moveStart('character', this.value.length);
r.select();
}
}
});
$("#commentForm").validate();
});
</script>

Notes: If you want valid - With that DOCTYPE you need the type attribute on the script tag. I'm now using a document ready syntax that can work with jQuery even if it's in noConflict mode. Using $(this).val() for setting the value is more resource intensive than the ordinary javascript this.value = method and gains no advantage here.

Rain Lover
04-21-2011, 03:06 PM
I really appreciate your time and help on this and like your code much better. But would you mind focusing on the filed using the Tab key in Firefox, Chrome or Safari? Instead of putting the cursor in the right place the whole text get selected! :confused:

jscheuer1
04-21-2011, 03:39 PM
That's normal behavior in Firefox for tabbing to a text input (not for textarea by the way). Like if you remove all scripts from the page and tab from one field to another, each text input gets highlighted. One should think twice about modifying that. It's what the user expects.

However, if you feel you must, then why not do it for all the text input fields?

The code could probably be rewritten to do that without exposing any global variable and without using the (in this case) 'expensive' $(this).val() method.

Let me know.

Rain Lover
04-21-2011, 03:47 PM
if you feel you must, then why not do it for all the text input fields?

Makes sense and it probably resolves the IE issue as well, but how can it be done?

P.S. I'm not good at scripting at all. :(

jscheuer1
04-21-2011, 04:45 PM
Well, come to think of it, you do want to select those others (including the textarea), if they contain the default value, even if navigated to via the mouse, because those values are intended to be replaced. After that (after the user has changed the value), I think we should let the browser decide. So combining that with the desired behavior for #curl:


<script type="text/javascript">
jQuery(document).ready(function($){
var o, r;
$('.cmxform input[type=text]').not('#curl').add('#ccomment').focus(function(){
if(this.value === this.defaultValue){
this.select();
}
});
$('#curl').focus(function() {
if(this.value === this.defaultValue){
this.value = 'http://';
o = this;
if (o.setSelectionRange){ // DOM
setTimeout(function(){o.setSelectionRange(o.value.length, o.value.length);}, 2);
}
else if (o.createTextRange){ // IE
r = o.createTextRange();
r.moveStart('character', o.value.length);
r.select();
}
}
});
$("#commentForm").validate();
});
</script>

Note: For this to work, you need to give the text inputs the required type attribute. Like this and similar:


<input type="text" id="cname" name="name" size="25" class="required" value="Name" />

I say required as in for it to work. It might also be required for HTML validation in some or all standards compliant DOCTYPES.

Rain Lover
04-21-2011, 05:08 PM
you're a coding genius!
My problem is to do with the URL field only and this is just a sample form. I used just part of your code and it works like a charm in all browsers -- even IE6:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript" src="http://dev.jquery.com/view/trunk/plugins/validate/jquery.validate.js"></script>
<style type="text/css">
* { font-family: Verdana; font-size: 96%; }
label { width: 10em; float: left; }
label.error { float: none; color: red; padding-left: .5em; vertical-align: top; }
p { clear: both; }
.submit { margin-left: 12em; }
em { font-weight: bold; padding-right: 1em; vertical-align: top; }
</style>
<script>
$(document).ready(function(){
$('#curl').focus(function() {
if(this.value === this.defaultValue){
this.value = 'http://';
o = this;
if (o.setSelectionRange){ // DOM
setTimeout(function(){o.setSelectionRange(o.value.length, o.value.length);}, 2);
}
else if (o.createTextRange){ // IE
r = o.createTextRange();
r.moveStart('character', o.value.length);
r.select();
}
}
});
$("#commentForm").validate();
});
</script>

</head>
<body>


<form class="cmxform" id="commentForm" method="get" action="">
<fieldset>
<legend>A simple comment form with submit validation and default messages</legend>
<p>
<input id="cname" name="name" size="25" class="required" />
</p>
<p>
<input id="cemail" name="email" size="25" class="required email" />
</p>
<p>
<input id="curl" name="url" size="25" class="url" value="URL" />
</p>
<p>
<textarea id="ccomment" name="comment" cols="22" class="required"></textarea>
</p>
<p>
<input class="submit" type="submit" value="Submit"/>
</p>
</fieldset>
</form>
</body>
</html>


here's the test (http://rain-lover.webs.com/sample.htm).
I wonder if you see any problem with the embed code or any way to improve/simplify it.

jscheuer1
04-21-2011, 07:52 PM
<script type="text/javascript">
jQuery(document).ready(function($){
var o, r;
$('#curl').focus(function() {
if(this.value === this.defaultValue){
this.value = 'http://';
o = this;
if (o.setSelectionRange){ // DOM
setTimeout(function(){o.setSelectionRange(o.value.length, o.value.length);}, 2);
}
else if (o.createTextRange){ // IE
r = o.createTextRange();
r.moveStart('character', o.value.length);
r.select();
}
}
});
$("#commentForm").validate();
});
</script>

Other than give it consistent indenting, the edited lines are, in order:


The type attribute is required for script tags in this DOCTYPE.


The document ready call should be done in a way that will allow it to function should this script ever find itself in a jQuery noConflict environment.


To avoid polluting the global scope and potential DOM conflicts, the o and r variables must be formally declared in a narrower scope.

Rain Lover
04-21-2011, 07:57 PM
You're an angel!


<html>
<body>
<script type="text/javascript">
var i=0;
for (i=0;i<3;i++)
{
document.write("Thank you!!!");
document.write("<br />");
}
</script>
</body>
</html>