// {{{ YAHOO.utilx.Collectione
YAHOO.namespace('utilx');
YAHOO.utilx.Collection = function() {
  var _each = function(data, iterator) {
    if (YAHOO.lang.isArray(data)) {
      for (var i = 0, l = data.length; i < l; i++) {
        iterator(data[i]);
      }
    } else if (data && typeof data === 'object') {
      for (var property in data) {
        iterator({key: property, value:data[property]});
      }
    }
  };
  return {
    $break: {},
    $continue: new Error('"throw $continue" is deprecated, use "return" instead'),
    each: function(data, iterator) {
      var index = 0;
      try {
        _each(data, function(value) {
          iterator(value, index++);
        });
      } catch (e) {
        if (e != this.$break) throw e;
      }
      return data;
    },
    map: function(data, iterator) {
      var results;
      this.each(data, function(value, index) {
        var result = (iterator || function(v) { return v;})(value, index);
        if (YAHOO.lang.isArray(data)) {
          results = results || [];
          results.push(result);
        } else {
          results = results || {};
          if (result && result['key'] && result['value']) {
            results[result['key']] = result['value'];
          }
        }
      });
      return results;
    },
    times: function(num, iterator) {
      for (var i = 0; i < num; i++) {
        iterator(i);
      }
    }
  }
}();
// }}}

// {{{ YAHOO.utilx.DDList
YAHOO.utilx.DDList = function(id, sGroup, config) {
  YAHOO.utilx.DDList.superclass.constructor.call(this, id, sGroup, config);

  var el = this.getDragEl();
  YAHOO.util.Dom.setStyle(el, "opacity", 0.67); // The proxy is slightly transparent

  this.goingUp = false;
  this.lastY = 0;
};

YAHOO.extend(YAHOO.utilx.DDList, YAHOO.util.DDProxy, {
  startDrag: function(x, y) {
    // make the proxy look like the source element
    var dragEl = this.getDragEl();
    var clickEl = this.getEl();
    YAHOO.util.Dom.setStyle(clickEl, "visibility", "hidden");

    dragEl.innerHTML = clickEl.innerHTML;

    YAHOO.util.Dom.setStyle(dragEl, "color", YAHOO.util.Dom.getStyle(clickEl, "color"));
    YAHOO.util.Dom.setStyle(dragEl, "backgroundColor", "#fcd575");
    YAHOO.util.Dom.setStyle(dragEl, "border", "2px solid gray");
  },

  endDrag: function(e) {

    var srcEl = this.getEl();
    var proxy = this.getDragEl();

    // Show the proxy element and animate it to the src element's location
    YAHOO.util.Dom.setStyle(proxy, "visibility", "");
    var a = new YAHOO.util.Motion(
      proxy, { points: { to: YAHOO.util.Dom.getXY(srcEl) } },
      0.2,
      YAHOO.util.Easing.easeOut
      )
    var proxyid = proxy.id;
    var thisid = this.id;

    // Hide the proxy and show the source element when finished with the animation
    a.onComplete.subscribe(function() {
      YAHOO.util.Dom.setStyle(proxyid, "visibility", "hidden");
      YAHOO.util.Dom.setStyle(thisid, "visibility", "");
    });
    a.animate();
  },

  onDragDrop: function(e, id) {
    // If there is one drop interaction, the li was dropped either on the list,
    // or it was dropped on the current location of the source element.
    if (YAHOO.util.DragDropMgr.interactionInfo.drop.length === 1) {

      // The position of the cursor at the time of the drop (YAHOO.util.Point)
      var pt = YAHOO.util.DragDropMgr.interactionInfo.point; 

      // The region occupied by the source element at the time of the drop
      var region = YAHOO.util.DragDropMgr.interactionInfo.sourceRegion; 

      // Check to see if we are over the source element's location.  We will
      // append to the bottom of the list once we are sure it was a drop in
      // the negative space (the area of the list without any list items)
      if (!region.intersect(pt)) {
        var destEl = YAHOO.util.Dom.get(id);
        var destDD = YAHOO.util.DragDropMgr.getDDById(id);
        destEl.appendChild(this.getEl());
        destDD.isEmpty = false;
        YAHOO.util.DragDropMgr.refreshCache();
      }
    }
  },

  onDrag: function(e) {

    // Keep track of the direction of the drag for use during onDragOver
    var y = YAHOO.util.Event.getPageY(e);

    if (y < this.lastY) {
      this.goingUp = true;
    } else if (y > this.lastY) {
      this.goingUp = false;
    }

    this.lastY = y;
  },

  onDragOver: function(e, id) {

    var srcEl = this.getEl();
    var destEl = YAHOO.util.Dom.get(id);

    // We are only concerned with list items, we ignore the dragover
    // notifications for the list.
    if (destEl.nodeName.toLowerCase() == "li") {
      var orig_p = srcEl.parentNode;
      var p = destEl.parentNode;

      if (this.goingUp) {
        p.insertBefore(srcEl, destEl); // insert above
      } else {
        p.insertBefore(srcEl, destEl.nextSibling); // insert below
      }

      YAHOO.util.DragDropMgr.refreshCache();
    }
  }
});
// }}}

YAHOO.namespace('Narabete');

// {{{ YAHOO.Narabete.Locale
YAHOO.Narabete.Resource = Resource || null;
Resource = null;
YAHOO.Narabete.Locale = function() {
  var data = {};
  return {
    getText: function(type, defaultText) {
      var text = defaultText || '';
      if (YAHOO.Narabete.Resource[type]) {
        text = YAHOO.Narabete.Resource[type];
      }
      return text;
    }
  }
}();
// }}}

// {{{ YAHOO.Narabete.Util
YAHOO.Narabete.Util = function() {
  var yud = YAHOO.util.Dom;
  function extend(destination, source) {
    for (var property in source) {
      destination[property] = source[property];
    }
    return destination;
  }
  return {
    getSimpleDialog: function(id, configs) {
      configs = extend({
        width: "300px",
          fixedcenter:true,
          draggable:false,
          close: false,
          modal:true,
          constraintoviewport: true
      }, configs || {});
      return new YAHOO.widget.SimpleDialog(id, configs);
    },

    getDialog: function(id, configs) {
      configs = extend({
          width: '600px',
          fixedcenter: true,
          draggable: false,
          modal: true,
          constraintoviewport: true
      }, configs || {});
      return new YAHOO.widget.Dialog(id, configs);
    },

    getCSRFValue: function() {
      return yud.get('userlogin').getElementsByTagName('input')[0].value;
    },
    setClipboard: function(element, path) {
      // IE only
      if (YAHOO.env.ua.ie != '0') {
        var copyText = element.createTextRange();
        copyText.execCommand("Copy");
        return;
      }
      // Mozilla uses flash player
      var swf_data = path + "setClipboard.swf";
      var tmp = document.createElement("div");
      tmp.innerHTML = [
        '<embed src="', swf_data, '"',
        ' FlashVars="code=',encodeURIComponent(element.value),'"',
        ' width="0" height="0"',
        '></embed>'
      ].join("");
      with(tmp.style){
        position ="absolute";
        left = "-10px";
        top  = "-10px";
        visibility = "hidden";
      };
      document.body.appendChild(tmp);
      setTimeout(function(){document.body.removeChild(tmp)},1000)
      return;
    },
    getText: function(element) {
      return (YAHOO.env.ua.ie != '0') ? element.innerText : element.textContent;
    },
    getLength: function(str) {
      var len = 0;
      for (var i = 0, l = str.length; i < l; i++) {
        var c = str.charCodeAt(i);
        if ((c >= 0x0 && c < 0x81) || (c == 0xf8f0) ||
          (c >= 0xff61 && c < 0xffa0) ||
          (c >= 0xf8f1 && c < 0xf8f4)) {
          len = len + 1;
          } else {
          len = len + 2 ;
        }
      }
      return len;
    }
  }
}();
// }}}

