www.webdeveloper.com
Results 1 to 7 of 7

Thread: [RESOLVED] Everything in onsubmit handler is undefined!!!

  1. #1
    wylbur is offline Wylbur the Possum-Hearted
    Join Date
    Apr 2006
    Location
    South Texas
    Posts
    64

    resolved [RESOLVED] Everything in onsubmit handler is undefined!!!

    Hi All;

    I'm instantiating an object, then trying to use the function defined
    within the object as a submit handler for the page/form. The handler
    ("val_obj.js_onsubmit_hndl") does indeed get called, but everything
    in it is undefined - including the reference parameter to the event
    object that should be passed when onsubmit is fired.

    This is the most recent version of my code:
    -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
    <script type="text/javascript"><!--

    function the_obj_def ()
    {
    this.val1 = 3;
    alert ("this.val1 = " + this.val1);

    this.js_onsubmit_hndl
    = function onsubmit_hndl (the_event)
    {
    alert ("onsubmit: this.val1 = " + this.val1);

    if (the_event == undefined)
    alert ("the_event == undefined");
    else if (the_event == null)
    alert ("the_event == null");

    if (undefined == the_event) return;

    val1 = val1 + 1;

    alert ("val1 = " + val1);
    }
    }


    var val_obj = new the_obj_def ();

    alert ("After new object: val_obj.val1 = "
    + val_obj.val1);

    var the_form = document.forms["Form_01"];
    the_form.onsubmit = val_obj.js_onsubmit_hndl;

    // --></script>

    -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-



    Can anyone give this poor fool a clue?


    THANKS!!!

  2. #2
    Join Date
    Feb 2003
    Location
    Michigan, USA
    Posts
    5,755
    When the onsubmit runs, the scope in which the function is executed changes. This code might be easier to understand and maintain:
    Code:
    /**
     * @class   ActionControls
     * 
     * Manages user interface controls and DOM events.
     * @param   object  required  Scope in which event handler functions are executed
     * @param   object  required  [handler name].[action] functions
     * @return  void
     */
    function ActionControls(scope, eventHandlers) {
      this.scope = scope;
      this.eventHandlers = eventHandlers;
    }
    ActionControls.prototype = {
      
      /**
       * @property  object  Event handler functions
       */
      eventHandlers : null,
      
      /**
       * @property  object  Scope in which event handler functions are executed
       */
      scope : null,
      
      /**
       * Adds a user interface control.
       * @param   mixed   required  HTML tag Id or DOM node
       * @param   string  required  Event handler name, e.g. "onclick"
       * @param   string  required  Name of action performed
       * @param   array   optional  Array of arguments passed to event handler
       * @return  void
       */
      addControl : function(id, handlerName, action, args) {
        var node = (typeof(id) == "string") ? document.getElementById(id) : id;
        if ( !node ) {
          return;
        }
        if (!args) {
          args = [];
        }
        args.unshift(node);
        node[handlerName] = this.bind( this.scope, args, this.getEventHandler(handlerName, action) );
        node = null;
      },
      
      /**
       * Binds a function to a certain scope.
       * @param   object  required  Scope in which function executes
       * @param   array   optional  Array of arguments passed to bound function
       * @param   func    required  Function to be bound
       * @return  func    Function closure that executes fn when executed.
       */
      bind : function(scope, args, fn) {
        if (!args) {
          args = [];
        }
        return function(e) {
          if (!e) {
            e = window.event;
          }
          args.unshift(e);
          return fn.apply(scope, args);
        }
      },
      
      /**
       * Class destructor to prevent memory leaks.
       * @param   void
       * @return  void
       */
      destroy : function() {
        this.eventHandlers = null;
        this.scope = null;
      },
      
      /**
       * Gets an event handler function.
       * @param   string  required  Event handler name
       * @param   string  required  Action performed
       * @return  func    Function executed during an event.
       */
      getEventHandler : function(handlerName, action) {
        var fn = function() { alert(handlerName+"."+action+" is not a function."); };
        var handlerObj = this.eventHandlers[handlerName];
        
        if ( typeof(handlerObj) == "object") {
          if ( typeof(handlerObj[action]) == "function" ) {
            fn = handlerObj[action];
          } else if ( typeof(handlerObj.defaultAction) == "function" ) {
            fn = handlerObj.defaultAction;
          }
        }
        handlerObj = null;
        return fn;
      }
      
    };
    
    function ValueAdder(val1, val2)
    {
      this.val1 = val1;
      this.val2 = val2;
      this.controls = new ActionControls(this, this.eventHandlers);
    }
    ValueAdder.prototype = {
      
      controls : null,
      val1 : 0,
      val2 : 0,
      
      eventHandlers : {
        onsubmit : {
          
          calculate : function(e, el) {
            var total = this.val1 + this.val2;
            alert( "The calculated value is: " + total );
            return false;
          }
          
        }
      },
      
      addControlSubmit : function(id) {
        this.controls.addControl(id, "onsubmit", "calculate");
      }
      
    };
    
    var myAdder = new ValueAdder(3, 2);
    
    myAdder.addControlSubmit("form_id_here");
    The ActionControls class takes care of all the mess. It provides a bridge between the onsubmit event handler and the instance of the ValueAdder class. In your code, the "this" keyword in the onsubmit actually points to the <form> tag, not an instance of the "the_obj_def" class.

    I called my class "ValueAdder" instead of "the_obj_def" because, in this case, "ValueAdder" is more descriptive of what the class does.

  3. #3
    Join Date
    Feb 2003
    Location
    Michigan, USA
    Posts
    5,755

  4. #4
    wylbur is offline Wylbur the Possum-Hearted
    Join Date
    Apr 2006
    Location
    South Texas
    Posts
    64
    Hi toicontien;

    That's pretty slick, dood.

    Can you come up with a simpler way to get my onsubmit object/function
    into proper scope?


    THANKS!!!

  5. #5
    Join Date
    Feb 2003
    Location
    Michigan, USA
    Posts
    5,755
    Not really. Using the ActionControls class is about as simple as it gets. Your class definition needs a property called "controls" which is an instance of the ActionControls class. Then create a method in your class for each control you want to create. Here is a stripped down example of how to use this programming pattern:
    Code:
    function MyClass() {
      this.controls = new ActionControls(this, this.eventHandlers);
    }
    MyClass.prototype = {
      
      eventHandlers : {
        
        onclick : {
          
          cancel : function(e, el) {
            window.location = "/cancel.html";
            return false;
          }
          
        },
        
        onsubmit : {
          
          validate : function(e, el) {
            alert("Your info is valid!");
            return true;
          }
          
        }
        
      },
      
      addControlCancel : function(id) {
        this.controls.addControl(id, "onclick", "cancel");
      },
      
      addControlSubmit : function(id) {
        this.controls.addControl(id, "onsubmit", "validate");
      }
      
    };
    You don't really need to bother with exactly how the ActionControls class works. It allows you to go about solving the problem that the class is supposed to solve, rather than worry about assigning event handlers. Furthermore, it allows you to write event handler code in a more structured and maintainable way, with all event handler functions going in a class's eventHandlers property. The event handlers are then broken down further by the event handler name (e.g. "onclick", "onmouseover", etc), with the actual event handler functions inside that.

    Say 8 months from now you go back to a class you wrote utilizing this programming pattern. You need to add some functionality to an onclick of a button. You know all the event handler functions are located in the eventHandlers property. Inside that is a property called "onclick" which houses all the onclick event handlers. The button you want to change is the Cancel button, so you know you need to edit the eventHandlers.onclick.cancel function. Makes it super easy to come back to your code later and pick up where you left off, instead of sifting through many lines of code looking for where you assigned an onclick event handler.

    It also provides the client code utilizing your class an easy interface for assigning event handlers.
    Code:
    var x = new MyClass();
    
    x.addControlSubmit("form_id");
    x.addControlCancel("button_id");
    Of course, if you do want to know how the ActionControls class works, I'd be more than happy to oblige.

  6. #6
    wylbur is offline Wylbur the Possum-Hearted
    Join Date
    Apr 2006
    Location
    South Texas
    Posts
    64
    Hi toicontien;

    > Not really. Using the ActionControls class is about as simple as it gets.

    The thing that I neglected to tell you is that I'm operating under ASP.NET,
    and generating the Javascript dynamically from the server. I need for the
    script to be as short and sweet as possible.

    THIS is what I needed to know - and it put me on the right track:
    > In your code, the "this" keyword in the onsubmit actually points to
    > the <form> tag, not an instance of the "the_obj_def" class.

    THANKS!!!

    Keep in mind that - in Javascript - a person can add objects to other
    objects at any time, at any point, and for any reason. Once I realized
    what "this" is referring to, it was a simple matter to just add the submit
    object ("the_obj_def") to the form object, and then make the proper
    references within the handler accordingly.

    This is the script that worked:
    -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

    <script type="text/javascript"><!--

    function the_obj_def ()
    {
    this.val1 = 3;
    alert ("this.val1 = " + this.val1);

    this.js_onsubmit_hndl = function ()
    {
    alert ("onsubmit: this.the_submit_obj.val1 = "
    + this.the_submit_obj.val1);

    if (event == undefined)
    alert ("event == undefined");
    else if (event == null)
    alert ("event == null");

    if (undefined == event) return;

    this.the_submit_obj.val1
    = this.the_submit_obj.val1 + 8;
    alert (" onsubmit: val1 = "
    + this.the_submit_obj.val1);

    return true;
    }
    }

    //===========================================================

    var the_form = document.forms["Form_01"];
    the_form.the_submit_obj = new the_obj_def ();

    alert ("New object: the_form.the_submit_obj.val1 = "
    + the_form.the_submit_obj.val1);

    the_form.onsubmit = the_form.the_submit_obj.js_onsubmit_hndl;

    // --></script>

    -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-


    Thanks dood - I would've been lost without you!

    -Wylbur

  7. #7
    Join Date
    Feb 2003
    Location
    Michigan, USA
    Posts
    5,755

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles