abcjs-rails 1.8 → 1.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/app/assets/javascripts/abcjs/api/abc_animation.js +224 -0
  4. data/app/assets/javascripts/abcjs/api/abc_tunebook.js +158 -154
  5. data/app/assets/javascripts/abcjs/data/abc_tune.js +35 -1
  6. data/app/assets/javascripts/abcjs/edit/abc_editor.js +18 -17
  7. data/app/assets/javascripts/abcjs/parse/abc_parse.js +23 -6
  8. data/app/assets/javascripts/abcjs/parse/abc_parse_header.js +5 -1
  9. data/app/assets/javascripts/abcjs/{write/raphael.js → raphael.js} +2562 -266
  10. data/app/assets/javascripts/abcjs/write/abc_absolute_element.js +163 -0
  11. data/app/assets/javascripts/abcjs/write/abc_beam_element.js +162 -0
  12. data/app/assets/javascripts/abcjs/write/abc_cresendo_element.js +46 -0
  13. data/app/assets/javascripts/abcjs/write/abc_dynamic_decoration.js +36 -0
  14. data/app/assets/javascripts/abcjs/write/abc_ending_element.js +53 -0
  15. data/app/assets/javascripts/abcjs/write/abc_glyphs.js +6 -3
  16. data/app/assets/javascripts/abcjs/write/abc_layout.js +84 -29
  17. data/app/assets/javascripts/abcjs/write/abc_relative_element.js +72 -0
  18. data/app/assets/javascripts/abcjs/write/abc_staff_group_element.js +225 -0
  19. data/app/assets/javascripts/abcjs/write/abc_tie_element.js +83 -0
  20. data/app/assets/javascripts/abcjs/write/abc_triplet_element.js +85 -0
  21. data/app/assets/javascripts/abcjs/write/abc_voice_element.js +177 -0
  22. data/app/assets/javascripts/abcjs/write/abc_write.js +65 -28
  23. data/lib/abcjs-rails/version.rb +1 -1
  24. metadata +24 -14
  25. 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: 7dbac8c0a5ad9f76a40c25b8c005af7e252d3511
4
- data.tar.gz: 0577ccedd11d130f22d2b6c2c3c89506f61e9dcb
3
+ metadata.gz: 69dc7543800ee59c97f476146e4d23392cf201f0
4
+ data.tar.gz: f36703aa7021da85d79ca7e8e287749f28db1b24
5
5
  SHA512:
6
- metadata.gz: ede96b70bf4fd02a9594fee34e9dae661b5fd2bb5e05dbc0770b57ae4c5e889876d70c3552b26cf956e7589ca437a46944faaaeae3c2ee6451c64ccb11e7856f
7
- data.tar.gz: 94f0fba0cab72e74cf8ab2c1e581250f334a974c19ebd9a5a0a954673b011967d509075886448132c3240e0513181784ee22566c7fcc3409f32fcfa8b7e10f99
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 http://code.google.com/p/abcjs/wiki/InstallationDocumentation?tm=6 for complete
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
- 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;
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
- 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
- };
79
-
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
- };
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.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;
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 renderEngine(callback, output, abc, parserParams, renderParams) {
97
- var isArray = function(testObject) {
98
- return testObject && !(testObject.propertyIsEnumerable('length')) && typeof testObject === 'object' && typeof testObject.length === 'number';
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
- // check and normalize input parameters
102
- if (output === undefined || abc === undefined)
103
- return;
104
- if (!isArray(output))
105
- output = [ output ];
106
- if (parserParams === undefined)
107
- parserParams = {};
108
- if (renderParams === undefined)
109
- renderParams = {};
110
- var currentTune = renderParams.startingTune ? renderParams.startingTune : 0;
111
-
112
- // parse the abc string
113
- var book = new ABCJS.TuneBook(abc);
114
- var abcParser = new window.ABCJS.parse.Parse();
115
-
116
- // output each tune, if it exists. Otherwise clear the div.
117
- for (var i = 0; i < output.length; i++) {
118
- var div = output[i];
119
- if (typeof(div) === "string")
120
- div = document.getElementById(div);
121
- if (div) {
122
- div.innerHTML = "";
123
- if (currentTune < book.tunes.length) {
124
- abcParser.parse(book.tunes[currentTune].abc, parserParams);
125
- var tune = abcParser.getTune();
126
- callback(div, tune);
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
- currentTune++;
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, printerParams, renderParams) {
151
- function callback(div, tune) {
152
- var width = renderParams ? renderParams.width ? renderParams.width : 800 : 800;
153
- var paper = Raphael(div, width, 400);
154
- if (printerParams === undefined)
155
- printerParams = {};
156
- var printer = new ABCJS.write.Printer(paper, printerParams);
157
- printer.printABC(tune);
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
- renderEngine(callback, output, abc, parserParams, renderParams);
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
- function callback(div, tune) {
181
- if (midiParams === undefined)
182
- midiParams = {};
183
- var midiwriter = new ABCJS.midi.MidiWriter(div, midiParams);
184
- midiwriter.writeABC(tune);
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
- renderEngine(callback, output, abc, parserParams, renderParams);
188
- };
191
+ return renderEngine(callback, output, abc, parserParams, renderParams);
192
+ };
189
193
  })();