var org = {p3k: ({url:"http://feeds.feedburner.com/tscom?format=xml", xml:"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<?xml-stylesheet type=\"text/xsl\" media=\"screen\" href=\"/~d/styles/rss2full.xsl\"?><?xml-stylesheet type=\"text/css\" media=\"screen\" href=\"http://feeds.feedburner.com/~d/styles/itemcontent.css\"?><rss xmlns:itunes=\"http://www.itunes.com/dtds/podcast-1.0.dtd\" version=\"2.0\">\n  <channel>\n    <title>TimSchropp.com RSS</title>\n    <link>http://www.timschropp.com/index.html</link>\n    <description>RSS Feed Kanal</description>\n    <copyright>2010 Tim Schropp</copyright>\n    <managingEditor>info@timschropp.com</managingEditor>\n    <pubDate>Fri, 05 Feb 2010 16:31:55 GMT+01:00</pubDate>\n    <generator>FeedMe, by the Nowhere Man (http://thenowhereman.com/hacks)</generator>\n    <atom10:link xmlns:atom10=\"http://www.w3.org/2005/Atom\" rel=\"self\" type=\"application/rss+xml\" href=\"http://feeds.feedburner.com/tscom\" /><feedburner:info xmlns:feedburner=\"http://rssnamespace.org/feedburner/ext/1.0\" uri=\"tscom\" /><atom10:link xmlns:atom10=\"http://www.w3.org/2005/Atom\" rel=\"hub\" href=\"http://pubsubhubbub.appspot.com\" /><item>\n      <title>Icon PSD-Vorlagen fuer Apple Mobilgeraete</title>\n      <pubDate>Fri, 05 Feb 2010 16:31:04 GMT+01:00</pubDate>\n      <link>http://www.timschropp.com/index.html#iconpsds</link>\n      <guid isPermaLink=\"false\">1265383864</guid>\n      <description>Fuer die Entwickler von iPhone- und zukuenftig auch speziellen iPad-Apps haben die Macher des \"Cocoia Blog\" pixelgetreue &lt;a href=\"http://blog.cocoia.com/2010/iphone-ipad-icon-psd-template/\"&gt;Icons zur Verfuegung gestellt&lt;/a&gt;.&lt;br&gt;Geboten werden exakt angepasste Icons mit Glanzeffekt und weiteren Vorlagen, die auch beliebig angepasst werden duerfen. Das PSD-Dokument steht &lt;a href=\"http://blog.cocoia.com/2010/iphone-ipad-icon-psd-template/\"&gt;zum kostenlosen Download&lt;/a&gt; bereit.</description>\n    </item>\n    <item>\n      <title>Flash, und dann?</title>\n      <pubDate>Sun, 31 Jan 2010 16:29:32 GMT+01:00</pubDate>\n      <link>http://www.timschropp.com/index.html#flashunddann</link>\n      <guid isPermaLink=\"false\">1264951772</guid>\n      <description>Lange ist die Beliebtheit von Flash nicht mehr so gering gewesen wie heute. Immer traeger und ressourcenhungriger ist Flash ueber die Jahre geworden. Die Folgen sind Abstuerze, hochdrehende Luefter, traeges Rechnerverhalten. Auch Microsoft hat dieses Problem erkannt und 'Silverlight' entwickelt - Derzeit benutzen aber nur sehr wenige Webseiten den Microsoft-Pedanten.&lt;br&gt;Erst durch heftige Kritik seitens des Apple CEO Steve Jobs bei der Vorstellung des neuen Apple iPad kamen die Steine ins rollen. Nun hat auch Adobe reagiert und in seinem Firmenblog bekannt gegeben, Flash &lt;a href=\"http://www.maclife.de/mac/software/internet/adobe-beschleunigt-flash-fuer-mac-os-x\"&gt;vor allem fuer Mac OS X&lt;/a&gt; mit Hilfe Apples 'Core Animation\" zu beschleunigen.&lt;br&gt;Ebenfalls gab Adobe bekannt sehr wohl zu wissen, dass Flash alles andere als zukunftstraechtig sei. An HTML5 und CSS3 glaube man jedoch nicht, dennoch moechte Adobe hierfuer Tools bereitstellen.</description>\n    </item>\n    <item>\n      <title>Twitter vor dem Aus?</title>\n      <pubDate>Thu, 28 Jan 2010 22:31:36 GMT+01:00</pubDate>\n      <link>http://www.timschropp.com/index.html#twittervordemaus</link>\n      <guid isPermaLink=\"false\">1264714296</guid>\n      <description>Totgesagte leben laenger, heisst es. Schon des oefteren meinten Experten zu wissen, dass der eigentlich so beliebte Kurznachrichtendienst Twitter kurz vor dem Aus stuende. Anlass dazu gab in erster Linie die Tatsache, dass der Ansturm langsam abflacht - ebenfalls, dass der Dienst eine grosse Anzahl &lt;a href=\"http://www.heute.de/ZDFheute/inhalt/23/0,3672,8021815,00.html\"&gt;inaktiver Benutzerkonten&lt;/a&gt; aufweist - angeblich jedes vierte. &lt;br&gt;Mit ca. 350 Millionen Nutzern ist Facebook wohl derzeit das Schlachtschiff auf dem Social Media-Meer, etwa die Haelfte davon ist taeglich aktiv. Twitter hingegen kann bis Dato nur noch etwa 15 Millionen weltweit aktive Nutzer verzeichnen. Unter den beliebten Accounts von bekannten Persoenlichkeiten, Stars, Politiker oder auch Gesellschaften ist derzeit aber noch kein akuter Benutzerschwund zu verzeichnen.</description>\n    </item>\n    <item>\n      <title>Schoenes Neujahr und guten Rutsch!</title>\n      <pubDate>Fri, 01 Jan 2010 03:32:35 GMT+01:00</pubDate>\n      <link>http://www.timschropp.com/index.html#neujahr</link>\n      <guid isPermaLink=\"false\">1262313155</guid>\n      <description>Die Weihnachtszeit ist zwar noch nicht vorbei, das Jahr 2009 allerdings dauert nur noch wenige Stunden. Die aeusserst optimistische &lt;a href=\"http://www.faz.net/s/Rub594835B672714A1DB1A121534F010EE1/Doc%7EEFA0AB68141574A11B138BEE9C14773A7%7EATpl%7EEcommon%7EScontent.html?rss_googlenews\"&gt;Neujahrsansprache&lt;/a&gt; von Frau Kanzlerin Merkel laesst zwar nichts gutes erhoffen, denken wir jedoch positiv und wuenschen uns persoenlich das Beste. Alles Gute fuer das neue Jahr 2010!&lt;br&gt;&lt;br&gt;Passend zum Neujahr habe ich eine kleine Geschichte geschrieben, die ihr bei Lust und Laune gerne lesen duerft. &gt;&gt;&lt;a href=\"http://timschropp.com/downloads/eine_silvester_party.pdf\"&gt;Eine Silvester-Party, oder: Warum ich nie wieder Silvester feiere&lt;/a&gt;&lt;&lt; (PDF-Dokument)</description>\n    </item>\n  </channel>\n</rss>\n", message:undefined, modified:(new Date(1265732828682)), baseUri:"http://p3k.org/rss/", query:"frameColor=#EEEEEE&textColor=black&_=1205286474625&titleBarColor=#EEEEEE&compact=true&fontFace=&align=center&showXmlButton=true&maxItems=3&boxFillColor=#EEEEEE&undefined=&titleBarTextColor=black&width=180&url=http://feeds.feedburner.com/tscom?format=xml&", param:{textColor:"black", width:"180", align:"center", fontFace:"", url:"http://feeds.feedburner.com/tscom?format=xml", compact:"true", frameColor:"#EEEEEE", showXmlButton:"true", undefined:"", boxFillColor:"#EEEEEE", _:"1205286474625", titleBarColor:"#EEEEEE", maxItems:"3", titleBarTextColor:"black"}, box:"<table class=\"rssBox\" width=\"${width}\" bgcolor=\"${frameColor}\" \n      style=\"table-layout: fixed; overflow: hidden; font-family: ${fontFace};\" \n      align=\"${align}\" cellspacing=\"1\" cellpadding=\"7\" border=\"0\">\n<tr bgcolor=\"${titleBarColor}\">\n<td>\n   ${xmlButton}\n   <strong>${title}</strong>\n   <div>\n      <small style=\"color: ${titleBarTextColor};\">${date}</small>\n   </div>\n</td>\n</tr>\n<tr bgcolor=\"${boxFillColor}\">\n<td class=\"rssBoxContent\" style=\"color: ${textColor};\">\n   ${image}\n   ${items}\n   ${input}\n   <div class=\"rssBoxPromo\" style=\"margin-top: 0px; text-align: left; \n         font: 9px verdana, sans-serif\">\n      RSS box by <a href=\"http://p3k.org/rss\">p3k.org</a>.\n   </div>\n</td>\n</tr>\n</table>\n\n", image:"<a href=\"${link}\"><img src=\"${source}\" width=\"${width}\" height=\"${height}\" \nalt=\"${title}\" title=\"${title}\" align=\"${align}\" valign=\"${valign}\" \nhspace=\"${hspace}\" vspace=\"${vspace}\" border=\"0\" /></a>\n\n", input:"<form method=\"get\" action=\"${link}\">\n${description}\n<input type=\"text\" name=\"${name}\" size=\"15\" /> <input type=\"submit\" \nvalue=\"${title}\" />\n</form>\n\n", item:"<div class=\"rssBoxItemContent\">\n${title}\n${break}\n${description}\n${buttons}\n</div><br />\n\n", date:"${year}-${month}-${day}, ${hours}:${minutes}h\n\n", link:"<a class=\"${class}\" href=\"${link}\" style=\"${style}\">${text}</a>\n", error:"<?xml version=\"1.0\"?>\n<rss version=\"error\">\n   <channel>\n      <title>RSS Box Error</title>\n      <link>${link}</link>\n      <description>This output was automatically generated to report an error \n      that occurred during a request to the JavaScript RSS Box Viewer.</description>\n      <item>\n         <title>Oops, something went wrong...</title>\n         <description>An error occurred while processing the request to the \n         JavaScript RSS Box Viewer.</description>\n      </item>\n      <item>\n         <title>An error message was returned by the server.</title>\n         <description>${message}</description>\n      </item>\n      <item>\n         <description>Most likely, this might have happened because of a \n         non-existent or invalid RSS feed URL. Please check and possibly correct \n         your input, then try again.</description>\n      </item>\n   </channel>\n</rss>\n\n"})};
function debug(str) {
   return document.write('<p><span style="background-color: yellow;">', 
         str, '</span><p>');
}

