function ajax(method, url, args, func) {
  var http;
  if (!http && typeof XMLHttpRequest != 'undefined') {
    http = new XMLHttpRequest(); // For non-IE browsers
  }
  if (!http) {
    try {
      http = new ActiveXObject("Msxml2.XMLHTTP"); // Newer IE
    } catch (e) {
      try {
        http = new ActiveXObject("Microsoft.XMLHTTP"); // Older IE
      } catch (E) {
      }
    }
  }
       
  var encodedArgs = "";
  // args is an array of strings" {"key", "value, "key" ... "value"}
  for (var i = 0; i < args.length; i += 2) { 
    for (var j = 0; j <= 1; j++) {
      args[i + j] += "";
      args[i + j] = args[i + j].replace(/%/g, "%25")
      args[i + j] = args[i + j].replace(/&/g, "%26")
      args[i + j] = args[i + j].replace(/=/g, "%3D")
      
      // Encode characters so no invalid parameters get passed
    }
      
    if (i > 0) {
      encodedArgs += "&"
    }
    encodedArgs += args[i] + "=" + args[i + 1];
  }
      
  if (method == "get" && encodedArgs != "") {
    url += "?" + encodedArgs; // Encode as a query string
  }
           
  http.open(method, url, true);
  http.onreadystatechange = function() {
    if (http.readyState == 4) { // Connection closed
      if (http.status == 0) {
        func("ERROR Unable to connect... you may be using HTTP when HTTPS " +
          "was expected.", new Array());
      } else {
        func(http.responseText, http.getAllResponseHeaders());
      }
      // Callback with the text and headers.
    }
  }

  if (method == "post") { // If it's a POST
    http.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    //http.setRequestHeader("Content-Length", encodedArgs.length);

    http.send(encodedArgs);
      
    // send in the body
  } else {
    http.send(null);
  }
}

function getCode(reply) {
  var index = reply.indexOf(" ");
  if (index == -1) {
    return reply;
  }
  return reply.substr(0, index);
}

function getContent(reply) {
  var index = reply.indexOf(" ");
  if (index == -1) {
    return "";
  }  
  return reply.substr(index + 1);
}

function ajaxaddtags() {
  var errorblock = document.getElementById("message");
  errorblock.className = "hidden";

  var id = document.getElementById("addtagcomicid").value;
  var addtagbox = document.getElementById("addtagbox");
  var tagbox = document.getElementById("addtags");
  var tags = tagbox.value;

  ajax("post", baseURL, new Array("ajax", "addtag", "id", id, "tag", tags),
    function(text) {

    var reply = getCode(text);
    if (reply != "OK") {
      errorblock.innerText = getContent(text);
      errorblock.className = "error";
      return;
    }
    
    tagbox.value = "";

    var comictags = document.getElementById("comictags");
    var fullTags = new Array();
    for (var i = 0; i < comictags.childNodes.length; i++) {
      var node = comictags.childNodes[i];
      if (node.nodeName == null || node.nodeName.toLowerCase() != 'a') {
        continue;
      }
      fullTags.push(node.childNodes[0].nodeValue);
    }

    tags = tags.split(",");
    for (var i = 0; i < tags.length; i++) {
      var match = false;
      for (var j = 0; j < fullTags.length; j++) {
        if (fullTags[j].toLowerCase() == tags[i].toLowerCase()) {
          match = true;
          break;
        }
      }
      
      if (!match) {
        fullTags.push(tags[i]);
      }
    }
    
    var k = 0;
    while (k < comictags.childNodes.length) {
      var node = comictags.childNodes[k];
      if (node.nodeName == null || (node.nodeName.toLowerCase() != 'form' &&
        node.nodeName.toLowerCase() != 'h2')) {
            
        comictags.removeChild(node);
        continue;
      }
    
      k++;
    }
    
    for (var i = 0; i < fullTags.length; i++) {
      var a = document.createElement("a");
      if (usePrettyUrls) {
        a.href = baseURL + "tag/" + fullTags[i] + "/";
      } else {
        a.href = baseURL + "?page=tag&tag=" + fullTags[i];
      }
      a.appendChild(document.createTextNode(fullTags[i]));
      comictags.insertBefore(a, addtagbox);
      
      if (i < fullTags.length - 1) {
        comictags.insertBefore(document.createTextNode(", "), addtagbox);
      }
    }
  });
  
  return false;
}