0

EDIT: I've made a few changes to re-clarify the issue I'm having.

I have a simple Javascript plugin that I want to add some callback features to as part of its default functionality. Users would be able to specify a function to be called when a certain button is clicked on.

// Define option defaults
var defaults = {
  //some other defaults
  onOK: null, //callback functions to be specified here (exists as string)
  onClose: null //callback functions to be specified here (exists as string)
}

Normally, this works fine when there's a simple function with no arguments. The option is passed to here:

function initializeEvents() {
    //If a close button event is clicked, run this.
    if (this.closeButton) {
      this.closeButton.addEventListener('click', this.close.bind(this)); //Bind close event to the button
      this.closeButton.addEventListener('click', window[this.options.onClose]); //passed to here
    }
    //If an OK button event is clicked, run this.
    if (this.okButton) {
      this.okButton.addEventListener('click', this.close.bind(this));
      this.okButton.addEventListener('click', window[this.options.onOK]); //passed to here
    }
  }

window[] is supposed to become a function call to the appropriate button. It has come to my attention that I should NOT be using window[].

EDIT: However, as @adeneo pointed out, I'm making a BIG mistake here by adding my functions as strings, which simply results in the function becoming undefined instead when I have to add it to an event listener.

I've tried using an anonymous function, but I'm still not getting the function to work:

var callbackModal = new raModal({
            content: '<div>You clicked on the Callback button. This shows the popup, but has a custom callback function, called when the user clicks OK and/or Close.</div>',
            onOK:{function(){
                    okCallback('4');
                 }
            },
            onClose: "closeCallback",
            closeButtonText: "Close"
        });
        callbackModal.open();

So, my question has changed to: How can I properly add my anonymous functions from the defaults?

Link to a JSFiddle that reproduces the issue. You'll notice that while the Close button works as intended (with closeCallback printing the console.log message), the OK button calling okCallback(num) does nothing.

Any help is greatly appreciated.

Miega
  • 45
  • 6
  • Why would you add functions as strings? The issue is that you're expecting a reference to a function, and when you add the parentheses you call the function and return the result, which in your case is just `undefined`. If you really need to pass arguments, you can use an anonymous function, but then you'd have to expect references, not strings – adeneo Aug 30 '17 at 19:50
  • @adeneo Strings seemed to work at the time, because otherwise I was running into a syntax error. I tried anonymous functions, but all I got was `Uncaught SyntaxError: Unexpected number`. – Miega Aug 30 '17 at 20:03
  • Whatever floats your goat, I'm just telling you that you're not doing it correctly. It's a really bad idea to pass the function names as strings, and then use `window["functionName"]` to call those functions. – adeneo Aug 30 '17 at 20:08
  • @adeneo Yup, I definitely know now that that's not the correct way to do it! Thanks for pointing that out. ;) I've edited my post with your information as well as what I've tried. – Miega Aug 30 '17 at 20:16
  • Maybe it's easier if I just show you -> https://jsfiddle.net/cw1Lscsw/ – adeneo Aug 30 '17 at 20:30
  • @adeneo I'm afraid I'm still lost. Care to add more details in an answer? – Miega Aug 30 '17 at 20:47

2 Answers2

0

You can pass arguments to JavaScript functions without having a parameter name on the function's signature. This should be a workaround for your problem.

See Is it possible to get all arguments of a function as single object inside that function?

iquellis
  • 979
  • 1
  • 8
  • 26
0

Instead of trying to bind the callbacks to the button in initializeEvents() using the risky window[] implementation, it's much easier to simply append them after the button object after they're constructed.

I made two additional functions to add the event listeners for the OK and Close buttons:

  function closeCallback(callback){
    $(".ra-close").click(callback);
  }
  function okCallback(callback){
    $(".ra-ok").click(callback);
  }

And inside the buildOut() function, after everything is done, add the calls to the event listeners, using our custom option as the argument, which can be an anonymous function now!

closeCallback(this.options.onClose);
okCallback(this.options.onOK);

There was an additional utility function that extended user options to the new modal, but didn't track null values properly. I removed an if statement that checked for those, seeing as we had them as part of the defaults variable.

  // Utility method to extend defaults with user options
  function extendDefaults(source, properties) {
    var property;
    for (property in properties) {
        source[property] = properties[property];
    }
    return source;
  }

Here's the updated JSFiddle with the corrected plugin code.

Miega
  • 45
  • 6