  function show_error(s) {
    var m = "<img src='http://static.supernifty.com.au/images/exclamation.png'/ style='vertical-align: middle' width='16' height='16'/> <b>Error: </b> " + s;
    show_status(m, "status");
    show_status(m, "status2");
  }

  function show_status( s, e ) {
    var el = document.getElementById(e),
      anim;
    if ( el != null ) {
      el.innerHTML = s; 
      anim = new YAHOO.util.ColorAnim(el, { backgroundColor:{to:"#fff", from:"#ff0"}, duration:1});
      anim.animate();
    }
  }

  function show_progress(s) {
    var m = s + " <img src='http://static.supernifty.com.au/images/progress.gif' style='vertical-align: middle' width='32' height='32'/></span>"; 
    show_status(m, "status");
    show_status(m, "status2");
  }

  function show_good(s) {
    var m = "<img src='http://static.supernifty.com.au/images/accept.png'/ style='vertical-align: middle' width='16' height='16'/> " + s; 
    show_status(m, "status");
    show_status(m, "status2");
  }

  function set_option( e, v ) {
    var el = document.getElementById(e),
      i;
    for ( i=0; i< el.options.length; i++ ) {
      if ( el.options[i].value == v ) {
        el.selectedIndex = i;
        break;
      }
    }
  }

  function parse_xml_string(xml) {
    try {
      xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
      xmlDoc.async="false";
      xmlDoc.loadXML(xml);
      return xmlDoc;
    }
    catch(e) {
      try {
        parser=new DOMParser();
        return parser.parseFromString(xml,"text/xml");
      }
      catch(e) {
        show_error( "Failed to parse XML" );
      }
    }
  }

  function raise_if_empty( element_name, display_name ) {
    if ( document.getElementById(element_name).value == "" ) {
      throw display_name + " cannot be empty";
    }
  }

  function build_xml() {
    raise_if_empty( "title", "Title" );
    raise_if_empty( "artist", "Artist" );
    raise_if_empty( "media_url", "YouTube URL" );
    raise_if_empty( "instrument", "Instrument" );
    var result = "<?xml version=\"1.0\"?> <playalong version=\"1.0\"> <title>" + 
        document.getElementById("title").value + "</title><artist>" + 
        document.getElementById("artist").value + "</artist><media type=\"youtube\">" + 
        document.getElementById("media_url").value + "</media><instrument>" +
        document.getElementById("instrument").value + "</instrument> <events>",
      events = dataTable.getRecordSet(),
      current, idx;
    if ( events.getLength() == 0 ) {
      throw "No chords specified";
    }
    for ( idx = 0; idx < events.getLength(); idx++ ) {
      current = events.getRecord(idx);
      if ( current.getData("start") == -1 ) {
        throw "Please define all timing information";
      }
      result += "<event start=\"" + current.getData("start") + "\"><chord>" + 
        current.getData("note") + "</chord><lyric>" +
        current.getData("lyric") + "</lyric></event>";
    }

    return result + "</events></playalong>";
  }

  function xml_details(root) {
    var result = [],
      events = root.getElementsByTagName('events')[0].getElementsByTagName('event'),
      event_data = [],
      idx, start;
    result['title'] = root.getElementsByTagName('title')[0].firstChild.nodeValue;
    result['artist'] = root.getElementsByTagName('artist')[0].firstChild.nodeValue;
    result['instrument'] = root.getElementsByTagName('instrument')[0].firstChild.nodeValue;
    result['media_url'] = root.getElementsByTagName('media')[0].firstChild.nodeValue;
    result['media_type'] = root.getElementsByTagName('media')[0].getAttribute("type");
    for ( idx = 0; idx < events.length; idx++ ) {
      start = events[idx].getAttribute("start");
      event_data[idx] = { "note":events[idx].getElementsByTagName("chord")[0].firstChild.nodeValue, "lyric":events[idx].getElementsByTagName("lyric")[0].firstChild.nodeValue, "start":start, "finish":9999 };
      if ( idx > 0 ) {
        event_data[idx-1]["finish"] = start;
      }
    }
    result['event_data'] = event_data;
    result['events_length'] = events.length;
    return result;
  }

  function show_hide( e ) {
    var box = document.getElementById(e);
    if ( box.style.display == "none" )
    {
      box.style.display = "block";
    }
    else
    {
      box.style.display = "none";
    }
  }

  function insert_line() {
    index = dataTable.getRecordIndex(dataTable.getLastSelectedRecord());
    dataTable.addRow( { "note":"C major", "lyric":"Double click to edit...", "start":-1 }, index );
    dataTable.unselectAllRows();
    adding = true;
    dataTable.selectRow(index);
  }

  function delete_line() {
    var rows = dataTable.getSelectedRows();
    if ( rows.length > 0 ) {
      dataTable.deleteRow( rows[0] );
    }
  }

  function add_line() {
    dataTable.addRow( { "note":"C major", "lyric":"Double click to edit...", "start":-1 } );
    dataTable.unselectAllRows();
    adding = true;
    dataTable.selectRow(dataTable.getLastTrEl());
  }

  function transpose_all(amt) {
     var events = dataTable.getRecordSet(),
       i;
     for ( i = 0; i < events.getLength(); i++ ) {
       note = events.getRecord(i).getData("note");
       events.getRecord(i).setData( "note", transpose(note, amt) );
     }
     dataTable.render();
  }

  var notes = [ "Ab", "A", "Bb", "B", "C", "C#", "D", "Eb", "E", "F", "F#", "G" ];
  function transpose(note, amount) {
    var found = false,
      i,
      components = note.split( " " );
    for ( i = 0; i < notes.length; i++ ) {
      if  ( notes[i] == components[0] ) {
        found = true;
        break;
      }
    }
    if ( !found ) {
      return note;
    }
    return notes[ ( i + amount + notes.length ) % notes.length ] + " " + components[1];
  }


