Control Cursor Location on Focus in Form Field - javascript

I have a form with 4 fields. I want the first of the four to have the autofocus and be the first the user fills out. But then, either by tab or mouse or whatever, when the user gets to second field, I want the cursor to end up at the end of the string to start. There is a pre-filled string in that field.
I'm using Django so I have a form widget controlling the attributes. I can get the string to show up and even get the cursor to the end, but this always causes autofocus as well on that second field. I haven't managed to get both.
Here is code I'm using so far:
Django
field = forms.URLField(
widget = forms.URLInput(
attrs = {
'placeholder': 'enter field',
# call to javascript function - this works
'onfocus': 'add_string("field_id", "string")',
}
)
)
JavaScript:
// add string to element
function add_string(id, string) {
var input = document.getElementById(id);
input.value = string;
}
I've played around with various JS scripts but to no avail. I then found setSelectionRange and played around with this like so:
input.setSelectionRange(7, 7)
Where 7 would be end of the particular "string" in the onfocus JavaScript function call, but I could't get this to work...
Finally, I played around with some jQuery that looked like this:
// focus after string, no highlight
$(document).ready(function() {
var $field = $("#field_id");
var old_val = $field.val();
$field.focus().val('').val(old_val);
});
But this did the same thing: brought initial focus to second field and brought cursor to the end.
Any idea how I can do this, get both autofocus on field one but get cursor to jump to end of pre-filled string of field two on it's focus? Might be a nice trick if I knew how to do it.

You're almost there, you just need to fire your code when your form field is focused, instead of on document ready. In my tests it was necessary to add a zero timeout, because otherwise the field value remains selected:
$(document).ready(function() {
var $field = $("#field_id");
$field.on('focus', function() {
setTimeout(function() {
var old_val = $field.val();
$field.val('').val(old_val);
}, 0);
});
});
JSFiddle demo

Related

Event handler keypress loading at beginning of page instead of on input

