
Number.prototype.humanreadable = function() {
  var str = this.toString();
  var nd = str.length%3;
  var ret = str.substr(0,nd);
  for(var frst = nd;frst < str.length; frst+=3) {
    ret += (ret.length?',':'')+str.substr(frst,3);
  }
  return ret;
}

var ABWidget = {
  skip: 0,
  count: 8,
  height: 350,
  width: 650,

  SCROLLBAR_PPE: document.opera?60:(document.all?43:15), // scrollbar up/down pixels per element

  getRows: function() {
    return this.rows;
  },

  getScrollbar: function() {
    return this.firstChild;
  },

  initialize: function() {
    // scrollwheel support
    Event.observe(this,"DOMMouseScroll",this.scrollwheelHandler,false); 
    this.onmousewheel = this.scrollwheelHandler.bindAsEventListener(this); //IE
    // scrollbar
    var scrollbar = '<div style="width:19px;height:'+this.height+'px;overflow:auto;background:inherit;padding:0px;position:absolute;top:0px;left:'+(this.width-19)+'px;"><div style="background:inherit;width:1px;padding:0px;margin:0px;height:'+(this.getRows().length * this.SCROLLBAR_PPE + this.height)+'px"> </div></div>';
    new Insertion.Top(this.id,scrollbar);
    var table = '<table id="'+this.id+'_ws_table" class="ws_table"><thead><tr><th>'+this.renderHeader()+'</th></tr></thead><tbody id="'+this.id+'_ws_content"><tr><td colspan="4">&nbsp;</td></tr></tbody></table>';
    new Insertion.Bottom(this.id,table);
    var ss = this.getScrollbar();
    ss.style.height = this.height+'px';
    ss.style.width = '19px';
    ss.firstChild.style.height = this.getRows().length * this.SCROLLBAR_PPE + this.height+'px';
    ss.style.overflow = 'auto';
    ss.onscroll = this.scrollEvent.bindAsEventListener(this);
    this.onkeypress = this.widgetKeyPress.bindAsEventListener(this);
    // block unneeded events
    ss.onselect = this.blockEvent.bindAsEventListener(this);
    ss.ondragdrop = this.blockEvent.bindAsEventListener(this);
    // set height and style for widget
    this.style.height = this.height+'px';
    this.style.width = this.width+'px';
    this.style.clip = 'rect(0px, 0px, '+this.width+'px, '+this.height+'px)';
    //numscrollevents=0;
  },

  scrollEvent: function(event) {
    Event.stop(event);
    var ss = this.getScrollbar();
    // var numelems = Math.floor((ss.scrollHeight-ss.offsetHeight)/this.SCROLLBAR_PPE);
    this.skip = Math.ceil((ss.scrollTop>0?ss.scrollTop:1)/this.SCROLLBAR_PPE) - 1;
    this.redrawPane();
    //numscrollevents++;
    //window.status = "num: "+numscrollevents+" scrolltop: "+ss.scrollTop+" skip: "+this.skip;
  },

  widgetKeyPress: function(event) {
    // make sure layer doesn't get scrolled when tab changes focus to a hidden part
    if (this.scrollTop != 0) {
        this.scrollTop = 0;
        // FIXME: manipulate tab order
    }

    var key = event.which || event.keyCode;
    var handled = true;
    switch(key) {
      case Event.KEY_HOME:
        this.skip = 0;
        this.redrawPane();
        break;
      case Event.KEY_END:
        this.skip = this.getRows().length-1;
        this.redrawPane();
        break;
      case Event.KEY_PAGEUP:
        this.scrollPane(-4);
        break;
      case Event.KEY_PAGEDOWN:
        this.scrollPane(4);
        break;
      case Event.KEY_UP:
        this.scrollPane(-1);
        break;
      case Event.KEY_DOWN:
        this.scrollPane(1);
        break;
      case Event.KEY_TAB:
        // FIXME: Reroute tab to next widget
        Event.stop(event);
        //$(this.id).focus();
        handled = false;
        break;
      default:
        handled = false;
    }
    if (handled) {
      Event.stop(event);
      var elems = $$('#'+this.id+'_ws_content input');
      if (elems.length>0) elems[0].focus();
    }
  },

  blockEvent: function(event) {
    Event.stop(event);
  },

  scrollwheelHandler: function(event){
    var delta = 0;
    if (event.wheelDelta) {
      delta = event.wheelDelta/120; 
      if (window.opera) delta = -delta;
    } else if (event.detail) { delta = -event.detail/3; }
    if (delta) {
      this.scrollPane(delta < 0 ? 1 : -1); 
    }
    Event.stop(event);
  },

  scrollPane: function(diff) {
    this.skip = this.skip + diff;
    this.redrawPane();
    // adjust slider position
    this.getScrollbar().scrollTop = Math.floor(this.skip * this.SCROLLBAR_PPE);
  },

  redrawPane: function() {
    var skip = this.skip;
    var count = this.count;
    var rows = this.getRows();
    var len = rows.length;
    var tbody = '';
    if (len!=0 && (skip < 0 || skip >= len)) {
      return;
    }
    if (len==0) {
      tbody += this.renderEmptyRow();
    } else {
      for(var i=skip;i < skip + count && i < len; i++) {
        tbody += this.renderRow(i,rows[i]);
      }
      if (this.renderHiddenSelection != null) {
        tbody += this.renderHiddenSelection();
      }
    }
    Element.update(this.id+'_ws_content',tbody);
    this.scrollTop = 0;
  },

  runFilter: function() {
    this.rows = this.dataSet.filter(this, false, false);
    this.skip = 0;
    
    // resize and reset slider
    var ss = this.getScrollbar();
    ss.firstChild.style.height = this.getRows().length * this.SCROLLBAR_PPE + this.height+'px';
    ss.scrollTop = 0;

    this.redrawPane();
    return false;
  },
  
  runFilter_for_blogs: function() {
    this.rows = this.dataSet.filter(this, false, true);
    this.skip = 0;
    
    // resize and reset slider
    var ss = this.getScrollbar();
    ss.firstChild.style.height = this.getRows().length * this.SCROLLBAR_PPE + this.height+'px';
    ss.scrollTop = 0;

    this.redrawPane();
    return false;
  },
  
  runFilterNonOptimal: function() {
    this.rows = this.dataSet.filter(this, true, false);
    this.skip = 0;
    
    // resize and reset slider
    var ss = this.getScrollbar();
    ss.firstChild.style.height = this.getRows().length * this.SCROLLBAR_PPE + this.height+'px';
    ss.scrollTop = 0;

    this.redrawPane();
    return false;
  },

  KeypressChecking: function(evt) {
    var keycode;
    if (window.event) keycode = window.event.keyCode;
    else if (evt) keycode = evt.which;
    
    this.rows = this.dataSet.filter(this, true, false);
    this.skip = 0;
    
    // resize and reset slider
    var ss = this.getScrollbar();
    ss.firstChild.style.height = this.getRows().length * this.SCROLLBAR_PPE + this.height+'px';
    ss.scrollTop = 0;

    this.redrawPane();
  },

  KeypressChecking_enter: function(evt) {
    var keycode;

    if (window.event) keycode = window.event.keyCode;
    else if (evt) keycode = evt.which;
    
    if (keycode==13){
      this.runFilterNonOptimal();
      return false;
    }
    return true;
  },

  dataSet: null,
  renderRow: null,
  renderEmptyRow: null,
  renderHeader: null,
  renderHiddenSelection: null,

  rows: []
}
