contenteditable divs has a weird behaviour on focus in Opera - javascript

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/

Related

How to detect where in an input element user has clicked

Is there a way to detect where in an input element's content a user has clicked? Specifically in Firefox?
I need to know not where the caret is but where the caret would be when the user clicks into an input element.
I am trying to fix a bug in firefox where the user cannot click to place the caret into an input element which has had '.select()' called on it -- the caret fails to appear in firefox, so I want to place it manually if possible.
Thanks!
You can get the pixel position of the user's click (relative to the input field) by reading the click event's offsetX and offsetY:
// get the click position:
document.getElementById('test').onclick = function(e) {
console.log(e.offsetX, e.offsetY)
};
// for testing the 'select' issue:
document.getElementById('btn').onclick = function() {
document.getElementById('test').select();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="test">xxxxxx</textarea>
<button id="btn">Select</button>
Converting that to the desired caret location is not easy, though, because it will depend on font sizes and the text content of the input field. The best I can think of would be to do something like the technique used in textarea-caret-position, except iterating through every possible caret position in the textarea to find the one closest to where the user clicked. Which is almost certainly overkill for the task you have in mind.
(For what it's worth, the current version of firefox (v57) does not seem to have any trouble placing the caret correctly whether the input field is selected or not. I'm not certain whether this was the case in previous versions.)
Found the root of the problem, some bad css had set text-select to auto on input elements. Changing it to text-select:text allowed the fix I used for Safari to work in Firefox as well.

onpaste / paste event not firing for table on first few attempts

Google Chrome specific - this is an internal-use app that does not require cross-browser compatibility
See http://jsfiddle.net/spetnik/vpcyt4yv/
I have a table into which I am attempting to allow pasting of data. I made the individual cells selectable as such:
<td tabindex="0">
I originally tried adding the onpaste event to the TD elements themselves, but this did not work at all. So instead, I added the event to the table element and just check to make sure that the focused element is a TD and then paste the data to that element:
document.getElementById("tblData").onpaste = function(evt){
if(document.querySelector(":focus").tagName.toLowerCase() != "td"){
return;
}
document.querySelector(":focus").innerText = evt.clipboardData.getData("text/plain");
};
While this does essentially work, the event usually does not fire on the first attempt. It seems that I need to either a) click around in the table a random number of times (each time is different) or b) change focus to another window and then back again before the event fires. In the jsFiddle I have added a console.log() call to the very beginning of the event so that I can see exactly when the event fires in the debug pane.
See the above jsFiddle or just the result at https://jsfiddle.net/spetnik/vpcyt4yv/embedded/result/
Wow. The culprit seems to be the -webkit-user-select/user-select CSS! I discovered this when I noticed that pasting would be allowed only after initially clicking and dragging the mouse over a cell (which explains the random clicking - only after I clicked until my mouse moved mid-click did it work). I removed this CSS and now it works. Of course, now I need to find a workaround to prevent selecting, but at least I'm no longer stumped.
Edit: It seems that on a normal element (e.g. a DIV with the onpaste set to the element itself) onpaste does not work at all when -webkit-user-select is set to none. I submitted a bug report here
EDIT 2: I have managed to find the following workaround: If I programmatically select the contents of the cell before Ctrl-V is pressed, then it will work, even with -webkit-user-select set to none. I accomplished this by adding the following event handler (jQuery shown here) to the TD (this still does not work in a standalone DIV with -webkit-user-select set to none):
$(elem).click(function(evt){
var selection = window.getSelection();
var range = document.createRange();
range.selectNodeContents(this);
selection.removeAllRanges();
selection.addRange(range);
})

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.

IE-10 Cursor position when set focus on textbox using jquery

I have a problem in IE -10(window -7 SP-1) when set focus on a text box. my cursor position at the beginning in text-box. how can i set position End of text-box value.
DEMO
I am try j-query code for this problem --
var input = $("#txt1"); // textbox Id
var len = input.val().length;
input[0].focus();
input[0].setSelectionRange(len, len);
TRY WITH JQUERY CODE
WITH JQUERY problem is resolved but why cursor set beginning in IE-10(window -7 SP-1)?
And any any other solution for this.
This appears to be an implementation choice on the part of the browser. I can't find anywhere in the HTML spec where it says where the cursor should be positioned when a text input gains focus. If you use the mouse to give an input focus, the cursor is at the clicked position in IE10, Firefox and Chrome, but absent a click event, the browsers seem to do their own thing - Chrome, for example, appears to select the entire contents of the input.

createTextRange - strange behavior in IE8

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%');
});

Categories