/* graph_bar.js - Paul Seamons - License BSD - Copyright 2007 */
/* $Id: graph_bar.js,v 1.5 2007-02-14 21:58:13 paul Exp $ */

function graph_bar (args) {
  var div = args.div;
  if (! div) {
    var id = args.div_id;
    if (id) div = document.getElementById(id);
    if (! div) {
      var d = new Date();
      id = 'graph_bar_' + d.getTime();
      // we aren't using document.createElement because we want this relative to the current document flow
      document.write("<div id='"+id+"' class='graph_bar'></div>");
      div = document.getElementById(id);
      if (! args.width)  args.width  = 300;
      if (! args.height) args.height = 200;
      if (! div) {
        alert("Had trouble getting the div inline - aborting effort");
        return;
      }
    }
  }

  if (args.width)  div.style.width  = args.width;
  if (args.height) div.style.height = args.height;

  // look for built in css
  var selector = '#' + div.getAttribute('id');
  var found = 0;
  for (var i = 0; i < document.styleSheets.length; i++) {
    var s = document.styleSheets[i];
    var r = s.cssRules ? s.cssRules : s.rules ? s.rules : [];
    for (var j = 0; j < r.length; j++) if (r[j].selectorText == selector) found ++;
  }

  if (! found) {
    div.style.padding = '0px';
    if (! args.background      ) args.background       = 'white';
    if (! args.border_color    ) args.border_color     = 'blue';
    if (! args.border          ) args.border           = '2px solid '+args.border_color;
    if (! args.color           ) args.color            = 'black';
    if (! args.title_background) args.title_background = args.border_color;
    if (! args.title_color     ) args.title_color      = args.background;
    if (! args.padding         ) args.padding          = '1ex';
  }

  if (args.background) div.style.background = args.background;
  if (args.color)      div.style.color      = args.color;
  if (args.border)     div.style.border     = args.border;
  if (args.width > 0)  div.style.width      = args.width;
  if (args.height >0)  div.style.height     = args.height;

  div.style.display = 'block';
  var offset = graph_bar_object_offset(div);
  var X = offset.left + parseInt(div.style.borderLeftWidth);
  var Y = offset.top  + parseInt(div.style.borderTopWidth);
  var W = div.clientWidth;
  var H = div.clientHeight;

  var title_margin   = 10;
  var left_margin    = 10;
  var label_x_margin = 10;
  var label_y_margin = 10;

  // add many of the labels
  if (args.title) {
    title_margin = 30;
    graph_bar_text({
      center_x: X + W/2,
      y:        Y,
      h:        title_margin,
      parent:   div,
      html:     args.title
    });
  }

  if (args.label_x) {
    label_x_margin = 20;
    graph_bar_text({
      center_x: X + W/2,
      y:        Y + H - label_x_margin,
      h:        label_x_margin,
      parent:   div,
      html:     args.label_x
    });
  }

  if (args.label_y) {
    label_y_margin = 60;
    graph_bar_text({
      center_y: Y + H/2,
      x:        X + W-label_y_margin + 2,
      w:        label_y_margin - 2,
      parent:   div,
      html:     args.label_y
    });
  }

  var gw = W - left_margin  - label_y_margin;
  var gh = H - title_margin - label_x_margin;
  var gx = X + left_margin;
  var gy = Y + H - label_x_margin;

  // box around the graph area
  graph_bar_line({x:gx-1,    y:gy,      w:gw+2, h:1,    parent:div, color:'black'});
  graph_bar_line({x:gx-1,    y:gy-gh-1, w:gw+2, h:1,    parent:div, color:'black'});
  graph_bar_line({x:gx-1,    y:gy-gh-1, w:1,    h:gh+2, parent:div, color:'black'});
  graph_bar_line({x:gx+gw,   y:gy-gh-1, w:1,    h:gh+2, parent:div, color:'black'});

  // figure out a suitable max
  var max = 0;
  for (var i = 0; i < args.data.length; i++) if (args.data[i] > max) max = args.data[i];
  if (args.trend) for (var i = 0; i < args.trend.length; i++) if (args.trend[i] > max) max = args.trend[i];
  var inc = 1 * Math.pow(10, ((""+max).length - 1));
  max = (1 + parseInt(max / inc)) * inc;

  // back bars
  var I = max / (inc * .25) * 5;
  while (I > 15) I /= 5;
  while (I < 10) I *= 2;
  for (var i = 1; i < I; i++) {
    var n = i * max / I;
    var val = parseInt(n / max * gh);
    var el = graph_bar_line({
      x: gx,
      y: gy - val,
      w: gw,
      h: 1,
      parent: div,
      color: '#aaa'
    });
    el.setAttribute('title', n);
  }

  // the data elements
  var d = args.data.length;
  var bar_wo = gw / d;
  var bar_wi = bar_wo * (bar_wo < 5 ? 1 : .8);
  for (var i = 0; i < d; i++) {
    var val = parseInt(args.data[i] / max * gh);
    var el = graph_bar_line({
      x: gx + parseInt(i * bar_wo + (bar_wo - bar_wi)/2),
      y: gy - val,
      w: parseInt(bar_wi),
      h: val,
      parent: div,
      color: 'blue'
    });
    el.setAttribute('title', args.data[i]);
  }

  // the trend elements
  if (args.trend) {
  var t = args.trend.length;
  var tdx = parseInt(gw / (t-1));
  for (var i = 0; i < gw; i++) {
    var j = parseInt(i / tdx);
    var n = args.trend[j] + (i%tdx) / tdx * (args.trend[j + 1] - args.trend[j]);
    var val = parseInt(n / max * gh);
    var el = graph_bar_line({
      x: gx + i,
      y: gy - val,
      w: 1,
      h: 2,
      parent: div,
      color: 'red'
    });
    el.setAttribute('title', n);
  }
  }

  return div;
}