// {{{ YAHOO.Narabete.Moderate
YAHOO.Narabete.Moderate = function() {
  var yud = YAHOO.util.Dom;
  var ynu = YAHOO.Narabete.Util;
  var ynl = YAHOO.Narabete.Locale;
  function send(className, columnName, id, path) {
    var postData = 'class='+className+'&column='+columnName+'&id='+id+'&_csrf_token='+ynu.getCSRFValue();
    YAHOO.util.Connect.asyncRequest('POST', path, {
        success: function(o) {
          var moderation = yud.get('moderate-'+className+'-'+columnName+'-'+id);
          moderation.onclick = '';
          moderation.innerHTML = '×';
          yud.setStyle(moderation, 'backgroundColor', '#ccc');
        },
        failure: function(o) {
//          alert(ynl.getText('ajax_error'));
        }
    }, postData);

  }

  return {
    open: function(className, columnName, id, path) {
      var element = yud.get("moderate-"+className+"-"+columnName+"-"+id);
      var menuId = 'menu-'+className+'-'+columnName+'-' + id;

      var menu = null;
      if (!yud.get(menuId)) {
        menu = new YAHOO.widget.Menu(menuId, { visible: true });
        menu.addItem({ text: ynl.getText('moderation'), onclick: {fn: function() { send(className, columnName, id, path);} }});
      menu.render(yud.get(element));
      } else {
        menu = YAHOO.widget.MenuManager.getMenu(menuId);
        menu.show();
      }
    }
  }
}();
// }}}

// {{{ YAHOO.Narabete.DataTable
YAHOO.Narabete.DataTable = function(elContainer, oColumnSet, oDataSource, oConfigs) {
  if (arguments.length > 0) {
    YAHOO.Narabete.DataTable.superclass.constructor.call(this, elContainer , oColumnSet , oDataSource , oConfigs);
  }
}
YAHOO.lang.extend(YAHOO.Narabete.DataTable, YAHOO.widget.DataTable);
// {{{ overwrite _addTrEl and _onTbodyClick and _initColumnSort
/**
 * Adds a TR element to the primary TBODY at the page row index if given, otherwise
 * at the end of the page. Formats TD elements within the TR element using data * from the given Record.
 * FIXED BY shin 2007/11/10 for the first cols to be TH element.
 *
 * @method _addTrEl
 * @param oRecord {YAHOO.widget.Record} Record instance.
 * @param index {Number} (optional) The page row index at which to add the TR
 * element.
 * @return {String} ID of the added TR element, or null.
 * @private
 */
YAHOO.Narabete.DataTable.prototype._addTrEl = function(oRecord, index) {
  this.hideTableMessage();

  // It's an append if no index provided, or index is negative or too big
  var append = (!YAHOO.lang.isNumber(index) || (index < 0) ||
    (index >= (this._elTbody.rows.length))) ? true : false;

  var oColumnSet = this._oColumnSet;
  var oRecordSet = this._oRecordSet;
  var isSortedBy = this.get("sortedBy");
  var sortedColKeyIndex  = null;
  var sortedDir, newClass;
  if(isSortedBy) {
    sortedColKeyIndex = (isSortedBy.column) ?
      isSortedBy.column.getKeyIndex() :
      this._oColumnSet.getColumn(isSortedBy.key).getKeyIndex();
    sortedDir = isSortedBy.dir;
    newClass = (sortedDir === "desc") ? YAHOO.Narabete.DataTable.CLASS_DESC :
      YAHOO.Narabete.DataTable.CLASS_ASC;

  }

  var elRow = (append) ? this._elTbody.appendChild(document.createElement("tr")) :
    this._elTbody.insertBefore(document.createElement("tr"),this._elTbody.rows[index]);

  elRow.id = this.id+"-bdrow"+this._nTrCount;
  this._nTrCount++;
  elRow.yuiRecordId = oRecord.getId();

  // Create TD cells
  for(var j=0; j<oColumnSet.keys.length; j++) {
    var oColumn = oColumnSet.keys[j];
    // XXX fixed by shin
    var colTag = (j === 0) ? "th" : "td";
    var elCell = elRow.appendChild(document.createElement(colTag));
    elCell.id = elRow.id+"-cell"+oColumn.getId();
    elCell.yuiColumnKey = oColumn.getKey();
    elCell.yuiColumnId = oColumn.getId();

    for(var k=0; k<oColumnSet.headers[j].length; k++) {
      elCell.headers += this.id + "-col" + oColumnSet.headers[j][k] + " ";
    }
    // For SF2 cellIndex bug: http://www.webreference.com/programming/javascript/ppk2/3.html
    elCell.yuiCellIndex = j;

    // Update UI
    this.formatCell(elCell, oRecord, oColumn);

    // Set FIRST/LAST on TD
    if (j === 0) {
      YAHOO.util.Dom.addClass(elCell, YAHOO.Narabete.DataTable.CLASS_FIRST);
    }
    else if (j === this._oColumnSet.keys.length-1) {
      YAHOO.util.Dom.addClass(elCell, YAHOO.Narabete.DataTable.CLASS_LAST);
    }

    // Remove ASC/DESC
    YAHOO.util.Dom.removeClass(elCell, YAHOO.Narabete.DataTable.CLASS_ASC);
    YAHOO.util.Dom.removeClass(elCell, YAHOO.Narabete.DataTable.CLASS_DESC);

    // Set ASC/DESC on TD
    if(j === sortedColKeyIndex) {
      newClass = (sortedDir === "desc") ?
        YAHOO.Narabete.DataTable.CLASS_DESC :
        YAHOO.Narabete.DataTable.CLASS_ASC;
      YAHOO.util.Dom.addClass(elCell, newClass);
    }

        /*p.abx {word-wrap:break-word;}
    ought to solve the problem for Safari (the long words will wrap in your
tds, instead of overflowing to the next td.
(this is supported by IE win as well, so hide it if needed).

One thing, though: it doesn't work in combination with
        'white-space:nowrap'.*/

    // need a div wrapper for safari?
    //TODO: fix fixedWidth
    if(this.fixedWidth) {
      elCell.style.overflow = "hidden";
      //elCell.style.width = "20px";
    }
  }
  return elRow.id;
};
/**
 * Handles click events on the primary TBODY element.
 *
 * @method _onTbodyClick
 * @param e {HTMLEvent} The click event.
 * @param oSelf {YAHOO.widget.DataTable} DataTable instance.
 * @private
 */
YAHOO.widget.DataTable.prototype._onTbodyClick = function(e, oSelf) {
  var elTarget = YAHOO.util.Event.getTarget(e);
  var elTag = elTarget.tagName.toLowerCase();

  if(oSelf._oCellEditor && oSelf._oCellEditor.isActive) {
    oSelf.fireEvent("editorBlurEvent", {editor:oSelf._oCellEditor});
  }

  while(elTarget && (elTag != "table")) {
    switch(elTag) {
    case "body":
      break;
    case "input":
      if(elTarget.type.toLowerCase() == "checkbox") {
        oSelf.fireEvent("checkboxClickEvent",{target:elTarget,event:e});
      }
      else if(elTarget.type.toLowerCase() == "radio") {
        oSelf.fireEvent("radioClickEvent",{target:elTarget,event:e});
      }
      oSelf.fireEvent("tableClickEvent",{target:(elTarget || oSelf._elTable),event:e});
      return;
    case "a":
      oSelf.fireEvent("linkClickEvent",{target:elTarget,event:e});
      oSelf.fireEvent("tableClickEvent",{target:(elTarget || oSelf._elTable),event:e});
      return;
    case "button":
      oSelf.fireEvent("buttonClickEvent",{target:elTarget,event:e});
      oSelf.fireEvent("tableClickEvent",{target:(elTarget || oSelf._elTable),event:e});
      return;
    case "td":
      oSelf.fireEvent("cellClickEvent",{target:elTarget,event:e});
      break;
      // this 3 lines are added.
    case "th":
      oSelf.fireEvent("headerCellClickEvent",{target:elTarget,event:e});
      break;
    case "tr":
      oSelf.fireEvent("rowClickEvent",{target:elTarget,event:e});
      break;
    default:
      break;
    }
    elTarget = elTarget.parentNode;
    if(elTarget) {
      elTag = elTarget.tagName.toLowerCase();
    }
  }
  oSelf.fireEvent("tableClickEvent",{target:(elTarget || oSelf._elTable),event:e});
};