org.p3k.RssBox = function() {
   var ref;
   var ISOPATTERN = /([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9:]+).*$/;
   
   var data = org.p3k;
   data.defaults = {
      url: "http://blog.p3k.org/rss",
      maxItems: 7,
      width: 200,
      align: "",
      frameColor: "black",
      titleBarColor: "lightblue",
      titleBarTextColor: "black",
      boxFillColor: "white",
      textColor: "black",
      showXmlButton: "",
      compact: ""
   };
   
   var baseUri = data.baseUri;
    
   var getColor = function(str) {
      if (str.length === 6 && parseInt(str, 16) && str.indexOf("#") !== 0) {
         str = "#" + str;
      }
      return str.toLowerCase();
   }

   var value;
   for (var i in data.defaults) {
      value = data.param[i];
      if (!value || value.length === 0) {
         data.param[i] = data.defaults[i];
      } else if (i.indexOf("Color") > 0) {
         data.param[i] = getColor(value);
      }
   }

   // FIXME: Ugly work-around for many boxes using too small width 
   // values because the former version did not show the exact output.
   if (data.param.javascript && data.param.width < 200) {
      data.param.width = 200;
   }
   // Remove obsolete parameters from param and query
   delete data.param.javascript;
   data.query = data.query.replace("javascript=true", "");   

   var NAMESPACES = {
      dc: "http://purl.org/dc/elements/1.1/",
      rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   };

   var getUrl = function(url) {
      url = baseUri + "proxy.r?" + encodeURIComponent(url);
   
      var HttpRequest = function() {
         return (typeof XMLHttpRequest !== "undefined") ?
            new XMLHttpRequest() : new ActiveXObject("Msxml2.XMLHTTP");
      }
   
      var request = new HttpRequest();
      request.open("GET", url, false);
      request.send(null);   
      if (!request.getResponseHeader("Date")) {
         var cached = request;
         var ifModifiedSince = cached.getResponseHeader("Last-Modified") || 
               new Date(0); // January 1, 1970
         request = new HttpRequest();
         request.open("GET", url, false);
         request.setRequestHeader("If-Modified-Since", ifModifiedSince);
         request.send("");
         if (request.status === 304) {
            request = cached; 
         }
      }
      return request;
   }
   
   var getDocument = function(source) {
      if (source) {
         if (document.implementation.createDocument) {
            var parser = new DOMParser();
            var doc = parser.parseFromString(source, "text/xml");
            return doc;
         } else if (window.ActiveXObject) {
            var doc = new ActiveXObject("Microsoft.XMLDOM");
            doc.async = "false";
            doc.loadXML(source);
            return doc;
         }
      }
      return null;
   }
   
   var getError = function() {
      var msg = null, root;
      if (!xml || data.message) {
         msg = data.message || "Unknown error.";
      } else if (xml.parseError && xml.parseError.errorCode) {
         msg = xml.parseError.reason; // IExplore
      } else if (root = xml.documentElement) {
         var errorNode;
         if (root.nodeName === "parsererror") {
            msg = xml.documentElement.textContent; // Mozilla
         } else if ((errorNode = root.childNodes[0]) && 
               errorNode.nodeName === "parsererror") {
            msg = errorNode.textContent; // Safari
         } else if (!/rss|rdf|scriptingNews/i.test(xml.documentElement.nodeName)) {
            msg = "Incompatible data format. Are you sure this is an RSS feed?";
         }
      }
      return msg;
   }
   
   var getNode = function(parent, name, namespace) {
      if (namespace) {
         if (typeof parent.getElementsByTagNameNS === "undefined") {
            var elements = parent.getElementsByTagName(namespace + ":" + name);
         } else {
            var elements = parent.getElementsByTagNameNS(NAMESPACES[namespace], name);
         }
      } else {
         var elements = parent.getElementsByTagName(name);
      }
      if (elements && elements[0]) {
         return elements[0];
      }
      return null;
   }
   
   var getText = function(node) {
      if (node && node.childNodes && node.childNodes.length > 0) {
         return node.childNodes[0].nodeValue || "";
      }
      return "";
   }
   
   var trim = function(str) {
      if (str) {
         return str.replace(/^\s*(\S*)\s*$/, "$1");
      }
      return "";
   }
   
   var padZero = function(n) {
      if (n < 10) {
         return "0" + n
      }
      return n;
   }

   var encodeXml = function(str) {
      if (!str) {
         return "";
      }
      return str.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/&/g, "&amp;");
   }
      
   var render = function(template, param) {
      if (!template || !param) {
         return template;
      }
      template = template.replace(/\$\{([^}]+)\}/g, function() {
         var key = arguments[1];
         return param[key] || "";
      });
      return template;
   }
   
   var renderDate = function(date) {
      if (date.constructor !== Date) {
         var str = String(date);
         var millis = Date.parse(str.replace(ISOPATTERN, "$1/$2/$3 $4"));
         if (millis) {
            date = new Date(millis);
         } else {
            date = new Date;
         }
      }

      return render(data.date, {
         year: date.getFullYear(),
         month: padZero(date.getMonth() + 1),
         day: padZero(date.getDate()),
         hours: padZero(date.getHours()),
         minutes: padZero(date.getMinutes()),
         seconds: padZero(date.getSeconds()),
         timeZone: "" // date.getTimezoneOffset()
      });
   }
   
   var renderButtons = function(enclosure, source) {
      var result = "";
      if (enclosure && enclosure.link) {
         result += render(data.image, {
            source: baseUri + "enclosure.gif",
            title: enclosure.type,
            link: encodeURI(enclosure.link),
            width: 13,
            height: 16
         });
      }
      if (source && source.link) {
         result += render(data.image, {
            source: baseUri + "source.gif",
            title: source.title,
            link: encodeURI(source.link),
            width: 15,
            height: 15
         });
      }
      return result;         
   }
   
   var param = data.param;
   var rss = data.rss = {items: []};
   var xml = getDocument(data.xml);

   rss.error = getError();
   if (rss.error !== null) {
      xml = getDocument(render(data.error, {
         link: baseUri + "?" + encodeXml(data.query),
         message: encodeXml(rss.error)
      }));
      param.compact = 0;
      param.showXmlButton = 1;
   }

   var root = xml.documentElement;
   var type = root.nodeName;

   if (type === "scriptingNews") {
      var channel = getNode(xml, "header");
      rss.format = "Scripting News";
      rss.version = getText(getNode(channel, "scriptingNewsVersion"));
      rss.title = getText(getNode(channel, "channelTitle"));
      rss.description = getText(getNode(channel, "channelDescription"));
      rss.link = getText(getNode(channel, "channelLink"));
      if (ref = getText(getNode(channel, "imageUrl"))) {
         ref = rss.image = {source: ref};
         ref.title = getText(getNode(channel, "imageTitle"));
         ref.link = getText(getNode(channel, "imageLink"));
         ref.width = getText(getNode(channel, "imageWidth"));
         ref.height = getText(getNode(channel, "imageHeight"));
         ref.description = getText(getNode(channel, "imageCaption"));
      }
   } else {
      var channel = getNode(xml, "channel");
      rss.format = "RSS";
      rss.version = (type === "rdf:RDF") ? "1.0" : 
            root.getAttribute("version");
      rss.title = getText(getNode(channel, "title"));
      rss.description = getText(getNode(channel, "description"));
      rss.link = getText(getNode(channel, "link"));
      var image = getNode(xml, "image");
      if (image) {
         ref = rss.image = {};
         ref.source = getText(getNode(image, "url"));
         ref.title = getText(getNode(image, "title"));
         ref.link = getText(getNode(image, "link"));
         ref.width = getText(getNode(image, "width"));
         ref.height = getText(getNode(image, "height"));
         ref.description = getText(getNode(image, "description"));
      }
   }
   
   if (type === "rdf:RDF") {
      rss.date = renderDate(getText(getNode(channel, "date", "dc")) || data.modified);
      rss.rights = getText(getNode(channel, "creator", "dc"));
      var input = getNode(root, "textinput");
      if (input && !getNode(input, "link")) {
         input = root.getElementsByTagName("textinput")[1];
      }
      if (input) {
         ref = rss.input = {};
         ref.link = getText(getNode(input, "link"));
         ref.description = getText(getNode(input, "description"));
         ref.name = getText(getNode(input, "name"));
         ref.title = getText(getNode(input, "title"));
      }
   } else {
      rss.date = renderDate(getText(getNode(channel, "lastBuildDate") || getText(getNode(channel, "pubDate"))) || data.modified);
      rss.rights = getText(getNode(channel, "copyright"));
   }
   
   var item, text, node;
   var items = xml.getElementsByTagName("item");

   for (var i=0; i<Math.min(items.length, param.maxItems); i+=1) {
      item = items[i];

      if (type === "scriptingNews") {
         ref = {title: ""};
         ref.description = getText(getNode(item, "text")).replace(/\n/g, " ");
         ref.link = getText(getNode(item, "link"));
         if (text = trim(getText(getNode(item, "linetext")).replace(/\n/g, " "))) {
            ref.description = ref.description.replace(new RegExp(text), 
                  '<a href="' + getText(getNode(item, "url")) + '">' + text + '</a>');
         }
      } else {
         ref = {
            title: getText(getNode(item, "title")),
            description: getText(getNode(item, "description")),
            link: getText(getNode(item, "link") || getNode(item, "guid"))
         };
     }

     if (node = getNode(item, "source")) {
        ref.source = {
           link: node.getAttribute("url"),
           title: getText(node)
        }
     }
     
     if (node = getNode(item, "enclosure")) {
        ref.enclosure = {
           link: node.getAttribute("url"),
           length: node.getAttribute("length"),
           type: node.getAttribute("type")
        }
     }
     
     if (node = getNode(item, "category")) {
        ref.category = {
           domain: node.getAttribute("domain") || "",
           content: getText(node)
        }
     }
     
     rss.items.push(ref);
   }
   
   var item, items = "";
   for (var i=0; i<rss.items.length; i+=1) {
      item = rss.items[i];
      items += render(data.item, {
         title: new function() {
            var title = (!param.compact ? "<strong>" : "");
            if (item.link) {
               title += render(data.link, {
                  link: encodeURI(item.link),
                  text: item.title,
                  'class': "rssBoxItemTitle"
               });
            } else {
               title += item.title;
            }
            !param.compact && (title += "</strong>");
            return new String(title); // FIXME: Funny, title alone will be rendered as [object]
         }(),
         'break': item.title && item.description ? "<br />" : "",
         description: (!param.compact || !item.title) && item.description,
         buttons: renderButtons(item.enclosure, item.source)
      });
   }
   
   var box = render(data.box, {
      title: rss.link ? render(data.link, {
         link: encodeURI(rss.link),
         text: rss.title,
         'class': "rssBoxTitle",
         style: "color: " + param.titleBarTextColor
      }) : rss.title,
      description: rss.description,
      items: items,

      xmlButton: param.showXmlButton && render(data.image, {
         link: param.url,
         source: baseUri + "rss.png",
         title: rss.format + " " + rss.version,
         width: 16,
         height: 16,
         align: "right",
         hspace: 3
      }),
      
      image: !param.compact && rss.image && render(data.image, {
         link: encodeURI(rss.image.link),
         source: rss.image.source,
         width: rss.image.width,
         height: rss.image.height,
         title: rss.image.title,
         align: "right",
         valign: "baseline",
         hspace: 5,
         vspace: 5
      }),
      
      input: !param.compact && rss.input && render(data.input, {
         link: encodeURI(rss.input.link),
         description: rss.input.description,
         name: rss.input.name,
         title: rss.input.title
      }),
      
      date: rss.date,
      width: param.width,
      frameColor: param.frameColor,
      fontFace: param.fontFace,
      align: param.align,
      titleBarColor: param.titleBarColor,
      titleBarTextColor: param.titleBarTextColor,
      boxFillColor: param.boxFillColor,
      textColor: param.textColor
   });

   if (!window.rssBoxSetup) {
      document.write(box);
   }
   
   return box;
};

org.p3k.RssBox();

