10

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') });
Ron I
  • 4,090
  • 8
  • 33
  • 64
  • quite interesting - you want to get all js functions which are bound to a specific HTML class? – messerbill May 31 '16 at 16:27
  • @messerbill - yes, I want to extract all js functions that are related to an html element via a selector (class or attribute, etc). – Ron I May 31 '16 at 16:33
  • 1
    @RonI can you clarify why you need this. There might be some simpler solution. – rishabh dev May 31 '16 at 16:44
  • @rishabhdev - I have started working on a tool that would enable a web developer to store their UI source code dynamically and automatically. – Ron I May 31 '16 at 16:56

4 Answers4

5

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>
rishabh dev
  • 1,711
  • 1
  • 15
  • 26
3

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.

Community
  • 1
  • 1
Anders Elmgren
  • 637
  • 5
  • 12
2

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>
gaetanoM
  • 41,594
  • 6
  • 42
  • 61
2

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>
Regis Portalez
  • 4,675
  • 1
  • 29
  • 41