How to detect where in an input element user has clicked - javascript

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.

Related

Moving caret in the contents of a read-only div allowing for dynamic highlighting

I've been struggling with getting a field working properly. This field displays a lot of data, and the user wants to select and copy a large portion of it. The data is basically a big list and the user wants to select all entries below a certain point. The way that they achieve the selection is by highlighting a word or two in the first entry they want then pressing ctrl+shft+end to select everything to the bottom. This was working until a new feature on the page was added below the contents of the list. Now the hot key select also selects the contents of the rest of the page.
The current implementation is simply :
<div id='diff-contents'>[content here]</div>
<div id='trailing-content'>blah blah blah...</div>
I have tried a read-only input field:
<input id='diff-contents' value='[content here]' readonly/>
This works in Firefox to some extent however the contents contains HTML, and the input field show html literally, not rendered. In addition to that Chrome doesn't show a blinking caret and the hot keys do nothing, so the input field is sadly not viable for me in this situation.
How can I make a selectable field that maintains focus for the cursor and shows a blinking caret but is not editable using javascript, CSS, HTML, or JQuery?
Edit: jsfiddle example that should clarify a bit.
Look at these questions how to determine the current selection: Getting selected text in a browser, cross-platform
The next step is to create a new range which starts at the end tag of #diff-contents. With this information, you should be able to extend/modify the existing selection.
I suggest to either add a button to the UI or use JavaScript with a key-press handler to trigger this code.
With that, the correct amount of HTML should be selected. Users can then copy that into the clipboard with Ctrl+C.
#Aaron Digulla mentioned key listeners, and that got me thinking about simply stopping the events.
The diff-content element is still a div but it is set to editable. This gives both HTML rendering and a blinking caret.
$(this).keydown(function (event) {
if (document.activeElement.id == 'diff-content') {
if (!allowedKeys(event.keyCode)) {
//The only other key presses that should be processed are ctrl+c (keycode 67) and ctrl+a (65)
if (!event.ctrlKey || !(event.keyCode == 67 || event.keyCode == 65)) {
event.preventDefault();
}
}
}
});
The javascript adds a keydown event listener to the entire page. This is necessary since if you just add it to the element, the event has already propagated through the rest of the page and will still be processed, and this was causing funny issues for me. Next we check if it's the diff-content that is active since we want other input elements to still operate normally. Then we check if the key event is an allowed key (tab, home, end, arrows). And finally, check for ctrl+c and ctrl+a and allow those too. I tried event.stopPropogation() and event.stopImmediatePropogation(), and neither of those worked, but preventDefault did.
Lastly, I added style="outline-style:none" to the element so that the blue border would not appear when the element has focus.
The only issue that I have yet to resolve is that since it is editable, the browser still allows you to select and then right click to either cut or paste, which will allow you to alter the text.
Here is the final jsfiddle for what I am using: http://jsfiddle.net/wh3nzmj8/12/

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.

Can I move a DOMElement while preserving focus?

