abcjs-rails 1.8 → 1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/assets/javascripts/abcjs/api/abc_animation.js +224 -0
- data/app/assets/javascripts/abcjs/api/abc_tunebook.js +158 -154
- data/app/assets/javascripts/abcjs/data/abc_tune.js +35 -1
- data/app/assets/javascripts/abcjs/edit/abc_editor.js +18 -17
- data/app/assets/javascripts/abcjs/parse/abc_parse.js +23 -6
- data/app/assets/javascripts/abcjs/parse/abc_parse_header.js +5 -1
- data/app/assets/javascripts/abcjs/{write/raphael.js → raphael.js} +2562 -266
- data/app/assets/javascripts/abcjs/write/abc_absolute_element.js +163 -0
- data/app/assets/javascripts/abcjs/write/abc_beam_element.js +162 -0
- data/app/assets/javascripts/abcjs/write/abc_cresendo_element.js +46 -0
- data/app/assets/javascripts/abcjs/write/abc_dynamic_decoration.js +36 -0
- data/app/assets/javascripts/abcjs/write/abc_ending_element.js +53 -0
- data/app/assets/javascripts/abcjs/write/abc_glyphs.js +6 -3
- data/app/assets/javascripts/abcjs/write/abc_layout.js +84 -29
- data/app/assets/javascripts/abcjs/write/abc_relative_element.js +72 -0
- data/app/assets/javascripts/abcjs/write/abc_staff_group_element.js +225 -0
- data/app/assets/javascripts/abcjs/write/abc_tie_element.js +83 -0
- data/app/assets/javascripts/abcjs/write/abc_triplet_element.js +85 -0
- data/app/assets/javascripts/abcjs/write/abc_voice_element.js +177 -0
- data/app/assets/javascripts/abcjs/write/abc_write.js +65 -28
- data/lib/abcjs-rails/version.rb +1 -1
- metadata +24 -14
- data/app/assets/javascripts/abcjs/write/abc_graphelements.js +0 -790
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69dc7543800ee59c97f476146e4d23392cf201f0
|
4
|
+
data.tar.gz: f36703aa7021da85d79ca7e8e287749f28db1b24
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab12f67b09329ba8245b574c226519cb6fc8e202bf8cd9b6c6323662cedbfca851e1abde4b94d8d02961dd007aa19389043a7f7ed9dd6fc92ed6cb2bd4d0e39d
|
7
|
+
data.tar.gz: 6228eac5b18e3cc8d6ce3b56545c29d8c12f741f321da6cf95a55a8e92994273dc4763931eba3836199f11b5625522c540f2211aa193151adb839cebe735f219
|
data/README.md
CHANGED
@@ -23,7 +23,7 @@ To include abcjs in your Rails app, add this line to application.js:
|
|
23
23
|
|
24
24
|
//= require abcjs-rails
|
25
25
|
|
26
|
-
See
|
26
|
+
See https://github.com/paulrosen/abcjs for complete
|
27
27
|
usage of abcjs. There is no additional functionality supplied by this gem.
|
28
28
|
|
29
29
|
Here is a cheatsheet for using the functionality:
|
@@ -0,0 +1,224 @@
|
|
1
|
+
// abc_animation.js: handles animating the music in real time.
|
2
|
+
// Copyright (C) 2014 Paul Rosen (paul at paulrosen dot net)
|
3
|
+
//
|
4
|
+
// This program is free software: you can redistribute it and/or modify
|
5
|
+
// it under the terms of the GNU General Public License as published by
|
6
|
+
// the Free Software Foundation, either version 3 of the License, or
|
7
|
+
// (at your option) any later version.
|
8
|
+
//
|
9
|
+
// This program is distributed in the hope that it will be useful,
|
10
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
// GNU General Public License for more details.
|
13
|
+
//
|
14
|
+
// You should have received a copy of the GNU General Public License
|
15
|
+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
/*global ABCJS, console */
|
18
|
+
|
19
|
+
if (!window.ABCJS)
|
20
|
+
window.ABCJS = {};
|
21
|
+
|
22
|
+
(function() {
|
23
|
+
|
24
|
+
function hasClass(element, cls) {
|
25
|
+
var elClass = element.getAttribute("class");
|
26
|
+
var rclass = /[\t\r\n\f]/g;
|
27
|
+
var className = " " + cls + " ";
|
28
|
+
return (element.nodeType === 1 && (" " + elClass + " ").replace(rclass, " ").indexOf(className) >= 0);
|
29
|
+
}
|
30
|
+
|
31
|
+
function getAllElementsByClasses(startingEl, class1, class2) {
|
32
|
+
var els = startingEl.getElementsByClassName(class1);
|
33
|
+
var ret = [];
|
34
|
+
for (var i = 0; i < els.length; i++) {
|
35
|
+
if (hasClass(els[i], class2))
|
36
|
+
ret.push(els[i]);
|
37
|
+
}
|
38
|
+
return ret;
|
39
|
+
}
|
40
|
+
|
41
|
+
function getBeatsPerMinute(tune, options) {
|
42
|
+
// We either want to run the timer once per measure or once per beat. If we run it once per beat we need a multiplier for the measures.
|
43
|
+
// So, first we figure out the beats per minute and the beats per measure, then depending on the type of animation, we can
|
44
|
+
// calculate the desired interval (ret.tick) and the number of ticks before we want to run the measure
|
45
|
+
var bpm;
|
46
|
+
if (options.bpm)
|
47
|
+
bpm = options.bpm;
|
48
|
+
else {
|
49
|
+
if (tune && tune.metaText && tune.metaText.tempo && tune.metaText.tempo.bpm)
|
50
|
+
bpm = tune.metaText.tempo.bpm;
|
51
|
+
else
|
52
|
+
bpm = 120; // Just set it to something. The user should have set this.
|
53
|
+
}
|
54
|
+
return bpm;
|
55
|
+
}
|
56
|
+
|
57
|
+
// This is a way to manipulate the written music on a timer. Their are two ways to manipulate the music: turn off each measure as it goes by,
|
58
|
+
// and put a vertical cursor before the next note to play. The timer works at the speed of the original tempo of the music unless it is overwritten
|
59
|
+
// in the options parameter.
|
60
|
+
//
|
61
|
+
// parameters:
|
62
|
+
// paper: the output div that the music is in.
|
63
|
+
// tune: the tune object returned by renderAbc.
|
64
|
+
// options: a hash containing the following:
|
65
|
+
// hideFinishedMeasures: true or false [ false is the default ]
|
66
|
+
// showCursor: true or false [ false is the default ]
|
67
|
+
// bpm: number of beats per minute [ the default is whatever is in the Q: field ]
|
68
|
+
var stopNextTime = false;
|
69
|
+
var cursor;
|
70
|
+
ABCJS.startAnimation = function(paper, tune, options) {
|
71
|
+
if (paper.getElementsByClassName === undefined) {
|
72
|
+
console.error("ABCJS.startAnimation: The first parameter must be a regular DOM element. (Did you pass a jQuery object or an ID?)");
|
73
|
+
return;
|
74
|
+
}
|
75
|
+
if (tune.getBeatLength === undefined) {
|
76
|
+
console.error("ABCJS.startAnimation: The second parameter must be a single tune. (Did you pass the entire array of tunes?)");
|
77
|
+
return;
|
78
|
+
}
|
79
|
+
if (options.showCursor) {
|
80
|
+
cursor = $('<div class="cursor" style="position: absolute;"></div>');
|
81
|
+
$(paper).append(cursor);
|
82
|
+
}
|
83
|
+
|
84
|
+
stopNextTime = false;
|
85
|
+
var beatsPerMinute = getBeatsPerMinute(tune, options);
|
86
|
+
var beatsPerMillisecond = beatsPerMinute / 60000;
|
87
|
+
var beatLength = tune.getBeatLength(); // This is the same units as the duration is stored in.
|
88
|
+
|
89
|
+
var startTime;
|
90
|
+
|
91
|
+
function processMeasureHider(lineNum, measureNum) {
|
92
|
+
var els = getAllElementsByClasses(paper, "l"+lineNum, "m"+measureNum);
|
93
|
+
|
94
|
+
if (els.length > 0) {
|
95
|
+
for (var i = 0; i < els.length; i++) {
|
96
|
+
var el = els[i];
|
97
|
+
if (!hasClass(el, "bar"))
|
98
|
+
el.style.display = "none";
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
function makeSortedArray(hash) {
|
104
|
+
var arr = [];
|
105
|
+
for (var k in hash) {
|
106
|
+
if (hash.hasOwnProperty(k))
|
107
|
+
arr.push(hash[k]);
|
108
|
+
}
|
109
|
+
arr = arr.sort(function(a,b) {
|
110
|
+
return a.time - b.time;
|
111
|
+
});
|
112
|
+
return arr;
|
113
|
+
}
|
114
|
+
|
115
|
+
var timingEvents = [];
|
116
|
+
function setupEvents(engraver) {
|
117
|
+
var eventHash = {};
|
118
|
+
// The time is the number of measures from the beginning of the piece.
|
119
|
+
var time = 0;
|
120
|
+
var isTiedState = false;
|
121
|
+
for (var line=0;line<engraver.staffgroups.length; line++) {
|
122
|
+
var group = engraver.staffgroups[line];
|
123
|
+
var voices = group.voices;
|
124
|
+
var top = group.y;
|
125
|
+
var height = group.height;
|
126
|
+
var maxVoiceTime = 0;
|
127
|
+
// Put in the notes for all voices, then sort them, then remove duplicates
|
128
|
+
for (var v = 0; v < voices.length; v++) {
|
129
|
+
var voiceTime = time;
|
130
|
+
var elements = voices[v].children;
|
131
|
+
for (var elem=0; elem<elements.length; elem++) {
|
132
|
+
var element = elements[elem];
|
133
|
+
if (element.duration > 0) {
|
134
|
+
// There are 3 possibilities here: the note could stand on its own, the note could be tied to the next,
|
135
|
+
// the note could be tied to the previous, and the note could be tied on both sides.
|
136
|
+
var isTiedToNext = element.startTie;
|
137
|
+
if (isTiedState) {
|
138
|
+
if (!isTiedToNext)
|
139
|
+
isTiedState = false;
|
140
|
+
// If the note is tied on both sides it can just be ignored.
|
141
|
+
} else {
|
142
|
+
// the last note wasn't tied.
|
143
|
+
eventHash["event"+voiceTime] = { type: "event", time: voiceTime, top: top, height: height, left: element.x, width: element.w };
|
144
|
+
if (isTiedToNext)
|
145
|
+
isTiedState = true;
|
146
|
+
}
|
147
|
+
voiceTime += element.duration;
|
148
|
+
}
|
149
|
+
if (element.type === 'bar') {
|
150
|
+
if (timingEvents.length === 0 || timingEvents[timingEvents.length-1] !== 'bar') {
|
151
|
+
if (element.elemset && element.elemset.length > 0 && element.elemset[0].attrs) {
|
152
|
+
var klass = element.elemset[0].attrs['class'];
|
153
|
+
var arr = klass.split(' ');
|
154
|
+
var lineNum;
|
155
|
+
var measureNum;
|
156
|
+
for (var i = 0; i < arr.length; i++) {
|
157
|
+
var match = /m(\d+)/.exec(arr[i]);
|
158
|
+
if (match)
|
159
|
+
measureNum = match[1];
|
160
|
+
match = /l(\d+)/.exec(arr[i]);
|
161
|
+
if (match)
|
162
|
+
lineNum = match[1];
|
163
|
+
}
|
164
|
+
eventHash["bar"+voiceTime] = { type: "bar", time: voiceTime, lineNum: lineNum, measureNum: measureNum };
|
165
|
+
}
|
166
|
+
}
|
167
|
+
}
|
168
|
+
}
|
169
|
+
maxVoiceTime = Math.max(maxVoiceTime, voiceTime);
|
170
|
+
}
|
171
|
+
time = maxVoiceTime;
|
172
|
+
}
|
173
|
+
// now we have all the events, but if there are multiple voices then there may be events out of order or duplicated, so normalize it.
|
174
|
+
timingEvents = makeSortedArray(eventHash);
|
175
|
+
}
|
176
|
+
setupEvents(tune.engraver);
|
177
|
+
|
178
|
+
function processShowCursor() {
|
179
|
+
var currentNote = timingEvents.shift();
|
180
|
+
if (!currentNote) {
|
181
|
+
stopNextTime = true;
|
182
|
+
return 0;
|
183
|
+
}
|
184
|
+
if (currentNote.type === "bar") {
|
185
|
+
if (options.hideFinishedMeasures)
|
186
|
+
processMeasureHider(currentNote.lineNum, currentNote.measureNum);
|
187
|
+
return processShowCursor();
|
188
|
+
}
|
189
|
+
if (options.showCursor)
|
190
|
+
cursor.css({ left: currentNote.left + "px", top: currentNote.top + "px", width: currentNote.width + "px", height: currentNote.height + "px" });
|
191
|
+
if (timingEvents.length > 0)
|
192
|
+
return timingEvents[0].time / beatLength;
|
193
|
+
stopNextTime = true;
|
194
|
+
return 0;
|
195
|
+
}
|
196
|
+
|
197
|
+
function processNext() {
|
198
|
+
if (stopNextTime) {
|
199
|
+
ABCJS.stopAnimation();
|
200
|
+
return;
|
201
|
+
}
|
202
|
+
var nextTimeInBeats = processShowCursor();
|
203
|
+
var nextTimeInMilliseconds = nextTimeInBeats / beatsPerMillisecond;
|
204
|
+
var currentTime = new Date();
|
205
|
+
currentTime = currentTime.getTime();
|
206
|
+
var interval = startTime + nextTimeInMilliseconds - currentTime;
|
207
|
+
if (interval <= 0)
|
208
|
+
processNext();
|
209
|
+
else
|
210
|
+
setTimeout(processNext, interval);
|
211
|
+
}
|
212
|
+
startTime = new Date();
|
213
|
+
startTime = startTime.getTime();
|
214
|
+
processNext();
|
215
|
+
};
|
216
|
+
|
217
|
+
ABCJS.stopAnimation = function() {
|
218
|
+
stopNextTime = true;
|
219
|
+
if (cursor) {
|
220
|
+
cursor.remove();
|
221
|
+
cursor = null;
|
222
|
+
}
|
223
|
+
};
|
224
|
+
})();
|
@@ -15,175 +15,179 @@
|
|
15
15
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
16
|
|
17
17
|
/*global document, Raphael */
|
18
|
-
/*global window */
|
18
|
+
/*global window, ABCJS, console */
|
19
19
|
|
20
20
|
if (!window.ABCJS)
|
21
21
|
window.ABCJS = {};
|
22
22
|
|
23
23
|
(function() {
|
24
|
-
ABCJS.numberOfTunes = function(abc) {
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
};
|
30
|
-
|
31
|
-
ABCJS.TuneBook = function(book) {
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
});
|
45
|
-
if (This.tunes.length > 1 && !window.ABCJS.parse.startsWith(This.tunes[0].abc, 'X:')) { // If there is only one tune, the X: might be missing, otherwise assume the top of the file is "intertune"
|
46
|
-
// There could be file-wide directives in this, if so, we need to insert it into each tune. We can probably get away with
|
47
|
-
// just looking for file-wide directives here (before the first tune) and inserting them at the bottom of each tune, since
|
48
|
-
// the tune is parsed all at once. The directives will be seen before the printer begins processing.
|
49
|
-
var dir = This.tunes.shift();
|
50
|
-
var arrDir = dir.abc.split('\n');
|
51
|
-
window.ABCJS.parse.each(arrDir, function(line) {
|
52
|
-
if (window.ABCJS.parse.startsWith(line, '%%'))
|
53
|
-
directives += line + '\n';
|
24
|
+
ABCJS.numberOfTunes = function(abc) {
|
25
|
+
var tunes = abc.split("\nX:");
|
26
|
+
var num = tunes.length;
|
27
|
+
if (num === 0) num = 1;
|
28
|
+
return num;
|
29
|
+
};
|
30
|
+
|
31
|
+
ABCJS.TuneBook = function(book) {
|
32
|
+
var This = this;
|
33
|
+
var directives = "";
|
34
|
+
book = window.ABCJS.parse.strip(book);
|
35
|
+
var tunes = book.split("\nX:");
|
36
|
+
for (var i = 1; i < tunes.length; i++) // Put back the X: that we lost when splitting the tunes.
|
37
|
+
tunes[i] = "X:" + tunes[i];
|
38
|
+
// Keep track of the character position each tune starts with.
|
39
|
+
var pos = 0;
|
40
|
+
This.tunes = [];
|
41
|
+
window.ABCJS.parse.each(tunes, function(tune) {
|
42
|
+
This.tunes.push({ abc: tune, startPos: pos});
|
43
|
+
pos += tune.length;
|
54
44
|
});
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
if
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
45
|
+
if (This.tunes.length > 1 && !window.ABCJS.parse.startsWith(This.tunes[0].abc, 'X:')) { // If there is only one tune, the X: might be missing, otherwise assume the top of the file is "intertune"
|
46
|
+
// There could be file-wide directives in this, if so, we need to insert it into each tune. We can probably get away with
|
47
|
+
// just looking for file-wide directives here (before the first tune) and inserting them at the bottom of each tune, since
|
48
|
+
// the tune is parsed all at once. The directives will be seen before the engraver begins processing.
|
49
|
+
var dir = This.tunes.shift();
|
50
|
+
var arrDir = dir.abc.split('\n');
|
51
|
+
window.ABCJS.parse.each(arrDir, function(line) {
|
52
|
+
if (window.ABCJS.parse.startsWith(line, '%%'))
|
53
|
+
directives += line + '\n';
|
54
|
+
});
|
55
|
+
}
|
56
|
+
This.header = directives;
|
57
|
+
|
58
|
+
// Now, the tune ends at a blank line, so truncate it if needed. There may be "intertune" stuff.
|
59
|
+
window.ABCJS.parse.each(This.tunes, function(tune) {
|
60
|
+
var end = tune.abc.indexOf('\n\n');
|
61
|
+
if (end > 0)
|
62
|
+
tune.abc = tune.abc.substring(0, end);
|
63
|
+
tune.pure = tune.abc;
|
64
|
+
tune.abc = directives + tune.abc;
|
65
|
+
|
66
|
+
// for the user's convenience, parse and store the title separately. The title is between the first T: and the next \n
|
67
|
+
var title = tune.pure.split("T:");
|
68
|
+
if (title.length > 1) {
|
69
|
+
title = title[1].split("\n");
|
70
|
+
tune.title = title[0].replace(/^\s+|\s+$/g, '');
|
71
|
+
} else
|
72
|
+
tune.title = "";
|
73
|
+
|
74
|
+
// for the user's convenience, parse and store the id separately. The id is between the first X: and the next \n
|
75
|
+
var id = tune.pure.substring(2, tune.pure.indexOf("\n"));
|
76
|
+
tune.id = id.replace(/^\s+|\s+$/g, '');
|
77
|
+
});
|
78
|
+
};
|
87
79
|
|
88
|
-
ABCJS.TuneBook.prototype.
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
};
|
80
|
+
ABCJS.TuneBook.prototype.getTuneById = function(id) {
|
81
|
+
for (var i = 0; i < this.tunes.length; i++) {
|
82
|
+
if (this.tunes[i].id === id)
|
83
|
+
return this.tunes[i];
|
84
|
+
}
|
85
|
+
return null;
|
86
|
+
};
|
95
87
|
|
96
|
-
function
|
97
|
-
|
98
|
-
|
88
|
+
ABCJS.TuneBook.prototype.getTuneByTitle = function(title) {
|
89
|
+
for (var i = 0; i < this.tunes.length; i++) {
|
90
|
+
if (this.tunes[i].title === title)
|
91
|
+
return this.tunes[i];
|
92
|
+
}
|
93
|
+
return null;
|
99
94
|
};
|
100
95
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
96
|
+
function renderEngine(callback, output, abc, parserParams, renderParams) {
|
97
|
+
var ret = [];
|
98
|
+
var isArray = function(testObject) {
|
99
|
+
return testObject && !(testObject.propertyIsEnumerable('length')) && typeof testObject === 'object' && typeof testObject.length === 'number';
|
100
|
+
};
|
101
|
+
|
102
|
+
// check and normalize input parameters
|
103
|
+
if (output === undefined || abc === undefined)
|
104
|
+
return;
|
105
|
+
if (!isArray(output))
|
106
|
+
output = [ output ];
|
107
|
+
if (parserParams === undefined)
|
108
|
+
parserParams = {};
|
109
|
+
if (renderParams === undefined)
|
110
|
+
renderParams = {};
|
111
|
+
var currentTune = renderParams.startingTune ? renderParams.startingTune : 0;
|
112
|
+
|
113
|
+
// parse the abc string
|
114
|
+
var book = new ABCJS.TuneBook(abc);
|
115
|
+
var abcParser = new window.ABCJS.parse.Parse();
|
116
|
+
|
117
|
+
// output each tune, if it exists. Otherwise clear the div.
|
118
|
+
for (var i = 0; i < output.length; i++) {
|
119
|
+
var div = output[i];
|
120
|
+
if (typeof(div) === "string")
|
121
|
+
div = document.getElementById(div);
|
122
|
+
if (div) {
|
123
|
+
div.innerHTML = "";
|
124
|
+
if (currentTune < book.tunes.length) {
|
125
|
+
abcParser.parse(book.tunes[currentTune].abc, parserParams);
|
126
|
+
var tune = abcParser.getTune();
|
127
|
+
ret.push(tune);
|
128
|
+
callback(div, tune);
|
129
|
+
}
|
127
130
|
}
|
131
|
+
currentTune++;
|
128
132
|
}
|
129
|
-
|
133
|
+
return ret;
|
130
134
|
}
|
131
|
-
}
|
132
135
|
|
133
|
-
// A quick way to render a tune from javascript when interactivity is not required.
|
134
|
-
// This is used when a javascript routine has some abc text that it wants to render
|
135
|
-
// in a div or collection of divs. One tune or many can be rendered.
|
136
|
-
//
|
137
|
-
// parameters:
|
138
|
-
// output: an array of divs that the individual tunes are rendered to.
|
139
|
-
// If the number of tunes exceeds the number of divs in the array, then
|
140
|
-
// only the first tunes are rendered. If the number of divs exceeds the number
|
141
|
-
// of tunes, then the unused divs are cleared. The divs can be passed as either
|
142
|
-
// elements or strings of ids. If ids are passed, then the div MUST exist already.
|
143
|
-
// (if a single element is passed, then it is an implied array of length one.)
|
144
|
-
// (if a null is passed for an element, or the element doesn't exist, then that tune is skipped.)
|
145
|
-
// abc: text representing a tune or an entire tune book in ABC notation.
|
146
|
-
// renderParams: hash of:
|
147
|
-
// startingTune: an index, starting at zero, representing which tune to start rendering at.
|
148
|
-
// (If this element is not present, then rendering starts at zero.)
|
149
|
-
// width: 800 by default. The width in pixels of the output paper
|
150
|
-
ABCJS.renderAbc = function(output, abc, parserParams,
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
136
|
+
// A quick way to render a tune from javascript when interactivity is not required.
|
137
|
+
// This is used when a javascript routine has some abc text that it wants to render
|
138
|
+
// in a div or collection of divs. One tune or many can be rendered.
|
139
|
+
//
|
140
|
+
// parameters:
|
141
|
+
// output: an array of divs that the individual tunes are rendered to.
|
142
|
+
// If the number of tunes exceeds the number of divs in the array, then
|
143
|
+
// only the first tunes are rendered. If the number of divs exceeds the number
|
144
|
+
// of tunes, then the unused divs are cleared. The divs can be passed as either
|
145
|
+
// elements or strings of ids. If ids are passed, then the div MUST exist already.
|
146
|
+
// (if a single element is passed, then it is an implied array of length one.)
|
147
|
+
// (if a null is passed for an element, or the element doesn't exist, then that tune is skipped.)
|
148
|
+
// abc: text representing a tune or an entire tune book in ABC notation.
|
149
|
+
// renderParams: hash of:
|
150
|
+
// startingTune: an index, starting at zero, representing which tune to start rendering at.
|
151
|
+
// (If this element is not present, then rendering starts at zero.)
|
152
|
+
// width: 800 by default. The width in pixels of the output paper
|
153
|
+
ABCJS.renderAbc = function(output, abc, parserParams, engraverParams, renderParams) {
|
154
|
+
function callback(div, tune) {
|
155
|
+
var width = renderParams ? renderParams.width ? renderParams.width : 800 : 800;
|
156
|
+
/* jshint -W064 */ var paper = Raphael(div, width, 400); /* jshint +W064 */
|
157
|
+
if (engraverParams === undefined)
|
158
|
+
engraverParams = {};
|
159
|
+
var engraver_controller = new ABCJS.write.Printer(paper, engraverParams);
|
160
|
+
engraver_controller.printABC(tune);
|
161
|
+
tune.engraver = engraver_controller;
|
162
|
+
}
|
159
163
|
|
160
|
-
|
161
|
-
};
|
164
|
+
return renderEngine(callback, output, abc, parserParams, renderParams);
|
165
|
+
};
|
162
166
|
|
163
|
-
// A quick way to render a tune from javascript when interactivity is not required.
|
164
|
-
// This is used when a javascript routine has some abc text that it wants to render
|
165
|
-
// in a div or collection of divs. One tune or many can be rendered.
|
166
|
-
//
|
167
|
-
// parameters:
|
168
|
-
// output: an array of divs that the individual tunes are rendered to.
|
169
|
-
// If the number of tunes exceeds the number of divs in the array, then
|
170
|
-
// only the first tunes are rendered. If the number of divs exceeds the number
|
171
|
-
// of tunes, then the unused divs are cleared. The divs can be passed as either
|
172
|
-
// elements or strings of ids. If ids are passed, then the div MUST exist already.
|
173
|
-
// (if a single element is passed, then it is an implied array of length one.)
|
174
|
-
// (if a null is passed for an element, or the element doesn't exist, then that tune is skipped.)
|
175
|
-
// abc: text representing a tune or an entire tune book in ABC notation.
|
176
|
-
// renderParams: hash of:
|
177
|
-
// startingTune: an index, starting at zero, representing which tune to start rendering at.
|
178
|
-
// (If this element is not present, then rendering starts at zero.)
|
179
|
-
ABCJS.renderMidi = function(output, abc, parserParams, midiParams, renderParams) {
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
167
|
+
// A quick way to render a tune from javascript when interactivity is not required.
|
168
|
+
// This is used when a javascript routine has some abc text that it wants to render
|
169
|
+
// in a div or collection of divs. One tune or many can be rendered.
|
170
|
+
//
|
171
|
+
// parameters:
|
172
|
+
// output: an array of divs that the individual tunes are rendered to.
|
173
|
+
// If the number of tunes exceeds the number of divs in the array, then
|
174
|
+
// only the first tunes are rendered. If the number of divs exceeds the number
|
175
|
+
// of tunes, then the unused divs are cleared. The divs can be passed as either
|
176
|
+
// elements or strings of ids. If ids are passed, then the div MUST exist already.
|
177
|
+
// (if a single element is passed, then it is an implied array of length one.)
|
178
|
+
// (if a null is passed for an element, or the element doesn't exist, then that tune is skipped.)
|
179
|
+
// abc: text representing a tune or an entire tune book in ABC notation.
|
180
|
+
// renderParams: hash of:
|
181
|
+
// startingTune: an index, starting at zero, representing which tune to start rendering at.
|
182
|
+
// (If this element is not present, then rendering starts at zero.)
|
183
|
+
ABCJS.renderMidi = function(output, abc, parserParams, midiParams, renderParams) {
|
184
|
+
function callback(div, tune) {
|
185
|
+
if (midiParams === undefined)
|
186
|
+
midiParams = {};
|
187
|
+
var midiwriter = new ABCJS.midi.MidiWriter(div, midiParams);
|
188
|
+
midiwriter.writeABC(tune);
|
189
|
+
}
|
186
190
|
|
187
|
-
|
188
|
-
};
|
191
|
+
return renderEngine(callback, output, abc, parserParams, renderParams);
|
192
|
+
};
|
189
193
|
})();
|