xref: /plugin/chordsheets/js/jtab.js (revision f54a007ee3d4a53d8d906316e58939838bd52897)
1/**
2 * JTab - Javascript/CSS Guitar Chord and Tab Notation for the Web.
3 * Version 1.3.1
4 * Written by Paul Gallagher (http://tardate.com), 2009. (original version and maintainer)
5 * Contributions:
6 *   Jason Ong (https://github.com/jasonong)
7 *   Bruno Bornsztein (https://github.com/bborn)
8 *   Binary Bit LAN (https://github.com/binarybitlan)
9 * See:
10 *   http://jtab.tardate.com : more information on availability, configuration and use.
11 *   http://github.com/tardate/jtab/tree/master : source code repository, wiki, documentation
12 *
13 * This library also depends on the following two libraries that must be loaded for it to work:
14 *   jQuery - http://www.jquery.com/
15 *   Raphael - http://raphaeljs.com/
16 *
17 *
18 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General
19 * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option)
20 * any later version.
21 *
22 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
23 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
24 * details.
25 *
26 * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to
27 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30//
31// define the jtab class
32//
33
34var jtab = {
35    Version : '1.3.1',
36    element_count:0, //TODO:
37    Strings : {
38        AboutDialog : '<html><head><title>About jTab</title></head><body style=""><p style="">jTab version: {V}</p><p><a href="http://jtab.tardate.com" target="_blank">http://jtab.tardate.com</a></p><p><input type="button" class="close" value="OK" onClick="window.close()"/></p></body></html>'
39    },
40    Chords : {
41               // chord data - currently explicit representation for 6 string guitar, standard tuning only, and
42               // each chord is an array of alternate positions
43               //   0   : 1st (open) position
44               //   1   : 1st barre position, generally at 12/13/14th fret
45               //         - minimum, only required for CAGED chords where open strings are used in the 1st (open) position
46               //           since the main purpose of this is to provide barre fingering positions for CAGED-based chords
47               //   2.. : alternative positions/fingerings
48               // each position is an array comprising: 1. base fret (0==nut); 2. 6x note definitions (strings 6,5,4,3,2,1)
49               // each note is an array: (fret position), (left hand fingering if applicable 1,2,3,4,T)
50               // fret position: -1 = muted/not played; 0 = open; 1,2,3... = fret position
51      C       : [ [ 0, [-1 ],  [3,3],  [2,2],  [0  ],  [1,1],  [0  ] ], [ 12, [-1,-1],  [15,4],  [14,3],  [12,1],  [13,2],  [12,1 ] ] ],
52      Cm      : [ [ 0, [-1 ],  [3,4],  [1,2],  [0  ],  [1,1],  [-1 ] ], [ 12, [-1,-1],  [15,4],  [13,3],  [12,1],  [13,2],  [-1,-1] ] ],
53      C6      : [ [ 0, [-1 ],  [0  ],  [2,2],  [2,3],  [1,1],  [3,4] ], [ 12, [-1,-1],  [12,1],  [14,3],  [14,3],  [13,2],  [15,4] ] ],
54      Cm6     : [ [ 0, [-1 ],  [-1 ],  [1,1],  [2,3],  [1,2],  [3,4] ], [  ] ],
55      C69     : [ [ 0, [-1 ],  [3,2],  [2,1],  [2,1],  [3,3],  [3,4] ], [  ] ],
56      C7      : [ [ 0, [-1 ],  [3,3],  [2,2],  [3,4],  [1,1],  [0  ] ], [ 12, [-1,-1],  [15,3],  [14,2],  [15,4],  [13,1],  [12,  ] ] ],
57      Cm7     : [ [ 0, [-1 ],  [-1 ],  [1,1],  [3,3],  [1,1],  [3,4] ], [  ] ],
58      Cmaj7   : [ [ 0, [-1 ],  [3,3],  [2,2],  [0  ],  [0  ],  [0  ] ], [ 12, [-1,-1],  [15,4],  [14,3],  [12,1],  [12,1],  [12,1] ] ],
59      C7b5    : [ [ 2, [-1 ],  [3,1],  [4,3],  [3,2],  [5,4],  [-1 ] ], [  ] ],
60      "C7#5"  : [ [ 0, [-1 ],  [-1 ],  [2,2],  [3,3],  [1,1],  [4,4] ], [  ] ],
61      "Cm7b5" : [ [ 0, [-1 ],  [3,1],  [4,3],  [3,2],  [4,4],  [-1 ] ], [  ] ],
62      C7b9    : [ [ 0, [-1 ],  [3,3],  [2,1],  [3,4],  [2,2],  [0  ] ], [  ] ],
63      C9      : [ [ 0, [-1 ],  [3,2],  [2,1],  [3,3],  [3,4],  [-1 ] ], [  ] ],
64      Cm9     : [ [ 0, [-1 ],  [3,2],  [1,1],  [3,3],  [3,3],  [3,3] ], [  ] ],
65      Cmaj9   : [ [ 0, [-1 ],  [3,3],  [0  ],  [0  ],  [0  ],  [0  ] ], [ 12, [-1 ],  [15,3],  [12,1],  [12,1],  [12,1],  [12,1] ] ],
66      Cadd9   : [ [ 0, [-1 ],  [3,2],  [2,1],  [0  ],  [3,3],  [0  ] ], [ 12, [-1 ],  [15,3],  [14,2],  [12,1],  [15,4],  [12,1] ] ],
67      C13     : [ [ 2, [-1 ],  [3,1],  [5,2],  [3,1],  [5,3],  [5,4] ], [  ] ],
68      Csus2   : [ [ 2, [ -1],  [3,1],  [5,3],  [5,4],  [3,1],  [3,1] ], [  ] ],
69      Csus4   : [ [ 2, [ -1],  [3,1],  [5,2],  [5,3],  [6,4],  [3,1] ], [  ] ],
70      Cdim    : [ [ 0, [-1 ],  [3,3],  [4,4],  [2,2],  [1,1],  [-1 ] ], [  ] ],
71      Cdim7   : [ [ 0, [-1 ],  [-1 ],  [1,1],  [2,3],  [1,2],  [2,4] ], [  ] ],
72      Caug    : [ [ 0, [-1 ],  [-1 ],  [2,2],  [1,1],  [1,1],  [4,4] ], [  ] ],
73
74      "C#"    : [ [ 0, [-1 ],  [4,4],  [3,4],  [1,1],  [2,2],  [1,1] ], [  ] ],
75      "C#m"   : [ [ 0, [-1 ],  [-1 ],  [2,2],  [1,1],  [2,3],  [0  ] ], [  ] ],
76      "C#6"   : [ [ 0, [-1 ],  [-1 ],  [3,2],  [3,3],  [2,1],  [4,4] ], [  ] ],
77      "C#m6"  : [ [ 0, [-1 ],  [4,3],  [2,1],  [3,2],  [2,1],  [4,4] ], [  ] ],
78      "C#69"  : [ [ 2, [-1 ],  [4,2],  [3,1],  [3,1],  [4,3],  [4,4] ], [  ] ],
79      "C#7"   : [ [ 0, [-1 ],  [-1 ],  [3,2],  [4,3],  [2,1],  [4,4] ], [  ] ],
80      "C#m7"  : [ [ 0, [-1 ],  [-1 ],  [2,1],  [4,3],  [2,1],  [4,4] ], [  ] ],
81      "C#maj7": [ [ 0, [-1 ],  [4,4],  [3,3],  [1,1],  [1,1],  [1,1] ], [  ] ],
82      "C#7b5" : [ [ 0, [3,2],  [0  ],  [3,3],  [4,4],  [2,1],  [-1 ] ], [  ] ],
83      "C#7#5" : [ [ 0, [-1 ],  [4,3],  [3,2],  [2,1],  [0  ],  [-1 ] ], [  ] ],
84      "C#m7b5": [ [ 0, [-1 ],  [2,1],  [2,2],  [0  ],  [2,3],  [0  ] ], [  ] ],
85      "C#7b9" : [ [ 0, [-1 ],  [4,2],  [3,1],  [4,3],  [3,1],  [4,4] ], [  ] ],
86      "C#9"   : [ [ 3, [-1 ],  [4,1],  [6,2],  [6,3],  [4,1],  [4,1] ], [  ] ],
87      "C#m9"  : [ [ 0, [0  ],  [2,2],  [1,1],  [1,1],  [2,3],  [0  ] ], [  ] ],
88      "C#maj9": [ [ 0, [-1 ],  [4,4],  [1,1],  [1,1],  [1,1],  [1,1] ], [  ] ],
89      "C#add9": [ [ 0, [1,1],  [-1 ],  [1,1],  [1,1],  [2,2],  [1,1] ], [  ] ],
90      "C#13"  : [ [ 3, [-1 ],  [4,1],  [6,2],  [4,1],  [6,3],  [6,4] ], [  ] ],
91      "C#sus2": [ [ 0, [-1 ],  [-1 ],  [3,3],  [3,4],  [1,1],  [1,1] ], [  ] ],
92      "C#sus4": [ [ 0, [-1 ],  [-1 ],  [3,2],  [3,3],  [4,4],  [1,1] ], [  ] ],
93      "C#dim" : [ [ 0, [-1 ],  [-1 ],  [2,1],  [3,3],  [2,2],  [3,4] ], [  ] ],
94      "C#dim7": [ [ 0, [-1 ],  [-1 ],  [2,1],  [3,3],  [2,2],  [3,4] ], [  ] ],
95      "C#aug" : [ [ 0, [-1 ],  [4,4],  [3,3],  [2,1],  [2,2],  [-1 ] ], [  ] ],
96
97
98      D      : [ [ 0, [-1 ],  [0  ],  [0  ],  [2,1],  [3,3],  [2,2] ], [ 12, [-1,-1],  [12,1],  [12,1],  [14,3],  [15,4],  [14,2] ] ],
99      Dm     : [ [ 0, [-1 ],  [0  ],  [0  ],  [2,2],  [3,3],  [1,1] ], [ 12, [-1,-1],  [12,1],  [12,1],  [14,3],  [15,4],  [13,2] ] ],
100      D6     : [ [ 0, [-1 ],  [0  ],  [0  ],  [2,2],  [0  ],  [2,3] ], [ 12, [-1,-1],  [12,1],  [12,1],  [14,3],  [12,1],  [14,4] ] ],
101      Dm6    : [ [ 0, [-1 ],  [2,2],  [0  ],  [2,3],  [0  ],  [1,1] ], [ 12, [-1,-1],  [14,3],  [12,1],  [14,4],  [12,1],  [1,2] ] ],
102      D69    : [ [ 3, [-1 ],  [5,2],  [4,1],  [4,1],  [5,3],  [5,4] ], [  ] ],
103      D7     : [ [ 0, [-1 ],  [0  ],  [0  ],  [2,2],  [1,1],  [2,3] ], [ 12, [-1,-1],  [12,1],  [12,1],  [14,3],  [13,2],  [14,4] ] ],
104      Dm7    : [ [ 0, [-1 ],  [-1 ],  [0  ],  [2,2],  [1,1],  [1,1] ], [ 12, [-1,-1],  [-1,-1], [12,1],  [14,4],  [13,2],  [13,3] ] ],
105      Dmaj7  : [ [ 0, [-1 ],  [5,4],  [4,3],  [2,1],  [2,1],  [2,1] ], [  ] ],
106      D7b5   : [ [ 4, [-1 ],  [5,1],  [6,3],  [5,2],  [7,4],  [-1 ] ], [  ] ],
107      "D7#5" : [ [ 0, [-1 ],  [-1 ],  [0  ],  [4,3],  [1,1],  [2,2] ], [ 12, [-1,-1],  [-1,-1], [12,1],  [16,4],  [13,2],  [14,3] ] ],
108      Dm7b5  : [ [ 0, [-1 ],  [-1 ],  [0  ],  [1,1],  [1,1],  [1,1] ], [ 12, [-1,-1],  [-1,-1], [12,1],  [12,2],  [12,3],  [12,4] ] ],
109      D7b9   : [ [ 3, [-1 ],  [5,2],  [4,1],  [5,3],  [4,1],  [5,4] ], [  ] ],
110      D9     : [ [ 0, [2,2],  [-1 ],  [0  ],  [2,3],  [1,1],  [0  ] ], [ 12, [14,4 ],  [-1,-1],  [12,1],  [14,3],  [13,2],  [12,1] ] ],
111      Dm9    : [ [ 0, [-1 ],  [-1 ],  [3,3],  [2,2],  [1,1],  [0  ] ], [ 12, [-1,-1],  [-1,-1],  [15,4],  [14,3],  [13,2],  [12,1] ] ],
112      Dmaj9  : [ [ 0, [-1 ],  [5,4],  [2,1],  [2,1],  [2,1],  [2,1] ], [  ] ],
113      Dadd9  : [ [ 0, [-1 ],  [-1 ],  [0  ],  [2,1],  [3,2],  [0  ] ], [ 12, [-1,-1],  [-1,-1],  [12,1],  [14,3],  [15,4],  [12,1] ] ],
114      D13    : [ [ 4, [-1 ],  [5,1],  [7,2],  [5,1],  [7,3],  [7,4] ], [  ] ],
115      Dsus2  : [ [ 0, [-1 ],  [-1 ],  [0  ],  [2,1],  [3,3],  [0  ] ], [ 12, [-1,-1],  [-1,-1],  [12,1],  [14,3],  [15,4],  [12,1] ] ],
116      Dsus4  : [ [ 0, [-1 ],  [-1 ],  [0  ],  [2,1],  [3,3],  [3,4] ], [ 12, [-1,-1],  [-1,-1],  [12,1],  [14,2],  [15,3],  [15,4] ] ],
117      Ddim   : [ [ 0, [-1 ],  [-1 ],  [0  ],  [1,1],  [0  ],  [1,2] ], [ 12, [-1,-1],  [-1,-1],  [12,1],  [13,2],  [12,1],  [13,3] ] ],
118      Ddim7  : [ [ 0, [-1 ],  [2,3],  [0  ],  [1,1],  [0  ],  [1,2] ], [ 12, [-1,-1],  [14,4],  [12,1],  [13,2],  [12,1],  [13,3] ] ],
119      Daug   : [ [ 0, [-1 ],  [-1 ],  [0  ],  [3,2],  [3,3],  [2,1] ], [ 12, [-1,-1],  [-1,-1],  [12,1],  [15,3],  [15,4],  [14,2] ] ],
120
121      "Eb"    : [ [ 0, [-1 ],  [-1 ],  [5,4],  [3,1],  [4,3],  [3,2] ], [  ] ],
122      "Ebm"   : [ [ 0, [-1 ],  [-1 ],  [4,3],  [3,2],  [4,4],  [2,1] ], [  ] ],
123      "Eb6"   : [ [ 0, [-1 ],  [3,1],  [5,3],  [3,1],  [4,2],  [3,1] ], [  ] ],
124      "Ebm6"  : [ [ 0, [-1 ],  [-1 ],  [1,1],  [3,3],  [1,1],  [2,2] ], [  ] ],
125      "Eb69"  : [ [ 0, [-1 ],  [-1 ],  [1,1],  [0  ],  [1,2],  [1,3] ], [  ] ],
126      "Eb7"   : [ [ 0, [-1 ],  [-1 ],  [1,1],  [3,3],  [2,2],  [3,4] ], [  ] ],
127      "Ebm7"  : [ [ 0, [-1 ],  [-1 ],  [1,1],  [3,4],  [2,2],  [2,3] ], [  ] ],
128      "Ebmaj7": [ [ 0, [-1 ],  [-1 ],  [1,1],  [3,2],  [3,3],  [3,4] ], [  ] ],
129      "Eb7b5" : [ [ 0, [-1 ],  [-1 ],  [1,1],  [2,2],  [2,3],  [4,4] ], [  ] ],
130      "Eb7#5" : [ [ 0, [-1 ],  [-1 ],  [1,1],  [4,4],  [2,2],  [3,3] ], [  ] ],
131      "Ebm7b5": [ [ 0, [-1 ],  [-1 ],  [1,1],  [2,2],  [2,3],  [2,4] ], [  ] ],
132      "Eb7b9" : [ [ 0, [-1 ],  [-1 ],  [1,1],  [0  ],  [2,3],  [0  ] ], [  ] ],
133      "Eb9"   : [ [ 0, [3,4],  [1,1],  [1,1],  [0  ],  [2,1],  [1,1] ], [  ] ],
134      "Ebm9"  : [ [ 0, [2,2],  [1,1],  [1,1],  [3,4],  [2,3],  [1,1] ], [  ] ],
135      "Ebmaj9": [ [ 0, [-1 ],  [-1 ],  [1,1],  [0  ],  [3,4],  [1,2] ], [  ] ],
136      "Ebadd9": [ [ 0, [3,4],  [2,2],  [2,2],  [0  ],  [-1 ],  [1,1] ], [  ] ],
137      "Eb13"  : [ [ 4, [-1 ],  [6,2],  [5,1],  [6,3],  [8,4],  [8,4] ], [  ] ],
138      "Ebsus2": [ [ 0, [1,1],  [1,1],  [1,1],  [3,3],  [-1 ],  [1,1] ], [  ] ],
139      "Ebsus4": [ [ 0, [-1 ],  [-1 ],  [1,1],  [3,3],  [4,4],  [4,4] ], [  ] ],
140      "Ebdim" : [ [ 0, [-1 ],  [-1 ],  [1,1],  [2,3],  [1,2],  [2,4] ], [  ] ],
141      "Ebdim7": [ [ 0, [-1 ],  [-1 ],  [1,1],  [2,3],  [1,2],  [2,4] ], [  ] ],
142      "Ebaug" : [ [ 0, [3,3],  [2,2],  [1,1],  [0  ],  [0  ],  [3,4] ], [  ] ],
143
144      E       : [ [ 0, [ 0 ],  [2,2],  [2,3],  [1,1],  [0  ],  [0  ] ], [ 12, [ 12,1],  [14,3],  [14,4],  [13,2],  [12,1],  [12,1] ] ],
145      Em      : [ [ 0, [ 0 ],  [2,2],  [2,3],  [0  ],  [0  ],  [0  ] ], [ 12, [ 12,1],  [14,3],  [14,4],  [12,1],  [12,1],  [12,1] ] ],
146      E6      : [ [ 0, [ 0 ],  [2,2],  [2,3],  [1,1],  [2,4],  [0  ] ], [ 12, [ 12,1],  [14,3],  [14,3],  [13,2],  [14,4],  [12,1] ] ],
147      Em6     : [ [ 0, [ 0 ],  [2,1],  [2,2],  [0  ],  [2,3],  [0  ] ], [ 12, [ 12,1],  [14,2],  [14,3],  [12,1],  [14,4],  [12,1] ] ],
148      E69     : [ [ 0, [-1 ],  [2,2],  [2,2],  [1,1],  [2,3],  [2,3] ], [  ] ],
149      E7      : [ [ 0, [ 0 ],  [2,2],  [0  ],  [1,1],  [0  ],  [0  ] ], [ 12, [ 12,1],  [14,3],  [12,1],  [13,2],  [12,1],  [12,1] ] ],
150      Em7     : [ [ 0, [ 0 ],  [2,2],  [2,3],  [0  ],  [3,4],  [0  ] ], [ 12, [ 12,1],  [14,2],  [14,3],  [12,1],  [15,4],  [12,1] ] ],
151      Emaj7   : [ [ 0, [ 0 ],  [2,3],  [1,1],  [1,2],  [0  ],  [0  ] ], [ 12, [ 12,1],  [14,4],  [13,2],  [13,3],  [12,1],  [12,1] ] ],
152      E7b5    : [ [ 0, [-1 ],  [1,1],  [0  ],  [1,2],  [3,4],  [0  ] ], [ 12, [-1,-1],  [13,2],  [12,1],  [13,3],  [15,4],  [12,1] ] ],
153      "E7#5"  : [ [ 0, [0  ],  [3,4],  [0  ],  [1,1],  [1,2],  [-1 ] ], [ 12, [ 12,1],  [15,4],  [12,1],  [13,3],  [13,2],  [-1 ] ] ],
154      Em7b5   : [ [ 0, [-1 ],  [-1 ],  [2,1],  [3,2],  [3,3],  [3,4] ], [  ] ],
155      E7b9    : [ [ 0, [0  ],  [2,3],  [0  ],  [1,1],  [0  ],  [1,2] ], [ 12, [ 12,1],  [14,4],  [12,1],  [13,3],  [12,1],  [13,2] ] ],
156      E9      : [ [ 0, [0  ],  [2,2],  [0  ],  [1,1],  [0  ],  [2,3] ], [ 12, [ 12,1],  [14,3],  [12,1],  [13,2],  [12,1],  [14,4] ] ],
157      Em9     : [ [ 0, [0  ],  [2,1],  [0  ],  [0  ],  [0  ],  [2,2] ], [ 12, [ 12,1],  [14,2],  [12,1],  [12,1],  [12,1],  [14,4] ] ],
158      Emaj9   : [ [ 0, [0  ],  [2,2],  [1,1],  [1,1],  [0  ],  [2,4] ], [ 12, [ 12,1],  [14,3],  [13,2],  [13,2],  [12,1],  [14,4] ] ],
159      Eadd9   : [ [ 0, [2,2],  [2,3],  [2,4],  [1,1],  [0  ],  [0  ] ], [ 12, [ 14,3],  [14,3],  [14,4],  [13,2],  [12,1],  [12,1] ] ],
160      E13     : [ [ 0, [0  ],  [2,2],  [0  ],  [1,1],  [2,3],  [0  ] ], [ 12, [ 12,1],  [14,3],  [12,1],  [13,2],  [14,4],  [12,1] ] ],
161      Esus2   : [ [ 0, [ -1],  [2,1],  [4,3],  [4,4],  [-1 ],  [0  ] ], [ 12, [ -1,-1],  [14,2],  [16,3],  [16,4],  [-1 ],  [12,1] ] ],
162      Esus4   : [ [ 0, [ 0 ],  [2,2],  [2,3],  [2,4],  [0  ],  [0  ] ], [ 12, [ 12,1],  [14,2],  [14,3],  [14,4],  [12,1],  [12,1] ] ],
163      Edim    : [ [ 0, [-1 ],  [1,1],  [2,2],  [3,4],  [2,3],  [-1 ] ], [  ] ],
164      Edim7   : [ [ 0, [-1 ],  [-1 ],  [2,1],  [3,3],  [2,2],  [3,4] ], [  ] ],
165      Eaug    : [ [ 0, [ 0 ],  [3,4],  [2,3],  [1,1],  [1,2],  [0  ] ], [ 12, [ 12,1],  [15,4],  [14,3],  [13,2],  [13,2],  [12,1] ] ],
166
167      F       : [ [ 0, [1,1],  [3,3],  [3,4],  [2,2],  [1,1],  [1,1] ], [  ] ],
168      Fm      : [ [ 0, [1,1],  [3,3],  [3,4],  [1,1],  [1,1],  [1,1] ], [  ] ],
169      F6      : [ [ 0, [-1 ],  [3,2],  [3,3],  [2,1],  [3,4],  [-1 ] ], [  ] ],
170      Fm6     : [ [ 0, [-1 ],  [-1 ],  [0  ],  [1,1],  [1,1],  [1,1] ], [  ] ],
171      F69     : [ [ 0, [1,1],  [0  ],  [0  ],  [0  ],  [1,2],  [1,3] ], [  ] ],
172      F7      : [ [ 0, [1,1],  [3,3],  [1,1],  [2,2],  [1,1],  [1,1] ], [  ] ],
173      Fm7     : [ [ 0, [1,1],  [3,3],  [3,4],  [1,1],  [4,4],  [1,1] ], [  ] ],
174      Fmaj7   : [ [ 0, [1,1],  [-1 ],  [2,3],  [2,4],  [1,2],  [-1 ] ], [  ] ],
175      F7b5    : [ [ 0, [1,1],  [-1 ],  [1,2],  [2,3],  [0  ],  [-1 ] ], [  ] ],
176      "F7#5"  : [ [ 0, [1,1],  [-1 ],  [1,2],  [2,3],  [2,4],  [-1 ] ], [  ] ],
177      Fm7b5   : [ [ 2, [-1 ],  [-1 ],  [3,1],  [4,2],  [4,3],  [4,4] ], [  ] ],
178      F7b9    : [ [ 0, [-1 ],  [-1 ],  [3,2],  [2,1],  [4,4],  [2,1] ], [  ] ],
179      F9      : [ [ 0, [3,3],  [0  ],  [3,4],  [2,2],  [1,1],  [1,1] ], [  ] ],
180      Fm9     : [ [ 0, [-1 ],  [-1 ],  [1,1],  [1,1],  [1,1],  [3,4] ], [  ] ],
181      Fmaj9   : [ [ 0, [0  ],  [0  ],  [3,3],  [0  ],  [1,1],  [3,4] ], [  ] ],
182      Fadd9   : [ [ 0, [-1 ],  [-1 ],  [3,3],  [2,2],  [1,1],  [3,4] ], [  ] ],
183      F13     : [ [ 0, [1,1],  [0  ],  [1,2],  [3,4],  [3,4],  [3,4] ], [  ] ],
184      Fsus2   : [ [ 0, [-1 ],  [3,3],  [3,4],  [0  ],  [1,1],  [1,1] ], [  ] ],
185      Fsus4   : [ [ 0, [1,1],  [3,2],  [3,3],  [3,4],  [1,1],  [1,1] ], [  ] ],
186      Fdim    : [ [ 0, [-1 ],  [-1 ],  [0  ],  [1,1],  [0  ],  [1,2] ], [  ] ],
187      Fdim7   : [ [ 0, [-1 ],  [2,3],  [0  ],  [1,1],  [0  ],  [1,2] ], [  ] ],
188      Faug    : [ [ 0, [1,1],  [-1 ],  [3,4],  [2,2],  [2,3],  [1,1] ], [  ] ],
189
190      "F#"    : [ [ 0, [2,1],  [4,3],  [4,4],  [3,2],  [2,1],  [2,1] ], [  ] ],
191      "F#m"   : [ [ 0, [2,1],  [4,3],  [4,4],  [2,1],  [2,1],  [2,1] ], [  ] ],
192      "F#6"   : [ [ 0, [2,1],  [4,3],  [-1 ],  [3,2],  [4,4],  [-1 ] ], [  ] ],
193      "F#m6"  : [ [ 0, [-1 ],  [-1 ],  [1,1],  [2,2],  [2,3],  [2,4] ], [  ] ],
194      "F#69"  : [ [ 0, [2,2],  [1,1],  [1,1],  [1,1],  [2,3],  [2,4] ], [  ] ],
195      "F#7"   : [ [ 0, [2,1],  [4,3],  [2,1],  [3,2],  [2,1],  [2,1] ], [  ] ],
196      "F#m7"  : [ [ 0, [2,1],  [4,3],  [4,4],  [2,1],  [5,4],  [2,1] ], [  ] ],
197      "F#maj7": [ [ 0, [2,1],  [-1 ],  [3,3],  [3,4],  [2,2],  [-1 ] ], [  ] ],
198      "F#7b5" : [ [ 0, [2,2],  [-1 ],  [2,3],  [3,4],  [1,1],  [-1 ] ], [  ] ],
199      "F#7#5" : [ [ 0, [2,2],  [-1 ],  [2,3],  [3,4],  [3,4],  [-1 ] ], [  ] ],
200      "F#m7b5": [ [ 0, [-1 ],  [-1 ],  [2,2],  [2,3],  [1,1],  [2,4] ], [  ] ],
201      "F#7b9" : [ [ 0, [2,2],  [1,1],  [2,3],  [0  ],  [2,4],  [0  ] ], [  ] ],
202      "F#9"   : [ [ 0, [2,1],  [4,3],  [2,1],  [3,2],  [2,1],  [4,4] ], [  ] ],
203      "F#m9"  : [ [ 0, [3,3],  [0  ],  [3,4],  [1,1],  [2,3],  [2,3] ], [  ] ],
204      "F#maj9": [ [ 0, [2,1],  [-1 ],  [3,2],  [3,3],  [-1 ],  [4,4] ], [  ] ],
205      "F#add9": [ [ 0, [2,2],  [1,1],  [-1 ],  [1,1],  [2,3],  [2,4] ], [  ] ],
206      "F#13"  : [ [ 0, [2,1],  [4,3],  [2,1],  [3,2],  [4,4],  [2,1] ], [  ] ],
207      "F#sus2": [ [ 0, [2,2],  [-1 ],  [-1 ],  [1,1],  [2,3],  [2,4] ], [  ] ],
208      "F#sus4": [ [ 0, [2,1],  [4,2],  [4,3],  [4,4],  [2,1],  [2,1] ], [  ] ],
209      "F#dim" : [ [ 0, [-1 ],  [-1 ],  [1,1],  [2,3],  [1,2],  [2,4] ], [  ] ],
210      "F#dim7": [ [ 0, [-1 ],  [-1 ],  [1,1],  [2,3],  [1,2],  [2,4] ], [  ] ],
211      "F#aug" : [ [ 0, [2,1],  [-1 ],  [4,4],  [3,2],  [3,3],  [2,1] ], [  ] ],
212
213      G       : [ [ 0, [3,3],  [2,2],  [0  ],  [0  ],  [0  ],  [3,4] ], [ 12, [15,3], [14,2], [12,1], [12,1], [12,1], [15,4] ] ],
214      Gm      : [ [ 0, [3,2],  [1,1],  [0  ],  [0  ],  [3,3],  [3,4] ], [ 12, [15,3], [13,2], [12,1], [12,1], [15,4], [15,4] ] ],
215      G6      : [ [ 0, [3,3],  [2,2],  [0  ],  [0  ],  [0  ],  [0  ] ], [ 12, [15,4],  [14,3],  [12,1],  [12,1],  [12,1],  [12,1] ] ],
216      Gm6     : [ [ 0, [-1 ],  [-1 ],  [2,1],  [3,3],  [3,3],  [3,3] ], [  ] ],
217      G69     : [ [ 0, [3,3],  [2,1],  [0  ],  [2,2],  [0  ],  [0  ] ], [ 12, [15,4],  [14,3],  [12,1],  [14,2],  [12,1],  [12,1] ] ],
218      G7      : [ [ 0, [3,3],  [2,2],  [0  ],  [0  ],  [0  ],  [1,1] ], [ 12, [15,4],  [14,3],  [12,1],  [12,1],  [12,1],  [13,2] ] ],
219      Gm7     : [ [ 0, [-1 ],  [1,1],  [3,3],  [0  ],  [3,4],  [-1 ] ], [ 12, [-1 ],  [13,2],  [15,3],  [12,1],  [15,4],  [-1 ] ] ],
220      Gmaj7   : [ [ 0, [3,3],  [2,2],  [0  ],  [0  ],  [0  ],  [2,1] ], [ 12, [15,3],  [14,2],  [12,1],  [12,1],  [12,1],  [14,4] ] ],
221      "G7b5"  : [ [ 0, [3,2],  [-1 ],  [3,3],  [4,4],  [2,1],  [-1 ] ], [  ], [ 4, [-1 ],  [-1 ],  [5,1],  [6,2],  [6,3],  [7,4] ] ],
222      "G7#5"  : [ [ 0, [3,1],  [-1 ],  [3,2],  [4,3],  [4,4],  [-1 ] ], [  ] ],
223      Gm7b5   : [ [ 2, [3,1],  [4,2],  [3,1],  [3,1],  [6,4],  [3,1] ], [  ] ],
224      G7b9    : [ [ 0, [3,4],  [2,3],  [0  ],  [1,1],  [0  ],  [1,2] ], [ 12, [15,4],  [14,3],  [12,1],  [13,2],  [12,1],  [13,] ] ],
225      G9      : [ [ 0, [3,3],  [-1 ],  [0  ],  [2,2],  [0  ],  [1,1] ], [ 12, [15,4],  [-1 ],  [12,1],  [14,3],  [12,1],  [13,2] ] ],
226      Gm9     : [ [ 2, [3,1],  [5,3],  [3,1],  [3,1],  [3,1],  [5,4] ], [  ] ],
227      Gmaj9   : [ [ 0, [3,3],  [-1 ],  [0  ],  [2,1],  [0  ],  [2,2] ], [ 12, [15,4],  [-1 ],  [12,1],  [14,3],  [12,1],  [14,2] ] ],
228      Gadd9   : [ [ 0, [3,2],  [0  ],  [0  ],  [0  ],  [0  ],  [3,3] ], [ 12, [15,3],  [12,1],  [12,1],  [12,1],  [12,1],  [15,4] ] ],
229      G13     : [ [ 0, [3,2],  [2,1],  [3,3],  [0  ],  [0  ],  [0  ] ], [ 12, [15,3],  [14,2],  [15,3],  [12,1],  [12,1],  [12,1] ] ],
230      Gsus2   : [ [ 0, [3,1],  [0  ],  [0  ],  [0  ],  [3,3],  [3,4] ], [ 12, [15,2],  [12,1],  [12,1],  [12,1],  [15,3],  [15,4] ] ],
231      Gsus4   : [ [ 2, [3,1],  [5,2],  [5,3],  [5,4],  [3,1],  [3,1] ], [  ] ],
232      Gdim    : [ [ 2, [-1 ],  [-1 ],  [5,2],  [6,4],  [5,3],  [3,1] ], [  ] ],
233      Gdim7   : [ [ 0, [-1 ],  [-1 ],  [2,1],  [3,3],  [2,2],  [3,4] ], [  ] ],
234      Gaug    : [ [ 0, [3,1],  [-1 ],  [5,4],  [4,2],  [4,3],  [3,1] ], [  ] ],
235
236      "G#"    : [ [ 0, [4,4],  [3,3],  [1,1],  [1,1],  [1,1],  [-1 ] ], [  ] ],
237      "G#m"   : [ [ 0, [-1 ],  [2,2],  [1,1],  [1,1],  [4,4],  [4,4] ], [  ] ],
238      "G#6"   : [ [ 0, [-1 ],  [-1 ],  [1,1],  [1,1],  [1,1],  [1,1] ], [  ] ],
239      "G#m6"  : [ [ 0, [-1 ],  [-1 ],  [1,1],  [1,2],  [0  ],  [1,3] ], [  ] ],
240      "G#69"  : [ [ 0, [4,2],  [3,1],  [3,1],  [3,1],  [4,3],  [4,4] ], [  ] ],
241      "G#7"   : [ [ 0, [-1 ],  [-1 ],  [1,1],  [1,1],  [1,1],  [2,2] ], [  ] ],
242      "G#m7"  : [ [ 3, [4,1],  [6,3],  [4,1],  [4,1],  [7,4],  [4,1] ], [  ] ],
243      "G#maj7": [ [ 0, [-1 ],  [-1 ],  [1,1],  [1,1],  [1,1],  [3,3] ], [  ] ],
244      "G#7b5" : [ [ 2, [4,2],  [-1 ],  [4,3],  [5,4],  [3,2],  [-1 ] ], [  ] ],
245      "G#7#5" : [ [ 3, [4,1],  [-1 ],  [4,2],  [5,3],  [5,4],  [-1 ] ], [  ] ],
246      "G#m7b5": [ [ 0, [4,1],  [5,2],  [4,1],  [4,1],  [7,4],  [4,1] ], [  ] ],
247      "G#7b9" : [ [ 0, [4,3],  [3,2],  [4,4],  [2,1],  [-1 ],  [-1 ] ], [  ] ],
248      "G#9"   : [ [ 0, [2,2],  [1,1],  [1,1],  [1,1],  [1,1],  [2,4] ], [  ] ],
249      "G#m9"  : [ [ 0, [2,2],  [1,1],  [1,1],  [1,1],  [0  ],  [2,4] ], [  ] ],
250      "G#maj9": [ [ 2, [4,2],  [3,1],  [5,4],  [3,1],  [4,3],  [-1 ] ], [  ] ],
251      "G#add9": [ [ 0, [-1 ],  [1,1],  [1,1],  [1,1],  [1,1],  [-1 ] ], [  ] ],
252      "G#13"  : [ [ 0, [4,3],  [3,2],  [4,4],  [1,1],  [1,1],  [1,1] ], [  ] ],
253      "G#sus2": [ [ 0, [-1 ],  [1,1],  [1,2],  [1,3],  [-1 ],  [-1 ] ], [  ] ],
254      "G#sus4": [ [ 0, [-1 ],  [-1 ],  [1,1],  [1,1],  [2,2],  [4,4] ], [  ] ],
255      "G#dim" : [ [ 0, [-1 ],  [-1 ],  [0  ],  [1,1],  [0  ],  [1,2] ], [  ] ],
256      "G#dim7": [ [ 0, [-1 ],  [-1 ],  [0  ],  [1,1],  [0  ],  [1,2] ], [  ] ],
257      "G#aug" : [ [ 0, [0,-1], [3,4],  [2,3],  [1,1],  [1,2],  [0,-1] ], [  ] ],
258
259      A       : [ [ 0, [-1],  [0  ],  [2,2],  [2,1],  [2,3],  [0  ] ], [ 12, [-1,-1], [12,1], [14,2], [14,3], [14,4], [12,1] ] ],
260      Am      : [ [ 0, [-1],  [0  ],  [2,2],  [2,3],  [1,1],  [0  ] ], [ 12, [-1,-1], [12,1], [14,3], [14,4], [13,2], [12,1] ] ],
261      A6      : [ [ 0, [-1],  [0  ],  [2,1],  [2,1],  [2,1],  [2,1] ], [ 12, [-1,-1], [12,1], [14,3], [14,3], [14,3], [14,3] ] ],
262      Am6     : [ [ 0, [-1],  [0  ],  [2,2],  [2,3],  [1,1],  [2,4] ], [ 12, [-1,-1], [12,1], [14,3], [14,3], [13,2], [14,4] ] ],
263      A69     : [ [ 3, [5,2], [4,1],  [4,1],  [4,1],  [5,3],  [5,4] ], [  ] ],
264      A7      : [ [ 0, [-1],  [0  ],  [2,2],  [0  ],  [2,3],  [0  ] ], [ 12, [-1,-1], [12,1], [14,2], [12,1], [14,3], [12,1] ] ],
265      Am7     : [ [ 0, [-1],  [0  ],  [2,2],  [0  ],  [1,1],  [0  ] ], [ 12, [-1,-1], [12,1], [14,3], [12,1], [13,2], [12,1] ] ],
266      Amaj7   : [ [ 0, [-1],  [0  ],  [2,2],  [1,1],  [2,3],  [0  ] ], [ 12, [-1,-1], [12,1], [14,3], [13,2], [14,4], [12,1] ] ],
267      A7b5    : [ [ 3, [5,2], [-1 ],  [5,3],  [6,4],  [4,1],  [-1 ] ], [  ] ],
268      "A7#5"  : [ [ 4, [5,1], [-1 ],  [5,2],  [6,3],  [6,4],  [-1 ] ], [  ] ],
269      Am7b5   : [ [ 0, [-1],  [-1 ],  [1,1],  [2,3],  [1,2],  [3,4] ], [  ] ],
270      A7b9    : [ [ 0, [-1],  [0  ],  [2,1],  [3,3],  [2,2],  [3,4] ], [ 12, [-1,-1], [12,''],  [14,1],  [15,3],  [14,2],  [15,4] ] ],
271      A9      : [ [ 0, [-1],  [0  ],  [2,1],  [4,4],  [2,2],  [3,3] ], [ 12, [-1],  [12,],  [14,1],  [16,4],  [14,2],  [15,3] ] ],
272      Am9     : [ [ 0, [-1],  [0  ],  [1,1],  [1,1],  [1,1],  [3,4] ], [ 12, [-1],  [12,1],  [13,2],  [13,2],  [13,2],  [15,4] ] ],
273      Amaj9   : [ [ 0, [-1],  [0  ],  [2,1],  [4,3],  [2,1],  [4,4] ], [ 12, [-1],  [12,  ],  [14,1],  [16,3],  [14,1],  [16,4] ] ],
274      Aadd9   : [ [ 0, [-1],  [0  ],  [2,2],  [2,3],  [0  ],  [0  ] ], [ 12, [-1],  [12,1],  [14,3],  [14,4],  [12,1],  [12,1] ] ],
275      A13     : [ [ 0, [-1],  [0  ],  [2,1],  [0  ],  [2,2],  [3,3] ], [ 12, [-1],  [12,1],  [14,2],  [12,1],  [14,3],  [15,4] ] ],
276      Asus2   : [ [ 0, [-1],  [0  ],  [2,1],  [2,2],  [0  ],  [0  ] ], [ 12, [-1],  [12,1],  [14,3],  [14,4],  [12,1],  [12,1] ] ],
277      Asus4   : [ [ 0, [-1],  [0  ],  [2,1],  [2,2],  [3,3],  [0  ] ], [ 12, [-1],  [12,1],  [14,2],  [14,3],  [15,4],  [12,1] ] ],
278      Adim    : [ [ 0, [-1],  [0  ],  [1,1],  [2,3],  [1,2],  [-1 ] ], [ 12, [-1],  [12,1],  [13,2],  [14,4],  [13,3],  [-1 ] ] ],
279      Adim7   : [ [ 0, [-1],  [-1 ],  [1,1],  [2,3],  [1,2],  [2,4] ], [  ] ],
280      Aaug    : [ [ 0, [-1],  [0  ],  [3,4],  [2,2],  [2,3],  [1,1] ], [ 12, [-1],  [12,],  [15,4],  [14,2],  [14,3],  [13,1] ] ],
281
282      "Bb"    : [ [ 0, [-1],  [1,1],  [3,3],  [3,3],  [3,3],  [1,1] ], [  ] ],
283      "Bbm"   : [ [ 0, [-1],  [1,1],  [3,3],  [3,4],  [2,2],  [1,1] ], [  ] ],
284      "Bb6"   : [ [ 0, [-1],  [1,1],  [3,3],  [3,3],  [3,3],  [3,3] ], [  ] ],
285      "Bbm6"  : [ [ 0, [-1],  [1,1],  [3,3],  [0  ],  [2,2],  [-1 ] ], [  ] ],
286      "Bb69"  : [ [ 0, [-1],  [1,1],  [0  ],  [0  ],  [1,2],  [1,3] ], [  ] ],
287      "Bb7"   : [ [ 0, [-1],  [1,1],  [3,3],  [1,1],  [4,4],  [1,1] ], [  ] ],
288      "Bbm7"  : [ [ 0, [-1],  [1,1],  [3,3],  [1,1],  [2,2],  [1,1] ], [  ] ],
289      "Bbmaj7": [ [ 0, [-1],  [1,1],  [3,3],  [2,2],  [3,4],  [1,1] ], [  ] ],
290      "Bb7b5" : [ [ 4, [6,2], [-1 ],  [6,3],  [7,4],  [5,1],  [-1 ] ], [  ] ],
291      "Bb7#5" : [ [ 5, [6,1], [-1 ],  [6,2],  [7,3],  [7,4],  [-1 ] ], [  ] ],
292      "Bbm7b5": [ [ 0, [-1],  [1,1],  [-1 ],  [1,2],  [2,3],  [-1 ] ], [  ] ],
293      "Bb7b9" : [ [ 6, [-1],  [-1 ],  [8,2],  [7,1],  [9,4],  [7,1] ], [  ] ],
294      "Bb9"   : [ [ 0, [1,1], [1,2],  [0  ],  [1,3],  [1,3],  [1,3] ], [  ] ],
295      "Bbm9"  : [ [ 5, [-1],  [-1 ],  [-1 ],  [6,1],  [6,1],  [8,4] ], [  ] ],
296      "Bbmaj9": [ [ 0, [-1],  [1,1],  [0  ],  [2,4],  [1,2],  [1,3] ], [  ] ],
297      "Bbadd9": [ [ 0, [1,1], [1,1],  [0  ],  [3,4],  [1,1],  [1,1] ], [  ] ],
298      "Bb13"  : [ [ 0, [-1 ], [1,1],  [0  ],  [1,2],  [3,4],  [3,4] ], [  ] ],
299      "Bbsus2": [ [ 0, [-1],  [1,1],  [3,3],  [3,4],  [1,1],  [1,1] ], [  ] ],
300      "Bbsus4": [ [ 0, [-1],  [1,1],  [3,2],  [3,3],  [4,4],  [1,1] ], [  ] ],
301      "Bbdim" : [ [ 0, [-1],  [1,1],  [2,2],  [3,4],  [2,3],  [-1 ] ], [  ] ],
302      "Bbdim7": [ [ 0, [-1],  [-1 ],  [2,1],  [3,3],  [2,2],  [3,4] ], [  ] ],
303      "Bbaug" : [ [ 0, [-1],  [1,1],  [4,4],  [3,2],  [3,3],  [2,1] ], [  ] ],
304
305      B       : [ [ 0, [ -1], [2,1],  [4,3],  [4,3],  [4,3],  [2,1] ], [  ] ],
306      Bm      : [ [ 0, [ -1], [2,1],  [4,3],  [4,4],  [3,2],  [2,1] ], [  ] ],
307      B6      : [ [ 0, [ -1], [2,1],  [4,3],  [4,3],  [4,3],  [4,3] ], [  ] ],
308      Bm6     : [ [ 0, [ -1], [-1 ],  [4,2],  [4,3],  [3,1],  [4,4] ], [  ] ],
309      B69     : [ [ 0, [ -1], [2,2],  [1,1],  [1,1],  [2,3],  [2,4] ], [  ] ],
310      B7      : [ [ 0, [ -1], [2,2],  [1,1],  [2,3],  [0  ],  [2,4] ], [  ] ],
311      Bm7     : [ [ 0, [ -1], [2,2],  [0  ],  [2,3],  [0  ],  [2,4] ], [  ] ],
312      Bmaj7   : [ [ 0, [ -1], [2,1],  [4,3],  [3,2],  [4,4],  [2,1] ], [  ] ],
313      B7b5    : [ [ 5, [7,2], [-1 ],  [7,3],  [8,4],  [6,1],  [-1 ] ], [  ] ],
314      "B7#5"  : [ [ 0, [ -1], [2,2],  [1,1],  [2,3],  [0  ],  [3,4] ], [  ] ],
315      "Bm7b5" : [ [ 0, [-1 ], [2,2],  [0  ],  [2,3],  [0  ],  [1,1] ], [  ] ],
316      B7b9    : [ [ 0, [ -1], [2,2],  [1,1],  [2,3],  [1,1],  [2,4] ], [  ] ],
317      B9      : [ [ 6, [7,1], [9,3],  [7,1],  [8,2],  [7,1],  [9,4] ], [  ] ],
318      Bm9     : [ [ 0, [ -1], [2,1],  [0  ],  [2,2],  [2,3],  [2,4] ], [  ] ],
319      Bmaj9   : [ [ 0, [ -1], [2,2],  [1,1],  [3,4],  [2,3],  [2,3] ], [  ] ],
320      Badd9   : [ [ 0, [ -1], [2,1],  [4,3],  [4,4],  [2,1],  [2,1] ], [  ] ],
321      B13     : [ [ 0, [-1 ], [2,2],  [1,1],  [2,3],  [0  ],  [4,4] ], [  ] ],
322      Bsus2   : [ [ 0, [ -1], [2,1],  [4,3],  [4,4],  [2,1],  [2,1] ], [  ] ],
323      Bsus4   : [ [ 0, [ -1], [2,1],  [4,2],  [4,3],  [5,4],  [2,1] ], [  ] ],
324      Bdim    : [ [ 0, [-1],  [2,1],  [3,2],  [4,4],  [3,3],  [-1 ] ], [  ] ],
325      Bdim7   : [ [ 0, [-1],  [-1 ],  [0  ],  [1,1],  [0  ],  [1,2] ], [  ] ],
326      Baug    : [ [ 0, [-1],  [2,1],  [5,4],  [4,2],  [4,3],  [3,1] ], [  ] ]
327    },
328    WesternScale: {
329      BaseNotes:  { // for each: array[ translated western scale note, caged base, base fret ]
330        'C' : [ 'C' , 'C', 0 ],
331        'C#': [ 'C#', 'C', 1 ],
332        'Db': [ 'C#', 'C', 1 ],
333        'D' : [ 'D' , 'D', 0 ],
334        'D#': [ 'Eb', 'D', 1 ],
335        'Eb': [ 'Eb', 'D', 1 ],
336        'E' : [ 'E' , 'E', 0 ],
337        'F' : [ 'F' , 'E', 1 ],
338        'F#': [ 'F#', 'E', 2 ],
339        'Gb': [ 'F#', 'E', 2 ],
340        'G' : [ 'G' , 'G', 0 ],
341        'G#': [ 'G#', 'G', 1 ],
342        'Ab': [ 'G#', 'G', 1 ],
343        'A' : [ 'A' , 'A', 0 ],
344        'A#': [ 'Bb', 'A', 1 ],
345        'Bb': [ 'Bb', 'A', 1 ],
346        'B' : [ 'B' , 'A', 2 ]
347      },
348      BaseIntervals: ['C', 'C#', 'D', 'Eb', 'E', 'F', 'F#', 'G', 'G#', 'A', 'Bb', 'B']
349    },
350    ChordList : function() {
351      var list = [];
352      for (var key in jtab.Chords) {
353        list.push( key );
354      }
355      return list;
356    },
357    /*
358     * Usage: jtab.AddChord("ChordName", Chord-Array)
359     * Example of Add: jtab.AddChord("Dsus4l", [ [ 0, [-1 ],  [-1 ],  [3,2],  [2,1],  [3,3],  [3,4] ], [ 12, [-1,-1],  [-1,-1],  [12,1],  [14,2],  [15,3],  [15,4] ] ]);
360     * Example of Update: jtab.AddChord("A", [ [ 0, [-1],  [0  ],  [2,3],  [2,2],  [2,1],  [0  ] ], [ 12, [-1,-1], [12,1], [14,2], [14,3], [14,4], [12,1] ] ]);
361     */
362    AddChord : function(chordName, chord) {
363      this.Chords[chordName] = chord;
364    }
365  };
366
367  //
368  // define Array utility functions
369  //
370
371  Array.prototype.max_chars = function() {
372    var max = this[0].length;
373    var len = this.length;
374    for (var i = 1; i < len; i++) if (this[i].length > max) max = this[i].length;
375    return max;
376  }
377
378
379  //
380  // define jtabChord class
381  // public members:
382  //  isValid        = whether valid chord defined
383  //  isCaged        = whether chord is CAGED type
384  //  isCustom       = whether chord is a custom fingering
385  //  fullChordName  = full chord name, including position e.g. D#m7:3
386  //  chordName      = chord name, without position e.g. D#m7
387  //  baseName       = translated chord name (B <-> #), without position e.g. Ebm7
388  //  rootNote       = root note e.g. D#
389  //  rootExt        = root note extension e.g. m7
390  //  cagedBaseShape = caged base shape e.g. D
391  //  cagedBaseFret  = caged base fret e.g. 0
392  //  cagedPos       = caged position e.g. 3
393  //
394
395  function jtabChord (token) {
396
397    this.scale = jtab.WesternScale;
398    this.baseNotes = this.scale.BaseNotes;
399    this.baseChords = jtab.Chords;
400    this.chordArray = null;
401    this.isValid = false;
402
403    this.fullChordName = token;
404    this.isCustom = ( this.fullChordName.match( /\%/ ) != null )
405    this.isCaged = ( this.fullChordName.match( /\:/ ) != null )
406
407    if (this.isCaged) {
408      var parts = this.fullChordName.split(':');
409      this.chordName = parts[0];
410      this.cagedPos = parts[1];
411    } else if (this.isCustom){
412      var parts = this.fullChordName.match( /\[(.+?)\]/ );
413      if(parts){
414        this.chordName = parts[1];
415      } else {
416        this.chordName = '';
417      }
418    } else {
419      this.chordName = this.fullChordName;
420      this.cagedPos = 1;
421    }
422    this.rootExt = this.chordName.replace(/^[A-G#b]{1,2}/,'');
423    this.rootNote = this.chordName.substr(0, this.chordName.length - this.rootExt.length);
424    var baseNoteInfo = this.baseNotes[this.rootNote];
425    if (baseNoteInfo) {
426      this.baseName = baseNoteInfo[0] + this.rootExt;
427      this.cagedBaseShape = baseNoteInfo[1];
428      this.cagedBaseFret = baseNoteInfo[2];
429    } else {
430      this.cagedBaseShape = '';
431      this.cagedBaseFret = 0;
432    }
433
434    if ( ( this.isCaged ) && ( this.cagedPos > 1 ) ) {
435      this.setCagedChordArray();
436    } else if (this.isCustom){
437      this.setCustomChordArray();
438    } else {
439      this.setChordArray(this.baseName);
440    }
441  }
442
443  jtabChord.prototype.setCustomChordArray = function(){
444    this.chordArray = new Array();
445    this.chordArray = this.parseCustomChordArrayFromToken();
446  };
447
448  jtabChord.prototype.parseCustomChordArrayFromToken = function() {
449    notes = this.fullChordName.replace(/(\%|\[.+\])/g, '');
450    pairs = notes.split('.');
451    if (pairs.length < 6){
452      this.isValid = false;
453      return;
454    }
455    this.isValid = true;
456
457    array = [];
458    for (var i = 0; i < pairs.length; i++){
459      pair = pairs[i].split('/')
460      if (pair[0].match(/X/)){
461        pair = [-1]
462      }
463      array.push(pair)
464    }
465
466    fingeredFrets = jQuery.grep(array, function(pair){
467      return (pair.length != 1);
468    }).map(function(pair){
469      return parseInt(pair[0]);
470      }).map(function(i){
471        if ((i != 0) || (i != -1)){
472          return i;
473        } else {
474          return null;
475        }
476      })
477
478    fingeredFrets = jQuery.grep(fingeredFrets,function(n){
479      return(n);
480    });
481
482    min = Math.min.apply( Math, fingeredFrets );
483
484    array.unshift(min-1);
485    return array;
486  };
487
488  jtabChord.prototype.setChordArray = function(chordName) { // clones chord array (position 0) from chord ref data into this object
489    this.chordArray = new Array();
490    if (this.baseChords[chordName] === undefined ) {
491      this.isValid = false;
492      return;
493    }
494    this.isValid = true;
495    var modelRef = this.baseChords[chordName][0];
496    this.chordArray[0] = modelRef[0]
497    for (var i = 1; i < modelRef.length ; i++) {
498      this.chordArray[i] = modelRef[i];    // TODO: this.chordArray[i] = modelRef[i].clone();
499    }
500  };
501
502  jtabChord.prototype.setCagedChordArray = function() {
503    if ( ! this.cagedBaseShape.match( /[CAGED]/ ) ) return;
504    var caged_index = "CAGED".indexOf(this.cagedBaseShape) + 1;
505    var fret_widths = [3,2,3,2,2];
506    var starting_fret = this.cagedBaseFret;
507
508    for (var i = 1; i < this.cagedPos ; i++) {
509      var index = (caged_index - 1) % 5;
510      caged_index  = ( caged_index >= 5) ? 1 : caged_index + 1;
511      starting_fret += fret_widths[index];
512    }
513
514    var modelChord =  "CAGED".charAt( caged_index - 1 ) + this.rootExt;
515    this.setChordArray(modelChord);
516    this.shiftChordArray(starting_fret,modelChord);
517  };
518
519  jtabChord.prototype.shiftChordArray = function(atFret,modelChord) {
520    var initFret = this.chordArray[0];
521    if (atFret != initFret) {
522      var use_caged_fingering = ( (this.isCaged) && (this.cagedPos > 0) && ( ! ( this.baseChords[modelChord][1][0] === undefined ) )  );
523
524      this.chordArray[0] = atFret - 1;
525      for (var i = 1; i < this.chordArray.length ; i++) {
526        var fret = (this.chordArray[i][0] >= 0 ) ? this.chordArray[i][0] + atFret - initFret : this.chordArray[i][0];
527        var finger = (use_caged_fingering) ? this.baseChords[modelChord][1][i][1] : this.chordArray[i][1];
528        this.chordArray[i] = [ fret ,  finger ];
529      }
530    }
531  };
532
533  Raphael.fn.tabtype = 0;  // 0 = none, 1 = tab & chord, 2 = chord, 3 = tab
534  Raphael.fn.has_chord = false;
535  Raphael.fn.has_tab = false;
536
537  Raphael.fn.debug = false;
538  Raphael.fn.scale = 1;
539  Raphael.fn.margin_top = 36;
540  Raphael.fn.margin_bottom = 10;
541  Raphael.fn.margin_left = 16;
542  Raphael.fn.margin_right = 10;
543
544  Raphael.fn.current_offset = Raphael.fn.margin_left;
545
546  Raphael.fn.string_spacing = 16;
547  Raphael.fn.strings_drawn = 6;
548  Raphael.fn.fret_spacing = 16;
549  Raphael.fn.frets_drawn = 4;
550  Raphael.fn.note_radius = 7;
551
552  Raphael.fn.fret_width = Raphael.fn.string_spacing * ( Raphael.fn.strings_drawn - 1 );
553  Raphael.fn.fret_height = Raphael.fn.fret_spacing * (Raphael.fn.frets_drawn + 0.5);
554  Raphael.fn.chord_width = Raphael.fn.margin_left + Raphael.fn.fret_width + Raphael.fn.string_spacing + Raphael.fn.margin_right;
555  Raphael.fn.chord_height = Raphael.fn.margin_top + Raphael.fn.fret_height + Raphael.fn.margin_bottom;
556
557  Raphael.fn.tab_current_string = 0; // 1,2,3,4,5,6 or 0 = not set
558  Raphael.fn.tab_margin_top = 10;
559  Raphael.fn.tab_top = Raphael.fn.chord_height + Raphael.fn.tab_margin_top;
560  Raphael.fn.tab_spacing = Raphael.fn.fret_spacing;
561  Raphael.fn.tab_height = Raphael.fn.tab_spacing * 5;
562  Raphael.fn.tab_char_width = 8;
563
564  Raphael.fn.total_height = Raphael.fn.tab_top + Raphael.fn.tab_height + Raphael.fn.margin_bottom;
565
566  Raphael.fn.color = "#000";
567  Raphael.fn.fingering_text_color = "#fff";
568  Raphael.fn.tab_text_color = "#000";
569
570
571  // debug helper - puts grid marks on the rendered image
572  Raphael.fn.debug_grid = function (width) {
573    // h ticks
574    this.path(this.svg_params(this.current_offset, 0,0,4)).attr({stroke: this.color, "stroke-width":0.2 })
575    this.path(this.svg_params(  this.current_offset + this.margin_left, 0,0,2)).attr({stroke: this.color, "stroke-width":0.2 })
576    this.path(this.svg_params(  this.current_offset + width - this.margin_right, 0,0,2)).attr({stroke: this.color, "stroke-width":0.2 })
577    // v ticks
578    if (this.tabtype == 3) {
579      this.path(this.svg_params(this.current_offset, this.tab_margin_top,2,0)).attr({stroke: this.color, "stroke-width":0.2 })
580    } else {
581      this.path(this.svg_params(this.current_offset, this.margin_top,2, 0)).attr({stroke: this.color, "stroke-width":0.2 })
582    }
583  }
584
585
586  // step the current position for drawing
587  Raphael.fn.increment_offset = function (width) {
588    w = ( width === undefined ) ? this.chord_width : width;
589    if (this.debug) this.debug_grid(w);
590    this.current_offset += w;
591    this.setSize( this.current_offset, this.total_height );
592  }
593
594  Raphael.fn.svg_params = function(x,y,l1,l2) {
595    // http://www.w3.org/TR/SVG/paths.html#PathData --helpful reading
596    var move_line_to = "m"+x+" "+y+"l"+l1+" "+l2
597    if(arguments.length == 4) return move_line_to
598  }
599
600  // draw the fretboard
601  Raphael.fn.chord_fretboard = function ( position, chord_name ) {
602    var fret_left = this.current_offset + this.margin_left;
603    // conventional fret labels
604    var fret_labels = [ '', '', '', 'III', '', 'V', '', 'VII', '', 'IX', '', '', 'XII', '', '', 'XV', '', 'XVII', '', 'XIX', '', 'XXI', '' ];
605    // alternative friendly fret labels. Currently disabled, maybe bring these back as a configurable option?
606    // var fret_labels = [ '', '1fr', '2fr', '3fr', '4fr', '5fr', '6fr', '7fr', '8fr', '9fr', '10fr', '11fr', '12fr', '13fr', '14fr', '15fr', '16fr', '17fr', '18fr', '19fr', '20fr', '21fr', '' ];
607
608    this.text( // chord name
609      fret_left + 2.5 * this.string_spacing,
610      this.margin_top - 20,
611      chord_name).attr({fill: this.tab_text_color, "font-size":"20px"});
612
613    var stroke_width = position == 0 ? 3 : 0  // nut
614    var chord_fretboard_path = this.path(this.svg_params(fret_left,this.margin_top,this.string_spacing * (this.strings_drawn - 1),0))
615          chord_fretboard_path.attr({stroke: this.color, "stroke-width":stroke_width })
616
617    for (var i = 0; i <= this.frets_drawn; i++ ) { // frets
618
619      this.path(this.svg_params(fret_left,this.margin_top + (i * this.fret_spacing),this.string_spacing * (this.strings_drawn - 1), 0))
620
621      pos = ( fret_labels[ position + i ] === undefined ) ? '' : fret_labels[ position + i ];
622
623      if ( pos.length > 0 ) { // draw fret position
624        this.text(
625            fret_left + this.fret_width + this.string_spacing * 1.0,
626            this.margin_top + ( ( i - 0.5 ) * this.fret_spacing),
627            pos).attr({stroke: this.tab_text_color, "font-size":"12px"});
628      }
629    }
630    for (var i = 0; i < this.strings_drawn; i++ ) {
631      this.path(this.svg_params(fret_left + (i * this.string_spacing),this.margin_top,0, this.fret_spacing * (this.frets_drawn + 0.5)))  // strings
632    }
633    this.tab_extend(this.chord_width); // extend the tab if present
634  }
635
636
637  // draw a stroke (/)
638  Raphael.fn.stroke = function () {
639
640    if (this.has_tab) {
641      var width = this.tab_char_width * 3;
642      // extend tab
643      this.tab_extend(width);
644      //  stroke
645      var stroke_path = this.path(this.svg_params(this.current_offset + this.tab_char_width, this.tab_top  + (3.5 * this.tab_spacing),this.tab_char_width, - 2 * this.tab_spacing))
646          stroke_path.attr({stroke: this.tab_text_color, "stroke-width":4 })
647
648      this.increment_offset(width);
649    } else if (this.has_chord) {
650      var dx = this.string_spacing;
651      var dy = 2 * this.fret_spacing;
652      this.path(this.svg_params(this.current_offset + this.margin_left,
653                           this.margin_top + this.fret_spacing + dy,dx,-dy)).attr({stroke: this.tab_text_color, "stroke-width":4 })
654
655      this.increment_offset(  this.margin_left + dx + this.margin_right );
656    }
657  }
658
659
660  // draw a bar
661  Raphael.fn.bar = function () {
662
663    if (this.has_tab) {
664      var width = this.tab_char_width * 2;
665      // extend tab
666      this.tab_extend(width);
667      var bar_stroke=this.path(this.svg_params(this.current_offset + this.tab_char_width, this.tab_top,0, this.tab_height))
668      this.increment_offset(width);
669
670    } else if (this.has_chord) {
671      var fret_left = this.current_offset + this.margin_left;
672      var bar_stroke=this.path(this.svg_params(this.current_offset + this.margin_left, this.margin_top,0, 0, this.fret_height))
673      this.increment_offset( this.margin_left + this.margin_right );
674    }
675      bar_stroke.attr({stroke: this.color, "stroke-width":1 })
676
677  }
678
679
680  // draw double bar
681  Raphael.fn.doublebar = function () {
682    if (this.has_tab) {
683      var width = this.tab_char_width + 8;
684      // extend tab
685      this.tab_extend(width);
686      //  bar
687      var path_1 = this.path(this.svg_params(this.current_offset + this.tab_char_width, this.tab_top,0, this.tab_height))
688      var path_2 = this.path(this.svg_params(this.current_offset + this.tab_char_width + 6, this.tab_top,0, this.tab_height  ))
689      this.increment_offset(width);
690
691    } else if (this.has_chord) {
692      var left = this.current_offset + this.margin_left;
693
694      var path_1 = this.path(this.svg_params(left, this.margin_top,0, this.fret_height))
695      var path_2 = this.path(this.svg_params(left + 6, this.margin_top,0, this.fret_height))
696
697      this.increment_offset( this.margin_left + 6 + this.margin_right );
698    }
699      path_1.attr({stroke: this.color, "stroke-width":1 })
700      path_2.attr({stroke: this.color, "stroke-width":4 })
701  }
702
703
704  // draw a note in a chord
705  Raphael.fn.chord_note = function (position, string_number, note) {
706    // NB: internal string_number in chords counts from low to high
707    var fret_number = note[0];
708    var fret_left = this.current_offset + this.margin_left;
709
710    if (fret_number < 0 ) {
711      // muted/not played
712      this.text(fret_left + (string_number - 1) * this.string_spacing, this.margin_top - 8, "x").attr({stroke: this.tab_text_color, "font-size":"9px"});
713    } else if (fret_number == 0 ) {
714      // open
715      this.text(fret_left + (string_number - 1) * this.string_spacing, this.margin_top - 8, "o").attr({stroke: this.tab_text_color, "font-size":"9px"});
716    } else {
717      var fret_dy = (fret_number - position - 0.5) * this.fret_spacing;
718      //var circle =
719      this.circle(
720        fret_left + (string_number - 1) * this.string_spacing,
721        this.margin_top + fret_dy, this.note_radius).attr({stroke: this.color, fill: this.color});
722      if ( ! (note[1] === undefined) ) {
723        this.text( fret_left + (string_number - 1) * this.string_spacing,
724        this.margin_top + fret_dy, note[1] ).attr({fill: this.fingering_text_color, "font-size":"12px"});
725      }
726    }
727
728    if ( this.has_tab && fret_number >= 0 ) {
729      this.draw_tab_note( (this.strings_drawn - string_number + 1), fret_number, this.margin_left + this.string_spacing * 2.5 );
730    }
731  }
732
733
734  // extend the tab drawing area
735  Raphael.fn.tab_extend = function (width) {
736    if (this.has_tab == false) return;
737    for (var i = 0; i < this.strings_drawn; i++ ) {
738      this.path(this.svg_params(this.current_offset, this.tab_top  + (i * this.tab_spacing),width, 0)).attr({stroke: this.color})
739    }
740  }
741
742
743  // start the tab
744  Raphael.fn.tab_start = function () {
745    if (this.has_tab == false) return;
746    var width = this.tab_char_width * 3;
747    //  start bar
748    this.path(this.svg_params(this.current_offset, this.tab_top,0, this.tab_height)).attr({stroke: this.color, "stroke-width":1 })
749
750    // extend tab
751    this.tab_extend(width);
752
753    //write TAB
754    this.text(this.current_offset + this.tab_char_width, this.tab_top + this.tab_spacing * 1.5, "T").attr({stroke: this.color, "font-size":"14px"});
755    this.text(this.current_offset + this.tab_char_width, this.tab_top + this.tab_spacing * 2.5, "A").attr({stroke: this.color, "font-size":"14px"});
756    this.text(this.current_offset + this.tab_char_width, this.tab_top + this.tab_spacing * 3.5, "B").attr({stroke: this.color, "font-size":"14px"});
757    this.increment_offset(width);
758
759  }
760
761
762  // draw an individual note in the tab
763  Raphael.fn.draw_tab_note = function (string_number, token, left_offset) {
764    // NB: internal string_number in tab counts from high to low
765    this.text(this.current_offset + left_offset,
766            this.tab_top + this.tab_spacing * (string_number - 1),
767            token).attr({fill: this.color, "font-size":"16px"});
768  }
769
770  // gets string number from token $[1-6|EADGBe]
771  Raphael.fn.get_string_number = function (token) {
772    var string_number = null;
773    if ( token.match( /^\$[1-6]/ ) != null ) {
774       string_number = token.substr(1,1);
775    } else if ( token.match( /^\$[EADGBe]/ ) != null ) {
776       string_number =  6 - "EADGBe".indexOf(token.substr(1,1));
777    }
778    return string_number;
779  }
780
781
782  // identify if full chord of notes specified i.e. A:1 = X02220 or C:4 = 8.10.10.9.8.8
783  // returns:
784  //   false = not a full chord representation
785  //   array = array of notes (low to high)
786  Raphael.fn.get_fullchord_notes = function (token) {
787    var rc = false;
788    if ( token.match( /[^\.xX0-9]/ ) != null ) {
789      rc = false;
790    } else {
791      if ( token.match( /\./ ) != null ) {
792         rc = token.split('.');
793      } else {
794        rc = token.split('');
795      }
796      if (rc.length != 6) rc = false;
797    }
798    return rc;
799  }
800
801
802  // draw a token on the tab
803  Raphael.fn.tab_note = function (token) {
804    if (this.has_tab == false) return;
805
806    if ( token.match( /\$/ ) != null ) { // contains a string specifier
807      if ( token.match( /\./ ) != null ) { // is a multi-string specifier
808        var parts = token.split(".");
809        var width = 2;
810        for (var i = 0; i < parts.length ; i++) { // get the max length of the multi-string specifiers
811          if ( parts[i].length > width ) width = parts[i].length;
812        }
813        width *= this.tab_char_width + 1;
814        this.tab_extend( width );
815        for (var i = 0; i < parts.length ; i++) {
816          var part = parts[i];
817          var string_number = this.get_string_number(part);
818          if (string_number != null) {
819            this.tab_current_string = string_number;
820          } else if ( this.tab_current_string > 0 )  {
821            this.draw_tab_note( this.tab_current_string, part, width * 0.5 );
822          }
823        }
824        this.increment_offset( width );
825
826      } else { // just a string setting
827        this.tab_current_string = this.get_string_number(token);
828      }
829    } else {
830      var fullchord_notes = this.get_fullchord_notes(token);
831      if ( fullchord_notes ) {
832        var max_chars = fullchord_notes.max_chars();
833        var width = this.tab_char_width * (max_chars + 2);
834        this.tab_extend( width );
835        for (var i = 0; i < fullchord_notes.length ; i++) {
836          this.draw_tab_note( 6 - i, fullchord_notes[i], width * 0.5 );
837        }
838        this.increment_offset( width );
839      } else if ( this.tab_current_string > 0 ) { // else draw literal, but only if a current string selected
840        var width = this.tab_char_width * ( token.length + 2 );
841        this.tab_extend( width );
842        this.draw_tab_note( this.tab_current_string, token, width * 0.5 );
843        this.increment_offset( width );
844      }
845    }
846  }
847
848
849  // main drawing routine entry point: to render a token - chord or tab
850  Raphael.fn.render_token = function (token) {
851
852    var c = new jtabChord(token);
853
854    if ( c.isValid ) { // draw chord
855      var chord = c.chordArray;
856      // this.chord_fretboard(chord[0], c.fullChordName );
857      this.chord_fretboard(chord[0], c.chordName );
858      for (var i = 1; i < chord.length ; i++) {
859        this.chord_note(chord[0], i, chord[i]);
860      }
861      this.increment_offset();
862
863    } else {
864      if (token == "/" ) {
865        this.stroke();
866      } else if (token == "|" ) {
867        this.bar();
868      } else if (token == "||" ) {
869        this.doublebar();
870      } else if ( this.has_tab ) {
871        this.tab_note( token );
872      }
873
874    }
875  }
876
877
878  //
879  // add jtab class methods
880  //
881
882
883  // determine nature of the token stream
884  // returns:
885  //   1 : chord and tab present
886  //   2 : chord only
887  //   3 : tab only
888  //   0 : unknown
889  jtab.characterize = function (notation) {
890    var tabtype = 0;
891
892    if(notation == undefined){
893      notation = '';
894    }
895
896    var gotCustomChord = ( notation.match( /[\%]([0-4|T|X])?/ )   != undefined );
897    var gotNormalChord = ( notation.match( /[^\$][A-G]|^[A-G]/ )  != undefined );
898    var gotTab = ( ( notation.match( /\$/ ) != null ) || ( notation.match( /[^\%][0-9|Xx|\.]{6,}/ ) != null ) );
899    var gotChord =  gotNormalChord || gotCustomChord ;
900
901    // set defaults - apply scaling here (TODO)
902    Raphael.fn.current_offset = Raphael.fn.margin_left;
903    if ( gotChord && gotTab ) { // chord and tab
904      tabtype = 1;
905      Raphael.fn.has_chord = true;
906      Raphael.fn.has_tab = true;
907      Raphael.fn.tab_top = Raphael.fn.chord_height + Raphael.fn.tab_margin_top;
908      Raphael.fn.total_height = Raphael.fn.tab_top + Raphael.fn.tab_height + Raphael.fn.margin_bottom;
909    } else if ( gotChord ) { // chord only
910      tabtype = 2;
911      Raphael.fn.has_chord = true;
912      Raphael.fn.has_tab = false;
913      Raphael.fn.tab_top = Raphael.fn.chord_height + Raphael.fn.tab_margin_top;
914      Raphael.fn.total_height = Raphael.fn.chord_height;
915    } else if ( gotTab ) { // tab only
916      tabtype = 3;
917      Raphael.fn.has_chord = false;
918      Raphael.fn.has_tab = true;
919      Raphael.fn.tab_top = Raphael.fn.tab_margin_top;
920      Raphael.fn.total_height = Raphael.fn.tab_top + Raphael.fn.tab_height + Raphael.fn.margin_bottom;
921    }
922    Raphael.fn.tabtype = tabtype;
923    return tabtype;
924  }
925
926  // utility function to get calculated style based on given element
927  jtab.getStyle = function (element, style) {
928    var value = element.css(style);
929    if(!value) {
930      if(document.defaultView) {
931        value = document.defaultView.getComputedStyle(element[0], "").getPropertyValue(style);
932      } else if(element.currentStyle) {
933        value = element.currentStyle[style];
934      }
935    }
936
937    return value;
938  }
939
940  // set color pallette for the jtab rendering
941  jtab.setPalette = function (element) {
942    var fgColor = jtab.getStyle( jQuery(element), 'color' );
943    if (!fgColor) {
944      fgColor = '#000';
945    }
946    Raphael.fn.color = fgColor;
947    Raphael.fn.tab_text_color = fgColor;
948
949    bgColor = jtab.getStyle( jQuery(element), 'background-color' );
950    if (!bgColor || (bgColor == 'transparent') || (bgColor == 'rgba(0, 0, 0, 0)')) {
951      bgColor = '#fff';
952    }
953    Raphael.fn.fingering_text_color = bgColor;
954  }
955
956  // Render the tab for a given +element+.
957  // +element+ is a DOM node
958  // +notation_text+ is the optional notation to render (if not specified, +element+ text content will be used)
959  // After rendering, the +element+ will be given the additional "rendered" class.
960  jtab.render = function (element,notation_text) {
961
962    var notation = notation_text || jQuery(element).text() || '';
963
964    var tabtype = jtab.characterize( notation );
965    if (tabtype == 0 ) return;
966
967    var rndID="builder_"+jtab.element_count++;
968
969    // add the Raphael canvas in its own DIV. this gets around an IE6 issue with not removing previous renderings
970    var canvas_holder = jQuery('<div id="'+rndID+'"></div>').css({height: Raphael.fn.total_height});
971
972    jQuery(element).html(canvas_holder);
973    jtab.setPalette(element);
974    canvas = Raphael(rndID, 80, Raphael.fn.total_height );
975    canvas.tab_start();
976
977    var tokens = notation.split(/\s/);
978    for(var i = 0; i < tokens.length; i++) {
979      canvas.render_token(tokens[i]);
980    }
981    jQuery(element).addClass('rendered');
982  }
983
984  // Render all nodes with class 'jtab'.
985  // +within_scope+ is an optional selector that will restrict rendering to only those nodes contained within.
986  jtab.renderimplicit = function(within_scope) {
987    jQuery('.jtab',within_scope).not('.rendered').each( function(name, index) { jtab.render(this); } );
988  }
989
990  // initialize jtab library.
991  // Sets up to run implicit rendering on window.onload
992  jtab.init = function() {
993    var oldonload = window.onload;
994    window.onload = function() {
995      if (typeof oldonload == 'function') oldonload();
996      jtab.renderimplicit(null);
997    }
998  }
999
1000  // bootstrap jtab when jQuery is ready
1001  jQuery(document).ready(function($) {
1002    jtab.init();
1003  });
1004