/**
 * Initializes Column sorting.
 *
 * @method _initColumnSort
 * @private
 */
YAHOO.widget.DataTable.prototype._initColumnSort = function() { };

/**
 * Populates TH cell as defined by Column.
 *
 * @method _initThEl
 * @param elTheadCell {HTMLElement} TH cell element reference.
 * @param oColumn {YAHOO.widget.Column} Column object.
 * @param row {number} Row index.
 * @param col {number} Column index.
 * @private
 */
YAHOO.widget.DataTable.prototype._initThEl = function(elTheadCell,oColumn,row,col) {
    // Clear out the cell of prior content
    // TODO: purgeListeners and other validation-related things
    var index = this._nIndex;
    var colKey = oColumn.getKey();
    var colId = oColumn.getId();
    elTheadCell.yuiColumnKey = colKey;
    elTheadCell.yuiColumnId = colId;
    if(oColumn.abbr) {
        elTheadCell.abbr = oColumn.abbr;
    }
    if(oColumn.width) {
        elTheadCell.style.width = oColumn.width;
    }

    var aCustomClasses;
    if(YAHOO.lang.isString(oColumn.className)) {
        aCustomClasses = [oColumn.className];
    }
    else if(YAHOO.lang.isArray(oColumn.className)) {
        aCustomClasses = oColumn.className;
    }
    if(aCustomClasses) {
        for(var i=0; i<aCustomClasses.length; i++) {
            YAHOO.util.Dom.addClass(elTheadCell,aCustomClasses[i]);
        }
    }
    
    YAHOO.util.Dom.addClass(elTheadCell, "yui-dt-col-"+colKey);
    
    elTheadCell.innerHTML = YAHOO.lang.isValue(oColumn.label) ? oColumn.label : colKey;
    elTheadCell.rowSpan = oColumn.getRowspan();
    elTheadCell.colSpan = oColumn.getColspan();
};
// }}}


YAHOO.Narabete.DataTable.prototype.addCol = function(oConfig, setCellValueFunc) {
  // Add ColumnSet
  var oColumnSet = this._oColumnSet;
  var column = new YAHOO.widget.Column(oConfig);
  var index = oConfig.key.replace("col", "");
  column._sId = index + "";
  column._sName = "Column instance" + index;
  column._nKeyIndex = oColumnSet.keys.length;
  column._colspan = 1;

  oColumnSet.flat.push(column);
  oColumnSet.keys.push(column);
  oColumnSet.tree[0].push(column);
  oColumnSet.headers[column._nKeyIndex] = [column._sId];
  YAHOO.widget.Column._nCount++;

  var columnId = column._sId;
  // Add Header Column
  var theadRow = this._elThead.firstChild;
  var theadCell = theadRow.insertBefore(document.createElement("th"), theadRow.lastChild);
  theadCell.id = this.id+"-col"+columnId;
  this._initThEl(theadCell, column, 0, column._nKeyIndex);

  // Add Body Columns
  var tbodyRows = this._elTbody.rows;
  for (var i = 0, l = tbodyRows.length; i < l; i++) {
    var row = tbodyRows[i];
    var elCell = null;
    var lastTd = row.lastChild;

    if (lastTd.rowSpan && (lastTd.rowSpan > 1 || tbodyRows.length == 1)) {
      elCell = row.insertBefore(document.createElement("td"), row.lastChild);
    } else {
      elCell = row.appendChild(document.createElement("td"));
    }

    elCell.id = row.id+"-cell"+columnId;
    elCell.yuiColumnKey = column.getKey();
    elCell.yuiColumnId = columnId;
    // XXX something wrong with headers?
    elCell.headers = this.id + "-col" + columnId;
    YAHOO.util.Dom.addClass(elCell, "yui-dt-col-col" + columnId);
    elCell.innerHTML = setCellValueFunc(row.id);
  }
}

YAHOO.Narabete.DataTable.prototype.removeCol = function(elCell) {
  var oColumnSet = this._oColumnSet;
  var column = this.getColumn(elCell);
  // Remove ColumnSet
  var id = column._sId;
  for (var i = 0, l = oColumnSet.flat.length; i < l; i++) {
    if (oColumnSet.flat[i] == column) {
      oColumnSet.flat.splice(i, 1);
      oColumnSet.keys.splice(i, 1);
      oColumnSet.tree[0].splice(i, 1);
    }
  }
  oColumnSet.headers.splice(column._nKeyIndex, 1);
  YAHOO.widget.Column._nCount--;
  // Remove Header Column
  var theadRow = this._elThead.firstChild;
  theadRow.removeChild(YAHOO.util.Dom.get(this.id+"-col"+id));

  // Remove Body Columns
  var tbodyRows = this._elTbody.rows;
  for (var i = 0, l = tbodyRows.length; i < l; i++) {
    var row = tbodyRows[i];
    row.removeChild(YAHOO.util.Dom.get(row.id+"-cell"+id));
  }
}
// }}}

// {{{ YAHOO.Narabete.Element
YAHOO.Narabete.Element = function() {
  var getInnerHTML = function(element) {
    var div = document.createElement('div');
    div.appendChild(element);
    return div.innerHTML;
  }

  var setOptions = function(element, options) {
    for (var key in options) {
      if (YAHOO.env.ua.ie != '0' && key == 'class') {
        element.setAttribute('className', options[key]);
      } else {
        element.setAttribute(key, options[key]);
      }
    }
    return element;
  }
  return {
    createLiElement: function(options, asText) {
      var element = document.createElement('li');
      setOptions(element, options);
      return (asText) ? getInnerHTML(element) : element;
    },
    createInputElement: function(type, name, value, options, asText) {
      type = type || 'text';
      name = name || 'dummy';
      value = value || '';
      var element = null;

      if (YAHOO.env.ua.ie != '0') {
        element = document.createElement('<input name="'+name+'">');
      } else {
        element = document.createElement('input');
        element.setAttribute('name', name);
      }
      element.setAttribute('type', type);
      element.setAttribute('value', value);
      setOptions(element, options);
      return (asText) ? getInnerHTML(element) : element;
    },

    createAnchorElement: function(href, value, options, asText) {
      href = href || '#';
      value = value || href;
      var element = document.createElement('a');
      element.setAttribute('href', href);
      element.appendChild(document.createTextNode(value));
      setOptions(element, options);
      return (asText) ? getInnerHTML(element) : element;
    },

    createDivElemen: function(value, options, asText) {
      var element = document.createElement('div');
      element.appendChild(document.createTextNode(value));
      setOptions(element, options);
      return (asText) ? getInnerHTML(element) : element;
    },

    createSpanElement: function(value, options, asText) {
      value = value || 'foobar';
      var element = document.createElement('span');
      element.appendChild(document.createTextNode(value));
      setOptions(element, options);
      return (asText) ? getInnerHTML(element) : element;
    }
  }
}();
// }}}

