reptile7's JavaScript blog
Friday, June 08, 2007
 
An Associative Axe Array
Blog Entry #78

Back to the Script Tips #56-59 Script and the script element that composes the script's first td element. We've briefly mentioned a couple of times previously that, above and beyond the client-side and core objects we've heretofore been working with, JavaScript also allows you to create your own custom objects; today's post looks at a custom object that maps guitar chords onto their corresponding finger positions on the script's first-cell fretboard. The relevant code is loaded into the div below:

var chords = new Object( );
chords["A"] = "1;5;14;15;16";
chords["A7"] = "1;3;5;14;16";
chords["A9"] = "3;4;5;14;25;30";
chords["A13"] = "1;3;20;22;23";
chords["Am"] = "1;5;10;14;15";
chords["Am6"] = "0;1;10;14;15;17";
chords["Am7"] = "30;32;33;34";
chords["Bb"] = "7;20;21;22";
chords["B"] = "13;26;27;28";
chords["B7"] = "4;8;13;15;17";
chords["B9"] = "8;13;15;16";
chords["Bm"] = "13;22;26;27";
chords["Bm6"] = "2;4;9;13;17";
chords["Bm7"] = "2;4;13;15;17";
chords["C"] = "3;5;10;14;19";
chords["C6"] = "5;10;14;15;19";
chords["C7"] = "5;10;14;19;21";
chords["Cmaj7"] = "3;4;5;14;19";
chords["C9"] = "5;14;19;21;22";
chords["Csus4"] = "3;10;19;20";
chords["C7sus4"] = "4;19;20;21";
chords["Cdim7"] = "8;10;12;15";
chords["Cm"] = "19;28;32;33";
chords["Cm7"] = "19;21;28;32";
chords["D"] = "2;15;17;22";
chords["D6"] = "1;2;4;15;17";
chords["D7"] = "2;10;15;17";
chords["Dmaj7"] = "1;2;15;16;17";
chords["D9"] = "26;31;33;34;35";
chords["Dsus4"] = "1;2;15;22;23";
chords["D7sus4"] = "1;2;10;15;23";
chords["Ddim7"] = "2;4;9;11";
chords["Dm"] = "2;11;15;22";
chords["Dm7"] = "1;2;10;11;15";
chords["Eb9"] = "20;25;27;28;29";
chords["E"] = "0;4;5;9;13;14";
chords["E7"] = "0;2;4;5;9;13";
chords["E9"] = "0;2;9;13;17;22";
chords["E13"] = "0;2;5;9;13;16";
chords["Em"] = "0;3;4;5;13;14";
chords["Em6"] = "0;3;5;13;14;16";
chords["Em7"] = "0;3;5;13;14;22";
chords["F"] = "10;11;15;20";
chords["F5"] = "6;19";
chords["F6"] = "1;2;6;10;15";
chords["Fmaj7"] = "1;5;6;10;14;15";
chords["Fm"] = "6;9;10;11;19;20";
chords["Fm7"] = "6;8;9;10";
chords["F#"] = "12;16;17;21;25;26";
chords["F#7"] = "5;12;14;16;21";
chords["F#9"] = "7;9;12;14;16";
chords["F#m"] = "12;15;16;17;25;26";
chords["F#m7"] = "5;15;16;26";
chords["G"] = "2;3;4;13;18;23";
chords["G5"] = "24;37";
chords["G6"] = "14;18;22;27";
chords["G7"] = "2;3;4;11;13;18";
chords["Gmaj7"] = "18;22;26;27";
chords["G9"] = "4;15;18;20";
chords["G6/9"] = "14;15;22;23";
chords["Gsus4"] = "2;3;10;18;23";
chords["G7sus4"] = "3;10;18;20;23";
chords["Gdim7"] = "3;7;14;16;18";
chords["Gm"] = "2;3;7;18;22";
chords["Gm7"] = "18;20;21;22";

