// Speed of sound calculations
//
/* wrap everything in this undefined check */
// create the main namespace for everything
var com = com || {}; // "var" does nothing if com already exists
com.YourFriendPaul = com.YourFriendPaul || {}; // make the object if needed

if( typeof com.YourFriendPaul.speedOfSound != "undefined" ){ 
   alert( "Namespace com.YourFriendPaul.speedOfSound is already defined" );
   throw new Error( "Namespace com.YourFriendPaul.speedOfSound is already defined" );
}

/* wrap everything in this undefined check */
if ( typeof com.YourFriendPaul.speedOfSound == "undefined" || null === com.YourFriendPaul.speedOfSound ) {

   com.YourFriendPaul.speedOfSound = {
   
      addListener : function( eType, elem, funcName ){
      
         var oldE, onName = "on" + eType;
         if( document.addEventListener ){
            elem.addEventListener( eType, funcName, false );
         }
         else if( document.attachEvent ){
            elem.attachEvent( onName, funcName );
         } 
         else {
            if( elem[ onName ] !== null ){
               oldE = elem[ onName ];
               elem[onName] = function(e){ oldE(e); funcName(e); };
            } else {
               elem[onName] = funcName;
            }
         }
      },

      addEventHandlers: function(){
      
         var elems = null;
         //alert( "Elems to add: " + elems.length );
         var iCount;
         var here = com.YourFriendPaul.speedOfSound;

         elems = document.getElementById( "tempForm" ).getElementsByTagName( "input" );
         
         for( iCount=0; iCount < elems.length; iCount++ ){
         
            switch( elems[ iCount ].id ){
            
               case "tempC":
                  here.addListener( "keyup", elems[ iCount ], here.updateTempC );
                  //this.addListener( "change", elems[ iCount ], here.updateTempC );
                  break;
                  
               case "tempF":
                  here.addListener( "keyup", elems[ iCount ], here.updateTempF );
                  //this.addListener( "change", elems[ iCount ], com.YourFriendPaul.speedOfSound.updateTempF );
                  break;

               case "velM":
                  here.addListener( "keyup", elems[ iCount ], here.updateSpeedM );
                  //this.addListener( "change", elems[ iCount ], com.YourFriendPaul.speedOfSound.updateSpeedM );
                  break;
                  
               case "velF":
                  here.addListener( "keyup", elems[ iCount ], here.updateSpeedF );
                  //this.addListener( "change", elems[ iCount ], com.YourFriendPaul.speedOfSound.updateSpeedF );
                  break;
                  
               case "freqH":
                  here.addListener( "keyup", elems[ iCount ], here.updateFreqH );
                  //this.addListener( "change", elems[ iCount ], com.YourFriendPaul.speedOfSound.updateFreqH );
                  break;
                  
               default:
                  //alert( "new button? " + elems[ iCount ].className + " : " + elems[ iCount ].id + " : " + elems[ iCount ].parentNode.parentNode.id );
                  break;
            }
         }
         
         document.getElementById( "freqH" ).value = 100;
         document.getElementById( "tempC" ).value = 20;
         document.getElementById( "tempF" ).value = here.ctof( 20 );
         here.updateTemp( 20 );
      },
      
      getTargetElement: function( e ){
      
         e = e || window.event;
         var target = e.target || e.srcElement;
         if ( target.nodeType == 3 ){ // defeat Safari bug
  	 	target = target.parentNode;
         }
         //e = e? e : window.event;
         //var elem = e.target ? e.target : ( e.srcElement ? e.srcElement : null );
         return target;
      
      },
      
      whereIsThis: function(){
      
         return this;
      },

      updateFreqH: function( e ){
      
         var that = com.YourFriendPaul.speedOfSound.whereIsThis();
         //var tgt = that.getTargetElement( e );
         that.updateWaveLength();
         return e;
      },
      
      updateTempF: function( e ){
      
         var that = com.YourFriendPaul.speedOfSound.whereIsThis();
         var tgt = Number( that.getTargetElement( e ).value );
         document.getElementById( "tempC" ).value = that.ftoc( tgt );
         that.updateTemp( that.ftoc( tgt ) );
         return e;
      },
      
      updateTempC: function( e ){
      
         var that = com.YourFriendPaul.speedOfSound.whereIsThis();
         var tgt = Number( that.getTargetElement( e ).value );
         document.getElementById( "tempF" ).value = that.ctof( tgt );
         that.updateTemp( tgt );
         return e;
      },

      updateSpeedM: function( e ){
      
         var that = com.YourFriendPaul.speedOfSound.whereIsThis();
         var tgt = Number( that.getTargetElement( e ).value );
         document.getElementById( "velF" ).value = that.mtof( tgt );
         that.updateSpeed( tgt );
         return e;
      },

      updateSpeedF: function( e ){
      
         var that = com.YourFriendPaul.speedOfSound.whereIsThis();
         var tgt = Number( that.getTargetElement( e ).value );
         document.getElementById( "velM" ).value = that.ftom( tgt );
         that.updateSpeed( that.ftom( tgt ) );
         return e;
      },

      ctof : function( cel ) { return cel * 9/5 + 32; },
      ftoc : function( farn ) { return ( farn - 32 ) * 5/9; },
      mtof : function( meters ) { return meters * 3.2808; },
      ftom : function( feet ) { return feet / 3.2808; },
      
      calcSpeed : function( tmp ) {
         var spd = 331 + 0.6 * tmp;
         document.getElementById( "velM" ).value = spd;
         document.getElementById( "velF" ).value = this.mtof(spd);
      },
      
      calcTemp : function( spd ) {
         var celc = (spd - 331) / 0.6;
         document.getElementById( "tempC" ).value = celc;
         document.getElementById( "tempF" ).value = this.ctof(celc);
      },
      
      // expects the temp in deg. C
      updateTemp : function( tmp ) {
         this.calcSpeed( tmp );
         this.updateWaveLength();
      },
      
      // expect the speed in m/s
      updateSpeed : function( spd ) {
         this.calcTemp( spd );
         this.updateWaveLength();
      },
      
      updateWaveLength : function() {
         var freq = document.getElementById( "freqH" ).value;
         var spd = document.getElementById( "velM" ).value;
         var wlM = spd / freq / 4;
         document.getElementById( "waveLenM" ).innerHTML = wlM.toFixed(3);
         document.getElementById( "waveLenF" ).innerHTML = this.mtof(wlM).toFixed(3);
      }      
   };
}