jQuery enables it like so:
$( "input" ).triggerHandler( "focus" );
How can I achieve the same without jQuery?
https://api.jquery.com/triggerHandler/
You use dispatchEvent on the element for which you want focus to be triggered. See the
docs and an example here.
const event = new FocusEvent('focus', {
view: window,
bubbles: true,
cancelable: true
});
const myInput = document.getElementById('myInput');
myInput.dispatchEvent(event);
#myInput:focus {
background: red;
}
<input id="myInput" type="text" onfocus="console.log('Input focused!');"/>
As you can see in the above code, the console.log statement is run based on the bound event to the input tag, but the element is not actually focused (because otherwise the input box would be red, which you can try by clicking on it).
Use the getEventListeners(node) function
In your case:
console.log(getEventListeners(document.getElementsByTagName('input')[0]));
You will get all the listeners, then you can filter those that are attached to the focus event
Related
I am trying to automate somethings on some website
It has textarea and send btn (it all automatically generated with vue.js if it is matters, and this website is not mine)
<textarea class="index_textarea_1O4S1 mb2"></textarea>
<btn disabled='disabled> <span>send </span> </btn>
I need to set some text to textarea and press this button
But this code doesn't work
document.querySelector('textarea').textContent = "hello there"
document.querySelector('button').click()
As you can see btn stays disabled
I tried to remove disabled attribute of btn, but doesn't help also
So I guess the best option is to try to send keypress event to textarea
How do I do it?
BTW I don't know why but jquery $ functions seems to work strange from console on this website, so vanilla js is preferable
Assuming I understand correctly,
When I have run into this problem in the past, it's because there is some event listener that I'm trying to trigger and the element I send the event to is either targeting the wrong event or the wrong element. You can use dev tools to try and isolate the desired event, and you can send an event by creating it manually instead of calling the .click method.
For example:
const txtArea = document.querySelector('textarea');
txtArea.textContent = "hello there";
const inputEv = new Event("input", { bubbles: true });
const keydownEv = new Event("keydown", { bubbles: true });
const keyupEv = new Event("keyup", { bubbles: true });
txtArea.dispatchEvent(inputEv);
txtArea.dispatchEvent(keydownEv);
txtArea.dispatchEvent(keyupEv);
document.querySelector('button')
.dispatchEvent(new Event("click", { bubbles: true });
creating the event this way lets you even trigger custom events, once identified, by changing the first argument passed to the new Event constructor, and triggers parent elements by setting the option bubbles to true.
To move focus on the end of inputs when user click the input box,
I use something like this,
$(function() {
$('#test-input').on('click', function(evt) {
$target = $(evt.target);
var val = $target.val();
$target.val('').val(val);
});
}())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="test" id="test-input" value="abcdefgh" />
But if I change the 'click' to 'focus', it doesn't work.
$(function() {
$('#test-input').on('focus', function(evt) {
$target = $(evt.target);
var val = $target.val();
$target.val('').val(val);
});
}())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="test" id="test-input" value="abcdefgh" />
How different onClick and onFocus actions in that case?
There's some differences:
onClick: This event is fired whenever the user clicks in an object, like a button, an image, an input... After the click, then comes the:
onFocus: This event is fired when an element is selected, it doesn't need to be clicked, it can be done programmatically, calling .focus() or using the Tab key, for example. Also, using onfocus instead of onclick, can help to avoid bubbling.
To finish, use the snippet below (I added more inputs, cycle through it with TAB (or click too), you'll see the caret going to end on all of then.
Why I added a timeout?
Chrome Browser has an odd quirk where the focus event fires before the cursor is moved into the field, so, the event must wait to the cursor to get there before moving it to the end.;
$(function() {
$('.test-input').on('focus', function(evt) {
that = this;
setTimeout(function() {
that.selectionStart = that.selectionEnd = 10000;
}, 1);
});
}())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="test" class="test-input" value="abcdefgh" />
<input type="text" name="test" class="test-input" value="a1b2c3" />
<input type="text" name="test" class="test-input" value="abcdefghijklmnop" />
Extra:
If you are programming just for mobiles, will be nice to take a look at touchEvents (https://developer.mozilla.org/pt-BR/docs/Web/Events/touchstart)
This should be working just fine the first time you click on the textbox. This is when the focus event is triggered, since you're actually 'focusing on' the item. From then on, until you click anywhere outside the element, your item will already have the focus and therefore will not execute the onfocus event.
The main difference is focus event call any time when you will focus on input field like if you use tab button and focused on input field but in case of click you need to click on input field.
I think that it has to do with the fact that the code executed at the click is executed before focusing on the input and affecting a position to the cursor.
On the other hand, when you listen to the focus event, the cursor has already a position and stays at this position.
That's pure personal theory. However, if you want to make it work, I found a great solution that works in Chrome on this question: Use JavaScript to place cursor at end of text in text input element
You need to clear the value of the input, wait for one millisecond, and reapply the value:
$(function() {
$('#test-input').on('focus', function(evt) {
$target = $(evt.target);
var val = $target.val();
$target.val('');
setTimeout(() => {
$target.val(val)
},1)
});
})
I have a textarea element on which I wan't to fire an event.
When setting up a listener and the element is disabled I get an inconsistent behavior. Chrome (64.0.3282.186), Safari (11.0.3) and Edge fires the event and everything looks good (as I would expect them to do) but in Firefox (58.0.2) the eventlistener does not fire.
Anyone got any idea on how to solve this without enabling the element?
var eventName = 'bar',
element = document.querySelector('#foo'),
event = new CustomEvent(eventName, {
cancelable: true,
bubbles: false,
detail: null
});
element.addEventListener(eventName, function() {
element.value = 'X';
});
element.dispatchEvent(event);
<textarea id="foo" disabled="disabled"></textarea>
Add an HTMLElement method that enables the element, dispatches the event and then disables it again afterwards.
HTMLElement.prototype.fireEvent = function(e) {
const isDisabled = this.hasAttribute('disabled');
this.removeAttribute('disabled');
this.dispatchEvent(e);
if (isDisabled)
this.setAttribute('disabled', true);
};
var eventName = 'bar',
element = document.querySelector('#foo'),
event = new CustomEvent(eventName, {
cancelable: true,
bubbles: false,
detail: null
});
element.addEventListener(eventName, function() {
element.value = 'X';
});
element.fireEvent(event)
<textarea id="foo" disabled="disabled"></textarea>
Granted, this modifies the native element which is frowned upon - you can avoid prototype methods and just write a plain old function, i.e fireEvent(elem, event).
I posted an bug to Mozilla on the matter as nothing is mentioned in the w3 spec that the element should not dispatch events when the element is disabled.
The only thing that is mentioned is that mouse events should not be dispatched.
https://www.w3.org/TR/2011/WD-html5-20110525/association-of-controls-and-forms.html#attr-fe-disabled
A form control that is disabled must prevent any click events that are queued on the user interaction task source from being dispatched on the element.
The bug can be found here:
https://bugzilla.mozilla.org/show_bug.cgi?id=1443148
I'm trying to use JavaScript events to check an input checkbox in JSDOM.
<input type="checkbox" id="foo" />
But I can't seem to get it to check itself by dispatching an event on it:
var evt = document.createEvent("HTMLEvents");
evt.initEvent("click", false, true);
document.querySelector('#foo').dispatchEvent(evt)
However, it does work when I use jQuery's .trigger('click')
Why doesn't this code work in jsdom? I feel there's some minor inconsistency in jsdom and likely some other browser which jQuery fixes.
There is a browser dependency on the way you can manually trigger events in JavaScript.
Here's a demo.
The Code:
document.getElementById("foo").value='500';
if (document.getElementById("foo").fireEvent) {
document.getElementById("foo").fireEvent("onclick");
} else if (document.getElementById("foo").dispatchEvent) {
var clickevent=document.createEvent("MouseEvents");
clickevent.initEvent("click", true, true);
document.getElementById("foo").dispatchEvent(clickevent);
}
Updated Fiddle
Updated Code:
if (document.getElementById("foo").fireEvent) {
document.getElementById('car-make').attachEvent('onchange', update);
document.getElementById("foo").fireEvent("onchange");
} else if (document.getElementById("foo").dispatchEvent) {
document.getElementById('foo').addEventListener('change', update, false);
var clickevent=document.createEvent("MouseEvents");
clickevent.initEvent("change", true, true);
document.getElementById("foo").dispatchEvent(clickevent);
}
function update () {
alert('changed');
}
From the specs:
The change event occurs when a control loses the input focus and its value has been modified since gaining focus. This event is valid for INPUT, SELECT, and TEXTAREA. element.
Bubbles: Yes
Cancelable: No
Context Info: None
Note how this is different from the click event, for example:
The click event occurs when the pointing device button is clicked over an element.
Thus, triggering a change event will not actually change the input value.
Loosely speaking, the Cancelable: No property says that nothing will happen by default.
New on HTML5 there's an "invalid" event, to which you can add a listener:
document.addEventListener('invalid', function(e){
var element = $(e.target);
element.addClass("invalid");
element.parent().addClass("invalid");
}, true);
Please note, this event just works when submitting the form... If I style the input input:invalid { background: red }, the style is applied when the user starts typing and his input is not valid. Is that event only fired on submit? I tried adding the listener to the inputs themselves instead of the document and it didn't work.
I add a listener in order to apply a style to the input's parent... Now, when the user corrects it, it's valid again... I know there's not a "valid" event, so, how can I accomplish it?
Ok, so here's a fiddle --> http://jsfiddle.net/Osoascam/ceArQ/7/
The invalid listener seems to be only fired on submit... I just wanted to know whether there's a way to add a handler just like there is for focus. See that if you type a
Thanks in advance,
Óscar
You should use the :invalid pseudo selector and the input or the change event, to solve your problem.
$(document).bind('change', function(e){
if( $(e.target).is(':invalid') ){
$(e.target).parent().addClass('invalid');
} else {
$(e.target).parent().removeClass('invalid');
}
});
Here is a simple fiddle http://jsfiddle.net/trixta/YndYx/.
If you want to remove the error class as soon as possible you should add the error class on change and remove it on the input event (Note: input event is much better than here suggested keyup, simply because it also is triggered on paste etc., but it only works with input elements, not textarea.)
And here is a fiddle using a mixture of input and change event:
http://jsfiddle.net/trixta/jkQEX/
And if you want to have this cross browser you can simply use webshims lib to polyfill. Here is a x-browser example:
http://jsfiddle.net/trixta/RN8PA/
Since these classes are always added when a form is submit, remove the class prior validating:
$('#myForm').submit(function(){
$('.invalid', this).removeClass('invalid'); // Remove all invalid classes
$(this).removeClass('invalid'); // If the parent = form.
// Normal validation procedure.
});
Expected result:
User initiates submit
onsubmit is triggered > All invalid class names within the form are removed.
The invalid events are triggered, and the invalid classes are added when necessary
Update
Added an extra block to your fiddle, see updated fiddle: http://jsfiddle.net/ceArQ/10/. I have implemented the checkValidity() method and the validity.valid property. Now, the classes are automatically added when the input is invalid.
document.addEventListener('keyup', function(e){
var input = e.target;
if (!$.nodeName(input, 'input')) return;
input.checkValidity();
var element = $(input).parent();
if(input.validity.valid) {
element.removeClass('invalid');
element.parent().removeClass('invalid');
} else { //Remove the lines below if you don't want to automatically add
// classes when they're invalid.
element.addClass('invalid');
element.parent().removeClass('invalid');
}
});
On key-up, the validity of an input element is checked. If it's valid, the invalid class is removed from its parent.
You could bind your validation logic to the focus and blur events, or to be even more responsive, to the keyup event.
$('input').keyup(function() {
if(isValid(this)) {
$(this).removeClass('invalid').parent().removeClass('invalid');
$(this).addClass('valid').parent().addClass('invalid');
}
else {
$(this).removeClass('valid').parent().removeClass('valid');
$(this).addClass('invalid').parent().addClass('invalid');
}
});
Have you tried using :valid to give an indicator as to whether a field is valid. and having forms that are invalid just keep their default styling.
Then calling form.checkValidity() in the submit handler? (The browser should then tell the end-user which form element is not valid).