1/* DOKUWIKI:include_once js/raphael.js */ 2/* DOKUWIKI:include_once js/jtab.min.js */ 3 4function ready() { 5 "use strict"; 6 runSongHighlighter(); 7} 8 9var songBlockSelector = "song-with-chords"; 10var songChordSelector = "song-chord"; 11var songSectionSelector = "song-section"; 12var songSectionHeadingSelector = "song-section-heading"; 13var chordLineSelector = "song-chordLine"; 14var songTextLineSelector = "song-textLine"; 15 16function parseSong(song, transpose) { 17 "use strict"; 18 transpose = transpose || 0; 19 20 var coloredSong = ""; 21 var currentSection = ""; 22 var chordCount = 0; 23 24 function run() { 25 addClass(song, transpose); 26 displayColoredSong(coloredSong); 27 } 28 29 function addClass(song, transpose) { 30 var text = song.innerHTML; 31 var lines = text.split(/\n/g); 32 33 try { 34 transpose = Number(transpose); 35 } catch (error) { 36 transpose = 0; 37 } 38 findChords(lines, transpose); 39 40 coloredSong += lines.join("\n"); 41 } 42 43 function findChords(lines, transpose) { 44 for (var i = 0; i < lines.length; i++) { 45 var ln = parseLine(lines[i], transpose); 46 lines[i] = ln.text; 47 } 48 if (currentSection != "") { 49 lines.push("</div>"); 50 } 51 }; 52 53 function displayColoredSong(coloredSong) { 54 song.innerHTML = coloredSong; 55 }; 56 57 function parseLine(lineText, transpose) { 58 /* ignore empty lines, will be controlled by paragraphs */ 59 if (isNullOrWhiteSpace(lineText)) { 60 return { 61 'isChord': false, 62 'isSection': false, 63 'text': "" 64 }; 65 } 66 67 var isChord = false; 68 var isSection = false; 69 70 var chordRegEx = /(?:(\s*)([a-g]{1}[b#]?(?:no|add|sus|dim|maj|min|m|13|11|9|7|6|5|4|3|2)*(?:\s*\/\s*[a-g]{1}[b#]?)?)|\s*(\().*\))/iy; 71 72 var sectionRegex = new RegExp("^\\s*(\\[(.+)\\])", "i"); 73 74 var chordRep = lineText.replace(new RegExp("[a-g]{1}[b#]?(no|add|sus|dim|maj|min|m|13|11|9|7|6|5|4|3|2)*", "gi"), ""); 75 var hasTextRegExp = new RegExp("[a-z](?![^\\(]*\\))", "i"); 76 var isChord = hasTextRegExp.test(chordRep) == false; 77 78 if (isChord) { 79 var newLine = ""; 80 var chordMatch; 81 82 while ((chordMatch = chordRegEx.exec(lineText)) != null) { 83 if (chordMatch[3] === "(") { 84 newLine += '<span style="color:black;">' + chordMatch[0] + '</span>'; 85 continue; 86 } 87 try { 88 var subchords = chordMatch[2].split("/"); 89 } catch (error) { 90 var i = 0; 91 } 92 93 for (var i2 = 0; i2 < subchords.length; i2++) { 94 var chordRootRegEx = new RegExp("([a-g]{1}[b#]?)(.*)", "i"); 95 var chordRootMatch = chordRootRegEx.exec(subchords[i2]); 96 var transposed = substChord(chordRootMatch[1], transpose); 97 subchords[i2] = transposed + chordRootMatch[2] || ""; 98 } 99 var newChord = subchords.join("/"); 100 newLine += chordMatch[0].replace(chordMatch[2], '<span class="' + songChordSelector + ' tooltip">' + newChord + '<span class="tooltiptext jtab">' + subchords[0] + '</span></span>'); 101 } 102 lineText = '<p style="white-space: pre;color: #d73a49;font-family: \'Courier New\', Courier, monospace;margin:0;" class="' + chordLineSelector + '">' + newLine + '</p>'; 103 } 104 else if (sectionRegex.test(lineText)) { 105 var match = sectionRegex.exec(lineText); 106 var sectionText = ""; 107 if (currentSection != "") { 108 sectionText += "</div>\n" 109 } 110 currentSection = match[2].toLowerCase(); 111 sectionText += '<div class="' + songSectionSelector + ' ' + currentSection + '">\n'; 112 sectionText += '<h3 class="' + songSectionHeadingSelector + ' ' + currentSection + '">' + match[1] + '</h3>'; 113 lineText = sectionText; 114 isSection = true; 115 } else { 116 lineText = '<p style="white-space: pre;font-family: \'Courier New\', Courier, monospace;margin:0;" class="' + songTextLineSelector + '">' + lineText + '</p>'; 117 } 118 119 return { 120 'isChord': isChord, 121 'isSection': isSection, 122 'text': lineText 123 }; 124 }; 125 126 function substChord(chord, transp) { 127 chord = normalizeChord(chord); 128 var notes = ["A", "Bb", "B", "C", "C#", "D", "Eb", "E", "F", "F#", "G", "G#"]; 129 130 var x = notes.indexOf(chord); 131 x = (x + transp) % 12; 132 if (x < 0) x += 12; 133 return notes[x]; 134 }; 135 136 function normalizeChord(chord) { 137 138 chord = chord.charAt(0).toUpperCase() + chord.slice(1); 139 140 if (chord == "A#") chord = "Bb"; 141 else if (chord == "Db") chord = "C#"; 142 else if (chord == "Cb") chord = "B"; 143 else if (chord == "D#") chord = "Eb"; 144 else if (chord == "E#") chord = "F"; 145 else if (chord == "Gb") chord = "F#"; 146 else if (chord == "Ab") chord = "G#"; 147 return chord; 148 } 149 150 function isNullOrWhiteSpace(str) { 151 return str == null || str.replace(/\s/g, '').length < 1; 152 } 153 154 run(); 155} 156 157function runSongHighlighter() { 158 var songs = document.querySelectorAll('.' + songBlockSelector); 159 for (var i = 0; i < songs.length; i++) { 160 var transpose = songs[i].dataset.transpose; 161 parseSong(songs[i], transpose); 162 } 163}; 164 165function cSheetExportToWord(id) { 166 var song = document.getElementById(id); 167 var range = document.createRange(); 168 range.selectNode(song); 169 window.getSelection().addRange(range); 170 171 try { 172 // Now that we've selected the anchor text, execute the copy command 173 var successful = document.execCommand('copy'); 174 var msg = successful ? 'successfully' : 'unsuccessfully'; 175 alert(msg + " copied song to clipboard. Use CTRL + V to paste it in your word document."); 176 } catch (err) { 177 alert('Oops, unable to copy'); 178 } 179 180 // Remove the selections - NOTE: Should use 181 // removeRange(range) when it is supported 182 window.getSelection().removeAllRanges(); 183} 184 185function showJTab(element) { 186 element.style.visibility = "visible"; 187} 188 189function hideJTab(element) { 190 element.style.visibility = "hidden"; 191} 192 193document.addEventListener("DOMContentLoaded", ready);