Rosettas‎ > ‎

JavaScript


// Copyright (c) 2007 Art & Logic, Inc. All Rights Reserved.
// $Id: $

// Above: [sf02], [sf03]

// a note on the stuff inside the square brackets:
// Each of the codes inside brackets is a reference to the rule(s) in the
// Style Guide that's being illustrated, as follows:
// [sf##] - StyleGuide/SourceFiles
// [cas##] - StyleGuide/ClassesAndStructures
// [nr##] - StyleGuide/NamingRules
// [cg##] - StyleGuide/Commenting
// [fmt##] - StyleGuide/Formatting

// Throughout: [fmt01]; all indentation done with space characters (0x20),
// three spaces per logical tab stop.

// [nr21] C/C++ guard to prevent recursive inclusion of header files
// !!! Javascript - no preprocessor syntax !!!

// [sf05]
// !!! Javascript - no specific include syntax !!!

// [nr25] the 'q' prefix indicates that we are controlling conditional
// !!! Javascript - no precompilation macros !!!

// [sf07], only one class declared/defined in this source file.

// [cg02], comments useful to programmers who will use (but not necessarily
// maintain) this class are separated out into the header file, not in the
// implementation file.
/**
 * ARosetta
 * Simple, but meaningless class to demonstrate Art & Logic programming
 * style conventions as they are applied to the various programming languages
 * we use. In several places, you're asked to imagine a block of useful code
 * to avoid distracting you from the issues of formatting (etc) that are being
 * demonstrated.
 *
 * As you've already seen above, the thing about to be shown in this file is
 * called out in comments using the A&L-style markup '!!!'
 */
   // [nr11], [nr18] class names prefixed with "A"
   // !!! Javascript - Objects are declared using the Constructor function syntax !!!

   // [cas01] public member functions/methods listed first
   // !!! Javascript - Should be listed after Constructor function for clarity !!!

   // [nr08] new non-class types (enumerations, data structures, etc) are
   // named with MixedCase and no special prefix
   // !!! Javascript - No such syntax beyond functions !!!

   /**
    * Construct and initialize the Rosetta object.
    * \param fileName The file to use as our data source
    */
   function ARosetta(fileName)
   {
      // [cas01] Protected member functions declared after public
      // !!! Javascript - Privileged functions are declared in JS using
      // 'this' keyword to assign function to member !!!

      // protected:
      /**
       * [nr03] parameters passed to functions are named using lowerCamelCase
       */
      this.Test = function(firstVal, secondVal)
      {
         var retval = true;
         // [fmt07] -- if/else formatting
         if (firstVal < secondVal)
         {
            // [cg06] -- use '$$$' as a marker to indicate a request that the
            // following block of code be reviewed before a change is considered
            // complete
            // $$$ before
            // this->Process(secondVal);
            // $$$ after
            // Shouldn't this be processing the first value in this case?
            this.Process(firstVal);
            // $$$ end
         }
         else if (secondVal > kSomeConstant)
         {
            this.Process(secondVal);
         }
         else
         {
            // [fmt18] -- use curly braces even in cases where the language doesn't
            // require it to prevent maintenance errors.
            retval = false;
         }
      }

      // [cas01]  Private member function declared after protected
      // !!! Javascript - Private members functions are private to the constructor function through Closures !!!
      // private:

      /**
       * Useful function to process something or other.
       */
      function Process(val)
      {
         // [cg05] -- use '!!!' as a marker to indicate a section of code that
         // requires attention
         // !!!... removing old hardcoded value
         // fProcessResult = 131;
         // ...!!!
         var result = val;
         while (--val)
         {
            result *= val;
         }
         fProcessResult = result;
      }

      /**
       * Demonstrating the formatting of a switch statement.
       */
      function Decide(midiEventType)
      {
         // [fmt11] -- switch/case formatting.
         switch (midiEventType)
         {
            // comments precede the case
            case kNoteOn:
            this.NoteOn(now);
            if (duration > 0)
            {
               this.NoteOff(now + duration);
            }
            break;

            case kNoteOff:
            this.NoteOff(now);
            break;

            case  kPolyAfter:
            after = channelValue;
            // [fmt35] include, but comment out the break when falling through intentionally.
            // break;

            case kChannelAfter:
            this.AfterTouch(after);
            break;

            // [fmt36] no need to include a commented out break when falling through an empty case
            case kPitchbend:
                              // blank line...

            // [fmt12] -- switch statements should always have a default case.
            default:
            ASSERT(false);
            this.LogError("Unsupported event type!");
            break;
         }

      }

      // [cas02] member variables declared in the same order: public
      // (avoid in most languages), protected, private.
      // !!! Javascript - Public member variables must be declared OUTSIDE of constructor function !!!

      // protected:
      // !!! Javascript - Use this keyword with identifier to declare variable !!!

      // private:

      // [nr04], [nr19] Member variables are prefixed with a lowercase 'f', followed
      // by an  uppercase letter.

      // [fmt28] -- when declaring pointer variables, attach the '*' to the
      // typename, not the variable name.
      // !!! Javascript - no pointer syntax !!!
      var fInputFile = new (fFilename);

      // !!! Javascript - To declare a member variable, you should always assign a value or null !!!
      var fProcessResult = 0;
   }

   // !!! Javascript - Public methods associated with the ARosetta object prototype !!! //

   /**
    * [nr07] Member functions are named using CamelCase, with a leading upper case
    *     letter.
    */
   ARosetta.prototype.MemberFunctionWithMultipleWords = function()
   {
      var ok = true;
      // [fmt08] -- formatting  of a for() loop.
      for (var i = 0; i < kSomeConstant; ++i)
      {
         for (var j = 0; j < kSomeOtherConstant; ++j)
         {
// [fmt02] -- preprocessor directives go in column zero.
// !!! Javascript - No preprocessor syntax !!!

            // [nr07] -- Calls to member functions of the current object are
            // made through an explicit this-> pointer.
            // !!! Javascript - no pointer syntax, everything is by reference e.g this.member
            ok = this.Test(i, j);
            if (!ok)
            {
               alert("Fatal error testing: " + i + ", " + j );
               // goto CleanUp;
               // !!! Javascript - no labels, use break !!!
               break;
            }
         }
      }

      // [fmt19]
      if (ok)
      {
         return true;
      }
      else
      {
         return false;
      }
// [fmt02] -- labels used as the target of a goto are placed in column zero.
//   CleanUp:
// cleanup code here...
// !!! Javascript - no labels

   }

   /**
    * !!! Here's how we handle very long lines (i.e., longer than 79
    * characters)
    */
   ARosetta.prototype.LongLineWrapping = function()
   {
      // [fmt03] -- source lines should be less than 80 characters long.
      // [fmt04] -- break lines at the most logical point
//       1         2         3         4         5         6         7
//34567890123456789012345678901234567890123456789012345678901234567890123456789
      var retval = FunctionWithManyArguments(longArgumentName1, longArgumentName2,
       longArgumentName3, longArgumentName4);


      // alternative format #1
      retval = FunctionWithManyArguments(longArgumentName1,
       longArgumentName2,
       longArgumentName3,
       longArgumentName4);

      // alternative format #2
      retval = FunctionWithManyArguments(
       longArgumentName1,
       longArgumentName2,
       longArgumentName3,
       longArgumentName4);

      // [fmt05] -- prefer to break after a comma
      retval = anObject.SomeUsefulFunction(x.LeftMargin() + x.RightMargin(),
       x.TopMargin() + x.BottomMargin() - 1);

      // [fmt05] -- if that's not possible, break after an operator
      retval = anObject.SomeUsefulFunction(x.LeftMargin() + x.RightMargin() +
       anObject.HorizontalPadding(), x.TopMargin() + x.BottomMargin() - 1);

      return retval;
   }

   /**
    * !!! Loop formatting
    */
   ARosetta.prototype.Loops = function()
   {
      // [fmt08] -- for() loop; note the pre-incremented form of the loop control
      for (var i = 0; i < kSomeConstant; ++i)
      {
         // loop code here...
      }

      var someBoolean = true;
      // [fmt09]
      while (someBoolean)
      {
         // useful code...
      }

      // [fmt09] -- while loop with an empty body makes the emptiness explicit
      while (this.SomeFuncReturningBool())
      {
         // intentionally empty...
      }

      // [fmt10] -- do/while loop.
      // [fmt18] -- exception to the bracing rule saying that braces should
      // always be on a line by themselves
      do
      {
         // loop code here..
      } while (someBoolean);

   }

}