// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults

// Problems? 
// XXX escaping tagName ???

/*
 * ### sorting function ###
 *
 * alphabetizes the child tags of a tag by their text content
 *
 */ 
function sortChildren(e) {
  // the element whose children we'll be sorting
  if (typeof e == "string") {
    e = $(e);
  }

  // transfer the element (but not text node) children of e to a real array
  var kids = [];
  for(var x = e.firstChild; x != null; x = x.nextSibling) {
    // nodeType 1 is a Node.ELEMENT_NODE
    if (x.nodeType == 1) {
      kids.push(x);
    }
  }

  // sort the array based on the text content of each kid
  // we're assuming each kid has a first child that is a text node
  kids.sort(function(n, m) { // This is the comparator function for sorting
      var s = n.firstChild.data; // text of node n
      var t = m.firstChild.data; // text of node m
      if (s < t) return -1;      // n comes before m
      else if (s > t) return 1;  // n comes after m
      else return 0;             // n and m are equal
      });

  // append the kids back into the parent in their sorted order
  for(var i = 0; i < kids.length; i++) {
    e.appendChild(kids[i]);
    e.appendChild(document.createTextNode(" "));
  }
}

/*
 * ### select/option helper function ###
 *
 * retrieves the option tag of a select tag by the option tag's value
 *
 */ 
function getOptionByValue(selectElement, optValue) {
  var opts = selectElement.options;
  var o = null;
  var opt = null;
  for (var i = 0; i < opts.length; i++) {
    o = opts[i];
    if (optValue == o.value) {
      opt = o;
    }
  }
  return opt;
}


/*
 * ### dynamic tag addition and removal code ###
 */ 

// add filter tag to display
function addFilterTagDisplay(tagId, tagName) {
  // list of tags
  var list = $('tag-list-display');
  // create new tag span, a, text, etc.
  var newspan = document.createElement("span");
  newspan.id = ("tag-list-" + tagId);
  var newa = document.createElement("a");
  newa.href= "#";
  newa.className = "tag-remove";
  // add the removal function on clicks
  newa.onclick = removeFilterTag;
  var newimg = document.createElement("img");
  newimg.src = "/i/tag-cancel.gif";
  newimg.alt = "Remove Tag";
  var name = document.createTextNode(tagName);
  newa.appendChild(newimg);
  newspan.appendChild(name);
  newspan.appendChild(newa);
  list.appendChild(newspan);
  var space = document.createTextNode(" ");
  list.appendChild(space);
}

// add filter tag hidden form input
function addHiddenFilterTagInput(tagId, tagName) {
  // form fieldset
  var filterForm = $('tag-filter-form');
  // create new hidden tag input
  var newinput = document.createElement("input");
  newinput.id = ("tag-filter-" + tagId);
  newinput.type = "hidden";
  newinput.name = "filter_tags[]";
  newinput.value = tagName;
  filterForm.appendChild(newinput);
}

// add filter tag <input> to <select>
function addFilterTagSelect(tagId, tagName) {
  // get <select>
  var sel = $("add_tag");
  // create and append <option>
  var opt = document.createElement("option");
  var name = document.createTextNode(tagName);
  opt.value = tagId;
  opt.appendChild(name);
  sel.appendChild(opt);
}

// add filter tag
function addFilterTag() {
  var sel = $('add_tag');
  // nothing selected, don't do anything
  if (-1 == sel.selectedIndex) {
    return false;
  }
  // get tagId
  var tagId = sel.value;
  // the "(add a tag)" dummy value of -1 is selected, don't do anything
  if (-1 == tagId) {
    return false;
  }
  // get tagName
  var opt = sel.options[sel.selectedIndex];
  var tagName = opt.text;
  opt.parentNode.removeChild(opt);
  addHiddenFilterTagInput(tagId, tagName);
  addFilterTagDisplay(tagId, tagName);
  sortChildren('tag-list-display');
  return false;
}

// remove filter tag
function removeFilterTag() {
  // find filter tag <span>
  // 'this' is the <a> execcing the function onclick
  var span = this.parentNode;
  // get tagId with regexp
  var tagId = span.id.match(/-(\d+)$/)[1];
  // delete span
  span.parentNode.removeChild(span);
  // find filter tag <input>
  var hidden = $("tag-filter-" + tagId);
  // get tagName
  var tagName = hidden.value;
  // delete the hidden input
  hidden.parentNode.removeChild(hidden);
  addFilterTagSelect(tagId, tagName);
  sortChildren('add_tag');
  return false;
}

/*
 * ### smart select/form submission code ###
 *
 * only fires on mouse actions or enter
 * 
 * adapted from:
 * http://www.themaninblue.com/writing/perspective/2004/10/19/
 * http://www.themaninblue.com/experiment/AccessibleSelect/
 * http://www.themaninblue.com/experiment/AccessibleSelect/scripts/select_onchange.js
 */ 

function initSelect(selectId) {
    var theSelect = document.getElementById(selectId);

    theSelect.changed = false;
    theSelect.onfocus = selectFocused;
    theSelect.onchange = selectChanged;
    theSelect.onkeydown = selectKeyed;
    theSelect.onclick = selectClicked;

    return true;
}

function selectChanged(theElement) {
    var theSelect;

    if (theElement && theElement.value) {
        theSelect = theElement;
    }
    else {
        theSelect = this;
    }

    if (!theSelect.changed) {
        return false;
    }

    // action here
    if (theSelect.form.onsubmit) {
        // fire on submit if the form has it
        theSelect.form.onsubmit();
    }
    else {
        // fire submit
        theSelect.form.submit();
    }

    return true;
}

function selectClicked() {
    this.changed = true;
}

function selectFocused() {
    this.initValue = this.value;

    return true;
}

function selectKeyed(e) {
    var theEvent;
    var keyCodeReturn = "13";
    var keyCodeEsc = "27";

    if (e) {
        theEvent = e;
    }
    else {
        theEvent = event;
    }

    if ((theEvent.keyCode == keyCodeReturn) && this.value != this.initValue) {
        this.changed = true;
        selectChanged(this);
    }
    else if (theEvent.keyCode == keyCodeEsc) {
        this.value = this.initValue;
    }
    else {
        this.changed = false;
    }

    return true;
}
