Javascript Run function on all input fields on focus - javascript

I want to execute a function when any of the text field is focused.
Something like this, BUT purely in Javascript - NOT IN JQUERY
$("input").focus(function() {
alert("Hello World");
});
I am trying:
document.getElementById("text1").onfocus = alert(1);
But this only shows the alert after loading page, nothing else.
Thanks

Get elements by tag name & loop("Iterate") on them for attaching focus.
http://www.w3schools.com/jsref/met_doc_getelementsbytagname.asp
var x=document.getElementsByTagName("input");
EDIT : Put this at the end of page
<script>
var x=document.getElementsByTagName("input");
for(i=0;i<x.length;i++)
{
x[i].addEventListener('focus',function(){
alert("focus");
});
}
</script>

Yet another way with document.querySelectorAll for new browser
var inputs = document.querySelectorAll('input');
and then in loop for example use addEventListener
for(var i=0,len=inputs.length;i<len;i++){
inputs[i].addEventListener('focus',function(){
//handle event
})
}

If you like some aspects of jQuery, but do not want to include the entire library in your project, you can check out You Might Not Need jQuery. You can set the minimum version of IE that you support, in the settings at the top of the page.
function addEventListener(el, eventName, handler) {
if (el.addEventListener) {
el.addEventListener(eventName, handler);
} else {
el.attachEvent('on' + eventName, function(){
handler.call(el);
});
}
}
function addEventListeners(selector, type, handler) {
var elements = document.querySelectorAll(selector);
for (var i = 0; i < elements.length; i++) {
addEventListener(elements[i], type, handler);
}
}
addEventListeners('input', 'focus', function(e) {
if (this.value !== this.placeholder) {
this.value = this.placeholder;
} else {
this.value = '';
}
});
input {
display: block;
}
<input type="text" placeholder="One" />
<input type="text" placeholder="Two" />
<input type="text" placeholder="Three" />

I know I am probably late to this, but I just wanted to add my 2 cents, as I see a lot of Stackoverflow answers like this still using JQuery and many people have moved on from JQuery, and might want another option
You could either use the focusin event or capture the focus in the Capturing phase from the top down, in either JQuery or JS, If It works in JS, it should work in the other, as I dont use JQ
let form = document.forms.myForm;
form.addEventListener('focus', (event) => {
console.log('Focused!');
console.log(event.target);
}, true);
//Work around focusin
form.addEventListener('focusin', (event) => {
console.log('Focused In!');
console.log(event.target);
});

This one supports input elements that are loaded asynchronously too.
document.addEventListener("focusin", inputBoxListener)
function inputBoxListener(event) {
if (event.target.tagName === "INPUT") {
console.log("focused on input")
}
}
https://developer.mozilla.org/en-US/docs/Web/API/Element/focusin_event

Related

Only register events once

I wrote a small script to load pages with ajax. All links that have the ajax-pls- class, should be selected.
After I add the eventlistener I remove the class, because I need to parse the included html every time.... right?
(function() {
function addEvent(element, evnt, funct){
if (element.attachEvent)
return element.attachEvent('on'+evnt, funct);
else
return element.addEventListener(evnt, funct, false);
}
var link_click = function (e) {
e.preventDefault();
if (this.getAttribute("href") == 'test1.html') {
var content = document.getElementById('content');
content.innerHTML = "<a href='test3.html' class='ajax-pls'>Test3</a>";
register_listeners();
} else {
alert(this);
}
};
function register_listeners() {
var atags = document.querySelectorAll('a.ajax-pls');
for (i = 0; i < atags.length; i++) {
addEvent(atags[i], 'click', link_click);
atags[i].classList.remove("ajax-pls");
}
}
register_listeners();
})();
It is just test-code, but do I need to do the trick with the class or could I just call register_listeners() after every include?
Yes you need to remove classes otherwise, addEvent will add same handler several times to each link.
But you can bypass this issue by using event bubbling.
If you add handler to nearest common ancestor of every link (in worst case it would be document.body). It will catch every click event on every elements inside it. You will need to filter them by checking event.target.

Javascript onClick Globally

I have a web application with many forms that submit data to a MySQL Database.
On all pages i have include 'settings.php'; so whatever i put in there will be on every page (CSS Links, JS Code etc)
Whats the best JS Code i can put in my settings.php file to put an "onClick" event on every single button on all pages.
I want it to do this:
onClick="this.disabled=true; this.value='Please Wait…';"
So on all forms within the site, every button that is clicked will display the Please Wait... text until the form is submitted
Clearly most of the people answering this question have never heard of event delegation.
window.addEventListener("click",function(e) {
var t = e.srcElement || e.target;
if( !t.tagName) t = t.parentNode;
if( t.tagName == "INPUT" && t.type.toLowerCase() == "submit") {
t.disabled = true;
t.value = "Please wait...";
}
},false);
You really shouldn't be using onClick=... Instead, bind the actions via JS:
document.getElementById('element-id').onclick=function(){
alert('Hello World');
}
Something like this ought to do it:
(function() {
var buttons = document.getElementsByTagName('button');
for (var i=0,len=buttons.length; i<len; i++) {
buttons[i].addEventListener('click', function() {
this.disabled = true;
this.innerHTML = "Please Wait...";
});
}
})();
http://jsfiddle.net/ryanbrill/5WYN9/
// very simple with jQuery
$(document).on('click', 'button,input[type="button"],input[type="submit"]', function (e) {
var $this = $(this).prop('disabled', true);
if ($this.is('button')) {
$this.html('Please wait...');
} else {
$this.val('Please wait...');
}
});

