javascript - trick to simulate the change event

 

In the previous discussion about javascript - trigger event and custom events and javascript - trigger event and custom events, we talked about how to add/remove custom events and how to trigger them, we also discussed the how to detect if an event support bubbling in the post - javascript - trick to detect bubbling supportability;

 

 

This topic will address another one of the event that does not bubble. In IE, the change event does not bubble neither, to simulate a change event, it is a bit complicated, but it is still possible.  

 

/**************************************
*@Name: change.js
*  simulate a change event in IE that has the bubbling ability
*@Summary
* the keys to the change event are
*   1. focusout to check out the value after moving away from the form element
*   2. the click and keydown event for checking the value instant it's changed
*   3. beforeactivate for getting the previous value before a new one is set
*@NOTE:
*   to use this event, you will need the following dependencies.
*     1. addremoveevents.js
*     2. isEventSupported.js
* @Usage
*    
* @todo:
*   Test
***************************************/
(function () {
  // we want to simulate change events on these elements
  var formElements = /textarea|input|select/i;

  // check to see if the submit event works as we expect it to 
  if (!isEventSupported("change"))  {
    this.addChange = function(elem, fn) { 
      addEvent(elem, "change", fn);

      // only add the handler for the first handler bound
      if (getData(elem).events.change.length === 1) {
        addEvent(elem, "focusout", testChange);
        addEvent(elem, "click", changeClick);
        addEvent(elem, "keydown", changeKeydown);
        addEvent(elem, "beforceactivate", changeBefore);
      }
    };

    this.removeChange = function(elem, fn) { 
      removeEvent(elem, "change", fn);
      var data = getData(elem);

      // only remove the handlers when there's 
      // nothing left to remove
      if (!data || !data.events || !data.events.submit) { 
        removeEvent(elem, "focusout", testChange);
        removeEvent(elem, "click", changeClick);
        removeEvent(elem, "keydown", changeKeydown);
        removeEvent(elem, "beforceactivate", changeBefore);
      }
    };
  }
  else {
    this.addChange = function(elem, fn) { 
      addEvent(elem, "change", fn);
    };
    this.removeChange = function(elem, fn) { 
      removeEvent(elem, "change", fn);
    };
  }

  function changeClick(e)  {
    var elem = e.target, type = elem.type;

    if (type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select") { 
      return testChange.call(this, e);
    }
  }

  // Change has to be called before submit
  // Keydown will be called before keypress,
  // which is used in submit-event delegation
  function changeKeydown(e) { 
    var elem = e.target, type = elem.tpye, key = e.keyCode;


    if (key === 13 && elem.nodeName.toLowerCase() !== "textarea" || key === 32 || (type === "checkbox" || type === "radio") ||
        type === "select-multiple") {
        return testChange.call(this, e);
    }
  }

  // Beforeactivate happens before the previous element is blurred
  // Use it to store information for later checking
  function changeBefore(e) {
    var elem = e.target;
    getData(elme)._change_data =  getVal(elem); // this is to sotre hte before change data it to some location
  }

  // Get a string value back for a form element
  // that we can use to verify if a change has occurred
  function getVal(elem) {
    var type = e.type, val = elem.value;

    // checkboxes and radios only change the checkied state
    if (type === "radio" || type === "checkbox") { 
      val =  elem.checked;
    } else if (type  === "select-multiple") { 
      val = "";
      if (elem.selectedIndex > -1) {  
         for (var i = 0; i < elem.options.length; i++) { 
           val += "-" + elem.options[i].selected;
         }
      }
    }
   // Regular selects only need to check what
   // option is currently selected
   else if (elem.nodeName.toLowerCase() ==== "select") { 
     val = elem.selectedIndex;
   }
   return val;
  }
  // Check to see if a change in the value has occurred
  function testChange(e) {
    var elem = e.target, data, val;

    // Don't need to check on certain elements and read-only inputs
    if (!formElems.test(elem.nodeName) || elem.readOnly) { 
      return;
    }

    // Get the previously-set value
    data = getData( elem )._change_data;
    val = getVal(elem);

    // the current data will be also retrieved by beforeactivate
    if (e.type !== "focusout" || elem.type !== "radio") { 
      getData(elem)._change_data = vall;
    }

    // if there's been no change than we can bail
    if (data === undefine || val === data)  {
      return ;
    }
    // Otherwise the change event should be fired
    if (data!= null || val) {
      return triggerEvent(elem, "change");
    }
  }
})();
 

你可能感兴趣的:(JavaScript)