Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
<!doctype html>
Example of a DOM-based music notation application that assesses a user's ability
to identify the roots of randomly voiced triads. jQuery is used to manipulate a
a MusicXML DOM and to respond to user interaction gestures on the displayed notation.
<script src="/assets/lib/jquery-1.10.2.js"></script>
<script src="/clientapi/2.0.0/nfclient.js"></script>
<script src="discoverYourRoots.js"></script>
body, button {
font-size: 24px;
#correct {
color: green;
#incorrect {
color: red;
<!-- HTML user interface for the application -->
<div class="actionList">
<button onclick="generateNewTriads()">Next Problem Set</button>
<div class="results">
Right: <span id="correct" class="counter"></span>
<div class="results">
Wrong: <span id="incorrect" class="counter"></span>
<!-- this element will hold the Noteflight score iframe -->
<div id="score1"></div>
var exercise;
// This section employs a Noteflight-based MusicXML DOM renderer and is the only viewer-specific
// aspect of this example. The rest of the code only interacts with the DOM, not with Noteflight.
NFClient.onViewerLoad = function() {
// Load the skeleton of the document as a MusicXML DOM and tell the viewer to show it.
// Ordinary AJAX load of a MusicXML file; it comes back as a DOM
$.ajax({url: 'exercise.xml', type: 'GET', dataType: 'xml'}).done(function(data) {
// Save the DOM for local use, and tell Noteflight to show it in the given iframe
exercise = data;
NFClient.viewScore(exercise, "score1");
// Refresh the right/wrong counter fields in the display above the score
var correct = 0;
var incorrect = 0;
function displayCounters() {
// Generate a new triad problem set by randomly octave-displacing the notes of a diatonic triad
// starting on a random note.
function generateNewTriads() {
// Clear the counters
correct = incorrect = 0;
// Find and clear the first measure in the piece
var measure = $(exercise).find('measure').first();
// Generate 4 quarter-note triads
for (var beat = 0; beat < 4; beat++) {
var initialStep = Math.floor(Math.random() * 7); // root pitch of triad
var triadStructure = [0, 2, 4]; // expressed in terms of diatonic scale steps from root
// Generate the 3 notes of the triad in the chord as MusicXML <note> elements
for (var i = 0; i < 3; i++) {
// Build the note element in jQuery. Tag the non-initial notes as parts of a chord.
var note = $("<note><type>quarter</type></note>");
if (i > 0) {
// Include a randomly octave-displaced pitch element including the next note of the triad
var pitch = $("<pitch><step/><octave/></pitch>");
var octaveDisplacement = Math.floor(Math.random() * 3);
pitch.find("step").text("ABCDEFG".charAt((initialStep + triadStructure[i]) % 7));
pitch.find("octave").text(4 + octaveDisplacement);
// Stick it into the measure
// Attach the appropriate event listener for clicks on root and non-root triad tones
if (i == 0) { {
$(this).attr('color', '#009900'); // turn note green
displayCounters(); // update counter
else { {
$(this).attr('color', '#FF0000');
<?xml version="1.0" encoding="UTF-8"?>
<!-- MusicXML template for DOM programming example -->
<!DOCTYPE score-partwise PUBLIC "-//Recordare//DTD MusicXML 2.0 Partwise//EN"
<score-partwise version="2.0">
<work-title>Discover Your Roots</work-title>
<software>Noteflight version 0.3.2</software>
<supports attribute="new-system" element="print" type="no" value="no"/>
<supports attribute="new-page" element="print" type="no" value="no"/>
<page-margins type="both">
<score-part id="P1">
<part id="P1">
<measure number="1">
<time print-object="no">
<clef number="1">
<note id="rest1">
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.