//  Blogfeed
//  blogfeed.js
//  Version 0.1.40
//  Copyright (c) 2007 Gareth Hadfield
//  http://gtdesktop.com/blogfeed
//
//  Usage:
// Create a TBlogfeed object
//  ABlogfeed = new TBlogfeed("example");
//
// Output the result div
//  ABlogfeed.outputResultDiv();
//
// If you want to show the source website using show_source=true then you can output an appropriate div with this:
//  ABlogfeed.outputShowSourceDiv();
//
// If you are using blog_show_method="window" then you can output an appropriate div with this:
//  ABlogfeed.outputBlogHtmlDiv();
//
// To load a url into the blogfeed use this:
//  ABlogfeed.importXML("");
//
// If you want to have several feeds that popup in the same window then rename
// the blog_html_id for each blogfeed object to the same name
// Eg:
//  ABlogfeed1 = new TBlogfeed("example1");
//  ABlogfeed2 = new TBlogfeed("example2");
//  ABlogfeed3 = new TBlogfeed("example3");
//  ABlogfeed1.outputResultDiv();
//  ABlogfeed1.outputShowSourceDiv();
//  ABlogfeed2.outputResultDiv();
//  ABlogfeed2.outputShowSourceDiv();
//  ABlogfeed3.outputResultDiv();
//  ABlogfeed3.outputShowSourceDiv();
//
//  ABlogfeed1.outputBlogHtmlDiv();
//  ABlogfeed2.blog_html_id = ABlogfeed1.blog_html_id; // all use same popup window
//  ABlogfeed3.blog_html_id = ABlogfeed1.blog_html_id; // all use same popup window
//
//  ABlogfeed1.importXML("http://whatever1");
//  ABlogfeed2.importXML("http://whatever2");
//  ABlogfeed3.importXML("http://whatever3");
//

// Util functions

function zero_pad(astring, alength){
// add 0 to the left of astring until it reaches alength - returns result
  astring=astring.toString();
  while(astring.length < alength){
    astring = "0" + astring;
  }
  return(astring);
}

function limit_text(astring, limit){
// return a shortened version of astring with ... on the end
  if(astring==null){return("");}
  astring=astring.toString();
  if(astring.length > limit){
    result = astring.substr(0,limit) + "...";
  }
  else{
    result = astring;
  }
  return(result);
}

function preload(aImgSrc){
  // preload the given image
  aImg = new Image();
  aImg.src=aImgSrc;
}

function set_cookie(name, value, expires, path, domain, secure){
  document.cookie= name + "=" + escape(value) +
    ((expires) ? "; expires=" + expires.toGMTString() : "") +
    ((path) ? "; path=" + path : "") +
    ((domain) ? "; domain=" + domain : "") +
    ((secure) ? "; secure" : "");
}

// Date and time functions

function format_time(adate){
  hours = adate.getHours();
  if(hours<12){
    ampm = "am";
    hours = 12;
  }
  else/*if(hours>=12)*/{
    ampm = "pm";
    if(hours!=12){
      hours -= 12;
    }
  }
  result = zero_pad(hours, 2) + ":" + zero_pad(newDate.getMinutes(), 2) + ampm;
  return(result);
}

function decode_month(amonth){
  // takes short month eg JAN-DEC and returns 0-11
  var months = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
  for(m=0; m<months.length; m++){
    if(amonth==months[m]){
      return(m);
    }
  }
  return(-1);
}

function date1_to_jsdate(adate){
  // Accepts a date as ddd, DD MM YYYY HH:MM:SS GMT
  // Returns a corresponding javascript date object
  // Example formats:
  //Thu, 03 May 2007 03:27:40 GMT
  //Sun, 14 Jan 2007 15:07:33 -0600
  newDate = new Date();

  if((adate.substr(4,1)==" ") && (adate.substr(6,1)==" ")){
    // argh date not zero-padded!
    //Tue, 8 May 2007 02:41:06 -0800
    adate=(adate.substr(0,5) + "0" + adate.substr(5));
  }
  newDate.setYear(adate.substr(12,4));
  newDate.setMonth( decode_month(adate.substr(8,3)), parseInt(adate.substr(5,2)) );
  newDate.setHours(adate.substr(17,2));
  newDate.setMinutes(adate.substr(20,2));
  newDate.setSeconds(adate.substr(23,2));

  return(newDate);
}

