Javascript Dynamic Event Handling, Not Jquery - javascript

here is my code
<html>
<head>
<script type="text/javascript">
window.onload = function(){
sel = document.getElementsByTagName('select');
for(i=0;i<sel.length;i++)sel[i].onclick = function(){alert('');}
}
</script>
</head>
<body>
<div id="ss"></div>
<select></select>
<input type="button" onclick="document.getElementById('ss').appendChild(document.createElement('select'))"/>
</body>
</html>
"onclick" event working for static tag "Select" but not working for Dynamically created "Select". In other word i want to know what is alternate to .live of JQuery in Javascript.

Bind the event to a parent element, that already exists in the DOM:
document.body.addEventListener('click', function (e) {
if (e.target.tagName.toLowerCase() == 'select') {
alert('You clicked a select!');
}
});
JS Fiddle demo.
It would be slightly more sensible to bind the click to an element 'closer' to the form, and if you use getElementById() rather than getElementByTagName() it's more simple, since you don't have to worry about the index of the number you're binding to.

jQuery's live function works by using "Event Delegation". The basic idea is that you bind a listener on a parent element, which is guaranteed to exist when the page loads. Any element below that (with the exception of some) will fire off an event which can be caught by the parent listener. From there you would need to retrieve the target/sourceElement of the event and determine whether or not it's one you care about.
Something like this will work for listening to clicks. Just make sure that any new elements you are adding are located within the proper parent container and have an attribute which distinguishes them from the rest of the clickable elements.
<html>
<head>
<script type="text/javascript">
window.onload = function(){
// get the relevant container
var eventContainer = document.getElementById("EventContainer");
// bind a click listener to that container
eventContainer.onclick = function(e){
// get the event
e = e || window.event;
// get the target
var target = e.target || e.srcElement;
// should we listen to the click on this element?
if(target.getAttribute("rel") == 'click-listen')
{
alert("You clicked something you are listening to!");
}// if
};
};
</script>
</head>
<body>
<div id="EventContainer">
<input type="button" rel="click-listen" name="myButton" value="Listening to this button." />
<input type="button" name="anotherButton" value="Not listening." />
<p>I'm also listening to this a element: listening to this</p>
</div>
</body>
</html>

there's no need to bind the onclick handler to every select every time you add one.
I am not going to retype your whole page, but you'll see what's going on by reading following snippets:
function handler() {
alert('You clicked a select!');
}
window.onload = function(){
sel = document.getElementsByTagName('select');
for(int i= 0; i < sel.length; i++) {
sel[i].onclick = handler;
}
}
function addSelect() {
var slt = document.createElement("select");
document.getElementById('ss').appendChild(slt);
slt.onclick = handler;
}
<input type="button" onclick="addSelect();"/>

You're only setting the onclick when the window loads. All you need to do is put the code currently in the window.onload into a named function, then call it every time you add a new select.
here's the dumb way to do it:
<html>
<head>
<script type="text/javascript">
function update () {
sel = document.getElementsByTagName('select');
for(i=0;i<sel.length;i++)sel[i].onclick = function(){alert('');}
}
window.onload = update;
</script>
</head>
<body>
<div id="ss"></div>
<select></select>
<input type="button" onclick="document.getElementById('ss').appendChild(document.createElement('select'));update();"/>
</body>
</html>

You can use a cross-browser solution as shown below to add event handler dynamically
sel = document.getElementsByTagName('select');
for( i=0; i<sel.length; i++){
if (sel[i].addEventListener){
sel[i].addEventListener("click", clickHandler, false);
} else if (sel[i].attachEvent){
sel[i].attachEvent("onclick", clickHandler);
}else{
sel[i].onclick = clickHandler;
}
}
function clickHandler(event){
}

Related

Javascript Execute onclick event stored in variable

