'How to override the existing onclick() methods of html anchor tags
In a HTML page there are couple of anchor tags with onclick() methods - of which codes I cannot or must not change. However, I can add a new js file or jQuery to this page. How can I add an event listener for click events of those anchor tags - which must be fired/called before those existing onclick() methods? After that the existing onclick() methods should be called. Something like the following.
<a href='#' class="edit" onclick='edit()'>Edit First</a>
<a href='#' class="edit" onclick='edit()'>Edit Second</a>
<a href='#' class="edit" onclick='edit()'>Edit Third</a>
and
const el = document.getElementsByClassName("edit");
el.addEventListener("click", beforeEdit, false);
function beforeEdit() {
//this should be called before edit(), after that edit() must be called.
}
Solution 1:[1]
Remove the attribute, then call edit yourself in your own handler. Also you'll need to iterate over the elements properly - getElementsByClassName returns a collection, not an element.
for (const anchor of document.querySelectorAll('.edit')) {
anchor.removeAttribute('onclick');
anchor.addEventListener('click', () => {
// insert your function code here, then:
edit();
});
}
Solution 2:[2]
how can get/retrieve that body of edit() method using js and execute it
In other words, your requirement is that the onclick="edit()" is not always edit().
You could use eval but even the MDN page states:
"Executing JavaScript from a string is an enormous security risk."
An alternative, to ensure your code runs first is to insert your code at the start of the onclick=, eg:
$(".edit").attr("onclick", (i, attr) => "beforeEdit();"+attr);
Example snippet:
$(".edit").attr("onclick", (i, attr) => "beforeEdit();"+attr);
function beforeEdit() {
console.log("before edit");
}
function edit() {
console.log("edit");
}
function edit2() {
console.log("edit2");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<a href='#' class="edit" onclick='edit()'>Edit First</a>
<a href='#' class="edit" onclick='edit2()'>Edit Second</a>
<a href='#' class="edit" onclick='edit()'>Edit Third</a>
Solution 3:[3]
Since event attributes are fired at the target or bubbling phases, you can add a capturing event on these elements, and wrap their content in a new element so that the event actually fires on the child:
let val = 0;
const els = document.querySelectorAll(".edit");
els.forEach(el => el.addEventListener("click", beforeEdit, {capture: true}));
function beforeEdit() {
console.log("setting global val to ", val = Math.random());
}
function edit() {
console.log("global val is now", val);
event.preventDefault();
}
<a href='#' class="edit" onclick='edit()'><span>Edit First</span></a>
<a href='#' class="edit" onclick='edit()'><span>Edit Second</span></a>
<a href='#' class="edit" onclick='edit()'><span>Edit Third</span></a>
Or, maybe cleaner, you can attach the event handler on a parent:
let val = 0;
document.body.addEventListener("click", beforeEdit, {capture: true});
function beforeEdit(evt) {
if (evt.target.matches("a.edit,a.edit *")) {
console.log("setting global val to ", val = Math.random());
}
}
function edit() {
console.log("global val is now", val);
event.preventDefault();
}
<a href='#' class="edit" onclick='edit()'>Edit First</a>
<a href='#' class="edit" onclick='edit()'>Edit Second</a>
<a href='#' class="edit" onclick='edit()'>Edit Third</a>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | CertainPerformance |
| Solution 2 | freedomn-m |
| Solution 3 |
