How to get all related javascript to an html element - javascript

Is there a way to get all javascript associated with an html element by class name returned in an array? Any suggestion as to how one would achieve doing this? Are there any node packages that would allow me to do something like this?
For example:
HTML
<div class="click_me">Click Me</div>
JS
$('.click_me').on('click', function() { alert ('hi') });
I would want something like (psuedo-code either on the client or server side):
function meta() {
let js = [];
js = getAllJavascriptByClassName('click_me');
console.log(js[0]);
}
Output of meta()
$('.click_me').on('click', function() { alert ('hi') });

This will pull out all event handlers of all elements of given class.
But these handlers must be attached using jquery.
function getAllEventHandlersByClassName(className) {
var elements = $('.' + className);
var results = [];
for (var i = 0; i < elements.length; i++) {
var eventHandlers = $._data(elements[i], "events");
for (var j in eventHandlers) {
var handlers = [];
var event = j;
eventHandlers[event].forEach(function(handlerObj) {
handlers.push(handlerObj.handler.toString());
});
var result = {};
result[event] = handlers;
results.push(result);
}
}
return results;
}
// demo
$('.target').on('click',function(event){
alert('firstClick handler')
});
$('.target').on('click',function(event){
alert('secondClick handler')
});
$('.target').on('mousedown',function(event){
alert('firstClick handler')
});
console.log(getAllEventHandlersByClassName('target'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='target'> </div>

You can use getEventListeners() which is part of the chrome devtools but for employing client side, there's an possible-duplicate question that partially answers this: How to find event listeners on a DOM node when debugging or from the JavaScript code? which basically shows (in the second voted answer) that depending on how the events are set (javascript attribute, eventListener, jquery, other lib) there are different ways to retrieve the functions.
The Visual Event 2 program mentioned in the first question seems to be more of a library doing what the second answer is suggesting so maybe this will solve your problem.

If you are interested only in jQuery solution I may suggest you (I assume there is only one event per type, but you need to cycle on all instances):
function getAllJavascriptByClassName(className) {
var elem = $('.' + className);
var result = [];
$('.' + className).each(function(index, element) {
var resultObjs = jQuery._data(element, "events");
var partialResult = [];
var x = Object.keys(resultObjs).forEach(function(currentValue, index, array) {
partialResult.push(resultObjs[currentValue][0].handler.toString());
});
result.push(partialResult);
});
return result;
}
function meta() {
let js = [];
js = getAllJavascriptByClassName('click_me');
console.log(JSON.stringify(js, null, 4));
}
$(function () {
$('.click_me').on('click', function (e) {
alert('Click event: hi')
});
$('.click_me:last').on('keypress', function (e) {
alert('Keypress event: hi')
});
meta();
});
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<div class="click_me">Click Me</div>
<div class="click_me">Click Me</div>

I would personally override addEventListener at the right places (meaning at the very top) with some safe guards.
UNfortunately jquery event handlers appear to be quite hard to read...
var element = document.getElementById("zou");
element.addEventListener("click", function(e) {
console.log("clicked from addevent");
});
element.addEventListener("mouseup", function(e) {
console.log("mouseup from addevent");
});
$(element).on("mousedown", function(e) {
console.log("mousedown from $")
});
console.log(element.getListeners());
<script>
window.eventStorage = {};
(function() {
var old = HTMLElement.prototype.addEventListener;
HTMLElement.prototype.addEventListener = function(a, b, c) {
if (!window.eventStorage[this]) {
window.eventStorage[this] = [];
}
var val = {
"event": a,
"callback": b
};
var alreadyRegistered = false;
var arr = window.eventStorage[this];
for (var i = 0; i < arr.length; ++i) {
if (arr.event == a && arr.callback == b) {
alreadyRegistered = true;
break;
}
}
if (!alreadyRegistered) {
arr.push(val);
}
old.call(this, a, b, c);
}
HTMLElement.prototype.getListeners = function() {
return window.eventStorage[this] || {};
}
}());
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="zou">click on me</div>

Related

Function when multiple elements have been clicked

I want a to have an animation only when seven elements have been click. Here is the code but it doesn't work:
var animp5 = function () {
var i = 0;
$("#ans1_p5").on('click', function () {
i = i + 1;
$("#ans1_p5").fadeOut(800);
$("#correct1_p5").fadeIn(1000);
});
$("#ans2_p5").on('click', function () {
i = i + 1;
$("#ans2_p5").fadeOut(800);
$("#correct2_p5").fadeIn(1000);
});
$("#ans3_p5").on('click', function () {
i = i + 1;
$("#ans3_p5").fadeOut(800);
$("#correct3_p5").fadeIn(1000);
});
$("#ans5_p5").on('click', function () {
i = i + 1;
$("#ans5_p5").fadeOut(800);
$("#correct4_p5").fadeIn(1000);
});
$("#ans7_p5").on('click', function () {
i = i + 1;
$("#ans7_p5").fadeOut(800);
$("#correct5_p5").fadeIn(1000);
});
$("#ans9_p5").on('click', function () {
i = i + 1;
$("#ans9_p5").fadeOut(800);
$("#correct6_p5").fadeIn(1000);
});
$("#ans10_p5").on('click', function () {
i = i + 1;
$("#ans10_p5").fadeOut(800);
$("#correct7_p5").fadeIn(1000);
});
if (i === 7) {
$("#ans4").fadeOut(800);
$("#ans6").fadeOut(800);
$("#ans8").fadeOut(800);
$("#wrong1_p5").fadeIn(1000);
$("#wrong2_p5").fadeIn(1000);
$("#wrong3_p5").fadeIn(1000);
$("#cor_p5").fadeIn(1000);
}
};
I have tried other solutions (like .data('clicked') or .attr('clicked') but they didn't work either.
You can use observer design pattern in javascript to achieve this the right way.
First create handlers, subscribe and execute functions and then you can subscribe waht ever you like in your case its comparison i===7. execute fade.execute after every click to validate.
Also it's advisable to use class selectors than id selectors in your case. As id selectors will be unmanageable and you will end up with a lot of duplicate code.
But for the sake of your question observer is your way to go.
jsFiddle
function Fade() { // Create Fade handlers
this.handlers = []; // observers
}
Fade.prototype = { // define subscribe and execute
subscribe: function(fn) {
this.handlers.push(fn);
},
execute: function(o, thisObj) {
var scope = thisObj || window;
this.handlers.forEach(function(item) {
item.call(scope, o);
});
}
};
var fade = new Fade();
fade.subscribe(function(){ // pass function you want to subscribe
console.log(i);
if(i===7){
$("#ans4").fadeOut(800);
$("#ans6").fadeOut(800);
$("#ans8").fadeOut(800);
$("#wrong1_p5").fadeIn(1000);
$("#wrong2_p5").fadeIn(1000);
$("#wrong3_p5").fadeIn(1000);
$("#cor_p5").fadeIn(1000);
}
});
var animp5 = (function(){
var i = 0;
$("#ans1_p5").on('click',function(){
i=i+1;
$("#ans1_p5").fadeOut(800);
$("#correct1_p5").fadeIn(1000);
fade.execute(); // execute to check if condition met
});
$("#ans2_p5").on('click',function(){
i=i+1;
$("#ans2_p5").fadeOut(800);
$("#correct2_p5").fadeIn(1000);
fade.execute();
});
$("#ans3_p5").on('click', function(){
i=i+1;
$("#ans3_p5").fadeOut(800);
$("#correct3_p5").fadeIn(1000);
fade.execute();
});
$("#ans5_p5").on('click', function(){
i=i+1;
$("#ans5_p5").fadeOut(800);
$("#correct4_p5").fadeIn(1000);
fade.execute();
});
$("#ans7_p5").on('click', function(){
i=i+1;
$("#ans7_p5").fadeOut(800);
$("#correct5_p5").fadeIn(1000);
fade.execute();
});
$("#ans9_p5").on('click', function(){
i=i+1;
$("#ans9_p5").fadeOut(800);
$("#correct6_p5").fadeIn(1000);
fade.execute();
});
$("#ans10_p5").on('click', function(){
i=i+1;
$("#ans10_p5").fadeOut(800);
$("#correct7_p5").fadeIn(1000);
fade.execute();
});
})();
Thanks for your answers.
As I have not much experience working with jquery I was unable to code your solution but I found a new one that works perfect. I put the "if" inside every click function so each time I click, code checks if the condition has been fulfilled and once this happens run the appropriate code.
Thanks again

Javascript Dynamically invoke shortcut keys combination function to shortcutjs plugin

Am getting key Combination from the server. Based on that am assigning key Combination to function dynamically. The below code is working for last iteration in loop. how below code is work for all iterations.
In my page i have two buttons save and cancel the below code is working for last iteration in for loop, It means btnCanel button triggers if i press key for save function.Any suggestions. hope understand my question.
$(document).ready(function fn() {
var keyCombination = new Object();
keyCombination['btnAdd'] = "Alt+S";
keyCombination['btnCancel'] = "Alt+C";
for (var k in keyCombination) {
if (keyCombination.hasOwnProperty(k)) {
shortcut.add(String(keyCombination[k]), function () {
var btnAdd = document.getElementById(String(k));
btnAdd.focus();
btnAdd.click();
});
}
}
});
if i give like this means it is working
shortcut.add("Alt+S", function () {
var btnAdd = document.getElementById('btnAdd ');
btnAdd .focus();
btnAdd .click();
});
shortcut.add("Alt+C", function () {
var btnCancel = document.getElementById('btnCancel');
btnCancel.focus();
btnCancel.click();
});
but if i try to add dynamically its overriding help me this issue.
Thanks in Advance.
I created a separate function outside the document.ready function like this now its working fine.
$(document).ready(function fn() {
var keyCombination = new Object();
keyCombination['btnAdd'] = "Alt+S";
keyCombination['btnCancel'] = "Alt+C";
for (var k in keyCombination) {
if (keyCombination.hasOwnProperty(k)) {
Set_KeyCombinations(k, keyCombination);
}
}
});
function Set_KeyCombinations(k, keyCombination) {
shortcut.add(String(keyCombination[k]), function () {
var eleId = document.getElementById(String(k));
if (eleId) {
if ($('#' + String(k).trim()).css('display') !== 'none' && eleId.getAttribute("disabled") !== "disabled") {
eleId.click();
eleId.focus();
}
}
});
}
Try this:
var keyCombinations = [ "Ctrl+Shift+X" , "Ctrl+Shift+Y" ];
for(var i=0; i<keyCombinations.length; i++){
(function(shorcutCombination){
shortcut.add(shorcutCombination,function() {
alert("i am " + shorcutCombination);
});
})(keyCombinations[i]);
}
The idea is that you need to preserve the value of keyCombinations[i]
as i increases in the loop. Tested this here: Openjs

How to disable all ng-click and ng-submit event

is there any way, how can I globally (in service) disable and enable all ng-click and ng-submit events?
For example when user is offline I want to disable all actions till he gets connection back..
I tried to bind all elements with an onClick event which will call stopImmediatePropagation but it didn't work..
$('*[ng-click]').click(function( event ) {
event.stopImmediatePropagation();
});
Also this question is a little bit different from this one:
Disable ng-click on certain conditions of application for all types of element
I'd like to disable/enable all events in APP globally from service, I'm not able to modify all ng-* calls on all elements in the APP..
Try including a return false too:
$('*[ng-click]').click(function( event ) {
event.stopImmediatePropagation();
return false;
});
Snippet
The below snippet demonstrates that multiple event handlers attached to a single <a> works too.
$(function () {
$("a").click(function () {
alert("Hello!");
return false;
});
$("a").click(function () {
alert("Bye!");
return false;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
Click Me
So finally I end up with temporarily disabling all events on the page using jquery..
I got inspired from this plugin http://ignitersworld.com/lab/eventPause.html which for some reason did not work (without any error)
So I took main parts and put it to this class which is working now using jquery v2.1.1:
var EventManager = function() {
var self = this;
var nullFun=function(){};
var getIndex = function(array,value){
for(var i=0; i< array.length; i++){
if(array[i]==value){
return i;
}
}
return -1;
};
this.pauseEvent = function(elm,eventAry){
var events = $._data(elm, "events");
if (events) {
$.each(events, function(type, definition) {
if((getIndex(eventAry,type)!=-1)||(eventAry=='')){
$.each(definition, function(index, event) {
if (event.handler.toString() != nullFun.toString()){
if(!$._iwEventPause) $._iwEventPause = {};
$._iwEventPause["iw-event" + event.guid] = event.handler;
event.handler = nullFun;
}
})
}
})
}
};
this.activeEvent = function(elm,eventAry){
var events = $._data(elm, "events");
if (events) {
$.each(events, function(type, definition) {
if((getIndex(eventAry,type)!=-1)||(eventAry=='')){
$.each(definition, function(index, event) {
if (event.handler.toString() == nullFun.toString()){
event.handler = $._iwEventPause["iw-event" + event.guid];
}
})
}
})
}
};
this.disableAll = function(el) {
el = el || $('*');
el.each(function() {
self.pauseEvent($(this)[0], '');
});
self.pauseEvent($(window)[0], '');
};
this.enableAll = function(el) {
el = el || $('*');
el.each(function() {
self.activeEvent($(this)[0], '');
});
self.activeEvent($(window)[0], '');
};
return this;
};
var eManager = new EventManager();
eManager.disableAll();
eManager.enableAll();
This will go through window object and all elements on the page, move their event handlers away to _iwEventPause object and replace handlers with dummy function.. When enabling, it will move handlers back so they get normally called..
This solution does not handle event handlers added after disabling..

GetElementbyID fails to fire

From my reading here I would expect this code to work, but it doesn't. I have tried two ways to add click events to a button called "lonext". Neither work. I'm not sure why this might be?
window.onload = function() {
var goSC = function() { //go to the sucess criteria section
document.getElementsByClassName("guidance1").style.display = "none";
document.getElementsByClassName("guidance2").style.display = "";
alert("button clicked");
//first try
document.getElementById("lonext").addEventListener("click", function() {
goSC();
}, false);
//second try
document.getElementById("lonext").onclick = goSC;
}
The getElementsByClassName returns an NodeList because you could have many elements in your DOM with the same class, not a single element.
So:
var goSC = function() {
var guidance1 = document.getElementsByClassName("guidance1");
for (var i = 0; i < guidance1.length; i++) {
guidance[i].style.display = "none";
}
var guidance2 = document.getElementsByClassName("guidance2");
for (var i = 0; i < guidance2.length; i++) {
guidance[i].style.display = "";
}
alert("button clicked");
});
window.onload = function() {
document.getElementById("lonext").onclick = goSC;
};
which if you used jQuery could be simplified to:
$(function() {
$('#lonext').click(function() {
$('.guidance1').hide();
$('.guidance2').show();
});
});
I would also strongly recommend you using a javascript debugging tool such as FireBug or Chrome Developer toolbar to inspect your javascript code and see potential errors with it. The Console tab will contain valuable information about possible errors in your javascript code.

How to detect if some text box is changed via external script?

I have some jQuery plugin that changes some elements, i need some event or jQuery plugin that trigger an event when some text input value changed.
I've downloaded jquery.textchange plugin, it is a good plugin but doesn't detect changes via external source.
#MSS -- Alright, this is a kludge but it works:
When I call boxWatcher() I set the value to 3,000 but you'd need to do it much more often, like maybe 100 or 300.
http://jsfiddle.net/N9zBA/8/
var theOldContent = $('#theID').val().trim();
var theNewContent = "";
function boxWatcher(milSecondsBetweenChecks) {
var theLoop = setInterval(function() {
theNewContent = $('#theID').val().trim();
if (theOldContent == theNewContent) {
return; //no change
}
clearInterval(theLoop);//stop looping
handleContentChange();
}, milSecondsBetweenChecks);
};
function handleContentChange() {
alert('content has changed');
//restart boxWatcher
theOldContent = theNewContent;//reset theOldContent
boxWatcher(3000);//3000 is about 3 seconds
}
function buttonClick() {
$('#theID').value = 'asd;lfikjasd;fkj';
}
$(document).ready(function() {
boxWatcher(3000);
})
try to set the old value into a global variable then fire onkeypress event on your text input and compare between old and new values of it. some thing like that
var oldvlaue = $('#myInput').val();
$('#myInput').keyup(function(){
if(oldvlaue!=$('#myInput').val().trim())
{
alert('text has been changed');
}
});
you test this example here
Edit
try to add an EventListner to your text input, I don't know more about it but you can check this Post it may help
Thanks to #Darin because of his/her solution I've marked as the answer, but i have made some small jQuery plugin to achieve the same work named 'txtChgMon'.
(function ($) {
$.fn.txtChgMon = function (func) {
var res = this.each(function () {
txts[0] = { t: this, f: func, oldT: $(this).val(), newT: '' };
});
if (!watchStarted) {
boxWatcher(200);
}
return res;
};
})(jQuery);
var txts = [];
var watchStarted = false;
function boxWatcher(milSecondsBetweenChecks) {
watchStarted = true;
var theLoop = setInterval(function () {
for (var i = 0; i < txts.length; i++) {
txts[i].newT = $(txts[i].t).val();
if (txts[i].newT == txts[i].oldT) {
return; //no change
}
clearInterval(theLoop); //stop looping
txts[i].f(txts[i], txts[i].oldT, txts[i].newT);
txts[i].oldT = $(txts[i].t).val();
boxWatcher(milSecondsBetweenChecks);
return;
}
}, milSecondsBetweenChecks);
}

Categories