Detect click outside element (vanilla JavaScript)

I have searched for a good solution everywhere, yet I can't find one which does not use jQuery.
Is there a cross-browser, normal way (without weird hacks or easy to break code), to detect a click outside of an element (which may or may not have children)?
Add an event listener to document and use Node.contains() to find whether the target of the event (which is the inner-most clicked element) is inside your specified element. It works even in IE5
const specifiedElement = document.getElementById('a')
// I'm using "click" but it works with any event
document.addEventListener('click', event => {
const isClickInside = specifiedElement.contains(event.target)
if (!isClickInside) {
// The click was OUTSIDE the specifiedElement, do something
}
})
var specifiedElement = document.getElementById('a');
//I'm using "click" but it works with any event
document.addEventListener('click', function(event) {
var isClickInside = specifiedElement.contains(event.target);
if (isClickInside) {
alert('You clicked inside A')
} else {
alert('You clicked outside A')
}
});
div {
margin: auto;
padding: 1em;
max-width: 6em;
background: rgba(0, 0, 0, .2);
text-align: center;
}
Is the click inside A or outside?
<div id="a">A
<div id="b">B
<div id="c">C</div>
</div>
</div>
You need to handle the click event on document level. In the event object, you have a target property, the inner-most DOM element that was clicked. With this you check itself and walk up its parents until the document element, if one of them is your watched element.
See the example on jsFiddle
document.addEventListener("click", function (e) {
var level = 0;
for (var element = e.target; element; element = element.parentNode) {
if (element.id === 'x') {
document.getElementById("out").innerHTML = (level ? "inner " : "") + "x clicked";
return;
}
level++;
}
document.getElementById("out").innerHTML = "not x clicked";
});
As always, this isn't cross-bad-browser compatible because of addEventListener/attachEvent, but it works like this.
A child is clicked, when not event.target, but one of it's parents is the watched element (i'm simply counting level for this). You may also have a boolean var, if the element is found or not, to not return the handler from inside the for clause. My example is limiting to that the handler only finishes, when nothing matches.
Adding cross-browser compatability, I'm usually doing it like this:
var addEvent = function (element, eventName, fn, useCapture) {
if (element.addEventListener) {
element.addEventListener(eventName, fn, useCapture);
}
else if (element.attachEvent) {
element.attachEvent(eventName, function (e) {
fn.apply(element, arguments);
}, useCapture);
}
};
This is cross-browser compatible code for attaching an event listener/handler, inclusive rewriting this in IE, to be the element, as like jQuery does for its event handlers. There are plenty of arguments to have some bits of jQuery in mind ;)
How about this:
jsBin demo
document.onclick = function(event){
var hasParent = false;
for(var node = event.target; node != document.body; node = node.parentNode)
{
if(node.id == 'div1'){
hasParent = true;
break;
}
}
if(hasParent)
alert('inside');
else
alert('outside');
}
you can use composePath() to check if the click happened outside or inside of a target div that may or may not have children:
const targetDiv = document.querySelector('#targetDiv')
document.addEventListener('click', (e) => {
const isClickedInsideDiv = e.composedPath().includes(targetDiv)
if (isClickedInsideDiv) {
console.log('clicked inside of div')
} else {
console.log('clicked outside of div')
}
})
I did a lot of research on it to find a better method. JavaScript method .contains go recursively in DOM to check whether it contains target or not. I used it in one of react project but when react DOM changes on set state, .contains method does not work. SO i came up with this solution
//Basic Html snippet
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="mydiv">
<h2>
click outside this div to test
</h2>
Check click outside
</div>
</body>
</html>
//Implementation in Vanilla javaScript
const node = document.getElementById('mydiv')
//minor css to make div more obvious
node.style.width = '300px'
node.style.height = '100px'
node.style.background = 'red'
let isCursorInside = false
//Attach mouseover event listener and update in variable
node.addEventListener('mouseover', function() {
isCursorInside = true
console.log('cursor inside')
})
/Attach mouseout event listener and update in variable
node.addEventListener('mouseout', function() {
isCursorInside = false
console.log('cursor outside')
})
document.addEventListener('click', function() {
//And if isCursorInside = false it means cursor is outside
if(!isCursorInside) {
alert('Outside div click detected')
}
})
WORKING DEMO jsfiddle
using the js Element.closest() method:
let popup = document.querySelector('.parent-element')
popup.addEventListener('click', (e) => {
if (!e.target.closest('.child-element')) {
// clicked outside
}
});
To hide element by click outside of it I usually apply such simple code:
var bodyTag = document.getElementsByTagName('body');
var element = document.getElementById('element');
function clickedOrNot(e) {
if (e.target !== element) {
// action in the case of click outside
bodyTag[0].removeEventListener('click', clickedOrNot, true);
}
}
bodyTag[0].addEventListener('click', clickedOrNot, true);
Another very simple and quick approach to this problem is to map the array of path into the event object returned by the listener. If the id or class name of your element matches one of those in the array, the click is inside your element.
(This solution can be useful if you don't want to get the element directly (e.g: document.getElementById('...'), for example in a reactjs/nextjs app, in ssr..).
Here is an example:
document.addEventListener('click', e => {
let clickedOutside = true;
e.path.forEach(item => {
if (!clickedOutside)
return;
if (item.className === 'your-element-class')
clickedOutside = false;
});
if (clickedOutside)
// Make an action if it's clicked outside..
});
I hope this answer will help you !
(Let me know if my solution is not a good solution or if you see something to improve.)

Onsubmit validate change background requried fields?

Anyone know of a good tutorial/method of using Javascript to, onSubmit, change the background color of all empty fields with class="required" ?
Something like this should do the trick, but it's difficult to know exactly what you're looking for without you posting more details:
document.getElementById("myForm").onsubmit = function() {
var fields = this.getElementsByClassName("required"),
sendForm = true;
for(var i = 0; i < fields.length; i++) {
if(!fields[i].value) {
fields[i].style.backgroundColor = "#ff0000";
sendForm = false;
}
else {
//Else block added due to comments about returning colour to normal
fields[i].style.backgroundColor = "#fff";
}
}
if(!sendForm) {
return false;
}
}
This attaches a listener to the onsubmit event of the form with id "myForm". It then gets all elements within that form with a class of "required" (note that getElementsByClassName is not supported in older versions of IE, so you may want to look into alternatives there), loops through that collection, checks the value of each, and changes the background colour if it finds any empty ones. If there are any empty ones, it prevents the form from being submitted.
Here's a working example.
Perhaps something like this:
$(document).ready(function () {
$('form').submit(function () {
$('input, textarea, select', this).foreach(function () {
if ($(this).val() == '') {
$(this).addClass('required');
}
});
});
});
I quickly became a fan of jQuery. The documentation is amazing.
http://docs.jquery.com/Downloading_jQuery
if You decide to give the library a try, then here is your code:
//on DOM ready event
$(document).ready(
// register a 'submit' event for your form
$("#formId").submit(function(event){
// clear the required fields if this is the second time the user is submitting the form
$('.required', this).removeClass("required");
// snag every field of type 'input'.
// filter them, keeping inputs with a '' value
// add the class 'required' to the blank inputs.
$('input', this).filter( function( index ){
var keepMe = false;
if(this.val() == ''){
keepMe = true;
}
return keepMe;
}).addClass("required");
if($(".required", this).length > 0){
event.preventDefault();
}
});
);

Catch only keypresses that change input?

I want to do something when a keypress changes the input of a textbox. I figure the keypress event would be best for this, but how do I know if it caused a change? I need to filter out things like pressing the arrow keys, or modifiers... I don't think hardcoding all the values is the best approach.
So how should I do it?
In most browsers, you can use the HTML5 input event for text-type <input> elements:
$("#testbox").on("input", function() {
alert("Value changed!");
});
This doesn't work in IE < 9, but there is a workaround: the propertychange event.
$("#testbox").on("propertychange", function(e) {
if (e.originalEvent.propertyName == "value") {
alert("Value changed!");
}
});
IE 9 supports both, so in that browser it's better to prefer the standards-based input event. This conveniently fires first, so we can remove the handler for propertychange the first time input fires.
Putting it all together (jsFiddle):
var propertyChangeUnbound = false;
$("#testbox").on("propertychange", function(e) {
if (e.originalEvent.propertyName == "value") {
alert("Value changed!");
}
});
$("#testbox").on("input", function() {
if (!propertyChangeUnbound) {
$("#testbox").unbind("propertychange");
propertyChangeUnbound = true;
}
alert("Value changed!");
});
.change() is what you're after
$("#testbox").keyup(function() {
$(this).blur();
$(this).focus();
$(this).val($(this).val()); // fix for IE putting cursor at beginning of input on focus
}).change(function() {
alert("change fired");
});
This is how I would do it: http://jsfiddle.net/JesseAldridge/Pggpt/1/
$('#input1').keyup(function(){
if($('#input1').val() != $('#input1').attr('prev_val'))
$('#input2').val('change')
else
$('#input2').val('no change')
$('#input1').attr('prev_val', $('#input1').val())
})
I came up with this for autosaving a textarea. It uses a combination of the .keyUp() jQuery method to see if the content has changed. And then I update every 5 seconds because I don't want the form getting submitted every time it's changed!!!!
var savePost = false;
jQuery(document).ready(function() {
setInterval('autoSave()', 5000)
$('input, textarea').keyup(function(){
if (!savePost) {
savePost = true;
}
})
})
function autoSave() {
if (savePost) {
savePost = false;
$('#post_submit, #task_submit').click();
}
}
I know it will fire even if the content hasn't changed but it was easier that hardcoding which keys I didn't want it to work for.

Categories