I've created the function below to identify an onclick event which is dynamically generated with each page load. I'm able to get the onclick event into a variable (developer console output shown below). I want to execute that onclick event but can't find a good way of doing that. Any assistance is appreciated.
"ƒ onclick(event) {
mstrmojo.dom.captureDomEvent('*lK1129*kWA92AF1C396244F28902B3171F9642E57*x1*t1530820506700','click', self, event)
}"
function applyAll() {
//Get the self Link to click it
var linkBys = document.getElementsByClassName("mstrmojo-DocTextfield-valueNode");
// loop through each result
for(y = 0;y < linkBys.length;y++){
// retrieve the current result from the variable
var linkBy = linkBys[y];
// check the condition that tells me this is the one I'm looking for
if(linkBy.innerText.indexOf("link") !== -1){
// Find the right class
var idy = document.getElementsByClassName("mstrmojo-DocTextfield-valueNode")[y].onclick;
console.log(idy);
}
}
}
If the property 'onclick' is defined as a function, you can just run it as a function.
var idy = document.getElementsByClassName("")[y].onclick();
You could also handle it another way:
var idy = document.getElementsByClassName("")[y].onclick;
idy();
onclick is not an event, it's a function which gets executed when element is clicked. If you want to simulate click you can do element.click()
If you used:
element.addEventListener('click',()=>...);
instead of:
element.onclick=()=>...
then all you have to do is:
document.getElementsByClassName("mstrmojo-DocTextfield-valueNode")[y].dispatchEvent(new Event('click'));
You can call the function returned , adding parens:
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
function foo() {
var idy = document.getElementsByClassName("mstrmojo-DocTextfield-valueNode")[0].onclick;
console.log(idy);
idy();//like so
}
function alertMe() {
alert('Hello');
}
</script>
</head>
<body>
<button id="btn" class="mstrmojo-DocTextfield-valueNode" onclick="alertMe();">No click</button>
<button id="btn2" onclick="foo()">Click me</button>
</body>
</html>

How can I remove every listener from a page?

I know how to remove a listener from an element, but how can I remove every event listener from every element on the page?
A jQuery and pure JS solution would be nice.
I would suggest to look into the .off function of jQuery.
Also, based on this stackoverflow question, I would try to remove all every listeners with the following code
$("body").find("*").off();
Hope this could help you.
You can try this too.
http://jsfiddle.net/LkfLezgd/9/
$("#cloneButton").click(function() {
$('body').replaceWith($('body').clone().html());
});
You can loop through the form elements as below to remove the event listeners at your preferred way.
The fastest way to do this is to just clone the node which will remove all event listeners but this won't remove if 'onclick' attribute is used.
document.getElementById('button').addEventListener('click', onClick, false);
function onClick() {
console.log('Form clicked');
var form = document.getElementById('myForm');
for(var i = 0; i < form.elements.length; i++){
var elm = form.elements[i];
removeEvents(elm);
}
}
function removeEvents(elm) {
// The fastest way to do this is to just clone the node, which will remove all event listeners:
var new_element = elm.cloneNode(true);
elm.parentNode.replaceChild(new_element, elm);
}
<form id="myForm">
<input id="button" type="button" value="Click" />
</form>
Just Clone the HTML dom, that will remove the events by default.
Here is an example.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script>
$(document).ready(function () {
$("#EventButton").click(function () {
alert("Click event worked");
var old_element = document.documentElement;
var new_element = old_element.cloneNode(true);
old_element.parentNode.replaceChild(new_element, old_element);
});
});
</script>
</head>
<body>
<button id="EventButton">Remove Events</button>
</body>
</html>

Propagation of custom events

