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