How to call a method within an object via a parameter

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Claus Mygind
    Contributor
    • Mar 2008
    • 571

    How to call a method within an object via a parameter

    I have an object with several methods within it.

    I would like to call a specific method based on a variable.

    Code:
    function mapDataObject()
    {
     this.a = function (){alert('a');};
     this.b = function (){alert('b');};
     this.c = function (){alert('c');};
     this.d = function (){alert('d');};
     this.e = function (){alert('e');};
    }
    
    var mdo = new mapDataObject;
    I could use "if, else if" or a switch statement. But I would like to reduce it either one or just a few lines of code using a variable parameter. I am struggling with var function = window[functionstring], .call() and .apply()

    The method to be executed will depend on the button clicked by the user.

    Code:
    function updatePage(button)
    {
    		var fn = window['mdo']+'.'+button.id;
    		fn();
    //		mdo.call(null, button.id);
    //		mdo.button.id();
    }


    Can someone show me a simple example.

    Yes I know I can just call mdo.a(); when a is clicked, but in this example other processing is occurring before arriving at updatePage();
  • Dormilich
    Recognized Expert Expert
    • Aug 2008
    • 8694

    #2
    The method to be executed will depend on the button clicked by the user.
    wouldn’t it be the obvious choice then to attach the appropriate method to the click event?

    alas, if that’s not possible, and you get the name of the method from the button itself (mind that this is somewhat unreliable), you can do
    Code:
    try {
        mdo[button.name]();
    }
    catch(e) {
        console.log("no such method name");
    }

    Comment

    • Claus Mygind
      Contributor
      • Mar 2008
      • 571

      #3
      Thank you for your response. I have had to put the current project on hold to resolve another issue that has crept up with sending out emails. I will get back to this when the other problem has been resolved.

      Comment

      • Claus Mygind
        Contributor
        • Mar 2008
        • 571

        #4
        The suggestion did not work. It simply returned an error "not a function"

        So perhaps there is another option out there. Here is more detail about sequence of events.

        1. I use a generic ajax call for all my calls. There may be many different types of calls from any individual page. They would include everything from submitting the whole form to smaller tasks like looking information for a small section of the page.

        2. Any type of event can trigger this call. click, change etc.

        3. The ajax object receives two pieces of information a form object (or pseudo form) and a data object. All information needed to make the ajax call and what to update on the callback are stored in these two objects.

        4. my ajax object is stored in a generic library that I can attach to any page. The callback response is routed to a page specific object "updateRout er".

        In the past I have simply used if - else if - etc. etc. to apply the specific update to the page on the client. There can be numerous response types, some require more coding than others but over all a very inefficient way of coding.

        So, I took all the response types and placed them in an "upDate" object kind of a pseudo class where I can make a direct call to each update without having to pass over all the others in the process, as for example if I wanted to access the last of the "if else".

        Now that just leaves me with the actual router which will call the specific update I need to apply. This gets back to my original question. I could use the same "if else" construct or use a switch statement. But what I really want is to make the call to the specific update method in my pseudo "update" class.

        The following is an example of this
        Code:
        function mapDataClass()
        {
          this.getjobLocation = function (callBack){
            do some stuff....
          }
        
          this.showAddrss = function (callBack){
            do some stuff....
          }
        }
        var mdo = new mapDataClass;
        
        var updateRouter = function(which_method_To_Call, callBack_data){
          //this would work
          switch(which_method_To_Call)
          {
           case "getjobLocation":
            mdo.getjobLocation(callBack_data);
            break;
           case "showAddrss":
            mdo.showAddrss(callBack_data);
            break;
          }
        }
        The question here is how to make the call directly without the switch. And as I understand it "eval()" is not a safe alternative as that leaves me open to injection.

        Hopefully the explanation gives enough overview to generate some ideas?

        Comment

        • Dormilich
          Recognized Expert Expert
          • Aug 2008
          • 8694

          #5
          The question here is how to make the call directly without the switch. And as I understand it "eval()" is not a safe alternative as that leaves me open to injection.
          if there is no such method, eval() would fail nonetheless.

          of course you can always use feature detection:
          Code:
          if (typeof obj[method_name] === "function") {
              obj[method_name](parameters);
          }

          The suggestion did not work. It simply returned an error "not a function"
          well, I said it to be somewhat unreliable.


          but I still don’t see why attaching the appropriate method to the resective event wouldn’t work.

          Comment

          • Claus Mygind
            Contributor
            • Mar 2008
            • 571

            #6
            eval() is a function. However it is still not a good option.
            W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.


            As I tried to explain above. I do not advance to "update" until I have returned from my ajax call.

            If I were to add it directly to the eventListner for the button, I would have to set a time out and not execute until the information was returned from the server.

            I choose to branch after I get a response from the ajax call.

            Here is a simplified example of the response branch.
            Code:
            request.onreadystatechange = function chkStateChange(){
             if (request.readyState == 4) {
               if (request.status == 200) {
                 goToUpdate(request.responseText, formObj);
               }
             }
            The method to call in the update has to be contained either in the responseText or in the formObj;

            Comment

            • Claus Mygind
              Contributor
              • Mar 2008
              • 571

              #7
              I can do this
              Code:
               mdo['doThisMethod'](param1);
              but this does not work
              Code:
              var makeThisCall = "doThisMethod";
              mdo[makeThisCall](param1);

              Comment

              • Dormilich
                Recognized Expert Expert
                • Aug 2008
                • 8694

                #8
                but this does not work
                Code:
                var makeThisCall = "doThisMethod";
                mdo[makeThisCall](param1);
                strange, it works for me (FF 26).

                Comment

                • Rabbit
                  Recognized Expert MVP
                  • Jan 2007
                  • 12517

                  #9
                  Are you referring to something like this?
                  Code:
                  <!DOCTYPE html>
                  <html>
                  <head>
                  <script>
                  function mapDataClass() 
                  { 
                    this.a = function (callBack){ 
                      alert('a');
                    } 
                    
                    this.b = function (callBack){ 
                      alert('b');
                    } 
                  } 
                  var mdo = new mapDataClass;
                  
                  function loadXMLDoc(funcToCall)
                  {
                  var xmlhttp;
                  if (window.XMLHttpRequest)
                    {// code for IE7+, Firefox, Chrome, Opera, Safari
                    xmlhttp=new XMLHttpRequest();
                    }
                  else
                    {// code for IE6, IE5
                    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
                    }
                  xmlhttp.onreadystatechange=function(funcToCall)
                    {
                    if (xmlhttp.readyState==4 && xmlhttp.status==200)
                      {
                      funcToCall();
                      }
                    }
                  xmlhttp.open("GET","ajax_info.txt",true);
                  xmlhttp.send();
                  }
                  </script>
                  </head>
                  <body>
                  
                  <div id="myDiv"><h2>Let AJAX change this text</h2></div>
                  <button type="button" onclick="loadXMLDoc(mdo.a())">a</button>
                  <button type="button" onclick="loadXMLDoc(mdo.b())">b</button>
                  
                  </body>
                  </html>

                  Comment

                  • Dormilich
                    Recognized Expert Expert
                    • Aug 2008
                    • 8694

                    #10
                    I had something like this in mind, though.

                    although some modifications are needed ...
                    Code:
                    <!DOCTYPE html>
                    <html>
                    <head>
                    <script>
                    // functions do not belong into an object constructor
                    var mdo = { 
                      // the functions are called without parameter
                      // (at least in this scenario)
                      a : function (){ 
                        alert('a');
                      } 
                      b : function (){ 
                        alert('b');
                      } 
                    };
                    
                    function loadXMLDoc(funcToCall)
                    {
                    var xmlhttp;
                    if (window.XMLHttpRequest)
                      {// code for IE7+, Firefox, Chrome, Opera, Safari
                      xmlhttp=new XMLHttpRequest();
                      }
                    else
                      {// code for IE6, IE5
                      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
                      }
                    // event handlers always pass the event (except IE before 8 (I think))
                    // therefore you need the Closure
                    xmlhttp.onreadystatechange=function()
                      {
                      if (xmlhttp.readyState==4 && xmlhttp.status==200)
                        {
                        funcToCall();
                        }
                      }
                    xmlhttp.open("GET","ajax_info.txt",true);
                    xmlhttp.send();
                    }
                    </script>
                    </head>
                    <body>
                    
                    <div id="myDiv"><h2>Let AJAX change this text</h2></div>
                    <!-- you have to pass the function itself, not its return value -->
                    <button type="button" onclick="loadXMLDoc(mdo.a)">a</button>
                    <button type="button" onclick="loadXMLDoc(mdo.b)">b</button>
                    
                    </body>
                    </html>
                    Last edited by Dormilich; Feb 3 '14, 08:54 PM.

                    Comment

                    • Claus Mygind
                      Contributor
                      • Mar 2008
                      • 571

                      #11
                      I appreciate the terrific input. I get the concept, but cannot implement it at this time because it changes the core of all my apps. So I have to stick to my current methods.

                      After a good night sleep, I was able to see that my problem came down to a typo in the code.

                      getjobLocation instead of getJobLocation. You were right Dormilich. This does work:
                      Code:
                          var makeThisCall = "doThisMethod";
                          mdo[makeThisCall](param1);
                      My router concept will work now. Thanks again Dormilich and Rabbit. It's nice to have a backup team like you guys.

                      Comment

                      Working...