function date2_to_jsdate(adate){
  // Accepts a date as YYYY-MM-DDTHH:MM:SS.000GMT
  // Returns a corresponding javascript date object
  // Example format:
  //2007-04-22T00:53:00.000+10:00
  newDate = new Date();

  newDate.setYear(adate.substr(0,4));
  newDate.setMonth( parseInt(adate.substr(5,2))-1, parseInt(adate.substr(8,2)) );
  newDate.setHours(adate.substr(11,2));
  newDate.setMinutes(adate.substr(14,2));
  newDate.setSeconds(adate.substr(17,2));

  return(newDate);
}

function short_date(newDate){
  // Accept javascript date
  // Return date as:
  // dd/mm hh:mmAMPM
  return(zero_pad(newDate.getDate(), 2) + "/" + zero_pad((newDate.getMonth()+1), 2) + " " + format_time(newDate));
}

function mid_date(newDate){
  // Accept javascript date
  // return date as:
  // ddd dd/mm hh:mmAMPM
  var day_string = new Array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");

  return(day_string[newDate.getDay()] + " " + zero_pad(newDate.getDate(), 2) + "/" + zero_pad((newDate.getMonth()+1), 2) + " " + format_time(newDate));
}




function do_mouse_over_x(aDiv){
  aDiv.className = aDiv.mouseoverstyle;
}

function do_mouse_out_x(aDiv){
  aDiv.className = aDiv.mouseoutstyle;
}



// TBlogfeed

// These are now the default values for the vars of the same name in a TBlogfeed
var title_limit = 55;
var show_blog_title_limit = 70;
var show_blog_source_limit = 60;
var blogfeed_dir = "";
var remote_file = "";
var mode = "";
var blog_entry_tag = "";
var blog_title_tag = "";
var blog_content_tag = "";
var blog_published_tag = "";
var blog_link_tag = "";
var show_source_id = "show_source"; // dont change this - use outputShowSourceDiv
var result_html_id = "resulthtml"; // dont change this - use outputResultDiv
var blog_html_id = "bloghtml"; // dont change this - use outputBlogHtmlDiv

var prev_button = "&lt;";
var next_button = "&gt;";
var close_button = "X";


var blog_show_method = "window";// "link" or "window"
var show_source = true;

/* xml loader */
function load_xml(aDocumentName, aOnLoad){
  var http = new XMLHttpRequest();
  var url = aDocumentName;

  http.open("GET", url, true);

  http.onreadystatechange = function(){
  	if(http.readyState == 4 && http.status == 200) {
      aOnLoad(http.responseXML);
  	}
  }
  http.send(null);
}


