var org = {p3k: ({url:"http://news.thomasnet.com/conewsxml/434429", xml:"<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n<!-- generator=\"FeedCreator 1.7.1\" -->\n<rss version=\"2.0\">\n    <channel>\n        <title>RSS Feed for U.S. Tsubaki, Inc.</title>\n        <description>ThomasNet News is a service of ThomasNet.com</description>\n        <link>http://news.thomasnet.com</link>\n        <lastBuildDate>Sun, 05 Sep 2010 23:22:01 -0400</lastBuildDate>\n        <generator>FeedCreator 1.7.1</generator>\n        <image>\n            <url>http://news.thomasnet.com/images/header/TN_News_footer.gif</url>\n            <title>Powered by ThomasNet News</title>\n            <link>http://news.thomasnet.com</link>\n            <width>129</width>\n            <height>38</height>\n        </image>\n        <item>\n            <title>Chains target oil field industry.</title>\n            <link>http://news.thomasnet.com/fullstory/Chains-target-oil-field-industry-28115</link>\n            <description>Energy Series&amp;#226;&amp;quot;&amp;#162; Chains are available in sizes 80&amp;#226;\ufffd&amp;quot;240 and up to 10 strands wide. Pins hold tight under extreme vibration, and smooth holes eliminate fatigue cracks that can compromise chain strength. Link plates help distribute loads evenly. Z-cotter connecting links hold tight, yet allow assembly and disassembly in the field. Chains are suited for on-shore and off-shore drilling applications.&lt;br&gt;&lt;br&gt;&lt;b&gt;This story is related to the following:&lt;/b&gt;&lt;br&gt;&lt;a href='http://news.thomasnet.com/news/machinery-machining-tools' target='_blank''&gt;Machinery and Machining Tools&lt;/a&gt;&lt;br&gt;&lt;br&gt;Search for suppliers of: &lt;a href='http://www.thomasnet.com/products/oil-well-drilling-chains-13312202-1.html' target='_blank''&gt;Oil Well Drilling Chains&lt;/a&gt;&lt;br&gt;</description>\n            <author>info@productnews.com (ThomasNet News)</author>\n            <pubDate>Thu, 13 Nov 2003 08:14:17 -0400</pubDate>\n        </item>\n        <item>\n            <title>Chain offers double barrier against corrosion.</title>\n            <link>http://news.thomasnet.com/fullstory/Chain-offers-double-barrier-against-corrosion-17591</link>\n            <description>NEPTUNE&amp;#226;&amp;quot;&amp;#162; Chain has chromium-free top coat that protects chain from physical impact and corrosive agents. Zinc base coat extends protection through sacrificing function that prevents oxidization from reaching chain core. Product withstands 500+ hours of saltwater spray testing without rusting. NEPTUNE Roller Chain is available in sizes 35&amp;#226;\ufffd&amp;quot;100, and NEPTUNE Conveyor Chain is available in single pitch and double pitch, sizes 40&amp;#226;\ufffd&amp;quot;100. NEPTUNE Leaf Chain is also available.&lt;br&gt;&lt;br&gt;&lt;b&gt;This story is related to the following:&lt;/b&gt;&lt;br&gt;&lt;a href='http://news.thomasnet.com/news/material-handling-storage' target='_blank''&gt;Material Handling and Storage&lt;/a&gt; Sponsored by:  &lt;a target='_blank' href='http://news.thomasnet.com/redir.html?lnty=rssad&amp;spclid=3473&amp;prid=17591&amp;cat=1424&amp;goto=http%3A%2F%2Fwww.reidsupply.com%2FCad.aspx'&gt;Reid Supply - FREE CAD Drawings of Tens-of-Thousands of Parts!&lt;/a&gt;&lt;br&gt;&lt;a href='http://news.thomasnet.com/news/mechanical-components-assemblies' target='_blank''&gt;Mechanical Components and Assemblies&lt;/a&gt;&lt;br&gt;&lt;br&gt;Search for suppliers of: &lt;a href='http://www.thomasnet.com/products/roller-chains-13330600-1.html' target='_blank''&gt;Roller Chains&lt;/a&gt;  |  &lt;a href='http://www.thomasnet.com/products/corrosion-resistant-chains-13240403-1.html' target='_blank''&gt;Corrosion Resistant Chains&lt;/a&gt;  |  &lt;a href='http://www.thomasnet.com/products/conveyor-chains-13231204-1.html' target='_blank''&gt;Conveyor Chains&lt;/a&gt;  |  &lt;a href='http://www.thomasnet.com/products/leaf-chains-13297007-1.html' target='_blank''&gt;Leaf Chains&lt;/a&gt;&lt;br&gt;</description>\n            <author>info@productnews.com (ThomasNet News)</author>\n            <pubDate>Mon, 16 Dec 2002 07:44:44 -0400</pubDate>\n        </item>\n        <item>\n            <title>Drive Chain reduces workplace noise.</title>\n            <link>http://news.thomasnet.com/fullstory/Drive-Chain-reduces-workplace-noise-7281</link>\n            <description>Low Noise Drive Chain offers spring roller construction, which absorbs impact of sprocket-chain interaction, reducing equipment noise by up to 10 decibels. It is available in sizes 40 through 80, and can directly replace ANSI standard chain for compliance with environmental management standards such as ISO 14000. Chain exceeds ANSI minimum tensile strength requirements and operates with standard sprockets in temperatures from 14&amp;#176;F to 140&amp;#176;F.&lt;br&gt;&lt;br&gt;&lt;b&gt;This story is related to the following:&lt;/b&gt;&lt;br&gt;&lt;a href='http://news.thomasnet.com/news/mechanical-power-transmission' target='_blank''&gt;Mechanical Power Transmission&lt;/a&gt;&lt;br&gt;&lt;br&gt;Search for suppliers of: &lt;a href='http://www.thomasnet.com/products/drive-chains-13252804-1.html' target='_blank''&gt;Drive Chains&lt;/a&gt;&lt;br&gt;</description>\n            <author>info@productnews.com (ThomasNet News)</author>\n            <pubDate>Wed, 27 Feb 2002 14:10:40 -0400</pubDate>\n        </item>\n        <item>\n            <title>Lube-free Chain exceeds ANSI specs.</title>\n            <link>http://news.thomasnet.com/fullstory/Lube-free-Chain-exceeds-ANSI-specs-4707</link>\n            <description>Xceeder Chain has oil-impregnated felt seals that keep dirt out and lubrication in for increased wear life. Drive, conveyor, and attachment chains are available in sizes 40 to 100, are interchangeable with ANSI standard chain, and work with standard sprockets. They handle same maximum loads as ANSI standard chain, and exceed ANSI minimum tensile strength requirements. \n\n&lt;br&gt;&lt;br&gt;&lt;b&gt;This story is related to the following:&lt;/b&gt;&lt;br&gt;&lt;a href='http://news.thomasnet.com/news/mechanical-power-transmission' target='_blank''&gt;Mechanical Power Transmission&lt;/a&gt;&lt;br&gt;&lt;br&gt;Search for suppliers of: &lt;a href='http://www.thomasnet.com/products/power-transmission-chains-13321807-1.html' target='_blank''&gt;Power Transmission Chains&lt;/a&gt;&lt;br&gt;</description>\n            <author>info@productnews.com (ThomasNet News)</author>\n            <pubDate>Wed, 21 Nov 2001 15:36:29 -0400</pubDate>\n        </item>\n    </channel>\n</rss>\n", message:undefined, modified:(new Date(1283743322008)), baseUri:"http://p3k.org/rss/", query:"textColor=#000000&align=&width=500&fontFace=&url=http://news.thomasnet.com/conewsxml/434429&compact=&frameColor=black&showXmlButton=&setup=true&boxFillColor=white&_=1266199291884&titleBarColor=orange&maxItems=7&titleBarTextColor=black&", param:{textColor:"#000000", width:"500", align:"", fontFace:"", url:"http://news.thomasnet.com/conewsxml/434429", frameColor:"black", compact:"", showXmlButton:"", setup:"true", boxFillColor:"white", _:"1266199291884", titleBarColor:"orange", maxItems:"7", 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();

