var org = {p3k: ({url:"http://fundingopps.cos.com/news/rss.xml", xml:"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rss version=\"2.0\">\n  <channel>\n    <title>COS Funding News</title>\n    <link>http://fundingopps.cos.com/news/</link>\n    <description>A sampling of current records from COS Funding Opportunities&#x2014;the most comprehensive source of grants, fellowships, awards, prizes, scholarships, and programs from sponsors around the globe.</description>\n    <language>en-us</language>\n    <copyright>2010 CSA, Bethesda, Maryland. All rights reserved.</copyright>\n    <docs>http://backend.userland.com/rss</docs>\n    <generator>Perl</generator>\n    <managingEditor>fo@cos.com</managingEditor>\n    <webMaster>webmaster@cos.com</webMaster>\n    <ttl>40</ttl>\n    <item>\n      <title>Sontag Foundation Funds Early Career Scientists\u2019 Brain Cancer Research Proposals</title>\n      <description>[us] The Sontag Foundation Distinguished Scientist Awards are presented to the most outstanding early career scientists with inspiring, high-potential proposals in brain cancer research. Applicants must hold a doctoral degree in a biomedical science, medicine, or other health-related field. At the time of application, applicants must hold their first independent full-time faculty appointment at the level of assistant professor, independent researcher, or equivalent position at a tax-exempt 501(c)(3) academic, research, or medical institution within the United States or an equivalent institution in Canada. The applicant&apos;s career track and proposed research should demonstrate potential to generate new knowledge relating to causes, cure or treatment of primary brain tumors or brain cancer. The research proposal submitted for funding must be a primary focus of the applicant. Up to three grants will be awarded. Each award consists of a four-year funding component at up to $150,000 per year, totaling a maximum of $600,000. The application deadline is March 24, 2010.</description>\n      <link>http://fundingopps.cos.com/cgi-bin/getRec?id=77727</link>\n      <pubDate>Thu Feb  4 21:08:57 2010 GMT</pubDate>\n      <guid>http://fundingopps.cos.com/cgi-bin/getRec?id=77727</guid>\n    </item>\n    <item>\n      <title>Postdoctoral Fellowship Offered in Austrian or Habsburg History</title>\n      <description>[canada] The Wirth Institute for Austrian and Central European Studies at the University of Alberta in Edmonton invites applications for a postdoctoral fellowship in an academic specialization in any aspect of Austrian or Habsburg history. The successful candidate will be expected to be actively engaged in research, to teach a course in the area of his or her specialization, and to participate actively in the operation and activities of the institute. Applicants must have an academic specialization in any aspect of Austrian or Habsburg history. Applicants may be no more than five years past their doctoral degree and should be fluent in German. An ability to work in an additional central European language would be an asset. The postdoctoral fellowship is for one year with the possibility of renewal for an additional year, effective September 1, 2010. The annual stipend is CAN $45,000. The application deadline is April 15, 2010.</description>\n      <link>http://fundingopps.cos.com/cgi-bin/getRec?id=123083</link>\n      <pubDate>Thu Feb  4 21:08:57 2010 GMT</pubDate>\n      <guid>http://fundingopps.cos.com/cgi-bin/getRec?id=123083</guid>\n    </item>\n    <item>\n      <title>APSF Grants Fund Activities in South West Pacific</title>\n      <description>[australia] The Australia and Pacific Science Foundation (APSF) sponsors activities with components within the southwest Pacific, managed by Australian institutions or other entities within those countries. The foundation provides support for the following activities: (1) The top priority is to encourage high-quality research by scientists in Australian national or state institutions, and similar institutions in other countries of the south west Pacific; (2) Occasional support may also be given to such activities as training, publications, or conferences. The research committee particularly favors activities that seem likely to lead to improved systems of managing land, water, plants, and animals in ways that will enhance the productivity and quality of food, fisheries, plants, and forests, while simultaneously conserving the natural environment, preserving biodiversity, avoiding pollution of soils and water, and enhancing human health and welfare. Grants are awarded to institutions within Australia or other countries of the southwest Pacific region for activities within those countries or within the region. In the current competitive environment, highly productive young postdoctoral researchers are more likely to be competitive than students with limited publications or other demonstrated successes. Typically the APSF provides project grants up to approximately A$15,000 per year for up to three years. The next round of applications will close March 12, 2010.</description>\n      <link>http://fundingopps.cos.com/cgi-bin/getRec?id=75621</link>\n      <pubDate>Thu Feb  4 21:08:57 2010 GMT</pubDate>\n      <guid>http://fundingopps.cos.com/cgi-bin/getRec?id=75621</guid>\n    </item>\n    <item>\n      <title>Postgraduate Scholarships Encourage Research in Scotland</title>\n      <description>[scotland] The Caledonian Research Foundation provides funding for postgraduates scholarships, which are awarded through the medium of the Carnegie Trust for the Universities of Scotland. There is no preference for subject, and at least one award each year is made in a non-scientific discipline. Applicants must be graduates of a Scottish university, or students who expect to graduate at a Scottish university within a short time of making their application. A degree with First-Class Honours from a Scottish university is a necessary prerequisite for consideration; in faculties which do not award honours, e.g., medicine, the equivalent standard will be expected. Applicants for scholarships must be nominated by a professor, reader, or lecturer in a Scottish university. Scholarships provide fees, maintenance, and a research and travel allowance. The application deadline is March 15, 2010.</description>\n      <link>http://fundingopps.cos.com/cgi-bin/getRec?id=117104</link>\n      <pubDate>Thu Feb  4 21:08:57 2010 GMT</pubDate>\n      <guid>http://fundingopps.cos.com/cgi-bin/getRec?id=117104</guid>\n    </item>\n    <item>\n      <title>Up to $375,000 Available From Ontario Trillium Foundation Community Program</title>\n      <description>[canada] The Ontario Trillium Foundation awards grants to fund operating, project, or capital costs in support of arts and culture, the environment, human and social sciences, and sports and recreation in Ontario. The foundation&apos;s Community Program provides grants for proposals that have primarily a local impact. The foundation will fund a charitable organization or foundation registered as a charity with the Canada Customs and Revenue Agency; an organization incorporated as a not-for-profit corporation without a share capital in a Canadian jurisdiction; an unincorporated branch or chapter of a charitable organization or incorporated not-for-profit organization (the incorporated or registered organization must authorize the application and accept responsibility for the grant); a First Nation; a Metis or other Aboriginal community; or a collaboration of two or more organizations that contains at least one eligible member. Through the Community Program, the foundation makes grants of up to $375,000 over five years. This can include up to $75,000 per year for operating or project expenses and up to $150,000 over one or more years for capital initiatives such as building renovations or equipment purchases. The grant application deadlines are March 1, July 1, and November 1.</description>\n      <link>http://fundingopps.cos.com/cgi-bin/getRec?id=44874</link>\n      <pubDate>Thu Feb  4 21:08:57 2010 GMT</pubDate>\n      <guid>http://fundingopps.cos.com/cgi-bin/getRec?id=44874</guid>\n    </item>\n  </channel>\n</rss>\n", message:undefined, modified:(new Date(1265727202000)), baseUri:"http://p3k.org/rss/", query:"frameColor=black&textColor=black&_=1204565181841&titleBarColor=lightblue&compact=&fontFace=&align=&showXmlButton=&maxItems=30&boxFillColor=white&undefined=&titleBarTextColor=black&width=600&url=http://fundingopps.cos.com/news/rss.xml&", param:{textColor:"black", width:"600", align:"", fontFace:"", url:"http://fundingopps.cos.com/news/rss.xml", compact:"", frameColor:"black", showXmlButton:"", undefined:"", boxFillColor:"white", _:"1204565181841", titleBarColor:"lightblue", maxItems:"30", 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();