Suppose I have a simple HTML page with a textarea, and I want to wrap that textarea in a DIV. However, this doesn't always happen on startup / page load, so the user might have focus in that area, or even be typing.
I can move / wrap the area by creating a DIV, appending it to the textarea's parent, then putting the textarea inside of it, and it works great. However, when I do that, focus is removed from the textarea and if the user was in the middle of typing, they're going to get angry.
How can I move the textarea's DOM node without interrupting the user? Is this even possible?
Depending on the browser you may be able to determine which element has focus by using document.activeElement. Save the value before performing the move and then afterwards set the focus back using .focus() in the textarea is the same element as what you saved.
Well, refocusing (using focus()) is one thing, but you'll also want to keep the user's cursor at the same location (and possibly his current selection, if he's made one). It is possible though, using the document.selection/range API, see https://developer.mozilla.org/en/DOM/range .
This link describes a solution (slightly different problem) using that API in IE.
You only have to reset the focus after you move everything.
Use
.focus()
On your textArea after the move.
After appending the textarea to the div you simply have to call focus on the textarea, demonstrated in this fiddle
HTML
<textarea id="test">test</textarea>
JAVASCRIPT
var textarea = document.getElementById('test');
setTimeout(function(){
var div = document.createElement('div');
document.body.appendChild(div);
div.appendChild(textarea);
textarea.focus();
console.log('appended');
},2000);

Manually triggering the iPhone/iPad/iPod keyboard from JavaScript

I am developing an HTML code editor using simple DIV's and capturing events. When I use this on the iPad the keyboard never pops up since i'm not technically in an editable field.
Is there a way to programatically tell the iPad that I need a keybaord?
If your code is executed via something that was initiated via a user action then it will work.
E.g;
this works (pops keyboard):
<input type='text' id='foo'><div onclick='$("#foo").focus();'>click</div>
this doesn't work (input gets a border but no keyboard pop):
<input type='text' id='foo'>
<script>
window.onload = function() {
$("#foo").focus();
}
</script>
To make the keyboard show on iOS devices you need to focus on an editable element such as an input or a textarea. Furthermore, the element must be visible and the .focus() function must to be executed in response to a user interaction such as a mouse click.
The thing is - we DON'T want the input element to be visible..
I have fiddled with this for quiet some time and eventually got the result I was looking for.
First, create an element you want to use to show the keyboard - in this case a button, and a hidden input element: (Working jsFiddle or Test on a mobile device)
<button id="openKeyboard">Open Keyboard</button>
<input id="hiddenInput" style="visibility: hidden;">
Then use the following javascript:
document.getElementById('openKeyboard').addEventListener('click', function(){
var inputElement = document.getElementById('hiddenInput');
inputElement.style.visibility = 'visible'; // unhide the input
inputElement.focus(); // focus on it so keyboard pops
inputElement.style.visibility = 'hidden'; // hide it again
});
Notes:
I have noticed that iOS safari will automatically scroll and zoom to the area of the input so make sure you use proper viewport and position your input element in a relevant location.
You can use some CSS on your input like setting the opacity, height and width to 0. However, if your input is completely hidden this won't work again, so make sure you leave the padding or border just so there's something to be rendered (even though it won't show up due to the opacity). This also means you shouldn't use display:none to hide it, hidden elements are just not allowed to be focused.
Use the regular keyboard events (keydown, keypress, keyup) on your hidden input to access the user's interaction as you would normally do. Nothing special here.
Place a transparent textarea over the contentEditable div. The keyboard will open, as soon as the user focus the textarea.
Register an event listener on the textarea for the focus event and set the visibilityof the textarea to hidden. This prevents the blinking cursor.
Set the visibility of the textarea back to visible after the blur event occurred.
Register additional event listeners for keydown, keyup, keypressevents and process theses events the same way, as you process them in the contentEditable div.
I have found that calling prompt("Enter some value") does trigger the keyboard on my iPad 2. Not sure if this is helpful in your situation or not.
The answers to this questions suggest that it's not possible: Why doesn't #contenteditable work on the iPhone?
A colleague of mine who was working on a similar project ended up using a textarea for the iPad version of his editor, and contenteditable divs/spans for browsers that support contenteditable. Perhaps something similar would work for you.
Proxy input trick
I figured out another dirty workaround, but works well.
The trick is based on the fact, that if the keyboard is already open, changing the focus will not close the keyboard.
Add a small "proxy invisible input" in top left of the page with position fixed (the fixed position prevents the flicker, also make sure that the field has font-size bigger than 16px to prevent iOS page zoom on focus)
On clicking the button, just .focus() on this invisible field. The keyboard will open...
Show or render your other input fields
Now with the keyboard open just .focus() on the desired input. You can use small setTimeout delay, for example 500ms if needed
Here's a solution for you:
<input id="my-input" type="text" />
<script type="text/javascript">
var textbox = document.getElementById('my-input');
textbox.select();
</script>

Firefox 3.03 and contentEditable

I'm using the contentEditable attribute on a DIV element in Firefox 3.03. Setting it to true allows me to edit the text content of the DIV, as expected.
Then, when I set contentEditable to "false", the div is no longer editable, also as expected.
However the flashing caret (text input cursor) remains visible even though the text is no longer editable. The caret is now also visible when I click on most other text in the same page, even in normal text paragraphs.
Has anyone seen this before? Is there any way to force the caret hidden?
(When I either resize the browser or click within another application, and come back, the caret magically disappears.)
I've dealt with this and my workaround is clearing the selection when I disable contentEditable:
if ($.browser.mozilla) { // replace with browser detection of your choice
window.getSelection().removeAllRanges();
}
I am actually removing the "contenteditable" attribute for browsers other than IE, rather than setting it to false:
if ($.browser.msie) {
element.contentEditable = false;
}
else {
$(element).removeAttr( 'contenteditable' );
}
The browsers manage the contentEditable attribute inconsistently and my testing revealed that this worked better overall. I don't remember if this contributed to fixing the caret problem, but I'm throwing it in here just in case.
The style attribute -moz-user-input can be used in Firefox to get the functionality contenteditable=false working.
The value assigned defines if user input is accepted. The possible values are
none : The element does not respond to user input.
enabled : The element can accepts user input. This is default.
disabled : The element does not accept user input.
E.g.:
// to disallow users to enter input
<asp:TextBox ID="uxFromDate" runat="server" style="-moz-user-input: disabled;"></asp:TextBox>
// to allow users to enter input
<asp:TextBox ID="uxFromDate" runat="server" style="-moz-user-input: enabled ;"></asp:TextBox>
Refer to https://developer.mozilla.org/en/CSS/-moz-user-input for further reference.
This solve the ploblem, looks like firefox is just checking is own way to make things :P
getDoc().designMode = "off";

Categories