|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="utf-8"> |
|
|
<meta http-equiv="x-ua-compatible" content="ie=edge"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
|
|
<link rel="icon" href="favicon.ico" type="image/x-icon"/> |
|
|
<link rel="stylesheet" href="examples-styles.css"/> |
|
|
|
|
|
<title>abcjs: Drag And Drop Demo</title> |
|
|
<script src="../dist/abcjs-basic.js" type="text/javascript"></script> |
|
|
<script type="text/javascript"> |
|
|
var renderAbc |
|
|
function sanitize(str) { |
|
|
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); |
|
|
} |
|
|
function formatAbc(start, end) { |
|
|
var abc; |
|
|
if (start < 0 || end < 0) |
|
|
abc = sanitize(abcString); |
|
|
else { |
|
|
abc = sanitize(abcString.substring(0, start)) + |
|
|
'<span class="select">' + |
|
|
sanitize(abcString.substring(start, end)) + |
|
|
'</span>' + |
|
|
sanitize(abcString.substring(end)); |
|
|
} |
|
|
var el = document.getElementById("source"); |
|
|
el.innerHTML = abc.replace(/\n/g,"<br>"); |
|
|
} |
|
|
function draw() { |
|
|
var allowDragging = document.getElementById("allowDragging").checked; |
|
|
var selectAll = document.getElementById("selectAll").checked; |
|
|
var options = { |
|
|
add_classes: true, |
|
|
selectionColor: "green", |
|
|
dragColor: "blue", |
|
|
clickListener: clickListener, |
|
|
dragging: allowDragging, |
|
|
selectTypes: selectAll ? true : [ 'note', 'bar' ] |
|
|
}; |
|
|
|
|
|
var start = Date.now(); |
|
|
renderAbc = ABCJS.renderAbc("paper", abcString, options); |
|
|
var len = Date.now() - start; |
|
|
|
|
|
var svg = document.getElementById("paper"); |
|
|
var size = svg.innerHTML; |
|
|
var el = document.getElementById("size"); |
|
|
el.innerText = Math.round(size.length / 1000); |
|
|
el = document.getElementById("time"); |
|
|
el.innerText = len; |
|
|
|
|
|
svg.addEventListener('mouseover', hoverListener) |
|
|
} |
|
|
|
|
|
var allPitches = [ |
|
|
'C,,,,', 'D,,,,', 'E,,,,', 'F,,,,', 'G,,,,', 'A,,,,', 'B,,,,', |
|
|
'C,,,', 'D,,,', 'E,,,', 'F,,,', 'G,,,', 'A,,,', 'B,,,', |
|
|
'C,,', 'D,,', 'E,,', 'F,,', 'G,,', 'A,,', 'B,,', |
|
|
'C,', 'D,', 'E,', 'F,', 'G,', 'A,', 'B,', |
|
|
'C', 'D', 'E', 'F', 'G', 'A', 'B', |
|
|
'c', 'd', 'e', 'f', 'g', 'a', 'b', |
|
|
"c'", "d'", "e'", "f'", "g'", "a'", "b'", |
|
|
"c''", "d''", "e''", "f''", "g''", "a''", "b''", |
|
|
"c'''", "d'''", "e'''", "f'''", "g'''", "a'''", "b'''", |
|
|
"c''''", "d''''", "e''''", "f''''", "g''''", "a''''", "b''''" |
|
|
]; |
|
|
|
|
|
function moveNote(note, step) { |
|
|
var x =allPitches.indexOf(note); |
|
|
if (x >= 0) |
|
|
return allPitches[x-step]; |
|
|
return note; |
|
|
} |
|
|
|
|
|
function tokenize(str) { |
|
|
var arr = str.split(/(!.+?!|".+?")/); |
|
|
var output = []; |
|
|
for (var i = 0; i < arr.length; i++) { |
|
|
var token = arr[i]; |
|
|
if (token.length > 0) { |
|
|
if (token[0] !== '"' && token[0] !== '!') { |
|
|
var arr2 = arr[i].split(/([A-Ga-g][,']*)/); |
|
|
output = output.concat(arr2); |
|
|
} else |
|
|
output.push(token); |
|
|
} |
|
|
} |
|
|
return output; |
|
|
} |
|
|
|
|
|
var selectionCallback; |
|
|
var currentIndex = -1; |
|
|
var maxIndex = -1; |
|
|
|
|
|
function selectPrevious() { |
|
|
if (selectionCallback && currentIndex > 0) |
|
|
selectionCallback(currentIndex-1); |
|
|
} |
|
|
|
|
|
function selectNext() { |
|
|
if (selectionCallback && currentIndex < maxIndex) |
|
|
selectionCallback(currentIndex+1); |
|
|
} |
|
|
|
|
|
function hoverListener(event) { |
|
|
var ret = renderAbc[0].findSelectableElement(event.relatedTarget) |
|
|
if (ret) |
|
|
console.log(ret) |
|
|
} |
|
|
|
|
|
function clickListener(abcelem, tuneNumber, classes, analysis, drag, mouseEvent) { |
|
|
if (drag) { |
|
|
selectionCallback = drag.setSelection; |
|
|
currentIndex = drag.index; |
|
|
maxIndex = drag.max; |
|
|
} |
|
|
var originalText = abcString.substring(abcelem.startChar, abcelem.endChar); |
|
|
if (abcelem.pitches && drag && drag.step && abcelem.startChar >= 0 && abcelem.endChar >= 0) { |
|
|
var arr = tokenize(originalText); |
|
|
|
|
|
for (var i = 0; i < arr.length; i++) { |
|
|
arr[i] = moveNote(arr[i], drag.step); |
|
|
} |
|
|
var newText = arr.join(""); |
|
|
|
|
|
abcString = abcString.substring(0, abcelem.startChar) + newText + abcString.substring(abcelem.endChar); |
|
|
formatAbc(abcelem.startChar, abcelem.endChar); |
|
|
draw(); |
|
|
} else if (abcelem.startChar >= 0 && abcelem.endChar >= 0) |
|
|
formatAbc(abcelem.startChar, abcelem.endChar); |
|
|
|
|
|
var data = ""; |
|
|
if (abcelem.startChar >= 0) |
|
|
data += "src: " + originalText + "<br>"; |
|
|
else |
|
|
data += "src: unknown<br>"; |
|
|
data += "type: " + abcelem.type + "<br>"; |
|
|
data += "el_type: " + abcelem.el_type + "<br>"; |
|
|
data += "name: " + analysis.name + "<br>"; |
|
|
data += "clickedName: " + analysis.clickedName + "<br>"; |
|
|
data += "clickedClasses: " + analysis.clickedClasses + "<br>"; |
|
|
data += "classes: " + analysis.parentClasses + "<br>"; |
|
|
document.getElementById("click-data").innerHTML = data; |
|
|
} |
|
|
function optionChanged() { |
|
|
formatAbc(-1,-1); |
|
|
draw(); |
|
|
} |
|
|
|
|
|
function load() { |
|
|
formatAbc(-1,-1); |
|
|
draw(); |
|
|
} |
|
|
|
|
|
var abcString = |
|
|
'X:1' + '\n' + |
|
|
'M:4/4' + '\n' + |
|
|
'L:1/16' + '\n' + |
|
|
'%%partsfont box' + '\n' + |
|
|
'%%stretchlast .7' + '\n' + |
|
|
'%%barnumbers 1' + '\n' + |
|
|
'T: Selection And Dragging Test' + '\n' + |
|
|
'T: Demonstrates a lot the different types of elements and their effect.' + '\n' + |
|
|
'C: Public Domain' + '\n' + |
|
|
'R: Play steady' + '\n' + |
|
|
'A: Paul Rosen' + '\n' + |
|
|
'S: abcjs website' + '\n' + |
|
|
'W: Now is the time for all good men' + '\n' + |
|
|
'W:' + '\n' + |
|
|
'W: To come to the aid of their party.' + '\n' + |
|
|
'H: This shows every type of thing that can possibly be drawn.' + '\n' + |
|
|
'H:' + '\n' + |
|
|
'H: And two lines of history.' + '\n' + |
|
|
'Q: "Easy Swing" 1/4=140' + '\n' + |
|
|
'P: AABB' + '\n' + |
|
|
'%%staves {(RH extra) (LH)}' + '\n' + |
|
|
'V:RH clef=treble name=RH' + '\n' + |
|
|
'V:LH clef=bass name=LH' + '\n' + |
|
|
'K:Bb' + '\n' + |
|
|
'P:A' + '\n' + |
|
|
'[V: RH] !mp![b8B8d8] f3g f4|!<(![d12b12] !<)![b4g4]| \\' + '\n' + |
|
|
'[Q:"left" 1/4=170"right"]z4 !<(! (bfdf) (3B2d2c2 !<)!B4|!f![c4f4] z4 [b8d8]|' + '\n' + |
|
|
'!p![G8e8] Tu[c8f8]|!<(![d12f12] !<)!g4|!f!a4 [g4b4] z4 =e4|[A8c8f8] d8|' + '\n' + |
|
|
'|1 [c8F8] [B4G4] z4|[d12B12] A4|!>(![D8A8] Bcde fAB!>)!c|!mp!d16:|' + '\n' + |
|
|
'w:Strang- ers in the night' + '\n' + |
|
|
'[V: extra] B,4- B,4- B,4 B,4 | "Bb"{C}B,4 {CD}B,4 B,4 B,4 | B,4 B,4 B,4 B,4 | B,4 B,4 B,4 B,4 |' + '\n' + |
|
|
'B,4 B,4 B,4 B,4 | B,4 B,4 B,4 B,4 | B,4 B,4 B,4 B,4 | B,4 B,4 B,4 B,4 |' + '\n' + |
|
|
'B,4 B,4 B,4 B,4 |B,4 B,4 B,4 B,4 |"^annotation"B,4 B,4 B,4 B,4 |B,4 B,4 B,4 B,4 :|' + '\n' + |
|
|
'[V: LH] B,6 D2 [F,8F8A,8]|B,2B,,2 C,4 D,4 E,F,G,2|F,2A,2 D4 D4 G,2E,2|[C4F,4A,4] z4 [F8B,8]|' + '\n' + |
|
|
'G,8 A,8|A,12 B,G,D,E,|F,G,A,F, (G,A,B,G,) C4 C4|[C,8A,8] [F8F,8B,8]|' + '\n' + |
|
|
'A,3C B,3D G,F,E,D, F,2A,2|D,2C,2 B,,2A,,2 G,,4 F,,A,,C,F,|F,,6 D,,2 [D,4G,,4] z4|B,,16:|' + '\n'; |
|
|
</script> |
|
|
<style> |
|
|
.side-by-side { |
|
|
display: flex; |
|
|
} |
|
|
.row { |
|
|
display: flex; |
|
|
flex-wrap: wrap; |
|
|
} |
|
|
#source { |
|
|
font-size: 13px; |
|
|
max-width: 700px; |
|
|
overflow: auto; |
|
|
font-family: "Lucida Console", Monaco, monospace; |
|
|
white-space: nowrap; |
|
|
} |
|
|
.select { |
|
|
background-color: #FCF9BB; |
|
|
box-shadow: 0 0 1px black; |
|
|
} |
|
|
ul { |
|
|
max-width: 700px; |
|
|
list-style: none; |
|
|
margin: 0; |
|
|
padding: 0; |
|
|
} |
|
|
li { |
|
|
margin-top: 10px; |
|
|
} |
|
|
label { |
|
|
font-weight: bold; |
|
|
} |
|
|
.click-data { |
|
|
background: #dddddd; |
|
|
padding: 10px; |
|
|
margin-left: 10px; |
|
|
width: 200px; |
|
|
} |
|
|
.click-data h2 { |
|
|
margin: 0; |
|
|
padding: 0; |
|
|
font-weight: normal; |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body onload="load()"> |
|
|
<header> |
|
|
<img src="https://paulrosen.github.io/abcjs/img/abcjs_comp_extended_08.svg" alt="abcjs logo"> |
|
|
<h1>Drag and drop demo</h1> |
|
|
</header> |
|
|
<div class="container"> |
|
|
<div class="side-by-side"> |
|
|
<div> |
|
|
<div>Render Time: <span id="time"></span>ms</div> |
|
|
<div>SVG size: <span id="size"></span>K</div> |
|
|
<ul> |
|
|
<li><label><input type="checkbox" id="allowDragging" onclick="optionChanged()" checked>Allow Dragging</label> |
|
|
<div>When checked, then text is not selectable on the music and notes are draggable. You can |
|
|
also navigate through the music with the tab key, and change notes with the up and down arrows. When not checked, then items are selectable, but not draggable. |
|
|
</div> |
|
|
</li> |
|
|
<li><label><input type="checkbox" id="selectAll" onclick="optionChanged()">Select All</label> |
|
|
<div>When this is checked, nearly every visible thing is selectable. When it is not checked, then only |
|
|
the notes, rests, and measures are selectable. |
|
|
</div> |
|
|
</li> |
|
|
<li><button onclick="selectPrevious()">Previous</button><button onclick="selectNext()">Next</button></li> |
|
|
</ul> |
|
|
</div> |
|
|
<div class="click-data"> |
|
|
<h2>Last Click</h2> |
|
|
<div id="click-data"> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
<div class="row"> |
|
|
<div> |
|
|
<h2>Output</h2> |
|
|
<div id="paper"></div> |
|
|
</div> |
|
|
<div> |
|
|
<h2>Source</h2> |
|
|
<div id="source"></div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</body> |
|
|
</html> |
|
|
|