// {{{ YAHOO.Narabete.Login
YAHOO.Narabete.Login = function() {
  var ynu = YAHOO.Narabete.Util;
  var yud = YAHOO.util.Dom;
  return {
    showLogin: function(id) {
      yud.setStyle(yud.get(id), 'display', 'block');
      var anim = new YAHOO.util.Anim(id, {height: {to: 48}}, 0.1);
      anim.animate();
    },
    hideLogin: function(id) {
      var anim = new YAHOO.util.Anim(id, {height: {to: 0}}, 0.1);
      anim.onComplete.subscribe(function() {
        yud.setStyle(this.getEl(), 'display', 'none');
      });
      anim.animate();
    },
    authorize: function(path, callback) {
      callback = callback || function() {};
      var postData = '_csrf_token='+ynu.getCSRFValue();
      YAHOO.util.Connect.asyncRequest('POST', path, {
        success: function(o) {
          if (o.responseText == 'OK') {
            callback('authorized');
          } else {
            callback('unauthorized');
          }
        },
        failure: function(o) {
            callback('unauthorized');
        }
      }, postData);
    }
  }
}();
// }}}

// {{{ YAHOO.Narabete.Mylist
YAHOO.Narabete.Mylist = function() {
  var yud = YAHOO.util.Dom;
  var ynu = YAHOO.Narabete.Util;
  var ynl = YAHOO.Narabete.Locale;

  function requestAdd(formElement, parameters) {
    parameters = parameters || [];

    var path = formElement.getAttribute('action');
    var inputs = formElement.getElementsByTagName('input');
    var select = formElement.getElementsByTagName('select')[0];
    for (var i = 0, l = inputs.length; i < l; i++) {
      parameters.push(inputs[i].name+'='+inputs[i].value);
    }
    parameters.push(select.name+'='+select[select.selectedIndex].value);

    YAHOO.util.Connect.asyncRequest('POST', path, {
        success: function(o) {
          yud.setStyle(yud.getNextSibling(formElement), 'display', 'inline');
        },
        failure: function(o) {
          alert(ynl.getText('ajax_error'));
        }
    }, parameters.join('&'));
  }

  return {
    dialog: null,
    add: function(id) {
      yud.setStyle(id, 'display', (yud.get(id).style.display != 'none') ? 'none' : 'inline');
      yud.setStyle('add-new-mylist', 'display', 'none');
    },

    show: function(id, mylistPath) {
      var postData = 'id='+id+'&_csrf_token='+ynu.getCSRFValue();
      YAHOO.util.Connect.asyncRequest('POST', mylistPath, {
        success: function(o) {
          if (o.responseText != 'NG') {
            yud.get('mylist').innerHTML = o.responseText;
            new YAHOO.widget.Button('mylist-add-button');
          }
        },
        failure: function(o) {
//          alert(ynl.getText('ajax_error'));
        }
      }, postData);
    },

    createCategory: function(select) {
      var dialog = this.dialog;
      var categoryId = select[select.selectedIndex].value;
      if (categoryId === 'newLabel') {
        yud.get('name').value = '';
        yud.setStyle('add-new-mylist', 'display', 'block');
        var buttons = [
          {text: 'OK', handler: function() {
            var options = select.getElementsByTagName('option');
            var nameValue = yud.get('name').value;
            for (var i = 0, l = options.length; i < l; i++) {
              if (options[i].text == nameValue) {
                alert(ynl.getText('duplicate_category'));
                return;
              }
            }
            var newOption = document.createElement('option');
            newOption.text = nameValue;
            newOption.value = '';
            select.insertBefore(newOption, select.firstChild);
            newOption.selected =  true;
            select.parentNode.insert
            dialog.cancel();
          }},
          {text: 'Cancel', handler: function() { dialog.cancel(); select.selectedIndex = 0;}}
        ];
        if (!dialog) {
          dialog = YAHOO.Narabete.Util.getDialog("add-new-mylist", {
            close: false,
            width: "400px",
            buttons: buttons
          });
          dialog.render();
          this.dialog = dialog;
        } else {
          dialog.show();
        }
      }
    },

    addOK: function(formElement) {
      var select = formElement.getElementsByTagName('select')[0];
      var categoryId = select[select.selectedIndex].value;
      if (categoryId !== 'newLabel') {
        requestAdd(formElement);
      } else {

      }
      // ALWAYS return false
      return false;
    },

    remove: function(element) {
      yud.setStyle(element.parentNode, 'display', 'none');
      yud.setStyle(yud.getNextSibling(element.parentNode), 'display', 'inline');
    },

    removeOK: function(element, id, requestPath, isCategory) {
      isCategory = isCategory || false;
      var postData = 'id='+id+'&_csrf_token='+ynu.getCSRFValue();
      YAHOO.util.Connect.asyncRequest('POST', requestPath, {
        success: function(o) {
          if (isCategory) {
            yud.get(element).innerHTML = ynl.getText('uncategorized');
          } else {
            var anim = new YAHOO.util.Anim(element, {height: {to: 0}}, 0.1);
            anim.onComplete.subscribe(function() {
              yud.setStyle(element, 'display', 'none');
            });
            anim.animate();
          }
        },
          failure: function(o) {
//            alert(ynl.getText('ajax_error'));
          }
      }, postData);
    },

    removeNG: function(element) {
        yud.setStyle(element.parentNode, 'display', 'none');
        yud.setStyle(yud.getPreviousSibling(element.parentNode), 'display', 'inline');
    }
  }
}();
// }}}

