function setOpacity(el, value) { /* value in 0-10 */
  el.style.opacity = value/10;  /* moz/saf */
  el.style.filter = 'alpha(opacity=' + value*10 + ')'; /*ie*/
}
function fadeStart(id, f) {
  var theDiv = document.getElementById(id);
  if (f > 0) {
    setOpacity (theDiv, f-1);
    setTimeout (function() { fadeStart(id,f-1) }, 90);
  } else {
    theDiv.innerHTML = '';
    setOpacity (theDiv, 10);
  }
}
function fade (id, s, delay) {
  var theDiv = document.getElementById(id);
  theDiv.innerHTML = s;
  if (delay > 0) {
    setTimeout (function() { fadeStart(id, 10) }, delay*1000);
  }
}

function markfeed(id) {
  var feedID = id.substring(4);
  sendRequest('ajax.php?op=markfeed&id='+feedID, handleResponse, 0);
  /* change class of items from new to seen */
  var dts = document.getElementById(id).getElementsByTagName("dt");
  for (var j = 0; j < dts.length; j++) {
    var links = dts[j].getElementsByTagName("a");
    for (var i = 0; i < links.length; i++) {
      if ((links[i].getAttribute("class") == "new") ||
         (links[i].getAttribute("className") == "new")) {
        links[i].setAttribute("class", "seen");
        links[i].setAttribute("className", "seen");
      }
    }
    if ((dts[j].getAttribute("class") == "feedlink") ||
        (dts[j].getAttribute("className") == "feedlink")) {
      collapse(dts[j].getAttribute("id"));
    }
  }
}

/* Mark the DT of the given id as read. */
function marklink(id) {
  var theDT = document.getElementById(id);
  for (var i = 0; i < theDT.childNodes.length; i++) {
    theDT.childNodes[i].setAttribute("class", "visited");
    theDT.childNodes[i].setAttribute("className", "visited");
  }
}

function expand(id) {
  var theAnchor = document.getElementById(id).firstChild;
  theAnchor.firstChild.nodeValue = "* ";
  sendRequest('ajax.php?op=expand&id='+id, handleResponse, 0);
}

/* Remove the first sibling of the DT with the given id.  Change the DT's
 * first anchor text and link to expand.
 */
function collapse(id) {
  var theDT = document.getElementById(id);
  var theSibling = theDT.nextSibling;
  while (theSibling.nodeType == "3") {
    theSibling = theSibling.nextSibling;
  }
  if (theSibling.nodeName == 'DD') {
    theDT.parentNode.removeChild(theSibling);  /* Gone! */
  }
  var theAnchor = theDT.firstChild;
  /*theAnchor.setAttribute ('onclick', 'expand('+id+');return false;'); */
  theAnchor.onclick = function() { expand(id); return false; } /* IE doesnt play nice */
  theAnchor.title = "expand";
  theAnchor.firstChild.nodeValue = "+ ";
}

function more(id, n) {
  sendRequest('ajax.php?op=more&id='+id+'&n='+n, handleResponse, 0);
}

/* For op='expand', data='id|description HTML ...'.
 * Find the DT with given id, create a DD sibling containing the description.
 * Change the DT's first anchor text and link to collapse.
 */
function handleResponseExpand(response) {
  var i = response.indexOf('|',0);
  if (i != -1) {
    var id = response.substring(0,i);
    var theDD = document.createElement("dd");
    theDD.innerHTML = response.substring(i+1);
    /* Add the new node after the DT node */
    var theDT = document.getElementById(id);
    var theDD = theDT.parentNode.insertBefore(theDD, theDT.nextSibling);
    /* Change the DT's first anchor to '-' and change its link to collapse */
    var theAnchor = theDT.firstChild;
    /* theAnchor.setAttribute ('onclick', 'collapse('+id+');return false;'); */
    theAnchor.onclick = function() { collapse(id); return false; } /* IE doesnt play nice */
    theAnchor.title = "hide";
    theAnchor.firstChild.nodeValue = "-- ";
  }
}

/* For op='more', data='feedid|morelink|linkid|title HTML|linkid|title HTML| ...'.
 * Append a new DT with each new link received.
 */
function handleResponseMore(response) {
  var i = response.indexOf('|',0);
  if (i == -1) { return; }

  var feedid = response.substring(0,i);
  var theDT = document.getElementById('none'+feedid);
  if (theDT) { theDT.parentNode.removeChild(theDT); }
  var moreDT = document.getElementById('more'+feedid);
  var theDL = moreDT.parentNode;
  theDL.removeChild(moreDT);

  var oldi = i;
  i = response.indexOf('|',i+1);
  if (i == -1) { return; }
  var morelink = response.substring(oldi+1,i);

  oldi = i;
  while ((i = response.indexOf('|',i+1)) != -1) {
    var id = response.substring(oldi+1,i);
    oldi = i;
    i = response.indexOf('|',i+1);
    var link = response.substring(oldi+1,i);

    var newDT = document.createElement("dt");
    newDT.setAttribute ('id', id);
    newDT.setAttribute ('class', 'feedlink');
    newDT.innerHTML = link;
    theDL.appendChild(newDT);

    oldi = i;
  }

  /* add the more link back at the end */
  moreDT.innerHTML = morelink;
  theDL.appendChild(moreDT);
}

/* Response is 'op|data'.  We switch on op and pass data to handlers.
 */
function handleResponse(req) {
  var response = req.responseText;
  var o = response.indexOf('|');
  if (o != -1) {
    var op = response.substring(0,o);
    if (op == 'expand') {
      handleResponseExpand(response.substring(o+1));
    } else if (op == 'more') {
      handleResponseMore(response.substring(o+1));
    } else if (op == 'ack') {
      fade ('status', 'Feed marked read.', 1);
      return;
    }
  }
}

/* From quirksmode */
function sendRequest(url,callback,postData) {
  var req = createXMLHTTPObject();
  if (!req) return;
  var method = (postData) ? "POST" : "GET";
  req.open(method,url,true);
  req.setRequestHeader('User-Agent','XMLHTTP/1.0');
  if (postData)
    req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
  req.onreadystatechange = function () {
    if (req.readyState != 4) return;
    if (req.status != 200 && req.status != 304) {
      alert('HTTP error ' + req.status);
      return;
    }
    callback(req);
  }
  if (req.readyState == 4) return;
  req.send(postData);
}

var XMLHttpFactories = [
  function () {return new XMLHttpRequest()},
  function () {return new ActiveXObject("Msxml2.XMLHTTP")},
  function () {return new ActiveXObject("Msxml3.XMLHTTP")},
  function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];

function createXMLHTTPObject() {
  var xmlhttp = false;
  for (var i=0;i<XMLHttpFactories.length;i++) {
    try { xmlhttp = XMLHttpFactories[i](); }
    catch (e) { continue; }
    break;
  }
  return xmlhttp;
}