function TBlogfeed(aName){
  this.name = aName; // used as a unique id

  var aBlogfeedObject = this; // used in binding functions
  //var xmlDoc;

  this.title_limit = title_limit;
  this.show_blog_title_limit = show_blog_title_limit;
  this.show_blog_source_limit = show_blog_source_limit;
  this.blogfeed_dir = blogfeed_dir;
  this.remote_file = remote_file;
  this.mode = mode;
  this.blog_entry_tag = blog_entry_tag;
  this.blog_title_tag = blog_title_tag;
  this.blog_content_tag = blog_content_tag;
  this.blog_published_tag = blog_published_tag;
  this.blog_link_tag = blog_link_tag;
  this.show_source_id = this.name + '_' + show_source_id;
  this.result_html_id = this.name + '_' + result_html_id;
  this.blog_html_id = this.name + '_' + blog_html_id;

  this.prev_button = prev_button;
  this.next_button = next_button;
  this.close_button = close_button;

  this.blog_show_method = blog_show_method;
  this.show_source = show_source;


  this.title = new Array();
  this.content = new Array();
  this.published = new Array();
  this.link = new Array();

  this.is_mode = function(amode, afile){
    return(afile.search(amode) != -1);
  }

  this.set_mode = function(amode){
    this.mode = amode;

    if(this.mode=="footboot"){
      this.blog_entry_tag = 'item';
      this.blog_title_tag = 'title';
      this.blog_content_tag = 'description';
      this.blog_published_tag = 'dc:date';
      this.blog_link_tag = 'link';
    }
    else if(this.mode=="blogspot"){ // is this atom?
      this.blog_entry_tag = 'entry';
      this.blog_title_tag = 'title';
      this.blog_content_tag = 'content';
      this.blog_published_tag = 'published';
      this.blog_link_tag = 'link';
    }
    else if(this.mode=="wordpress"){
      this.blog_entry_tag = 'item';
      this.blog_title_tag = 'title';
      this.blog_content_tag = 'content';
      this.blog_published_tag = 'pubDate';
      this.blog_link_tag = 'link';
    }
    else if(this.mode=="livejournal"){
      this.blog_entry_tag = 'item';
      this.blog_title_tag = 'title';
      this.blog_content_tag = 'description';
      this.blog_published_tag = 'pubDate';
      this.blog_link_tag = 'link';
    }
    else if(this.mode=="soulcast"){
      this.blog_entry_tag = 'item';
      this.blog_title_tag = 'title';
      this.blog_content_tag = 'description';
      this.blog_published_tag = 'pubDate';
      this.blog_link_tag = 'link';
    }
    else if(this.mode=="rss2"){
      this.blog_entry_tag = 'item';
      this.blog_title_tag = 'title';
      this.blog_content_tag = 'description';
      this.blog_published_tag = 'pubDate';
      this.blog_link_tag = 'link';
    }
    else if(this.mode=="slashdot"){
      this.blog_entry_tag = 'item';
      this.blog_title_tag = 'title';
      this.blog_content_tag = 'description';
      this.blog_published_tag = 'dc:date';
      this.blog_link_tag = 'link';
    }
    else{
      alert('Unknown File Format');
    }
  }

  this.detect_mode = function(afile){
    // detect which mode

    if(this.is_mode("footboot.", afile)){
      this.mode = "footboot";
    }
    else if(this.is_mode("blogspot.", afile)){
      this.mode = "blogspot";
    }
    else if(this.is_mode("feedburner.", afile)){
      this.mode = "wordpress";
    }
    else if(this.is_mode("livejournal.", afile)){
      this.mode = "livejournal";
    }
    else if(this.is_mode("soulcast.", afile)){
      this.mode = "soulcast";
    }
    else if(this.is_mode("spaces.live.", afile)){
      this.mode = "rss2";
    }
    else if(this.is_mode("slashdot.", afile)){
      this.mode = "slashdot";
    }
    else{
      this.mode = "rss2";
    }

    this.set_mode(this.mode); // yes :)
  }

  this.importXML = function(aXMLUrl){
    var aToken = "?blogurl=";
    var aBlogParam = aXMLUrl;
  	if((aBlogParam==null) || (aBlogParam=="")){
      // grab blogurl from the url
      // ?blogurl=http://
      aBlogParam=location.search;
      aPos = aBlogParam.search("&");
      if(aPos==-1){
        this.remote_file=aBlogParam.substr(aToken.length);
      }
      else{
        this.remote_file=aBlogParam.slice(aToken.length, aPos);
      }
    }
    else{
      this.remote_file=aBlogParam;
      aBlogParam=aToken+aBlogParam;
    }
    this.remote_file=unescape(this.remote_file);

    if(this.remote_file==""){
      return;
    }
/*
    requiredHead = "http://";
    var head=unescape(this.remote_file.substr(0, requiredHead.length));
    if(head != requiredHead){
      // prevent reading local files
      alert("File must be http://");
      return;
    }
*/
    this.detect_mode(this.remote_file);

    this.center_message("<img src='"+this.blogfeed_dir+"spin.gif'>");

    preload(this.blogfeed_dir+"spin.gif");

    var getUrl = this.blogfeed_dir + "getremotefile.php" + aBlogParam;

    set_cookie("blogfeed", this.remote_file); // used as a check in getremotefile.php

    load_xml(getUrl, this.createOutput);
  }

  this.createOutput = function(xmlDoc){
    if(!xmlDoc){
      //alert("Failed to load RSS Feed");
      return;
    }
    // current mode checking is unreliable
    // todo - use tag detection only
    if(xmlDoc.getElementsByTagName(this.blog_entry_tag).length==0){
      // there are no entry tags - likely wrong mode detetcted
      // swap to other mode
      if(this.blog_entry_tag=="item"){
        this.set_mode("blogspot");
      }
      else{
        this.detect_mode("rss2");
      }
    }

    //get first date - use as default if other dates are undefined
    var x = xmlDoc.getElementsByTagName(this.blog_published_tag);
    if(x[0]==null){
      this.defaultDate = "";
    }
    else{
      this.defaultDate = x[0].childNodes[0].nodeValue;
    }

    x = xmlDoc.getElementsByTagName(this.blog_entry_tag);

  	//create the rows
    for (i=0;i<x.length;i++){
      //message("Processing ("+i+" "+x.length+")");

      // these help to prevent adding multiples of tags with the same name
      var done_title = false;
      var done_content = false;
      var done_published = false;
      var done_link = false;
      var theNode;
      var theValue;

      for(j=0; j<x[i].childNodes.length; j++){
        theNode = x[i].childNodes[j];
        if((theNode.nodeType == 1)){
          if(theNode.firstChild==null){
            theValue = "";
          }
          else{
            //theValue = theNode.firstChild.nodeValue;
            theValue = "";
            for(iContentNode=0; iContentNode<theNode.childNodes.length; iContentNode++){
              theValue += theNode.childNodes[iContentNode].nodeValue;
            }
          }

          // search for : in node name
          aPos = theNode.nodeName.search(":");
          if(aPos!=-1){
            // we only want the inital part of the node name
            aNodeName = theNode.nodeName.slice(0, aPos);
          }
          else{
            aNodeName = theNode.nodeName;
          }

          if(((aNodeName==this.blog_title_tag) || (theNode.nodeName==this.blog_title_tag)) && (!done_title)){
            if(theValue==""){
              theValue="(no title)";
            }
            this.title[this.title.length]=theValue;
            done_title=true;
          }
          else if(((aNodeName==this.blog_content_tag) || (theNode.nodeName==this.blog_content_tag)) && (!done_content)){
            this.content[this.content.length]=theValue;
            done_content=true;
          }
          else if(((aNodeName==this.blog_published_tag) || (theNode.nodeName==this.blog_published_tag)) && (!done_published)){
            this.published[this.published.length]=theValue;
            done_published=true;
          }
        }

        if((theNode.nodeName==this.blog_link_tag) && (!done_link)){
          if(theNode.firstChild==null){
            // assume blogspot href attribute
            this.link[this.link.length]=theNode.getAttribute("href");
          }
          else{
            // use content of link tag
            this.link[this.link.length]=theNode.firstChild.nodeValue;
          }
          done_link=true;
        }
      }
  	}

    //alert(this.title.length + " " +  this.content.length + " " +  this.published.length + " " +  this.link.length);

  	// build the html
  	var html = "";
  	if(this.title.length>0){
      html += "<table class='blogtable'>";
    	for(field=0; field<this.title.length; field++){
        html += "<tr>";
        html += "<td class='blogtable_date' id='"+this.name+"_blog_date_"+field+"'>";
        html += "<span class='bloglink'>&nbsp;" + this.format_date(this.published[field]) + "</span></td>";
        html += "<td class='blogtable_title' id='"+this.name+"_blog_title_"+field+"'>";
        html += "<span class='bloglink'>&nbsp;" + this.title[field].substr(0, this.title_limit) + "</span></td>";
        html += "</tr>";
      }
      html +="</table>";
    }

    // Output the html
    if(html==""){
      this.message("&nbsp;(Empty)");
    }
    else{
      document.getElementById(this.result_html_id).innerHTML = html;
      for(field=0; field<this.title.length; field++){
        var date_td = document.getElementById(this.name+"_blog_date_"+field);
        var title_td = document.getElementById(this.name+"_blog_title_"+field);

        date_td.blogfeed = this;
        date_td.blog_id = field;
        date_td.onclick = function() { this.blogfeed.show_blog(this.blog_id); }

        title_td.blogfeed = this;
        title_td.blog_id = field;
        title_td.onclick = function() { this.blogfeed.show_blog(this.blog_id); }
      }
    }

    this.do_show_source();
  }

  // redefine the function so that the "this" is always bound to this instance
  var aCreateOutput = this.createOutput;
  this.createOutput = function (){ return aCreateOutput.apply(aBlogfeedObject, arguments); };

  this.do_show_source = function(){
    if(this.show_source){
      var html = "(Source: <a href='"+this.remote_file+"'>"+this.remote_file+"</a>)";
      document.getElementById(this.show_source_id).innerHTML = html;
    }
  }

  this.hide_blog = function(){
    var blog = document.getElementById(this.blog_html_id);
    blog.style.visibility="hidden";
  }

  this.next_blog = function(){
    var blog = document.getElementById(this.blog_html_id);
    this.show_blog(blog.current+1);
  }

  this.prev_blog = function(){
    var blog = document.getElementById(this.blog_html_id);
    this.show_blog(blog.current-1);
  }

  this.show_blog = function(iField){
    // popup the blog entry - or go to the blog entry link

    if(this.blog_show_method=="window"){
      // validate - keep within range
      if(iField>=this.content.length){
        iField = 0;
      }

      if(iField<0){
        iField = (this.content.length-1);
      }

      var html = "";
      html += "<div class='blog_top_div'>";
      if(this.show_source){
        html += "<div class='source_div'>(Source: <a class='source_link' href='"+this.link[iField]+"'>"+limit_text(this.link[iField], this.show_blog_source_limit)+"</a>)</div>";
      }
      html += "<div class='blog_buttons'>";
      html += "<div class='blog_prev' onmouseover='do_mouse_over_x(this);' onmouseout='do_mouse_out_x(this);' id='"+this.name+"_prev'>"+this.prev_button+"</div>";
      html += "<div class='blog_next' onmouseover='do_mouse_over_x(this);' onmouseout='do_mouse_out_x(this);' id='"+this.name+"_next'>"+this.next_button+"</div>";
      html += "<div class='blog_close' onmouseover='do_mouse_over_x(this);' onmouseout='do_mouse_out_x(this);' id='"+this.name+"_close'>"+this.close_button+"</div>";
      html += "</div>";

      html += "</div>";

      html += "<div class='blog_date'>"+this.format_date2(this.published[iField])+"</div>";
      html += "<a style='text-decoration:none;' href='"+this.link[iField]+"'><div class='blog_title'>"+limit_text(this.title[iField], this.show_blog_title_limit)+"</div></a>";
      html += "<div id = '"+this.blog_html_id + "_content"+"' class='blog_content'>"+this.content[iField]+"</div>";

      var blog = document.getElementById(this.blog_html_id);

      // todo - varoius browsers put a limit on innerHTML - how should i handle this?
      blog.innerHTML = html;

      blog.style.visibility="visible";
      blog.current = iField;

      var prev_button = document.getElementById(this.name+"_prev");
      prev_button.blogfeed = this;
      prev_button.onclick = function(){ this.blogfeed.prev_blog(); };
      prev_button.mouseoverstyle = "blog_prev_hover";
      prev_button.mouseoutstyle = "blog_prev";

      var next_button = document.getElementById(this.name+"_next");
      next_button.blogfeed = this;
      next_button.onclick = function(){ this.blogfeed.next_blog(); };
      next_button.mouseoverstyle = "blog_next_hover";
      next_button.mouseoutstyle = "blog_next";

      var close_button = document.getElementById(this.name+"_close");
      close_button.blogfeed = this;
      close_button.onclick = function(){ this.blogfeed.hide_blog(); };
      close_button.mouseoverstyle = "blog_close_hover";
      close_button.mouseoutstyle = "blog_close";

    }
    else{
      location=this.link[iField];
    }
  }

  this.toggle_usepopup = function(usepopup){
    if(usepopup){
      this.blog_show_method="window";
    }
    else{
      this.blog_show_method="link";
    }
  }

  this.message = function(amessage){
    document.getElementById(this.result_html_id).innerHTML = "<span class='bloglink'>"+amessage+"</span>";
  }

  this.center_message = function(amessage){
    document.getElementById(this.result_html_id).innerHTML = "<table style='width:100%;height:100%;border:none;vertical-align:middle;text-align:center;'><tr><td style='height:100%;border:none;vertical-align:middle;text-align:center;'>"+amessage+"</td></tr></table>";
  }

  this.format_date = function (adate){
    // Convert date based on rss mode
    // Return date as:
    // dd/mm hh:mmAMPM
    if(adate==null){
      adate=this.defaultDate;
    }

    if(this.blog_published_tag=="pubDate"){
      newDate = date1_to_jsdate(adate);
    }
    else{
      newDate = date2_to_jsdate(adate);
    }

    return(short_date(newDate));
  }

  this.format_date2 = function(adate){
    // Convert date based on rss mode
    // Return date as:
    // ddd dd/mm hh:mmAMPM
    if(adate==null){
      adate=this.defaultDate;
    }

    if(this.blog_published_tag=="pubDate"){
      newDate = date1_to_jsdate(adate);
    }
    else{
      newDate = date2_to_jsdate(adate);
    }

    return(mid_date(newDate));
  }

  this.resultDivHTML = function(){
    return('<div id="'+this.result_html_id+'" class="blogfeeddiv"></div>');
  }

  this.showSourceDivHTML = function(){
    return('<div id="'+this.show_source_id+'" class="show_source"></div>');
  }

  this.blogHtmlDivHTML = function(){
    return('<div id="'+this.blog_html_id+'" class="bloghtml"></div>');
  }

  this.outputResultDiv = function(){
    document.write(this.resultDivHTML());
  }

  this.outputShowSourceDiv = function(){
    document.write(this.showSourceDivHTML());
  }

  this.outputBlogHtmlDiv = function(){
    document.write(this.blogHtmlDivHTML());
  }

}