// {{{ YAHOO.Narabete.Table
YAHOO.Narabete.Table = function() {
  // {{{ protected
  var yud = YAHOO.util.Dom;
  var yuc = YAHOO.utilx.Collection;
  var yne = YAHOO.Narabete.Element;
  var ynu = YAHOO.Narabete.Util;
  var ynl = YAHOO.Narabete.Locale;
  var dataTable = null;

  function createRow(keys, rowName, cellValues, setCellFunc) {
    var results = {};
    yuc.each(keys, function(k, i) {
      if (k.key == "/") {
        results[k.key] = rowName;
      } else {
        var cellValue = (cellValues && cellValues[i-1]) ? cellValues[i-1] : 0;
        results[k.key] = setCellFunc(cellValue);
      }
    });
    return results;
  }

  function setAddRow(colSpan, label) {
    var table = dataTable.getTableEl();
    var lastChild = table.lastChild;
    if (lastChild.nodeName.toUpperCase() == 'TFOOT') {
      lastChild.getElementsByTagName('td')[0].setAttribute('colSpan', colSpan);
    } else {
      var td = document.createElement('td');
      td.setAttribute('id', 'create-addrow');
      td.setAttribute('colSpan', colSpan);
      td.innerHTML = label;

      var tr = document.createElement('tr');
      tr.appendChild(td);

      var tfoot = document.createElement('tfoot');
      tfoot.appendChild(tr);
      table.appendChild(tfoot);
    }
  }

  function setAddCol(rowSpan, label) {
    var firstTr = dataTable.getFirstTrEl();
    var lastChild = firstTr.lastChild;
    if (yud.get('create-addcol')) {
      lastChild.setAttribute('rowSpan', rowSpan);
    } else {
      var th = document.createElement('th');
      yud.addClass(th, 'add-col');
      th.innerHTML = "&nbsp;";
      dataTable.getTheadEl().firstChild.appendChild(th);

      var button = document.createElement('div');
      button.setAttribute('id', 'create-addcol');
      button.innerHTML = label;
      var td = document.createElement('td');
      td.setAttribute('rowSpan', rowSpan);
      td.appendChild(button);
      firstTr.appendChild(td);
    }
  }

  function createInitialColumnDef(colNames, setLabelFunc) {
    setLabelFunc = setLabelFunc || function(x) { return x; };
    var results = [{key:"/", label: "&nbsp;"}];
    yuc.each(colNames, function(colName, i) {
      results.push({key: "col"+(i+1), label: setLabelFunc(colName)});
    });
    return results;
  }

  function createInitialDataSource(colNames) {
    // initial DataSource
    var dataSource = new YAHOO.util.DataSource([]);
    dataSource.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
    dataSource.responseSchema = { fields: function() {
      var results = ["/"];
      yuc.times(colNames.length, function(i) { results.push("col"+(i+1)); });
      return results;
    }()};
    return dataSource;
  }

  // }}}
  return {
    // {{{ Creator
    Creator: function() {
      // {{{ private
      var rowIndex = 0;
      var colIndex = 0;

      function getOkValue(selected) {
        return yne.createSpanElement(ynl.getText('yea'), {
          'class': 'value'+ ((selected) ? ' yea selected' : ''),
          'onclick': 'narabete.selectValue(1, this);'
        }, true);
      }
      function getNgValue(selected) {
        return yne.createSpanElement(ynl.getText('nay'),{
          'class': 'value'+ ((selected) ? ' nay selected' : ''),
          'onclick': 'narabete.selectValue(-1, this);'
        }, true);
      }
      function getNonValue(selected) {
        return yne.createSpanElement(ynl.getText('neutral'),{
          'class': 'value'+ ((selected) ? ' non selected' : ''),
          'onclick': 'narabete.selectValue(0, this);'
        }, true);
      }
      function getValueHolder(rowIndex, cellValue) {
        return yne.createInputElement('hidden', 'cellValues['+(rowIndex)+'][]', 'neutral',
          { 'value': cellValue || '0' },
          true)
      }

      function getRowHeader(rowName) {
        if (YAHOO.lang.isObject(rowName)) {
          rowName = null;
        }
        rowIndex++;
        var name = 'rowNames[]';
        rowName = (rowName != null) ? rowName : ynl.getText('row') + rowIndex;
        return yne.createInputElement('text', name, rowName, { 'class': 'row-name' }, true) +
          yne.createAnchorElement('#', '[X]', {
            'onclick': 'narabete.removeRow(this); return false'
          }, true);
      }

      function getColHeader(colName) {
        colIndex++;
        var name = 'colNames[]';
        colName = (colName != undefined) ? colName : ynl.getText('column') + colIndex;
        return yne.createInputElement('text', name, colName, { 'class': 'col-name' }, true) +
          yne.createAnchorElement('#', '[X]', {
            'onclick': 'narabete.removeCol(this); return false'
          }, true);
      }

      function setCellFunc(cellValue) {
        return'<div class="create-text">' +
          getOkValue(cellValue > 0) +
          getNonValue(cellValue == 0) +
          getNgValue(cellValue < 0) +
          getValueHolder(rowIndex-1, cellValue) +
          '</div>';
      }
      // }}}
      return {
        // {{{ public
        init: function(id, data) {
          var self = this;

          var colNames = data.colNames;
          var rowNames = data.rowNames;

          var columnDef = createInitialColumnDef(colNames, getColHeader);
          var dataSource = createInitialDataSource(colNames);

          // create
          dataTable = new YAHOO.Narabete.DataTable(id, columnDef, dataSource);
          yuc.times(rowNames.length, function(i) {
            self.addRow(rowNames[i], (data.cellValues == null) ? null : data.cellValues[i]);
          });
          setTimeout(function() {
            setAddRow(colNames.length + 2, '<a href="#" onclick="narabete.addRow()">'+ynl.getText('row_add')+'</a>');
            setAddCol(rowNames.length, '<div style="margin:3em;width:1em;"><a href="#" onclick="narabete.addCol()">'+ynl.getText('column_add')+'</a></div>');
          }, 0);
        },

        addRow: function(rowName, cellValues) {
          var columnSet = dataTable.getColumnSet();
          dataTable.addRow(createRow(
            columnSet.keys,
            getRowHeader(rowName),
            cellValues,
            setCellFunc));
            setAddCol(dataTable.getTbodyEl().rows.length, '<div style="margin:3em;width:1em;"><a href="#" onclick="narabete.addCol()">'+ynl.getText('column_add')+'</a></div>');
        },

        removeRow: function(row) {
          if (dataTable.getTbodyEl().rows.length < 2) {
            alert(ynl.getText('row_invalid_removal'));
            return;
          }
          if (dataTable.getFirstTrEl() ==  row.parentNode.parentNode) {
            var theadTr = dataTable.getTheadEl().firstChild;
            theadTr.removeChild(theadTr.lastChild);
            var firstRow = dataTable.getFirstTrEl();
            firstRow.removeChild(firstRow.lastChild);
          }
          dataTable.deleteRow(row.parentNode);
          setAddCol(dataTable.getTbodyEl().rows.length, '<div style="margin:3em;;width:1em;"><a href="#" onclick="narabete.addCol()">'+ynl.getText('column_add')+'</a></div>');
        },

        addCol: function() {
          var setCellValueFunc = function(index) {
            index = index.replace(dataTable.id, "").replace("-bdrow", "");
            return'<div class="create-text">' +
              getOkValue(false) +
              getNonValue(true) +
              getNgValue(false) +
              getValueHolder(index) +
              '</div>';
          }

          dataTable.addCol({label: getColHeader(), key: "col"+colIndex}, setCellValueFunc);
          setAddRow(YAHOO.widget.Column._nCount + 1, '<a href="#" onclick="narabete.addRow()">'+ynl.getText('row_add')+'</a>');
        },

        removeCol: function(col) {
          if (dataTable.getTbodyEl().rows[0].getElementsByTagName('td').length < 3) {
            alert(ynl.getText('row_invalid_removal'));
            return;
          }
          dataTable.removeCol(col);
          setAddRow(YAHOO.widget.Column._nCount + 1, '<a href="#" onclick="narabete.addRow()">'+ynl.getText('row_add')+'</a>');
        },

        selectValue: function(value, element) {
          var cell = element.parentNode;
          var valueHolder = cell.lastChild;
          var className = '';

          yuc.each(cell.getElementsByTagName('span'), function(span) {
            yud.removeClass(span.value, 'yea');
            yud.removeClass(span.value, 'nay');
            yud.removeClass(span.value, 'non');
            yud.removeClass(span.value, 'selected');
          });
          if (valueHolder.value == value) {
            value = 0;
          }
          valueHolder.setAttribute('value', value);
          if (value > 0) {
            className = 'yea selected';
          } else if (value < 0) {
            className = 'nay selected';
          } else {
            className = 'non selected';
          }
          yud.addClass(element, className);
        },

        prepareSubmit: function() {
          var errors = [];
          var thead = dataTable.getTheadEl();
          var tbody = dataTable.getTbodyEl();

          var colNames = yud.getElementsByClassName('col-name', 'input', thead);
          var rowNames = yud.getElementsByClassName('row-name', 'input', tbody);

          // table-name is required
          if (yud.get('table-name').value == '') {
            errors.push(ynl.getText('name_required'));
          }
          // at least one col is required
          if (colNames.length == 0) {
            errors.push(ynl.getText('column_required'));
          }
          // at least one row is required
          if (rowNames.length == 0) {
            errors.push(ynl.getText('row_required'));
          }
          // colName value is required
          yuc.each(colNames, function(colName) {
            if (colName.value == '') {
              errors.push(ynl.getText('column_empty'));
            }
          });
          // rowName value is required
          yuc.each(rowNames, function(rowName) {
            if (rowName.value == '') {
              errors.push(ynl.getText('row_empty'));
            }
          });

          if (errors.length > 0) {
            alert(errors.join("\n"));
            return false;
          }
        }
      // }}}
      }
    }(),
// }}}

// {{{ Display
    Display: function() {
      // {{{ private
      var votedCells = [];
      var moderatePath = '';
      var configurePath = '';
      var showRowIds = [];
      var showColIds = [];
      var tabs = null;
      function isVoted(cellId) {
        for (var i = 0, l = votedCells.length; i < l; i++) {
          if (cellId == votedCells[i]) {
            return true;
          }
        }
        return false;
      }

      function setCellFunc(cellValue) {
        var value = '';
        var className = 'current';
        if (cellValue.value > 0) {
          value = ynl.getText('yea');
          className = 'current current-yea';
        } else if (cellValue.value < 0) {
          value = ynl.getText('nay');
          className = 'current current-nay';
        } else {
          value = ynl.getText('neutral');
          className = 'current';
        }
        var id = cellValue.id;
        var html = '<div id="'+id+'" class="show-text">';
        html += '<div id="positive-'+id+'" class="positive hidden" onclick="narabete.selectValue(1, this);">'+ynl.getText('yea')+'</div>';
        html += '<div class="'+className+'">'+value+'</div>';
        html += '<div id="negative-'+id+'" class="negative hidden" onclick="narabete.selectValue(-1, this);">'+ynl.getText('nay')+'</div>';
        html += '</div>';
        return html;
      }

      function getHeader(name, isRow) {
        var className = isRow ? 'row' : 'column';
        var columnClass = isRow ? '' : ' thumbs-column';
        var text = '<div class="show-text">';
        text += '<div id="'+name.id+'" class="label">'+name.value+'</div>';
        text += isRow ? '' : '<div></div>';
        text += '<div class="thumbs'+columnClass+'">';
        text += '<div class="up" onclick="narabete.thumbsDo(this, \''+className+'\', \'name\', '+name.id+', \'up\')"><img src="/images/up.gif" class="transparent clickable" onmouseover="YAHOO.util.Dom.removeClass(this, \'transparent\')" onmouseout="YAHOO.util.Dom.addClass(this, \'transparent\')"></div>';
        text += '<div class="down" onclick="narabete.thumbsDo(this, \''+className+'\', \'name\', '+name.id+', \'down\')"><img src="/images/down.gif" class="transparent clickable" onmouseover="YAHOO.util.Dom.removeClass(this, \'transparent\')" onmouseout="YAHOO.util.Dom.addClass(this, \'transparent\')"></div></div>';
        text += '</div>';
        return text;
      }
      function prepare(data, limit) {
          var pathArray = location.pathname.split("/");
          showRowIds = pathArray[pathArray.length - 2].split("-");
          showColIds = pathArray[pathArray.length - 1].split("-");

          var rowLength = data.rowNames.length;
          var colLength = data.colNames.length;

          var rowNames = [];
          var colNames = [];
          var cellValues = [];

          var rowMessage = '';
          var colMessage = '';

          if (!isNaN(+showRowIds[0]) && showRowIds.length > 0 && showColIds.length > 0) {
            var tCellValues = [];
            yuc.times(showRowIds.length, function(i) {
              yuc.times(data.rowNames.length, function(j) {
                if (data.rowNames[j].id == showRowIds[i]) {
                  rowNames.push(data.rowNames[j]);
                  tCellValues.push(data.cellValues[j]);
                }
              });
            });
            yuc.times(showColIds.length, function(i) {
              yuc.times(data.colNames.length, function(j) {
                if (data.colNames[j].id == showColIds[i]) {
                  colNames.push(data.colNames[j]);
                  yuc.times(tCellValues.length, function(k) {
                    cellValues[k] = cellValues[k] || [];
                    cellValues[k].push(tCellValues[k][j]);
                  });
                }
              });
            });
          } else {
            // DEAFAULT
            rowNames = data.rowNames.splice(0, limit);
            colNames = data.colNames.splice(0, limit);
            showRowIds = yuc.map(rowNames, function(o) { return o.id; });
            showColIds = yuc.map(colNames, function(o) { return o.id; });
            cellValues = data.cellValues;
          }

          if (rowLength > showRowIds.length) {
            rowMessage = "<div style='background:#dbb'>";
            rowMessage += "<a onclick='narabete.configure();return false;' href='#'>"+ynl.getText('row_overflow')+"</a>";
            rowMessage += "</div>";
          }
          if (colLength > showColIds.length) {
            colMessage = "<a onclick='narabete.configure();return false;' href='#'>"+ynl.getText('column_overflow')+"</a>";
          }
          if (rowNames.length < 1 && colNames.length < 1) {
            return false;
          }
          return {rowNames: rowNames, colNames: colNames, cellValues: cellValues, rowMessage: rowMessage, colMessage: colMessage};
      }
      function getIds(labels) {
        var tmp = null;
        var tmpArray = [];
        for (var i = 0, l = labels.length; i < l; i++) {
          tmp = labels.item(i).getElementsByTagName('div').item(1);
          if (tmp) {
            tmpArray.push(tmp.id);
          }
        }
        return tmpArray;
      }

      function setCopyPanelTab(tabId, element) {
        if (yud.get("widget-text")) {
          tabs.set('activeIndex', 0);
          return tabs;
        }
        tabs = new YAHOO.widget.TabView(tabId, {activeIndex: 0});
        tabs.addTab(new YAHOO.widget.Tab({
          label: ynl.getText("paste_as_widget"),
          content: '<textarea id="widget-text" rows="3" readonly="readonly" onclick="this.select();"></textarea><div>'+ynl.getText("widget_explanation")+'</div>',
          active: true
        }));
        tabs.addTab(new YAHOO.widget.Tab({
          label: ynl.getText("paste_as_html"),
          content: '<textarea id="html-text" rows="3" readonly="readonly" onclick="this.select();"></textarea><div>'+ynl.getText("html_explanation")+'</div>'
        }));
        tabs.addTab(new YAHOO.widget.Tab({
          label: ynl.getText("paste_as_text"),
          content: '<textarea id="text-text" rows="3" readonly="readonly" onclick="this.select();"></textarea><div>'+ynl.getText("text_explanation")+'</div>'
        }));
        tabs.getTab(0).addListener('click', function(e) {
          type = 'widget';
          setCopyText(element.getElementsByTagName('textarea')[0], type);
        });
        tabs.getTab(1).addListener('click', function(e) {
          type = 'html';
          setCopyText(element.getElementsByTagName('textarea')[1], type);
        });
        tabs.getTab(2).addListener('click', function(e) {
          type = 'text';
          setCopyText(element.getElementsByTagName('textarea')[2], type);
        });
        return tabs;
      }

      function setCopyText(container, type) {
        type = type || 'text';
        var tableName = yud.get('table-name').getElementsByTagName('span')[0].innerHTML;
        var tableUrl = location.href;

        showColIds = getIds(dataTable.getTheadEl().getElementsByTagName('th'));
        showRowIds = getIds(dataTable.getTbodyEl().childNodes);

        if (tableUrl.match("-") == null) {
          tableUrl = tableUrl+"/"+showRowIds.join('-')+"/"+showColIds.join('-');
        }

        var widgetOutputter = function() {
          var paths = tableUrl.split("/");
          var tableId = paths[paths.length - 3];
          var url = paths[0] + '/' + paths[1] + '/' + paths[2];
          var result = ["<script type=\"text/javascript\" src=\""+url+"/js/widget.js\"></script>\n"];
          result.push("<script type=\"text/javascript\">\n");
          result.push("<!--\n");
          result.push("Narabete.Widget.init({");
          result.push("tableId: "+tableId+" ,");
          result.push("url: \""+url+"/\" ,");
          return {
            setHeader: function(ths) {
              var header = null;
              var cols = [];
              for (var i = 0, l = ths.length; i < l; i++) {
                header = ths[i].getElementsByTagName('div')[1];
                if (header) {
                  cols.push(header.id);
                }
              }
              result.push("cols: ["+cols.join(",")+"], ");
            },
            setBody: function(trs) {
              var header = null;
              var rows = [];
              for (var i = 0, l = trs.length; i < l; i++) {
                header = trs[i].getElementsByTagName('div')[1];
                if (header) {
                  rows.push(header.id);
                }
              }
              result.push("rows: ["+rows.join(",")+"]");
            },
            getResult: function() {
              result.push("});\n");
              result.push("-->");
              result.push("</script>");
              return result.join("");
            }
          }
        }();
        var htmlOutputter = function() {
          var result = ["<table class='narabete'> "];
          result.push("<caption><a href='"+tableUrl+"'>"+tableName+"</a> by <a href='http://"+location.host+"/'>"+ynl.getText('app_name')+"</a></caption> ");
          return {
            setHeader: function(ths) {
              result.push("<thead><tr> ");
              for (var i = 0, l = ths.length; i < l; i++) {
                if (yud.hasClass(ths[i], 'add-col')) {
                  break;
                }
                result.push("<th>" + ynu.getText(ths[i]) + "</th> ");
              }
              result.push("</tr></thead> ");
            },
            setBody: function(trs) {
              result.push("<tbody>");
              var className = 'odd';
              for (var i = 0, l = trs.length; i < l; i++) {
                className = ((i+1)%2==1) ? 'odd' : 'even';
                result.push("<tr class=\""+className+"\"> ");
                var th = trs[i].getElementsByTagName('th')[0];
                result.push("<th>"+ynu.getText(th)+"</th> ");
                var values = yud.getElementsByClassName('current', 'div', trs[i]);
                for (var j = 0, jl = values.length; j < jl; j++) {
                  result.push("<td>"+ynu.getText(values[j])+"</td> ");
                }
                result.push("</tr> ");
              }
              result.push("</tbody>");
            },
            getResult: function() {
              result.push("</table>");
              return result.join("");
            }
          }
        }();
        var textOutputter = function() {
          var result = [];
          var longestRowLength = 0;
          var rowIndexes = [];
          var colsLength = [];
          return {
            setHeader: function(ths) {
              rowIndexes.push(0);
              for (var i = 0, l = ths.length; i < l; i++) {
                if (yud.hasClass(ths[i], 'add-col')) {
                  break;
                }
                var colName = ynu.getText(ths[i]);
                result.push(colName);
                colsLength.push(ynu.getLength(colName));
              }
              colsLength.shift();
              result.push("\n");
            },
            setBody: function(trs) {
              // xxx mozilla needs 1, while ie need 0 to fix whitespace.
              var start = (YAHOO.env.ua.ie != '0') ?  0 : 1;
              for (var i = 0, l = trs.length; i < l; i++) {
                var th = trs[i].getElementsByTagName('th')[0];
                var rowName = ynu.getText(th);

                var rowLength = ynu.getLength(rowName);

                longestRowLength = (longestRowLength < rowLength) ?  rowLength : longestRowLength;
                result.push(rowName);
                rowIndexes.push(result.length -1);

                var values = yud.getElementsByClassName('current', 'div', trs[i]);
                for (var j = 0, jl = values.length; j < jl; j++) {
                  var value = ynu.getText(values[j]);
                  var fixLength = colsLength[j] - ynu.getLength(value);

                  for (var k = start; k < fixLength; k++) {
                    value = value + " ";
                  }
                  result.push(value);
                }
                result.push("\n");
              }
            },
            getResult: function() {
              var rowLength = 0;
              for (var i = 0; i < rowIndexes.length; i++) {
                rowLength = ynu.getLength(result[rowIndexes[i]]);
                for (var j = rowLength; j < longestRowLength; j++) {
                  result[rowIndexes[i]] = result[rowIndexes[i]] + " ";
                }
              }
              result.unshift(tableName+" by "+ynl.getText('app_name')+"(http://"+location.host+")\n");
              var resultText = result.join("|") + "\n";
              resultText += resultText = ynl.getText("to_updated") + " " + tableUrl;
              return resultText;
            }
          }
        }();
        var outputter = eval(type + "Outputter");
        outputter.setHeader(dataTable.getTheadEl().getElementsByTagName('th'));
        outputter.setBody(dataTable.getTbodyEl().childNodes);
        container.value = outputter.getResult();
      }

      function setEvent() {
          dataTable.subscribe("cellMouseoverEvent", function(args) {
            var td = dataTable.getTdEl(args.target);
            var id = td.firstChild.id;
            if (id != 'create-addcol' && !(isVoted(id))) {
                yud.removeClass("positive-"+id, 'hidden');
                yud.removeClass("negative-"+id, 'hidden');
            }
          }, true);

          dataTable.subscribe("cellMouseoutEvent", function(args) {
            var td = dataTable.getTdEl(args.target);
            var id = td.firstChild.id;
            yud.addClass("positive-"+id, 'hidden');
            yud.addClass("negative-"+id, 'hidden');
          }, true);
      }

      function rowUpDown(element, action) {
        var source = yud.getAncestorByTagName(element, 'tr');
        var target = (action == 'up') ? yud.getPreviousSibling(source) : yud.getNextSibling(source);
        if (target == null) {
          return null;
        }

        var tmpS = null;
        var tmpT = null;
        var tmp = null;
        for (var i = 0, l = source.childNodes.length; i < l; i++) {
          tmpS = source.childNodes.item(i);
          tmpT = target.childNodes.item(i);
          tmpT.insertBefore(tmpS.firstChild, tmpT.firstChild);
          tmpS.appendChild(tmpT.childNodes.item(1));
        }
        return target;
      }

      function columnUpDown(element, action) {
        var source = yud.getAncestorByTagName(element, 'th');
        var target = (action == 'up') ? yud.getPreviousSibling(source) : yud.getNextSibling(source);
        if (yud.hasClass(target, 'yui-dt-first') || yud.hasClass(target, 'add-col')) {
          return null;
        }
        // get index
        var headers = dataTable.getTheadEl().firstChild.childNodes;
        var sourceIndex = 0;
        var targetIndex = 0;
        for (var i = 0, l = headers.length; i < l; i++) {
          if (headers.item(i) == source) {
            sourceIndex = i;
          } else if (headers.item(i) == target) {
            targetIndex = i;
          }
        }
        // swap header
        source.insertBefore(target.firstChild, source.firstChild);
        target.appendChild(source.childNodes.item(1));
        // swap values
        var trs = dataTable.getTbodyEl().childNodes;
        var targetCol;
        var sourceCol;
        for (var i = 0, l = trs.length; i < l; i++) {
          var children = trs.item(i).childNodes;
          sourceCol = children.item(sourceIndex);
          targetCol = children.item(targetIndex);
          sourceCol.insertBefore(targetCol.firstChild, sourceCol.firstChild);
          targetCol.appendChild(sourceCol.childNodes.item(1));
        }
        return target;
      }

      // }}}
      return {
        // {{{ public
        copyDialog: null,
        init: function(id, data, path, limit) {
          votePath = path.vote;
          moderatePath = path.moderate;
          configurePath = path.configure;
          limit = limit || 10;

          data = prepare(data, limit);
          if (data) {
            var columnDef = createInitialColumnDef(data.colNames, getHeader);
            var dataSource = createInitialDataSource(data.colNames);

            // create
            dataTable = new YAHOO.Narabete.DataTable(id, columnDef, dataSource, {selectionMode: "singleCell"});
            var columnSet = dataTable.getColumnSet();
            yuc.times(data.rowNames.length, function(i) {
              dataTable.addRow(createRow(columnSet.keys, getHeader(data.rowNames[i], true), data.cellValues[i], setCellFunc));
            });

            setEvent();
            setTimeout(function() {
              var rowText = data.rowMessage + '<a href="'+path.addRow+'">'+ynl.getText('row_add')+'</a>';
              var colText = '<table><tbody style="border:0">';
              if (data.colMessage != '') {
                colText += '<tr style="height:100px;background:#DDBBBB"><td style="text-align:center;border:none;border-bottom:solid 1px #000">' + data.colMessage +'</td></tr>';
              }
              colText += '<tr style="height:100px;"><td style="text-align:center;border:none"><a href="'+path.addColumn+'">'+ynl.getText('column_add')+'</a></td></tbody></table>';
              if (data.colMessage != '' || data.rowMessage != '') {
                yud.setStyle('show-all', 'display', 'block');
              }
              setAddRow(data.colNames.length + 2, rowText);
              setAddCol(data.rowNames.length, colText);
            }, 0);
          } else {
            alert(ynl.getText('invalid_url'));
          }
        },
        showCopyDialog: function(type) {
          var dialog = this.copyDialog;
          var tabs = null;
          var element = yud.get("modal-overlay");
          yud.setStyle(element, "display", "block");
          if (!dialog) {
            var dialog = ynu.getDialog(element, {
              visible: false,
              close: false,
              width: "400px",
              buttons: [
                {text: ynl.getText("copy_to_clipboard"), handler:function() {
                  var index = tabs.get('activeIndex') || 0;
                  var tmp = document.createElement('div');
                  tmp.innerHTML = tabs.getTab(index).get('content');
                  var textareaId = tmp.getElementsByTagName('textarea')[0].id;
                  var textarea = yud.get(textareaId);
                  textarea.select();
                  ynu.setClipboard(textarea, '/js/');
                }},
                {text: ynl.getText("close"), handler:function() { this.cancel(); }}
            ]
            });
            this.copyDialog = dialog;
            dialog.setHeader(ynl.getText("copy_to_clipboard"));
            dialog.setBody("<div id='tab'></div>");
          }
          dialog.render();
          tabs = setCopyPanelTab('tab', element);
          setCopyText(element.getElementsByTagName('textarea')[0], 'widget');
          dialog.show();
        },
        configure: function() {
          var rows = showRowIds.join("-");
          var cols = showColIds.join("-");
          var path = configurePath.replace("ROWS", rows).replace("COLUMNS", cols);
          location.href = path;
        },
        selectValue: function(value, element) {
          var valueString = element.id.split("-")[0];
          var id = element.id.split("-")[1];
          if (isVoted(id)) { return; }

          var postData = 'cellId='+id+'&value='+value+'&_csrf_token='+ynu.getCSRFValue();
          votedCells.push(id);
          YAHOO.util.Connect.asyncRequest('POST', votePath, {
            success: function(o) {
              var cell = yud.get(id);
              if (valueString == 'positive') {
                yud.setStyle("positive-"+id, 'visibility', 'visible');
                yud.setStyle("negative-"+id, 'visibility', 'hidden');
              } else {
                yud.setStyle("positive-"+id, 'visibility', 'hidden');
                yud.setStyle("negative-"+id, 'visibility', 'visible');
              }
              var anim = new YAHOO.util.ColorAnim(cell.parentNode, {
                duration: 0.4,
                backgroundColor: { from:'#ff9', to: "#ece"}
              });
              anim.onComplete.subscribe(function() {
                new YAHOO.widget.Tooltip("tooltip-"+id, {
                    context: cell,
                    text: ynl.getText('voted')
                });
                if (YAHOO.env.ua.ie != '0') {
                  cell.parentNode.style.removeAttribute("backgroundColor");
                } else {
                  cell.parentNode.style.backgroundColor = null;
                }
              });
              anim.animate();
            },
            failure: function(o) {
              alert(ynl.getText('ajax_error'));
            }
          }, postData);
        },
        thumbsDo: function(element, className, columnName, id, action) {
          var postData = 'class='+className+'&column='+columnName+'&id='+id+'&thumbs='+action+'&_csrf_token='+ynu.getCSRFValue();
          YAHOO.util.Connect.asyncRequest('POST', moderatePath, {
            success: function(o) {
              try {
                var target = (className == 'row') ? rowUpDown(element, action) : columnUpDown(element, action);
                var imgs = target.getElementsByTagName('img');
                for (var i = 0; i < imgs.length; i++) {
                  if (!yud.hasClass(imgs.item(i), 'tansparent')) {
                    yud.addClass(imgs.item(i), 'transparent');
                  }
                }
              } catch(e) {}
            },
            failure: function(o) {
            }
          }, postData);
        }
      }
      // }}}
    }(),
      // }}}

// {{{ Editor
    Editor: function() {
      var type = null;
      return {
        init: function(type) {
          type = type;
        },
        selectValue: function(value, element) {
          YAHOO.Narabete.Table.Creator.selectValue(value, element);
        }
      }
   }()
  // }}}
  }
}();
// }}}

