1

I would like to know how to reuse an event handler that is in an external js file that I can't change

If there are other ways to reuse event handlers, please let me know as well.

Not sure how to fix it

I am getting the below error and I don't know how to solve it.

Uncaught ReferenceError: show is not defined

<script src="https://cdn.tailwindcss.com"></script>
<script src="https://code.jquery.com/jquery-3.7.0.js"></script>

<ul class="flex gap-5 mb-5 [&_a]:underline [&_a:hover]:no-underline">
  <li><a href="#" class="org text-indigo-500 ">CLICK ORG</a></li>
  <li><a href="#" class="copy text-red-500 ">CLICK COPY</a></li>
</ul>

<div class="baz">BAZ</div>

<!--
external js file that I cannot change.
<script src="external.js"></script>
-->
<script>
//Contents of external.js
  jQuery(function($) {
    init();

    function init() {
      $('a').on('click', function(event){
        var foo = $('.baz').text();
        var bar = 'BAR';
        show({
          'one': foo,
          'two': bar,
        });
        event.preventDefault();
      });
    }

    function show(obj) {
      console.log(obj.one);
      console.log(obj.two);
    }
  });
</script>

<script>
  jQuery(function($) {
    const handler = $._data($('.org').get(0), "events")['click'][0]['handler'];
    const strFun = handler.toString();
    const funcFromStr = new Function('return ' + strFun.replace("$('.baz').text()", "'FOO'"))();

    $('.copy').on('click', function(event){
      funcFromStr();
      event.preventDefault();
    });
  });
</script>

Reference information

const handler = $._data($('.org').get(0), "events")['click'][0]['handler'];
const strFunBody = strFun.substring(strFun.indexOf("{") + 1, strFun.lastIndexOf("}")).replace("'FOO'", "$('.baz').text()");
const funcFromStr = new Function('return ' + strFun.replace("'FOO'", "$('.baz').text()"))();

When using javascript instead of jQuery


Contents of the past

Change Title

  • Previous Title
    How to avoid errors when using The "new Function" syntax to reuse event handlers(Uncaught SyntaxError: Unexpected token 'function')

Change Body

I would like to know how to avoid errors when using The "new Function" syntax to reuse event handlers.(Uncaught SyntaxError: Unexpected token 'function')

  • 2
    Could you explain what your trying to do here, this seems like an X/Y problem and using eval I'm pretty sure is not the way. – Keith Jul 05 '23 at 07:30
  • Thank you for your comment. I want to perform some processing that is inside an external js file that I cannot change. – eternal novice Jul 05 '23 at 07:40
  • 2
    Where did the error in the title come from? Running the code snippet reports the call to new `Function` is missing a formal parameter for me. The is because "Function" expects all its arguments to be strings and is being passed a function object (`show`) as its first argument. While this could be fixed it still appears to be an X/Y problem as already commented by @Keith . I _suggest_ including more information about what needs to achieved, and why, with code for an exemplary original handler, in the question itself. – traktor Jul 05 '23 at 08:43
  • 1
    "*START: external js file*", "*END: external js file*" - how is that external file in the middle of a `jQuery(function($) {…})` callback??? Is it actually loaded as a separate ` – Bergi Jul 05 '23 at 09:05
  • @traktor@Bergi Thank you for your comment. Fixed the Title and Body. – eternal novice Jul 06 '23 at 00:39
  • With names like 'FOO" and ' BAR' this seems to be tutorial. The use of `javascript:void(0)` to turn a link into a button of type "button" dates from HTML3 and hasn't been needed since HTML4, so example code you are following is seriously out of date. With best wishes in mind, I would suggest throwing out the example code you are using and write your own - there is no "best way" of dynamically modifying the code of an event handler at run time. It would be a hack best left alone. – traktor Jul 06 '23 at 08:26
  • 1
    See also [Best way to remove a click handler in jQuery?](https://stackoverflow.com/q/209029/5217142). As a last resort you could remove the click handler added in `external.js` and proceed from there. – traktor Jul 06 '23 at 08:37

1 Answers1

0

It's a half-finished content, but it will work for the time being, so I'll post it for the time being.

I didn't know how to deal with it with new Function or eval, so I dealt with it by removing the event handler once with jQuery off() and re-registering it.

<script src="https://cdn.tailwindcss.com"></script>
<script src="https://code.jquery.com/jquery-3.7.0.js"></script>

<ul class="flex gap-5 mb-5 [&_a]:underline [&_a:hover]:no-underline">
  <li><a href="#" class="org text-indigo-500 ">CLICK ORG</a></li>
  <li><a href="#" class="copy text-lime-500 ">CLICK COPY</a></li>
</ul>

<div class="baz">BAZ</div>

<!--
external js file that I cannot change.
<script src="external.js"></script>
-->
<script>
//Contents of external.js
  jQuery(function($) {
    init();

    function init() {
      $('a').on('click', function(event){
        var foo = $('.baz').text();
        var bar = 'BAR';
        show({
          'one': foo,
          'two': bar,
        });
        event.preventDefault();
      });
    }

    function show(obj) {
      console.log(obj.one);
      console.log(obj.two);
    }
  });
</script>

<script>
  jQuery(function($) {
    const objRegisteredEvents = {};
    Object.entries($._data($('a').get(0), 'events')).forEach(function([eventName, aryEvent]) {
      objRegisteredEvents[eventName] = aryEvent.reduce(function(acc, eventContent) {
        return [...acc, eventContent.handler];
      }, []);
    });

    $('a').off('click');

    $('.org').on('click', function(event){
      objRegisteredEvents['click'].forEach(function(handler) {
        handler(event);
      });
    });
    $('.copy').on('click', function(event){
      const orgBazTxt = $('.baz').text();
      $('.baz').text('FOO');
      objRegisteredEvents['click'].forEach(function(handler) {
        handler(event);
      });
      $('.baz').text(orgBazTxt);
    });
  });
</script>

Restore events removed by jQuery off()

  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 10 '23 at 16:30