createTextRange - strange behavior in IE8 - javascript

I have the following problem. In text input filed which work as an auto-completer some of suggestions it returns are wither than it. The problem comes when you leave the field. In IE the text cursor is positioned on the end of the suggested string, so you can actually see only the last part of it. So I used the code bellow to fix this and it works under IE6, but in IE8 this doesn't work, the field is always selected and I can not select anything on the page.
My question is what is the right way to move the cursor in the beginning of input field, after I leave it?
$('#myAutocompleter').blur(function(){
textRange = this.createTextRange();
textRange.collapse(true);
textRange.select();
});
(The used code is written in jQuery.)

I believe what you're looking for are the .moveStart and .moveEnd methods of the text range:
$('#myAutocompleter').blur(function(){
textRange = this.createTextRange();
textRange.collapse(true);
textRange.moveEnd('character',0);
textRange.moveStart('character',0);
textRange.select();
});
(Tested functional in IE8)

I'm not sure I understand your question, but IE has it's own set of methods for handling text selection on a page, so that would be why it behaves differently.
Look here for a tutorial:
http://www.quirksmode.org/dom/range_intro.html
And here for compatability:
http://www.quirksmode.org/dom/w3c_range.html
If that's not your problem, try doing a mouseup or click event check inside blur and putting the selection code there? Maybe that'll cause the selection to move away from the input field before placing it where the selection is.

I had a similar situation where I wanted to see the top/bottom of something depending upon things like this.
I used the jQuery scrollTo plugin
).scrollTo('100%')
).scrollTo('0%')
EDIT 1:
I am using it on this field:
<textarea cols="57" rows="2" class="cssTextarea cptEntryArea"></textarea>
with this code:
$(".cptEntryArea").change(function()
{
$(this).scrollTo('0%');
});

Related

Cursor at the begining of the text

I want to set the cursor to the beginning of the textbox(<input/>) always.
I found following code below which does the job. However if there is a text in the textbox (<input/>)already, cursor is set at the end of the text first, then moved to the beginning. Which causes the jumping effect which is undesirable.
Is there a way to always set cursor to the begging without this jumping effect? Note I have function below called in onFocus onClick.
var range;
if (elem.createTextRange) {
range = elem.createTextRange();
range.move("character", 0);
range.select();
} else if (elem.selectionStart) {
elem.focus();
elem.setSelectionRange(0, 0);
}
An alternative instead of doing it all by yourself is following jQuery plugin:
http://code.google.com/p/rangyinputs
A nice Demo can be found here:
http://rangyinputs.googlecode.com/svn/trunk/demos/textinputs_jquery.html
Hope this brings some new light into your task, please understand that without a plunker / jsfiddle a perfect solution is out of my scope right now.
Update
Another way would be to use (if you are in html5 context) the attribute autofocus. But the behavior is, that it gets the focus when the DOM was rendered and all existing text is selected. Don't know if you can live with this.
<input type="text" value="some text here" autofocus />
Update2
http://plnkr.co/Wag8fb #OP: please fork & edit it, so it works like your code. Because I used all your code pasted here and its not working at all.

contenteditable divs has a weird behaviour on focus in Opera

I decided to use div with contenteditable instead of input. Here is a code, it's simple <div contenteditable="true"></div> So, and look at jsfiddle: http://jsfiddle.net/QkfKk/
Just for jsfiddle I've marked an area of first line. In Opera, I must click directly to marked area to focus the div. Also, I can focus by double click in any space over there. But, that click shouldn't be double. I hope I explain it right. In Chrome and any other browser, I can make just one click to any place in div to focus it. On marked area or on non-marked area, whatever. That's correct behaviour, I believe.
I've solved it. That solution has some defects but that's enough for me. When I click on non-marked area focus-event triggers anyway. So, I decided just set cursor position to the last possible position on trigger focus-event. Here's code:
var range = document.createRange();
var selection = getSelection();
var children = this.childNodes;
var last = children[children.length-1];
if (last.textContent.length) {
range.setStart(last,last.textContent.length);
} else {
range.setStart(this,0);
}
range.collapse(true);
selection.removeAllRanges();
selection.addRange(range);
And this binds on focus, that's all. The solution is easy indeed but that works well.
fiddle: http://jsfiddle.net/QkfKk/7/

Show beginning of HTML input value on blur with JavaScript

I have a fixed width input of type text. If the user was to enter a long value into this field I would like the beginning of the value to be shown when the input no longer has focus.
Default behaviour in FF and IE leaves the view of the field value in the same state. Chrome on the other hand seems to behave as I want, it shows the beginning of the value.
I have tried to reset the caret position in IE through the textRange object's Select() method but this seems to re-invoke the blur event resulting in recursive chain (not sure why, but that's a separate issue).
Does anyone have any suggestions? There must be an easy way to do this?
I rigged this code together, it works on IE8. The setTimeout of 1ms is because IE automatically shows the second value if a textbox's value is set twice in a row(surprising):
function resetPosition(element){
var v = element.value;
element.value="";
setTimeout(function(){element.value = v;},1);
}
Also tested on IE7, and unobtrusive on Chrome(which does it automatically).
You can call
element.setSelectionRange(0, 0) to set the position.

