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 371Array.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 395function 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 443jtabChord.prototype.setCustomChordArray = function () { 444 this.chordArray = new Array(); 445 this.chordArray = this.parseCustomChordArrayFromToken(); 446}; 447 448jtabChord.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 488jtabChord.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 502jtabChord.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 519jtabChord.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 533Raphael.fn.tabtype = 0; // 0 = none, 1 = tab & chord, 2 = chord, 3 = tab 534Raphael.fn.has_chord = false; 535Raphael.fn.has_tab = false; 536 537Raphael.fn.debug = false; 538Raphael.fn.scale = 1; 539Raphael.fn.margin_top = 36; 540Raphael.fn.margin_bottom = 10; 541Raphael.fn.margin_left = 16; 542Raphael.fn.margin_right = 10; 543 544Raphael.fn.current_offset = Raphael.fn.margin_left; 545 546Raphael.fn.string_spacing = 16; 547Raphael.fn.strings_drawn = 6; 548Raphael.fn.fret_spacing = 16; 549Raphael.fn.frets_drawn = 4; 550Raphael.fn.note_radius = 7; 551 552Raphael.fn.fret_width = Raphael.fn.string_spacing * (Raphael.fn.strings_drawn - 1); 553Raphael.fn.fret_height = Raphael.fn.fret_spacing * (Raphael.fn.frets_drawn + 0.5); 554Raphael.fn.chord_width = Raphael.fn.margin_left + Raphael.fn.fret_width + Raphael.fn.string_spacing + Raphael.fn.margin_right; 555Raphael.fn.chord_height = Raphael.fn.margin_top + Raphael.fn.fret_height + Raphael.fn.margin_bottom; 556 557Raphael.fn.tab_current_string = 0; // 1,2,3,4,5,6 or 0 = not set 558Raphael.fn.tab_margin_top = 10; 559Raphael.fn.tab_top = Raphael.fn.chord_height + Raphael.fn.tab_margin_top; 560Raphael.fn.tab_spacing = Raphael.fn.fret_spacing; 561Raphael.fn.tab_height = Raphael.fn.tab_spacing * 5; 562Raphael.fn.tab_char_width = 8; 563 564Raphael.fn.total_height = Raphael.fn.tab_top + Raphael.fn.tab_height + Raphael.fn.margin_bottom; 565 566Raphael.fn.color = "#000"; 567Raphael.fn.fingering_text_color = "#fff"; 568Raphael.fn.tab_text_color = "#000"; 569 570 571// debug helper - puts grid marks on the rendered image 572Raphael.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 587Raphael.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 594Raphael.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 601Raphael.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 (/) 638Raphael.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 661Raphael.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 681Raphael.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 705Raphael.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 735Raphael.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 744Raphael.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 763Raphael.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] 771Raphael.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) 786Raphael.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 803Raphael.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 850Raphael.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 889jtab.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 927jtab.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 941jtab.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. 960jtab.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. 986jtab.renderimplicit = function (within_scope) { 987 jQuery('.jtab', within_scope).not('.rendered').each(function (name, index) { jtab.render(this); }); 988}