// {{{ YAHOO.Narabete.Confirm
YAHOO.Narabete.Confirm = function() {
  var yud = YAHOO.util.Dom;
  var ynl = YAHOO.Narabete.Locale;
  var ynu = YAHOO.Narabete.Util;
  return {
    confirmName: function(checkPath, tablePath) {
      var tableName = yud.get('tableName').value;
      var detected = tableName.match(new RegExp(ynl.getText('compare_words'), "i"));
      yud.setStyle("warning", "display", detected ? "block" : "none");
      var postData = 'name='+tableName+'&_csrf_token='+ynu.getCSRFValue();
      YAHOO.util.Connect.asyncRequest('POST', checkPath, {
          success: function(o) {
            var result = eval(o.responseText);
            if (result != undefined) {
              yud.setStyle("duplication_warning", "display", "block");
              var text = '';
              var path = '';
              var rows = '';
              var name = '';
              for (var i = 0, l = result.length; i < l; i++) {
                path = tablePath.replace("ID", result[i].id);
                rows = result[i].rows.join("&nbsp;|&nbsp;");
                name = result[i].name.replace(new RegExp("("+tableName+")", "ig"), "<span style=\"background:#c00;padding:2px;\">$1</span>");
                text += '<div style="background:#fff;border:1px solid #888;margin: 0.5em 2em;">';
                text += '<div style="font-size:1.2em;margin-top:1em"><a href="'+path+'" target="_blank">'+ name +'</a></div>';
                text += '<div style="margin:1em 0;font-size:0.8em">'+ rows +'</div>';
                text += '</div>';
              }
              var duplicationCheck = ynl.getText('duplication_check_'+ ((result.length == 1) ? 'single' : 'multiple'));
              yud.get("duplication_warning").innerHTML = '<div>'+duplicationCheck+'</div>'+text+'<div>'+ynl.getText('duplication_check_confirm')+'</div><div style="text-align:center"><a href="#" onclick="YAHOO.util.Dom.setStyle(\'duplication_warning\', \'display\', \'none\');">'+ynl.getText('hide_warning')+'</a></div>';
            } else {
              yud.setStyle("duplication_warning", "display", "none");
            }
          },
          failure: function(o) {
            alert(ynl.getText('ajax_error'));
          }
      }, postData);

    }
  }
}();

// }}}