I expect my CustomEvent to be propagated from document to all the DOM elements.
For some reason, it does not happen. What am I doing wrong?
<html>
<script>
function onLoad() {
var myDiv = document.getElementById("myDiv");
myDiv.addEventListener("myEvent",function(){alert("Yes!");});
document.dispatchEvent(new CustomEvent("myEvent",{detail:null}));
}
</script>
<body onload="onLoad()">
<div id="myDiv"></div>
</body>
</html>
By default Custom Events are not bubbled.
Reason being, Custom Event definition says:
let event = new CustomEvent(type,[,options]).
Options have a flag : bubbles, which is false by default, we have to enable it.
Following will fix your code
<html>
<script>
function onLoad() {
var myDiv = document.getElementById("myDiv");
myDiv.addEventListener("myEvent",function(){alert("Yes!");});
document.dispatchEvent(new CustomEvent("myEvent",{detail:null,bubbles:true}));
}
</script>
<body onload="onLoad()">
<div id="myDiv"></div>
</body>
</html>
You have to dispatchEvent the event on the element you want the event 'triggered' on. It will then propagate down and back up the DOM
<html>
<script>
function onLoad() {
var myDiv = document.getElementById("myDiv");
myDiv.addEventListener("myEvent",function(){alert("Yes!");});
myDiv.dispatchEvent(new CustomEvent("myEvent",{detail:null}));
}
</script>
<body onload="onLoad()">
<div id="myDiv"></div>
</body>
</html>
fiddle: https://jsfiddle.net/yrf9cvr3/
How propagation works: The event starts at the document and works it's way down to the element it was dispatched on (You can capture the event going this way using onCapture flag). Then goes back up to the document. Because you are dispatching on the document the event doesn't really go anywhere, only document see the event.
This is currently not possible as stated in the MDN doc https://developer.mozilla.org/en-US/docs/Web/Events/Creating_and_triggering_events#event_bubbling, event can only bubble from child to ancestors, i.e. upward for now.
The best way you can achieve this is use document.querySelector to target the element(s) you want to dispatch the event to, then dispatch as needed.
document.querySelector("#myDiv").dispatchEvent(customEv);
Try this one. Use document.querySelector and specify the events you want to track. Click the button or type some text in the text box
<html>
<script>
function onLoad() {
// var myDiv = document.getElementById("myDiv");
// myDiv.addEventListener("myEvent",function(){alert("Yes!");});
// document.dispatchEvent(new CustomEvent("myEvent",{detail:null}));
var myDiv = document.querySelector("#myDiv");
myDiv.addEventListener("click", myEventHandler, false);
myDiv.addEventListener("change", myEventHandler, false);
}
function myEventHandler(e)
{
alert('Element was '+e.target.id+'\nEvent was '+e.type);
}
</script>
<body onload="onLoad()">
<div id="myDiv">
<input type="button" id= "Button 1" value="Button 1"><br>
<input type="text" id="Text 2">
</div>
</body>
</html>
I am posting some solution, not really an answer.
This will propagate a custom event to all the elements in the DOM.
<html>
<script>
document.dispatchCustomEvent = function(event) {
function visit(elem,event) {
elem.dispatchEvent(event);
var child = elem.firstChild;
while(child) {
if(child.nodeType==1) visit(child,event);
child = child.nextSibling;
}
}
visit(document.documentElement,event);
}
function onLoad() {
var myDiv = document.getElementById("myDiv");
myDiv.addEventListener("myEvent",function(){alert("Yes!");});
document.dispatchCustomEvent(new CustomEvent("myEvent",{detail:null}));
}
</script>
<body onload="onLoad()">
<div id="myDiv"></div>
</body>
</html>
Going with the extreme. Events propagate down to the element they are dispatched on and back up... So in order to trigger an event on any and essentially all elements (since it is unknown which elements need the event) you can find the "ends" of all of the "branches" of the DOM and dispatch events to them.
jQuery makes it easy to select the end of the branches
function onLoad() {
var myDiv = document.getElementById("myDiv");
myDiv.addEventListener("myEvent", function() {
alert("Yes!");
});
$(':not(:has(*))').each(function(i, el){
el.dispatchEvent(new CustomEvent("myEvent", {
detail: null,
bubbles: true
}));
});
}
https://jsfiddle.net/dkqagnph/1/
Using this will ensure EVERY DOM element (attached to the body) gets the event (assuming that no element stop propagation itself) and thus making there be no need to know which elements are listening or care about the event. This doesn't dispatch to every individual element, as that would be overkill, but just the end and lets bubbling do it's thing.
NOTE: elements with more than one child will get the event more than one time. You may want to have a way to ensure that your code does run more than once or does not care if it runs more than once.

toggle display in pure javascript