Unselect textbox on blur with jQuery in IE8

I'm trying to have the default behavior of a form select (or highlight) the text when you tab to the next input. I've had to add the .select() function on my password form fields for this to work in IE8. Is there an equivalent to the jquery .select() for deselecting text?
$("#MyTextBox").focus(function() {
$(this).select();
});
$("#MyTextBox").blur(function() {
// Deselect here
});
Not that I am aware, however this ought to work for you:
$(this).val($(this).val());
Here you set the value of the field to itself. the cursor should automatically be put on the end.
The posted answer by James Wiseman worked perfectly in IE8, but for me at least, didn't work in Firefox 3.6.x.
I appreciate that the original question is specific to IE8, however, to help out those searching for a single solution that works in FF and IE, I used the following code:
var temptext = $(textbox).val();
$(textbox).val('');
$(textbox).val(temptext);
(where textbox is the textbox object to work with).
It uses the same theory as James Wiseman's solution, however, it adds the specific step of setting the textbox's text to a blank string prior to setting the textbox text back to the original string. Hope this helps!

Problem getting selected text when using a sprited button and selection.createRange() in Internet Explorer

I'm working on implementing sprited buttons in Stackoverflow's beloved WMD markdown editor and I've run into an odd bug. On all versions of IE, the selected text is lost upon button clicks, so, say, highlighting a block of text and clicking the code button acts like you placed the cursor at the end of the selection and clicked the button.
e.g. highlighting this:
This
Is
Code
and clicking the code button give you:
This
Is
Code`enter code here`
What's really weird is that I left the original non-sprited button bar in and that works just fine. In fact ALL buttons and keyboard shortcuts code use the same doClick(button) function!
Old-style non-sprited buttons: OK
Keyboard shortcuts: OK
Sprited buttons in non-IE browsers: OK
Sprited buttons in IE: WTF
I've isolated the problem down to a call to selection.createRange() which finds nothing only when the sprited button is clicked. I've tried screwing around with focus()ing and making sure as little as possible happens before the doClick() but no joy. The keyboard shortcuts seem to work because the focus is never lost from the input textarea. Can anyone think of a hack that will let me somehow collect the selected text in IE?
The onclick handler looks like this:
button.onmouseout = function(){
this.style.backgroundPosition = this.XShift + " " + normalYShift;
};
button.onclick = function() {
if (this.onmouseout) {
this.onmouseout();
}
doClick(this);
}
I've tried moving the onmouseout call to after the doClick in case that was causing a loss of focus but that's not the problem.
EDIT:
The only thing that seems to be different is that, in the original button code, you are clicking on an image. In the sprited code, you are clicking on a list item <li> with a background image set. Perhaps it's trying to select the non-existent text in my list item?
/EDIT
Actual code is located in my wmd repository on git in the button-cleanup branch.
If you revert to the 0d6d1b32bb42a6bd1d4ac4e409a19fdfe8f1ffcc commit you can see both button bars. The top one is sprited and exhibits the weird behavior. The bottom one contains the remnants of the original button bar and works fine. The suspect code is in the setInputAreaSelectionStartEnd() function in the TextareaState object.
One last thing I should mention is that, for the time being, I'm trying to keep the control in pure Javascript so I'd like to avoid fixing this with an external library like jQuery if that's possible.
Thanks for your help!
I know what the answer to my own question is.
The sprited buttons are implemented using an HTML list and CSS, where all the list items have a background image. The background image is moved around using CSS to show different buttons and states (like mouseover highlights). Standard CSS button spriting stuff.
This works fine in IE with one exception: IE tries to select the empty list text when you click on the background image "button". The selection in the input textarea goes away and the current selection (which will be returned by document.selection.createRange()) is moved to the empty text in the list item.
The fix for this is simple - I created a variable to cache the selection and a flag. In IE I cache the selection and set the flag in a mousedown event handler. In the text processing, I check for the presence of the flag - if it's set I use the cached range instead of querying document.selection.createRange().
Here are some code snippets:
wmd.ieCachedRange = null;
wmd.ieRetardedClick = false;
if(global.isIE) {
button.onmousedown = function() {
wmd.ieRetardedClick = true;
wmd.ieCachedRange = document.selection.createRange();
};
}
var range;
if(wmd.ieRetardedClick && wmd.ieCachedRange) {
range = wmd.ieCachedRange;
wmd.ieRetardedClick = false;
}
else {
range = doc.selection.createRange();
}
The solution is only a few lines of code and avoids messing around with the DOM and potentially creating layout engine issues.
Thanks for your help, Cristoph. I came up with the answer while thinking and googling about your answer.
You have to blur() a button before IE can select anything else on a page.
Can you provide a minimal example (only containing relevant code) which reproduces the bug?

Categories