On the first line, we create a new instance of the core JavaScript Object object; our new Object object is given the identifier chords. The chords object is in effect an 'empty container' object that can possess whatever properties and/or methods we choose to give it. (This isn't quite true: as you can see from Netscape's Object object page, the Object object does have a small collection of predefined, relatively abstract properties and methods, none of which finds use in the Script Tips #56-59 Script.)

The next 65 lines define properties for the chords object. This code block is formulated as an associative array: an array whose elements are indexed with strings (and not with ordinal numbers). However, we could also use the more familiar objectName.propertyName=propertyValue syntax to set these properties, i.e.:

var chords = new Object( );
chords.A = "1;5;14;15;16";
chords.A7 = "1;3;5;14;16";
chords.A9 = "3;4;5;14;25;30"; // etc.

Is the chords object an Array object? I ask this question because there's no treatment at all of associative arrays in Netscape's Array object documentation*. For that matter, an associative array would seem to not quite fit Netscape's definition of an array - [a]n array is an ordered set of values associated with a single variable name - in the sense that an associative array's elements are not "ordered".
(*The "Backward Compatibility" section does hint indirectly that arrays can be indexed associatively: JavaScript 1.0. You must index an array by its ordinal number; for example myArray[0].)

On the one hand, the var chords = new Object( ); statement can be replaced with

var chords = new Array( );

without any problems. On the other hand, my attempts to use Array object methods (specifically, the join( ), pop( ), and shift( ) methods) with a subset of the chords object were singularly unsuccessful. At HTML Goodies, Array object methods are discussed in two recently posted tutorials: "JavaScript Basics Part 5" and "The JavaScript Diaries: Part 13"; in neither of these articles is an associative array used with an Array object method. (However, the former article relevantly notes that arrayObjectName.length returns 0 for an associative array.)

The script element's showChord( ) and parser( ) functions act on the strings that are assigned to the chords object's properties/elements but do not manipulate the chords object itself, and thus this is admittedly all somewhat of an academic discussion. Anyway, two more points before moving on:

(1) Chapter 7 ("Working with Objects") of the JavaScript 1.5 Core Guide outlines two other ways to create custom JavaScript objects:

(a) Via an 'object literal' syntax:

var chords = { A: "1;5;14;15;16", A7: "1;3;5;14;16", A9: "3;4;5;14;25;30", ... };

(b) Via an object constructor function methodology in which we first use a function to define an object blueprint

function chords(A, A7, A9, ...) {
this.A = A;
this.A7 = A7;
this.A9 = A9; ... }

and then use the new operator to create one or more instances of that blueprint:

var guitarChords = new chords("1;5;14;15;16", "1;3;5;14;16", "3;4;5;14;25;30", ...);

In this case, the chords collection of properties and statements that assign values to those properties can be reused by whateverChords object instances for other fretted instruments.

(2) The properties of client-side and core JavaScript objects can also be accessed via the associative array syntax, if for some reason you wanted to do that:

document["bgColor"] = "red";
document["title"] = "Welcome, Visitor";
document.write(Math["PI"]);
// The above statements execute normally on my iMac when using either MSIE or Netscape.

Recommended reference: JavaScript Kit's "JavaScript and Object Oriented Programming (OOP)" tutorial contains a useful overview of custom JavaScript objects.

The chords property values

So now we have our custom chords object and an accompanying set of guitar chord properties. But what about those property values, huh?

chords["Dm"] = "2;11;15;22";

Each property value is a string of 2-6 numbers delimited by semicolons; what do these numbers mean?

In the previous post, we coded the alternating rows of radio buttons and horizontal rules that collectively compose the first table cell's 'guitar'; in this assembly, the radio buttons are the first 42 members of the elements[ ] array/property of the guitar form. The numbers in each chords property value are the index numbers of the guitar radio button elements that are checked to give the corresponding finger positions of the chord in question:

Radio-button display of the Dm chord on the Script Tips #56-69 Script fretboard.

Recalling that each radio button column is a 'string', upon selecting a chord:
(a) When checked, the guitar.elements[0]-guitar.elements[5] radio buttons in the headstock signify open strings that are played but not fretted (e.g., the 4th (third-from-the-left) string of the Dm chord).
(b) If a given radio button column does not contain a checked radio button, then that string is not played (e.g., the 5th and 6th strings of the Dm chord).
(As to overhauling the script so that it places X's at the top of unplayed strings, well, I'm still working on that...)

Perhaps you are thinking, "Hey, I always play the 5th (A) string when I play a Dm chord"; regarding the script's chord diagrams, I myself would play additional strings for a number of these chords - I would fully barre the B chord, I would play an open 6th string for the C chord, etc. It is left to you to augment or otherwise modify the index numbers in the chords property values to suit your own chord preferences.

Joe for his part discusses the E (major) property value and its radio button display in Script Tip #57.

At this point, we have yet to detail how the script strips the semicolons out of the chords property values and then acts on those radio button index numbers. To accomplish these tasks, we turn to the script's showChord( ) and parser( ) functions, which we'll go through line by line in the next post.

reptile7

Comments: Post a Comment

<< Home

Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)