I am trying to toggle visibility of signup and signin boxes if sign in and sign up buttons are clicked. I am trying to use only pure javascript.
I wrote simple html and javascript as below:
<div>
<button class="signin">sign in</button><button class="signup">sign up</button>
<div class="signin-box" style="display: none;">
<form class="signin-form">
<label>username<input></label><label>password<input></label><button type="submit">signin</button>
</form>
</div>
<div class="signup-box" style="display: none;">
<form class="signup-form">
<label>username<input></label><label>password<input></label><button type="submit">signup</button>
</form>
</div>
</div>
javascript part:
var signupButton = document.getElementsByClassName('signup')[0];
var signinButton = document.getElementsByClassName('signin')[0];
var signupBox = document.getElementsByClassName('signup-box')[0];
var signipBox = document.getElementsByClassName('signin-box')[0];
console.log("box: ", signupBox, "button: ",signupButton);
var toggleVisible = function(item){
if (item.style.display === 'none'){
return item.style.display = 'block';
}else{
return item.style.display = 'none';
}
};
window.onload = function(){
signupButton.onclick = toggleVisible(signupBox);
signinButton.onclick = toggleVisible(signipBox);
};
The problem here is that the javascript toggleVisible is automatically activated even if i never clicked the buttons.
as a result, the signin-box and signup-box both gets display:block property.
How do i solve this problem?
You're calling the function, not passing it in. Just wrap your function call in an anonymous function:
signupButton.onclick = function() {
toggleVisible(signupBox);
};
If you don't care about older browsers, you can also simplify your code a little if you put your JavaScript at the bottom of the <body> tag and add a rule to your CSS:
document.querySelector('.signup').addEventListener('click', function() {
document.querySelector('.signup-box').classList.toggle('hidden');
}, false);
document.querySelector('.signin').addEventListener('click', function() {
document.querySelector('.signin-box').classList.toggle('hidden');
}, false);
And the CSS:
.hidden {
display: none;
}
I would recommend to use a standard JavaScript method addEventListener() to attached onclick event listener to the button.
It has following advantages over different solution:
You can attach an event handler to an element without overwriting existing event handlers.
You can add many event handlers of the same type to one element, i.e
two "click" events.
In your code it will look like
window.onload = function(){
signupButton.addEventListener("click", function() { toggleVisible(signupBox); });
signinButton.addEventListener("click", function() { toggleVisible(signipBox); });
};
Current code invokes toggleVisible(..) method and assigns its result to the button attribute, which is not one would expect.
signupButton.onclick = toggleVisible(signupBox);

Get id of a span in JavaScript.

I want to get the span id in JavaScript following code always returning M26 but I want different values on different click M26 or M27:
function clickHandler() {
var xid= document.getElementsByTagName("span");
var xsp= xid[0].id;
alert(xsp);
}
}
<html>
<BODY LANGUAGE = "javascript" onClick = "clickHandler();">
<a href="javascript:void(0)"><u><b><span id=M26>2011-
2012</span></b></u></a>
<div id=c26 STYLE="display:none">
<a href="javascript:void(0)"><u><b><span id=M27>2012-
2013</span></b></u></a>
<div id=c27 STYLE="display:none">
</body>
</html>
The problem you are facing is that var xid= document.getElementsByTagName("span"); gets all spans on the page regardless of where you click.
To solve this problem you should just pass a reference to the clicked object within the function. For example:
<span id=M26 onclick="clickHandler(this);" >2011-2012</span>
Then in your javascript code:
function clickHandler(object) {
alert(object.id);
}
However it is a good idea to bind the events within javascript rather than inline in the html tags.
This article describes the different ways in which you can bind events to elements.
There are several ways to get the id of the element that has just been clicked:
Pass a reference to this to the handler:
onclick="handlerFunc(this);">
Or, better yet, pass the event object to the handler, this allows you to manipulate the event's behaviour, too:
onclick='handlerFunc(event);'>
//in JS:
function handlerFunc(e)
{
e = e || window.event;
var element = e.target || e.srcElement;
element.id;//<-- the target/source of the event (ie the element that was clicked)
if (e.preventDefault)
{//a couple of methods to manipulate the event
e.preventDefault();
e.stopPropagation();
}
e.returnValue = false;
e.cancelBubble = true;
}
You can use getAttribute() function for this...
function clickHandler() {
var xid= document.getElementsByTagName("span");
var xsp= xid[0].getAttribute('id');
alert(xsp);
}
<html>
<body LANGUAGE = "javascript" onload = "clickHandler();">
<a href="javascript:void(0)"><u><b><span id=M26>2011-
2012</span></b></u></a>
<div id=c26 STYLE="display:none">
<a href="javascript:void(0)"><u><b><span id=M27>2012-
2013</span></b></u></a>
<div id=c27 STYLE="display:none">
</body>
</html>
See working Demo

Categories