I have an HTML input box and want to use jQuery to get the value of user input as it is entered, however the DOM seems to be activated upon page load and it never takes the value of the input box as the user types it in. I'm new to this and can't figure out what I'm doing incorrectly, any ideas would be appreciated!
<input id="textFilter" type="text">
function addEventHandlerForSearch() { //Javascript Handler
$('#textFilter').val();
$('#searchText').text($('#textFilter').val());
let searchVal = $('#searchText').text();
$(document).ready(function() { // DOM
$('#textFilter').keypress(addEventHandlerForSearch());
loadSavedRunkeeperTweets().then(parseTweets);
});
Simple vanilla implementation to get the value of the text box as it is typed would be:
const input = document.getElementById('textFilter');
input.onkeyup = () => {
console.log(input.value)
}
Then you could do whatever you need to with that data. If jquery is a requirement, I apologize for not including that in my answer. Not my area of expertise lol.

Trigger function on input event if selected text is within input

I've built a page where you can filter results by typing into an input box.
Basic mechanics are:
Start typing, input event is fired, elements without matching text begin hiding
If input becomes empty (or if you click a reset button), all elements are shown again
I have noticed a problem, though, when highlighting text. Say I type "apple" into the input. Then I highlight it, and type "orange."
If an element exists on the page containing "orange," but it was already hidden because I filtered for "apple," it does not show up. I have gathered this is because the input never truly empties; rather, I simply replace "apple" with the "o" from orange before continuing with "r-a-n-g-e." This means I get a subset of "apple" results that contain "orange," as if I had typed "apple orange."
What I really want to do is clear my input on the keypress for the "o" in "orange" before hiding nonmatching elements, so I'm effectively searching the whole page for "orange."
What I've tried so far
1: Set input value to '' on select event:
$('.myinput').on('select', function(){
$(this).val('');
});
This doesn't work because it just deletes my highlighted text, which is unexpected. I only want to reset the input on the keypress following the highlight.
2: Include an if statement in my input event that checks if there is a selection within the input:
$('.myinput').on('input', function(){
var highlightedText = window.getSelection();
if($(highlightedText).parent('.myinput')) {
//reset my input
}
});
This doesn't work because it seems to fire on every keypress, regardless of if there is any actual selection. (Are user inputs always treated as selected?)
3: Add a select event listener to the input element, and set a variable to true if there's a selection. Then, in my input event, check if the variable is true on keypress.
$(function(){
var highlightedText = false;
$('.myinput').on('input', function(){
if(highlightedText = true) {
//reset my input
}
//do stuff
highlightedText = false;
});
$('.myinput').on('select', function(){
highlightedText = true;
});
});
I really thought this one would work because a basic console log in the select function only fires when I want it to – when text in the input is highlighted, but not when other text is highlighted and not when text is entered into the input. But alas, when I change that to a variable toggle, it seems to fire on every keypress again.
So the question is: How can I fire a function on input only if text in my input is highlighted?
I have found this question that suggests binding to the mouseup event, but it seems like overkill to check every single click when I'm only worried about a pretty particular situation. Also, that solution relies on window.getSelection(), which so far isn't working for me.
I've also found another question that suggests to use window.selectionEnd instead of window.getSelection() since I'm working with a text input. I tried incorporating that into option 2 above, but it also seems to fire on every keypress, rather than on highlight.
This answer is not about text selection at all.
But still solve your problem to refilter text when highlighted text is being replaced with new input.
var input = document.getElementById('ok');
var character = document.getElementById('char');
var previousCount = 0;
var currentCount = 0;
input.addEventListener('input', function(){
currentCount = this.value.length;
if (currentCount <= previousCount){
/*
This will detect if you replace the highlighted text into new text.
You can redo the filter here.
*/
console.log('Highlighted text replaced with: ' + this.value);
}
previousCount = currentCount;
char.innerHTML = this.value;
});
<input type="text" id="ok">
<div id="char"></div>
I'll agree with others that you will save yourself some trouble if you change your filtering strategy - I'd say you should filter all content from scratch at each keypress, as opposed to filtering successively the content that remains.
Anyway, to solve your immediate problem, I think you can just get the selection and see if it is empty. You can modify your second attempt:
$('.myinput').on('input', function(){
// get the string representation of the selection
var highlightedText = window.getSelection().toString();
if(highlightedText.length) {
//reset my input
}
});
EDIT
As this solution seems to have various problems, I can suggest another, along the lines of the comment from #Bee157. You can save the old search string and check if the new one has the old as a substring (and if not, reset the display).
var oldSearch = '';
$('.myinput').on('input', function(){
var newSearch = $('.myinput').val();
if (newSearch.indexOf(oldSearch) == -1) {
// reset the display
console.log('RESET');
}
oldSearch = newSearch;
// filter the results...
});
This approach has the added benefit that old results will reappear when you backspace. I tried it in your codepen, and I was able to log 'RESET' at all the appropriate moments.

"scroll" to the end of the input after js modifies input's value

I have a <input id="inp" type="text"> that user writes in, and sometimes uses suggests from a dictionary. When a suggest is selected I do:
var input = $('#inp');
input.val(input.val()+suggestedText+' ');
input.focus(); // that is because the suggest can be selected with mouse
everything works great, but when after adding a suggest that makes the resulting input.val() too long to fit in the edit field, the cursor is at the end of the string (which is good), but only the beginning of the string is visible in the edit field, so the cursor is hidden as well.
As soon as a key is pressed (a key that changes the value) the "scroll" goes to the end of the string hiding the beginning... How to trigger this behavior automatically, without having to press a key?
I have found a solution here - but it is not good as the whole input experience is changed...
Have you tried:
var input = $('#inp');
input.val(input.val()+suggestedText+' ');
input.focus(); // that is because the suggest can be selected with mouse
var height=input.contents()[0].outerHeight()
input.animate({
scrollTop:height
},'normal');
?
thank you all for answers, meanwhile I have found sth as well...
when using mouse to click the input lost focus (clik on sth else), and then regained it (thanks to input.focus()) - "scrolling" to the end, but when choosing a suggest was done with a keyboard, focus was never lost, and that is why it was not "scrolling" itself. I just simply added input.blur(), before input.focus(), now works like a charm... have a look at working example
http://46.4.128.78/input/
To make this work you need to set the focus() BEFORE you set the value. You can fix this in many ways, for example:
input.focus(); // that is because the suggest can be selected with mouse
var input = $('#inp');
input.val(input.val() + suggestedText + ' ');
Or this one:
function changeValue(element, newValue) {
element.focus();
element.val(element.val() + newValue + ' ');
}

Add a permanent prefix to a textbox

What I am trying to achieve is to force a textbox to start with a prefix ( country telephone code ) and to make this permanent, meaning that the user cannot bypass this. For example, the Phone textbox should always start with "+45" and after that the user can add the phone number. How to prevent it from deleting the code, by any means?
What I done so far, using jQuery:
//attach event on phone text boxes
$(document).delegate(".phone", "keyup", function(event){
var target = $(this);
var value = target.val().trim();
if (value.indexOf(CONSTANTS.DANISH_PHONE_CODE) == -1) {
//country code not found
//if the user starts deleting the country code
if (value.indexOf("+") == 0){
value = "";
}
//if the user types something in front of the country code, put the country code at the end
value = value.replace(CONSTANTS.DANISH_PHONE_CODE, "");
//phone doesn't start with +45
value = CONSTANTS.DANISH_PHONE_CODE + value;
target.val(value);
}
});
But the problem is that the user can delete the plus sign and the prefix is put automatically at the start so we will have +4545. Do you know an elegant way of achieving this? Thanks.
You can absolutely position the text (in a span) over the textbox and add a left-margin to it.
This way users won't be able to remove it. But you'll have to add it server side.
Add the +45 as static html before the field. Required the user to enter "the rest" of the number (not the +45).
If necessary, add the +45 server side before persisting the value. Similarly, remove the +45 when editing.
JSFiddle Example
This should actively keep them from deleting "+45" instead of trying to fix the problem after the user as changed it. Upon keypress, determine character position, if the position is too early in the string (i.e. inside the "+45" as oppose to after it) then don't allow the keypress, unless that key is the left or right arrow keys.
Acquired resources:
http://blog.vishalon.net/index.php/javascript-getting-and-setting-caret-position-in-textarea
Binding arrow keys in JS/jQuery

How to lock the first word of a textarea?

Basically I need to create a textarea that is character limited, but will have a single word at the beginning, that they can't change.
It needs to be a part of the textarea, but I don't want users to be able to remove it or edit it.
I was thinking I could create a JQuery function using blur() to prevent the user from backspacing, but I also need to prevent them from selecting that word and deleting it.
UPDATE
I wrote this JQuery which seems to work great! However I like the solution below as it requires no Javascript.
<script type="text/javascript">
var $el = $("textarea#message_create_body");
$el.data('oldVal', $el.val());
$el.bind('keydown keyup keypress', function () {
var header = "Header: ";
var $this = $(this);
$this.data('newVal', $this.val());
var newValue = $this.data("newVal");
var oldValue = $this.data("oldVal");
// Check to make sure header not removed
if (!(newValue.substr(0, header.length) === header)) {
$(this).val(oldValue);
} else {
$(this).data('oldVal', $(this).val());
}
});
</script>
If you just want the textarea to show a prefix, you can use a label, change the position, and indent the textarea content. User will not notice the difference.
You can see how it works here: http://jsfiddle.net/FLEA3/.
How about just putting this word as a label next to the textbox? It may be confusing for the users not to be able to edit part of the text in the textbox.
Wouldn't it be better if you just alert the user that whatever he inputs in the textarea will be submitted with a "prefix" and then
show the prefix as a label before the textarea
add the prefix to the inputted text before submitting

Categories