JavaScript/Notes/ParameterObject: Difference between revisions

From Noisebridge
Jump to navigation Jump to search
No edit summary
 
(11 intermediate revisions by 2 users not shown)
Line 3: Line 3:
The DOM event methods for creating events are an example of what not to do. My [http://lists.w3.org/Archives/Public/www-dom/2010OctDec/0188.html comments on w3c DOM mailing list] led to the current Event constructor.  
The DOM event methods for creating events are an example of what not to do. My [http://lists.w3.org/Archives/Public/www-dom/2010OctDec/0188.html comments on w3c DOM mailing list] led to the current Event constructor.  


 
=== Refactoring ===
Method <code>initTouchEvent</code> (Apple) is fine example of terrible design. Here's how to change that.
Method <code>initTouchEvent</code> (Apple) takes 18 parameter variables. It is hard to remember the order and type of each and every variable.
<source lang="javascript">
<source lang="javascript">
// Note: This code is iOS specific!
var touchEvent, canceled;
var touchEvent, canceled;


touchEvent = doc.createEvent("TouchEvent");
touchEvent = document.createEvent("TouchEvent");
if (typeof touchEvent.initTouchEvent == "function") {
if (typeof touchEvent.initTouchEvent == "function") {
   touchEvent.initTouchEvent(type, bubbles, cancelable, view,
   touchEvent.initTouchEvent(type, bubbles, cancelable, view,
Line 19: Line 20:
}
}
</source>
</source>
18 parameter variables is too many. Instead, we can pass in an object.
 
=== Pass an Object ===
It would be much easier can pass in an object that has named property values, and give some defaults for missing property values, such as <code>rotation</code>.


Like this:
Like this:
Line 25: Line 28:
Action.touchstart( document.body, {clientX: 330, clientY: 330} );
Action.touchstart( document.body, {clientX: 330, clientY: 330} );
</source>
</source>
Where <code>options</code> has a corresponding property for each argument.
Where <code>options</code> has a corresponding property for each argument for a single touch event.
 
<source lang="javascript">
touchstart : function(target, options) {
  return fireTouchEvent("touchstart", target, options);
}
</source>
<source lang="javascript">
function fireTouchEvent(type, target, options){
    var c = getTouchEventData(target, options),
    doc = target.ownerDocument || target.document || target;
    //setup default values.
 
    if (!doc || !doc.createTouch) {
        throw TypeError("simulateTouchEvent(): Invalid target.");
    }
 
    return simulateTouchEvent(doc,
            target, type, c.bubbles, c.cancelable, c.view,
            c.detail, // Not sure what this does in "touch" event.
            c.screenX, c.screenY, c.pageX, c.pageY,
            c.ctrlKey, c.altKey, c.shiftKey, c.metaKey,
            c.touches, c.targetTouches, c.changedTouches, c.scale, c.rotation);
}
</source>


== Defaults ==
<source lang="javascript">
function getTouchEventData(target, options) {
  options = options || {};
  var doc = target.ownerDocument || target.document || target;
  return {
    target        : target,
    bubbles      : ("bubbles" in options) ? !!options.bubbles : true,
    cancelable    : ("cancelable" in options) ? !!options.cancelable : true,
    view          : options.view||doc.defaultView,
    detail        : +options.detail||1, // Not sure what this does in "touch" event.
    screenX      : +options.screenX||0,
    screenY      : +options.screenY||0,
    pageX        : +options.pageX||0,
    pageY        : +options.pageY||0,
    ctrlKey      : ("ctrlKey" in options) ? !!options.ctrlKey : false,
    altKey        :  ("altKey" in options) ? !!options.altKey : false,
    shiftKey      : ("shiftKey" in options) ? !!options.shiftKey : false,
    metaKey      : ("metaKey" in options) ? !!options.metaKey : false,
    scale        : +options.scale||1,
    rotation      : +options.rotation||0,
    touches      : createTouchList(options.touches||options),
    targetTouches : createTouchList(options.targetTouches||options),
    changedTouches: createTouchList(options.changedTouches||options)
  };
}</source>
See also [http://c2.com/cgi/wiki?TooManyParameters Too Many Parameters].
See also [http://c2.com/cgi/wiki?TooManyParameters Too Many Parameters].

Latest revision as of 19:56, 25 April 2014

Passing around lists of parameters? Typechecking arguments? Stop doing that. Here's how to make your code clearer and less error-prone.

The DOM event methods for creating events are an example of what not to do. My comments on w3c DOM mailing list led to the current Event constructor.

Refactoring

[edit | edit source]

Method initTouchEvent (Apple) takes 18 parameter variables. It is hard to remember the order and type of each and every variable. <source lang="javascript"> // Note: This code is iOS specific! var touchEvent, canceled;

touchEvent = document.createEvent("TouchEvent"); if (typeof touchEvent.initTouchEvent == "function") {

 touchEvent.initTouchEvent(type, bubbles, cancelable, view,
 detail, screenX, screenY, pageX, pageY, ctrlKey,
 altKey, shiftKey, metaKey, touches, targetTouches,
 changedTouches, scale, rotation);
   // fire the event
 canceled = target.dispatchEvent(touchEvent);

} </source>

Pass an Object

[edit | edit source]

It would be much easier can pass in an object that has named property values, and give some defaults for missing property values, such as rotation.

Like this: <source lang="javascript"> Action.touchstart( document.body, {clientX: 330, clientY: 330} ); </source> Where options has a corresponding property for each argument for a single touch event.

<source lang="javascript"> touchstart : function(target, options) {

 return fireTouchEvent("touchstart", target, options);

} </source> <source lang="javascript"> function fireTouchEvent(type, target, options){

   var c = getTouchEventData(target, options),
   doc = target.ownerDocument || target.document || target;
   //setup default values.
   if (!doc || !doc.createTouch) {
       throw TypeError("simulateTouchEvent(): Invalid target.");
   }
   return simulateTouchEvent(doc,
           target, type, c.bubbles, c.cancelable, c.view,
           c.detail, // Not sure what this does in "touch" event.
           c.screenX, c.screenY, c.pageX, c.pageY,
           c.ctrlKey, c.altKey, c.shiftKey, c.metaKey,
           c.touches, c.targetTouches, c.changedTouches, c.scale, c.rotation);

} </source>

Defaults

[edit | edit source]

<source lang="javascript"> function getTouchEventData(target, options) {

 options = options || {};
 var doc = target.ownerDocument || target.document || target;
 return {
   target        : target,
   bubbles       : ("bubbles" in options) ? !!options.bubbles : true,
   cancelable    : ("cancelable" in options) ? !!options.cancelable : true,
   view          : options.view||doc.defaultView,
   detail        : +options.detail||1, // Not sure what this does in "touch" event.
   screenX       : +options.screenX||0,
   screenY       : +options.screenY||0,
   pageX         : +options.pageX||0,
   pageY         : +options.pageY||0,
   ctrlKey       : ("ctrlKey" in options) ? !!options.ctrlKey : false,
   altKey        :  ("altKey" in options) ? !!options.altKey : false,
   shiftKey      : ("shiftKey" in options) ? !!options.shiftKey : false,
   metaKey       : ("metaKey" in options) ? !!options.metaKey : false,
   scale         : +options.scale||1,
   rotation      : +options.rotation||0,
   touches       : createTouchList(options.touches||options),
   targetTouches : createTouchList(options.targetTouches||options),
   changedTouches: createTouchList(options.changedTouches||options)
 };

}</source> See also Too Many Parameters.