function graph_bar_text (args) {
  var el = document.createElement("DIV");
  args.parent.appendChild(el);
  el.innerHTML      = args.html;
  el.style.position = 'absolute';
  el.style.fontSize = 10;
  if (args.h) {
    graph_bar_resize_text({obj:el, initial_size:10, height: args.h});
    el.style.top  = args.y;
    el.style.left = args.center_x - (el.clientWidth / 2);
  } else if (args.w) {
    graph_bar_resize_text({obj:el, initial_size:10, width: args.w});
    el.style.top  = args.center_y - (el.clientHeight / 2);
    el.style.left = args.x;
  }
  return el;
}


function graph_bar_line (args) {
  var el = document.createElement("DIV");
  args.parent.appendChild(el);
  if (args.h < 10 && navigator.appVersion.indexOf('MSIE') != -1) {
    var i = document.createElement("IMG");
    i.width  = args.w;
    i.height = args.h;
    i.src    = './image/clear.gif';
    el.appendChild(i);
  }
  var off = graph_bar_object_offset(args.parent);
  el.style.top          = args.y;
  el.style.left         = args.x;
  el.style.width        = args.w;
  el.style.height       = args.h;
  el.style.maxWidth     = args.w;
  el.style.maxHeight    = args.h;
  el.style.position     = 'absolute';
  el.style.background   = args.color;
  return el;
}

function graph_bar_resize_text (args) {
  var el        = args.obj;
  var font_size = args.initial_size || alert("Missing initial_size");

  var i = 0;
  while (1) {
    if (i++ > 10) break;
    var new_fs;
    if (args.width) {
      var w = parseInt(el.offsetWidth);
      if (w <= 1.15 * args.width && w >= .95 * args.width) return; // { el.innerHTML += '('+i+')'; return }
      new_fs = parseInt(font_size * args.width / w);
    } else if (args.height) {
      var h = parseInt(el.offsetHeight);
      if (h <= 1.15 * args.height && h >= .95 * args.height) return; // { el.innerHTML += '('+i+')'; return }
      new_fs = parseInt(font_size * args.height / h);
    } else return;
    if (new_fs == font_size) return i;
    font_size = new_fs;
    el.style.fontSize = ""+(--font_size)+"pt";
  }
}

function graph_bar_object_offset (el) {
  if (! el.style) return {top : 0, left : 0};

  if (el.style.position == "absolute") {
    return {top : parseInt(el.style.top), left : parseInt(el.style.left)};
  } else {
    if (el.offsetParent == null) return {top : 0, left : 0};
    var offset = graph_bar_object_offset(el.offsetParent);
    return {top : offset.top + parseInt(el.offsetTop), left : offset.left + parseInt(el.offsetLeft)};
  }
}

