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);


}


}