Added: comdev/reporter.apache.org/tags/test/site/js/vendor/modernizr.js
URL: 
http://svn.apache.org/viewvc/comdev/reporter.apache.org/tags/test/site/js/vendor/modernizr.js?rev=1689512&view=auto
==============================================================================
--- comdev/reporter.apache.org/tags/test/site/js/vendor/modernizr.js (added)
+++ comdev/reporter.apache.org/tags/test/site/js/vendor/modernizr.js Mon Jul  6 
22:11:25 2015
@@ -0,0 +1,8 @@
+/*!
+ * Modernizr v2.8.3
+ * www.modernizr.com
+ *
+ * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton
+ * Available under the BSD and MIT licenses: www.modernizr.com/license/
+ */
+window.Modernizr=function(a,b,c){function d(a){t.cssText=a}function 
e(a,b){return d(x.join(a+";")+(b||""))}function f(a,b){return typeof 
a===b}function g(a,b){return!!~(""+a).indexOf(b)}function h(a,b){for(var d in 
a){var e=a[d];if(!g(e,"-")&&t[e]!==c)return"pfx"==b?e:!0}return!1}function 
i(a,b,d){for(var e in a){var g=b[a[e]];if(g!==c)return 
d===!1?a[e]:f(g,"function")?g.bind(d||b):g}return!1}function j(a,b,c){var 
d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+z.join(d+" ")+d).split(" 
");return f(b,"string")||f(b,"undefined")?h(e,b):(e=(a+" "+A.join(d+" 
")+d).split(" "),i(e,b,c))}function k(){o.input=function(c){for(var 
d=0,e=c.length;e>d;d++)E[c[d]]=!!(c[d]in u);return 
E.list&&(E.list=!(!b.createElement("datalist")||!a.HTMLDataListElement)),E}("autocomplete
 autofocus list placeholder max min multiple pattern required step".split(" 
")),o.inputtypes=function(a){for(var 
d,e,f,g=0,h=a.length;h>g;g++)u.setAttribute("type",e=a[g]),d="text"!==u.type,d&&(u.value=v,u.style.cssText="positi
 
on:absolute;visibility:hidden;",/^range$/.test(e)&&u.style.WebkitAppearance!==c?(q.appendChild(u),f=b.defaultView,d=f.getComputedStyle&&"textfield"!==f.getComputedStyle(u,null).WebkitAppearance&&0!==u.offsetHeight,q.removeChild(u)):/^(search|tel)$/.test(e)||(d=/^(url|email)$/.test(e)?u.checkValidity&&u.checkValidity()===!1:u.value!=v)),D[a[g]]=!!d;return
 D}("search tel url email datetime date month week time datetime-local number 
range color".split(" "))}var 
l,m,n="2.8.3",o={},p=!0,q=b.documentElement,r="modernizr",s=b.createElement(r),t=s.style,u=b.createElement("input"),v=":)",w={}.toString,x="
 -webkit- -moz- -o- -ms- ".split(" "),y="Webkit Moz O ms",z=y.split(" 
"),A=y.toLowerCase().split(" 
"),B={svg:"http://www.w3.org/2000/svg"},C={},D={},E={},F=[],G=F.slice,H=function(a,c,d,e){var
 
f,g,h,i,j=b.createElement("div"),k=b.body,l=k||b.createElement("body");if(parseInt(d,10))for(;d--;)h=b.createElement("div"),h.id=e?e[d]:r+(d+1),j.appendChild(h);return
 f=["&#173;",'<style id="s',r,'">'
 
,a,"</style>"].join(""),j.id=r,(k?j:l).innerHTML+=f,l.appendChild(j),k||(l.style.background="",l.style.overflow="hidden",i=q.style.overflow,q.style.overflow="hidden",q.appendChild(l)),g=c(j,a),k?j.parentNode.removeChild(j):(l.parentNode.removeChild(l),q.style.overflow=i),!!g},I=function(b){var
 c=a.matchMedia||a.msMatchMedia;if(c)return c(b)&&c(b).matches||!1;var d;return 
H("@media "+b+" { #"+r+" { position: absolute; } 
}",function(b){d="absolute"==(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).position}),d},J=function(){function
 a(a,e){e=e||b.createElement(d[a]||"div"),a="on"+a;var g=a in e;return 
g||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(a,""),g=f(e[a],"function"),f(e[a],"undefined")||(e[a]=c),e.removeAttribute(a))),e=null,g}var
 
d={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return
 
a}(),K={}.hasOwnProperty;m=f(K,"undefined")||f(K.call,"undefined")?function(a,b){ret
 urn b in a&&f(a.constructor.prototype[b],"undefined")}:function(a,b){return 
K.call(a,b)},Function.prototype.bind||(Function.prototype.bind=function(a){var 
b=this;if("function"!=typeof b)throw new TypeError;var 
c=G.call(arguments,1),d=function(){if(this instanceof d){var 
e=function(){};e.prototype=b.prototype;var f=new 
e,g=b.apply(f,c.concat(G.call(arguments)));return Object(g)===g?g:f}return 
b.apply(a,c.concat(G.call(arguments)))};return d}),C.flexbox=function(){return 
j("flexWrap")},C.flexboxlegacy=function(){return 
j("boxDirection")},C.canvas=function(){var 
a=b.createElement("canvas");return!(!a.getContext||!a.getContext("2d"))},C.canvastext=function(){return!(!o.canvas||!f(b.createElement("canvas").getContext("2d").fillText,"function"))},C.webgl=function(){return!!a.WebGLRenderingContext},C.touch=function(){var
 c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof 
DocumentTouch?c=!0:H(["@media 
(",x.join("touch-enabled),("),r,")","{#modernizr{top:9px;position:absolute}}"].join
 
(""),function(a){c=9===a.offsetTop}),c},C.geolocation=function(){return"geolocation"in
 
navigator},C.postmessage=function(){return!!a.postMessage},C.websqldatabase=function(){return!!a.openDatabase},C.indexedDB=function(){return!!j("indexedDB",a)},C.hashchange=function(){return
 
J("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},C.history=function(){return!(!a.history||!history.pushState)},C.draganddrop=function(){var
 a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in 
a},C.websockets=function(){return"WebSocket"in a||"MozWebSocket"in 
a},C.rgba=function(){return 
d("background-color:rgba(150,255,150,.5)"),g(t.backgroundColor,"rgba")},C.hsla=function(){return
 
d("background-color:hsla(120,40%,100%,.5)"),g(t.backgroundColor,"rgba")||g(t.backgroundColor,"hsla")},C.multiplebgs=function(){return
 d("background:url(https://),url(https://),red 
url(https://)"),/(url\s*\(.*?){3}/.test(t.background)},C.backgroundsize=function(){return
 j("backgroundSize")},C.border
 image=function(){return j("borderImage")},C.borderradius=function(){return 
j("borderRadius")},C.boxshadow=function(){return 
j("boxShadow")},C.textshadow=function(){return""===b.createElement("div").style.textShadow},C.opacity=function(){return
 e("opacity:.55"),/^0.55$/.test(t.opacity)},C.cssanimations=function(){return 
j("animationName")},C.csscolumns=function(){return 
j("columnCount")},C.cssgradients=function(){var 
a="background-image:",b="gradient(linear,left top,right 
bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, 
white);";return d((a+"-webkit- ".split(" 
").join(b+a)+x.join(c+a)).slice(0,-a.length)),g(t.backgroundImage,"gradient")},C.cssreflections=function(){return
 
j("boxReflect")},C.csstransforms=function(){return!!j("transform")},C.csstransforms3d=function(){var
 a=!!j("perspective");return a&&"webkitPerspective"in q.style&&H("@media 
(transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b){a=9===b.offsetLeft&&3===b
 .offsetHeight}),a},C.csstransitions=function(){return 
j("transition")},C.fontface=function(){var a;return H('@font-face 
{font-family:"font";src:url("https://";)}',function(c,d){var 
e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&0===g.indexOf(d.split("
 ")[0])}),a},C.generatedcontent=function(){var a;return H(["#",r,"{font:0/0 
a}#",r,':after{content:"',v,'";visibility:hidden;font:3px/1 
a}'].join(""),function(b){a=b.offsetHeight>=3}),a},C.video=function(){var 
a=b.createElement("video"),c=!1;try{(c=!!a.canPlayType)&&(c=new 
Boolean(c),c.ogg=a.canPlayType('video/ogg; 
codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; 
codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; 
codecs="vp8, vorbis"').replace(/^no$/,""))}catch(d){}return 
c},C.audio=function(){var 
a=b.createElement("audio"),c=!1;try{(c=!!a.canPlayType)&&(c=new 
Boolean(c),c.ogg=a.canPlayType('audio
 /ogg; 
codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav;
 
codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,""))}catch(d){}return
 c},C.localstorage=function(){try{return 
localStorage.setItem(r,r),localStorage.removeItem(r),!0}catch(a){return!1}},C.sessionstorage=function(){try{return
 
sessionStorage.setItem(r,r),sessionStorage.removeItem(r),!0}catch(a){return!1}},C.webworkers=function(){return!!a.Worker},C.applicationcache=function(){return!!a.applicationCache},C.svg=function(){return!!b.createElementNS&&!!b.createElementNS(B.svg,"svg").createSVGRect},C.inlinesvg=function(){var
 a=b.createElement("div");return 
a.innerHTML="<svg/>",(a.firstChild&&a.firstChild.namespaceURI)==B.svg},C.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(w.call(b.createElementNS(B.svg,"animate")))},C.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.
 test(w.call(b.createElementNS(B.svg,"clipPath")))};for(var L in 
C)m(C,L)&&(l=L.toLowerCase(),o[l]=C[L](),F.push((o[l]?"":"no-")+l));return 
o.input||k(),o.addTest=function(a,b){if("object"==typeof a)for(var d in 
a)m(a,d)&&o.addTest(d,a[d]);else{if(a=a.toLowerCase(),o[a]!==c)return 
o;b="function"==typeof b?b():b,"undefined"!=typeof p&&p&&(q.className+=" 
"+(b?"":"no-")+a),o[a]=b}return o},d(""),s=u=null,function(a,b){function 
c(a,b){var 
c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return
 
c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function
 d(){var a=s.elements;return"string"==typeof a?a.split(" "):a}function e(a){var 
b=r[a[p]];return b||(b={},q++,a[p]=q,r[q]=b),b}function 
f(a,c,d){if(c||(c=b),k)return c.createElement(a);d||(d=e(c));var f;return 
f=d.cache[a]?d.cache[a].cloneNode():o.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!f.canHaveChildren||n.test(a)||f.tagUrn?f:d.frag.appendChild(f)}function
 g(a
 ,c){if(a||(a=b),k)return a.createDocumentFragment();c=c||e(a);for(var 
f=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)f.createElement(h[g]);return 
f}function 
h(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return
 
s.shivMethods?f(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return
 function(){var 
n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-]+/g,function(a){return
 b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return 
n}")(s,b.frag)}function i(a){a||(a=b);var 
d=e(a);return!s.shivCSS||j||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),k||h(a,d),a}var
 
j,k,l="3.7.0",m=a.html5||{},n=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,o=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label
 
|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,p="_html5shiv",q=0,r={};!function(){try{var
 a=b.createElement("a");a.innerHTML="<xyz></xyz>",j="hidden"in 
a,k=1==a.childNodes.length||function(){b.createElement("a");var 
a=b.createDocumentFragment();return"undefined"==typeof 
a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof 
a.createElement}()}catch(c){j=!0,k=!0}}();var s={elements:m.elements||"abbr 
article aside audio bdi canvas data datalist details dialog figcaption figure 
footer header hgroup main mark meter nav output progress section summary 
template time 
video",version:l,shivCSS:m.shivCSS!==!1,supportsUnknownElements:k,shivMethods:m.shivMethods!==!1,type:"default",shivDocument:i,createElement:f,createDocumentFragment:g};a.html5=s,i(b)}(this,b),o._version=n,o._prefixes=x,o._domPrefixes=A,o._cssomPrefixes=z,o.mq=I,o.hasEvent=J,o.testProp=function(a){return
 h([a])},o.testAllProps=j,o.testStyles=H,o.prefixed=function(a,b,c){return 
b?j(a,b,c):j(a,
 "pfx")},q.className=q.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(p?" js 
"+F.join(" "):""),o}(this,this.document);

Propchange: comdev/reporter.apache.org/tags/test/site/js/vendor/modernizr.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: comdev/reporter.apache.org/tags/test/site/js/vendor/placeholder.js
URL: 
http://svn.apache.org/viewvc/comdev/reporter.apache.org/tags/test/site/js/vendor/placeholder.js?rev=1689512&view=auto
==============================================================================
--- comdev/reporter.apache.org/tags/test/site/js/vendor/placeholder.js (added)
+++ comdev/reporter.apache.org/tags/test/site/js/vendor/placeholder.js Mon Jul  
6 22:11:25 2015
@@ -0,0 +1,2 @@
+/*! http://mths.be/placeholder v2.0.9 by @mathias */
+!function(a){"function"==typeof 
define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){function 
b(b){var c={},d=/^jQuery\d+$/;return 
a.each(b.attributes,function(a,b){b.specified&&!d.test(b.name)&&(c[b.name]=b.value)}),c}function
 c(b,c){var 
d=this,f=a(d);if(d.value==f.attr("placeholder")&&f.hasClass("placeholder"))if(f.data("placeholder-password")){if(f=f.hide().nextAll('input[type="password"]:first').show().attr("id",f.removeAttr("id").data("placeholder-id")),b===!0)return
 f[0].value=c;f.focus()}else 
d.value="",f.removeClass("placeholder"),d==e()&&d.select()}function d(){var 
d,e=this,f=a(e),g=this.id;if(""===e.value){if("password"===e.type){if(!f.data("placeholder-textinput")){try{d=f.clone().attr({type:"text"})}catch(h){d=a("<input>").attr(a.extend(b(this),{type:"text"}))}d.removeAttr("name").data({"placeholder-password":f,"placeholder-id":g}).bind("focus.placeholder",c),f.data({"placeholder-textinput":d,"placeholder-id":g}).before(d)}f=f.removeAttr("id").hide().prevAll('i
 
nput[type="text"]:first').attr("id",g).show()}f.addClass("placeholder"),f[0].value=f.attr("placeholder")}else
 f.removeClass("placeholder")}function e(){try{return 
document.activeElement}catch(a){}}var f,g,h="[object 
OperaMini]"==Object.prototype.toString.call(window.operamini),i="placeholder"in 
document.createElement("input")&&!h,j="placeholder"in 
document.createElement("textarea")&&!h,k=a.valHooks,l=a.propHooks;i&&j?(g=a.fn.placeholder=function(){return
 this},g.input=g.textarea=!0):(g=a.fn.placeholder=function(){var a=this;return 
a.filter((i?"textarea":":input")+"[placeholder]").not(".placeholder").bind({"focus.placeholder":c,"blur.placeholder":d}).data("placeholder-enabled",!0).trigger("blur.placeholder"),a},g.input=i,g.textarea=j,f={get:function(b){var
 c=a(b),d=c.data("placeholder-password");return 
d?d[0].value:c.data("placeholder-enabled")&&c.hasClass("placeholder")?"":b.value},set:function(b,f){var
 g=a(b),h=g.data("placeholder-password");return 
h?h[0].value=f:g.data("placeholde
 
r-enabled")?(""===f?(b.value=f,b!=e()&&d.call(b)):g.hasClass("placeholder")?c.call(b,!0,f)||(b.value=f):b.value=f,g):b.value=f}},i||(k.input=f,l.value=f),j||(k.textarea=f,l.value=f),a(function(){a(document).delegate("form","submit.placeholder",function(){var
 
b=a(".placeholder",this).each(c);setTimeout(function(){b.each(d)},10)})}),a(window).bind("beforeunload.placeholder",function(){a(".placeholder").each(function(){this.value=""})}))});

Propchange: comdev/reporter.apache.org/tags/test/site/js/vendor/placeholder.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: comdev/reporter.apache.org/tags/test/site/render.js
URL: 
http://svn.apache.org/viewvc/comdev/reporter.apache.org/tags/test/site/render.js?rev=1689512&view=auto
==============================================================================
--- comdev/reporter.apache.org/tags/test/site/render.js (added)
+++ comdev/reporter.apache.org/tags/test/site/render.js Mon Jul  6 22:11:25 2015
@@ -0,0 +1,872 @@
+var jsdata = {}
+
+var templates = {}
+var nproject = null;
+
+// Function for async fetching of a single JSON file with JS callback
+
+function GetAsyncJSON(theUrl, xstate, callback) {
+       var xmlHttp = null;
+       if (window.XMLHttpRequest) {
+               xmlHttp = new XMLHttpRequest();
+       } else {
+               xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
+       }
+       xmlHttp.open("GET", theUrl, true);
+       xmlHttp.send(null);
+       xmlHttp.onprogress = function(state) {
+               var s = parseInt(xmlHttp.getResponseHeader('Content-Length'))
+               if (document.getElementById('pct')) {
+                       document.getElementById('pct').innerHTML = "<p 
style='text-align: center;'><b><i>Loading: " + parseInt((100 * 
(xmlHttp.responseText.length / s))) + "% done</i></b></p>";
+               }
+       }
+       xmlHttp.onreadystatechange = function(state) {
+
+               if (xmlHttp.readyState == 4 && xmlHttp.status == 200 || 
xmlHttp.status == 404) {
+                       if (callback) {
+                               if (xmlHttp.status == 404) {
+                                       callback({}, xstate);
+                               } else {
+                                       if (document.getElementById('pct')) {
+                                               
document.getElementById('pct').innerHTML = "<p style='text-align: 
center;'><b><i>Loading: 100% done</i></b></p>";
+                                       }
+                                       window.setTimeout(callback, 0.05, 
JSON.parse(xmlHttp.responseText), xstate);
+                               }
+                       }
+               }
+       }
+}
+
+
+function makeSelect(name, arr, sarr) {
+       var sel = document.createElement('select');
+       sel.setAttribute("name", name)
+       for (i in arr) {
+               var val = arr[i];
+               var opt = document.createElement('option')
+               opt.setAttribute("value", val)
+               opt.innerHTML = val
+               sel.appendChild(opt);
+       }
+       return sel
+}
+
+function getWednesdays(mo, y) {
+       var d = new Date();
+       if (mo) {
+               d.setMonth(mo);
+       }
+       if (y) {
+               d.setFullYear(y, d.getMonth(), d.getDay())
+       }
+       var month = d.getMonth(),
+               wednesdays = [];
+
+       d.setDate(1);
+
+       // Get the first Monday in the month
+       while (d.getDay() !== 3) {
+               d.setDate(d.getDate() + 1);
+       }
+
+       // Get all the other Mondays in the month
+       while (d.getMonth() === month) {
+               wednesdays.push(new Date(d.getTime()));
+               d.setDate(d.getDate() + 7);
+       }
+
+       return wednesdays;
+}
+
+function setReportDate(json, x) {
+       var pmc = x[0]
+       var reportdate = x[1]
+       var fullname = (x[2] ? x[2] : "Unknown").replace(/Apache /, "")
+       var m = ['January', 'February', 'March', 'April', 'May', 'June', 
'July', 'August', 'September', 'October', 'November', 'December']
+       var today = new Date()
+
+       var dates = []
+       if (!json[pmc]) {
+               pmc = fullname
+       }
+       for (i in json[pmc]) {
+               tm = 0;
+               sm = json[pmc][i]
+               for (x in m) {
+                       if (m[x] == sm) {
+                               tm = x;
+                       }
+               }
+               dates.push(getWednesdays(tm)[2])
+       }
+       var ny = today.getFullYear() + 1;
+       for (i in json[pmc]) {
+               tm = 0;
+               sm = json[pmc][i]
+               for (x in m) {
+                       if (m[x] == sm) {
+                               tm = x;
+                       }
+               }
+               dates.push(getWednesdays(tm)[2], ny)
+       }
+       var nextdate = dates[0];
+       while (nextdate < today) {
+               nextdate = dates.shift();
+       }
+       reportdate.innerHTML += "<b>Next report date: " + (nextdate ? 
nextdate.toDateString() : "Unknown(?)") + "</b>"
+       if (nextdate) {
+               var link = 
"https://svn.apache.org/repos/private/foundation/board/board_agenda_"; +  
nextdate.getFullYear() + "_" + (nextdate.getMonth() < 9 ? "0" : "") + 
(nextdate.getMonth() +1) + "_" + nextdate.getDate() + ".txt"
+               reportdate.innerHTML += "<br/>File your report in <a 
href='"+link+"'>"+link+"</a> when it has been seeded."
+       }
+       
+}
+
+function buildPanel(pmc, title) {
+       var parent = document.getElementById('tab_' + pmc);
+
+       var toc = document.getElementById('toc_' + pmc);
+       if (!toc) {
+               toc = document.createElement('cl')
+               toc.setAttribute("class", "sub-nav")
+               toc.setAttribute("id", "toc_" + pmc)
+               if (parent.firstChild.nextSibling) {
+                       parent.insertBefore(toc, parent.firstChild.nextSibling);
+               } else {
+                       parent.appendChild(toc)
+               }
+       }
+       var linkname = title.toLowerCase().replace(/[^a-z0-9]+/, "")
+       var li = document.createElement('dd');
+       li.setAttribute("role", "menu-item")
+       li.innerHTML = "<a href='#" + linkname + "_" + pmc + "'>" + title + 
"</a>"
+       toc.appendChild(li)
+
+       var div = document.createElement('div');
+       div.setAttribute("id", linkname + "_" + pmc);
+       parent.appendChild(div)
+
+       var titlebox = document.createElement('div');
+       titlebox.innerHTML = "<h3 style='background: #666; color: #EEE; border: 
1px solid #66A; margin-top: 30px;'>" + title + " &nbsp; &nbsp; <small> 
<b>&uarr;</b> <a href='#tab_" + pmc + "'>Back to top</a></small></h3>"
+       div.appendChild(titlebox);
+       return div;
+}
+
+function addLine(pmc, line) {
+       line = line ? line : "  "
+       var lines = line.split(/\n/)
+       for (x in lines) {
+               var xline = lines[x]
+               var words = xline.split(" ")
+               var len = 0;
+               var out = ""
+               for (i in words) {
+                       len += words[i].replace(/<.+?>/, "").length + (i == 
words.length - 1 ? 0 : 1)
+                       if (len >= 78) {
+                               out += "\n   "
+                               len = words[i].replace(/<.+?>/, "").length + (i 
== words.length - 1 ? 0 : 1)
+                       }
+                       out += words[i] + " "
+               }
+               templates[pmc] += out + "\n"
+       }
+}
+
+function renderFrontPage(json) {
+       jsdata = json
+       var container = document.getElementById('contents')
+       container.innerHTML = "<h2 style='text-align: center; margin-bottom: 
10px;' class='hide-for-small-only'>Apache Project Report Helper</h2>Click on a 
project name to view statistics:"
+       var top = document.createElement('div');
+       container.appendChild(top)
+
+
+       var panellist = document.createElement('ul');
+       panellist.style.background = "#AAA"
+       panellist.style.textAlign = "center"
+       panellist.style.margin = "0 auto"
+       panellist.style.paddingLeft = "5px"
+       //panellist.setAttribute("class", "tabs")
+       panellist.setAttribute("id", "tabs");
+       panellist.setAttribute("data-tab", "")
+       panellist.setAttribute("role", "tablist")
+       container.appendChild(panellist)
+
+       var pcontainer = document.createElement('div');
+       pcontainer.setAttribute("id", "tabcontents")
+       pcontainer.setAttribute("style", "text-align: left !important; margin: 
0 auto; width: 1000px; border-radius: 5px; border: 2px solid #666; height: 
100%; overflow: scroll !important; overflow-y: scroll !important; ")
+       container.appendChild(pcontainer)
+
+       var sproject = document.location.search.substr(1);
+       var hcolors = ["#000070", "#007000", "#407000", "#70500", "#700000", 
"#A00000"]
+       var hvalues = ["Super Healthy", "Healthy", "Mostly Okay", "Unhealthy", 
"Action required!", "URGENT ACTION REQUIRED!"]
+       for (i in json.pmcs) {
+
+               var pmc = json.pmcs[i]
+               templates[pmc] = "Report from the " + (json.pdata[pmc].name ? 
json.pdata[pmc].name : pmc) + " project [" + (json.pdata[pmc].chair ? 
json.pdata[pmc].chair : "Put your name here") + "]\n\n"
+
+               addLine(pmc, "## Description:")
+               if (json.pdata[pmc].shortdesc) {
+                       addLine(pmc, "   " + json.pdata[pmc].shortdesc)
+               } else {
+                       addLine(pmc, " - <font color='red'>Description goes 
here</font>")
+               }
+               addLine(pmc)
+
+               addLine(pmc, "## Activity:")
+               addLine(pmc, " - <font color='red'>TODO - the PMC 
<b><u>MUST</u></b> provide this information</font>")
+               addLine(pmc)
+
+               addLine(pmc, "## Issues:")
+               addLine(pmc, " - <font color='red'>TODO - list any issues that 
require board attention, \n  or say \"there are no issues requiring board 
attention at this time\"</font>")
+               addLine(pmc)
+
+               var obj = document.createElement('div');
+               obj.setAttribute("id", "tab_" + pmc)
+               obj.style = "padding: 10px; text-align: left !important;"
+               obj.setAttribute("aria-hidden", "true")
+               var title = document.createElement('h2')
+               title.innerHTML = json.pdata[pmc].name ? json.pdata[pmc].name : 
pmc
+               obj.appendChild(title)
+               var health = document.createElement('p');
+               if (json.health[pmc] && !isNaN(json.health[pmc]['cscore'])) {
+                       health.style.marginTop = "10px"
+                       health.innerHTML = "<b>Project Health score:</b> <a 
href='/chi.py#"+pmc+"'><u><font color='" + hcolors[json.health[pmc]['cscore']] 
+ "'>" + (6.33+(json.health[pmc]['score']*-1.00*(20/12.25))).toFixed(2) + " (" 
+ hvalues[json.health[pmc]['cscore']] + ")</u></font></a>"
+                       obj.appendChild(health)
+               }
+               pcontainer.appendChild(obj)
+
+
+
+               // Report date
+
+               var mo = new Date().getMonth();
+               var reportdate = buildPanel(pmc, "Report date")
+               if (json.pdata[pmc].chair) {
+                       reportdate.innerHTML += "<b>Project Chair: </b>" + 
json.pdata[pmc].chair + "<br/>"
+               }
+               GetAsyncJSON("reportingcycles.json?" + Math.random(), [pmc, 
reportdate, json.pdata[pmc].name], setReportDate)
+
+
+               // PMC + Committer changes
+
+               var mo = new Date().getMonth() - 3;
+               var after = new Date();
+               after.setMonth(mo);
+
+               var changes = buildPanel(pmc, "PMC/Committership changes");
+
+               var c = 0;
+               for (i in json.changes[pmc].committer) c++;
+               for (i in json.changes[pmc].pmc) c++;
+               var nc = 0;
+               var np = 0;
+               var ncn = null;
+               var npn = null;
+               addLine(pmc, "## PMC/Committership changes:")
+               addLine(pmc)
+               addLine(pmc, " - Currently " + json.count[pmc][1] + " 
committers and " + json.count[pmc][0] + " PMC members in the project.")
+               if (c == 0) {
+                       changes.innerHTML += "<font color='red'><b>No new 
changes to the PMC or committer base detected - (LDAP error or no changes for 
&gt;2 years)</b></font>"
+                       addLine(pmc, " - No new changes to the PMC or 
committership since last report.")
+                       addLine(pmc)
+               } else {
+                       changes.innerHTML += "<h5>Changes within the last 3 
months:</h5>"
+                       var l = 0;
+                       
+                       // pre-flight check
+                       var npmc = 0;
+                       for (i in json.changes[pmc].pmc) {
+                               var entry = json.changes[pmc].pmc[i];
+                               if (entry[1] > after.getTime() / 1000) {
+                                       npmc++;
+                               }
+                       }
+                       if (npmc > 1) {
+                               addLine(pmc, " - New PMC members:")
+                       }
+                       
+                       
+                       for (i in json.changes[pmc].pmc) {
+                               var entry = json.changes[pmc].pmc[i];
+                               if (entry[1] > np) {
+                                       np = entry[1]
+                                       npn = entry[0];
+                               }
+                               if (entry[1] > after.getTime() / 1000) {
+                                       l++;
+                                       changes.innerHTML += "&rarr; " + 
entry[0] + " was added to the PMC on " + new Date(entry[1] * 
1000).toDateString() + "<br/>";
+                                       addLine(pmc, (npmc>1? "   " : "") + " - 
" + entry[0] + " was added to the PMC on " + new Date(entry[1] * 
1000).toDateString())
+                               }
+                       }
+                       if (l == 0) {
+                               addLine(pmc, " - No new PMC members added in 
the last 3 months")
+                               changes.innerHTML += "&rarr; <font 
color='red'><b>No new PMC members in the last 3 months.</b></font><br/>";
+                       }
+                       if (npn) {
+                               if (np < after.getTime() / 1000) {
+                                       addLine(pmc, " - Last PMC addition was 
" + npn + " at " + new Date(np * 1000).toDateString())
+                               }
+                               changes.innerHTML += "&rarr; " + "<b>Latest PMC 
addition: </b>" + new Date(np * 1000).toDateString() + " (" + npn + ")<br/>"
+                       }
+                       
+                       
+                       // pre-flight check
+                       var ncom = 0;
+                       for (i in json.changes[pmc].committer) {
+                               var entry = json.changes[pmc].committer[i];
+                               if (entry[1] > after.getTime() / 1000) {
+                                       ncom++;
+                               }
+                       }
+                       if (ncom > 1) {
+                               addLine(pmc, " - New commmitters:")
+                       }
+                       for (i in json.changes[pmc].committer) {
+                               var entry = json.changes[pmc].committer[i];
+                               if (entry[1] > nc) {
+                                       nc = entry[1]
+                                       ncn = entry[0];
+                               }
+                               if (entry[1] > after.getTime() / 1000) {
+                                       l++;
+                                       changes.innerHTML += "&rarr; " + 
entry[0] + " was added as a committer on " + new Date(entry[1] * 
1000).toDateString() + "<br/>";
+                                       addLine(pmc, (ncom>1? "   " : "") + " - 
" + entry[0] + " was added as a committer on " + new Date(entry[1] * 
1000).toDateString())
+                               }
+                       }
+                       if (l == 0) {
+                               changes.innerHTML += "&rarr; <font 
color='red'><b>No new committers in the last 3 months.</b></font><br/>";
+                               addLine(pmc, " - No new committers added in the 
last 3 months")
+                       }
+                       
+                       if (ncn) {
+                               if (nc < after.getTime() / 1000) {
+                                       addLine(pmc, " - Last committer 
addition was " + ncn + " at " + new Date(nc * 1000).toDateString())
+                               }
+                               changes.innerHTML += "&rarr; " + "<b>Latest 
committer addition: </b>" + new Date(nc * 1000).toDateString() + " (" + ncn + 
")<br/>"
+                       } else {
+                               addLine(pmc, " - Last committer addition was 
more than 2 years ago")
+                               changes.innerHTML += "&rarr; " + "<b>Latest 
committer addition: </b><font color='red'>more than two years ago (not in the 
archive!)</font><br/>"
+                       }
+                       changes.innerHTML += "&rarr; " + "<b>Currently " + 
json.count[pmc][1] + " committers and " + json.count[pmc][0] + " PMC members."
+                       addLine(pmc)
+               }
+
+               // Release data
+
+               var releases = buildPanel(pmc, "Releases")
+               addLine(pmc, "## Releases:")
+               addLine(pmc)
+               var nr = 0;
+               var lr = null;
+               var lrn = 0;
+               var tr = 0
+               for (version in json.releases[pmc]) {
+                       tr++;
+                       var date = parseInt(json.releases[pmc][version])
+                       if (date > lrn) {
+                               lrn = date
+                               lr = version
+                       }
+                       if (date >= after.getTime() / 1000) {
+                               err = ""
+                               if (new Date(date * 1000) > new Date()) {
+                                       err = " (<font color='red'>This seems 
wrong?!</font>)"
+                               }
+                               releases.innerHTML += "&rarr; " + "<b>" + 
version + " was released on </b>" + new Date(date * 1000).toDateString() + err 
+ "<br/>"
+                               addLine(pmc, " - " + version + " was released 
on " + new Date(date * 1000).toDateString() + err)
+                               nr++;
+                       }
+               }
+
+               if (nr == 0) {
+                       if (lr) {
+                               releases.innerHTML += "&rarr; " + "<b>Latest 
release was " + lr + ", released on </b>" + new Date(lrn * 1000).toDateString() 
+ "<br/>"
+                               addLine(pmc, " - Last release was " + lr + " on 
" + new Date(lrn * 1000).toDateString())
+                       } else {
+                               releases.innerHTML += "No release data could be 
found.<br/>"
+                               addLine(pmc, " - <font color='red'>No release 
data could be found [FIX!]</font>")
+                       }
+               }
+               releases.innerHTML += "<i>(A total of " + (tr - nr) + " older 
release(s) were found for " + pmc + " in our db)</i><br/>"
+               releases.innerHTML += "<br/><a href='javascript:void(0);' 
onclick=\"$('#rdialog_" + pmc + "').dialog({minWidth: 450, minHeight: 
240});\">Add a release</a> - <a href='javascript:void(0);' 
onclick=\"$('#dialog_" + pmc + "').dialog({minWidth: 450, minHeight: 
240});\">Fetch releases from JIRA</a><br/>"
+
+               if (tr > 0) {
+                       var div = renderReleaseChart(json.releases[pmc], pmc, 
releases);
+                       releases.appendChild(div)
+               }
+
+
+               addLine(pmc)
+
+               var mlbox = buildPanel(pmc, "Mailing lists");
+
+               var ul = document.createElement('ul')
+               ul.style.textAlign = "left;"
+               mlbox.appendChild(ul)
+               var prev = ""
+               var f = 0
+               addLine(pmc, "## Mailing list activity:")
+               addLine(pmc)
+               var first = ['users', 'dev', 'commits', 'private', 'bugs', 
'modules-dev'];
+
+
+               for (i in first) {
+
+                       ml = pmc + ".apache.org-" + first[i]
+                       if (ml != prev && ml.search("infra") < 0 && 
json.mail[pmc] && json.mail[pmc][ml]) {
+                               f++;
+                               prev = ml
+                               var d = ml.split(".org-");
+                               var mlname = d[1] + "@" + d[0] + ".org"
+                               var lookup = d[0].split(/\./)[0] + "-" + d[1]
+
+                               var x = renderChart(json.mail[pmc], ml, obj, 
(json.delivery[pmc] && json.delivery[pmc][lookup]) ? 
json.delivery[pmc][lookup].weekly : {})
+                               var total = x[0]
+                               var diff = x[1]
+                               var div = x[2]
+
+                               add = ""
+                               if (json.delivery[pmc] && 
json.delivery[pmc][lookup]) {
+                                       add = ":\n    - " + 
json.delivery[pmc][lookup].quarterly[0] + " emails sent to list (" + 
json.delivery[pmc][lookup].quarterly[1] + " in previous quarter)";
+                               }
+                               var text = "Currently: " + total + " 
subscribers <font color='green'>(up " + diff + " in the last 3 months)</font>"
+                               if (diff < 0) {
+                                       text = "Currently: " + total + " 
subscribers <font color='red'>(down " + diff + " in the last 3 months)</font>"
+                                       if (d[1] != "private" && d[1] != 
"security" && d[1] != "commits") {
+                                               addLine(pmc, " - " + mlname + 
": ")
+                                               addLine(pmc, "    - " + total + 
" subscribers (down " + diff + " in the last 3 months)" + add)
+                                               addLine(pmc)
+                                       }
+                               } else {
+                                       if (d[1] != "private" && d[1] != 
"security" && d[1] != "commits") {
+                                               addLine(pmc, " - " + mlname + 
": ")
+                                               addLine(pmc, "    - " + total + 
" subscribers (up " + diff + " in the last 3 months)" + add)
+                                               addLine(pmc)
+                                       }
+                               }
+
+                               if (json.delivery[pmc] && 
json.delivery[pmc][lookup]) {
+                                       text += " (" + 
json.delivery[pmc][lookup].quarterly[0] + " emails sent in the past 3 months, " 
+ json.delivery[pmc][lookup].quarterly[1] + " in the previous cycle)"
+                               }
+
+                               var p = document.createElement('li');
+                               p.innerHTML = "<h5>" + mlname + ":</h5>" + text
+                               p.appendChild(div)
+                               ul.appendChild(p)
+                       }
+               }
+
+               for (ml in json.mail[pmc]) {
+                       var skip = false
+                       for (i in first) {
+                               xml = pmc + ".apache.org-" + first[i]
+                               if (ml.search(xml) == 0) {
+                                       skip = true
+                               }
+                       }
+                       if (!skip) {
+
+                               f++;
+                               if (ml != prev && ml.search("infra") < 0) {
+                                       prev = ml
+                                       var d = ml.split(".org-");
+                                       var mlname = d[1] + "@" + d[0] + ".org"
+                                       var lookup = d[0].split(/\./)[0] + "-" 
+ d[1]
+                                       var x = renderChart(json.mail[pmc], ml, 
obj, (json.delivery[pmc] && json.delivery[pmc][lookup]) ? 
json.delivery[pmc][lookup].weekly : {})
+                                       var total = x[0]
+                                       var diff = x[1]
+                                       var div = x[2]
+
+                                       add = ""
+                                       if (json.delivery[pmc] && 
json.delivery[pmc][lookup]) {
+                                               add = ":\n    - " + 
json.delivery[pmc][lookup].quarterly[0] + " emails sent to list (" + 
json.delivery[pmc][lookup].quarterly[1] + " in previous quarter)";
+                                       }
+                                       var text = "Currently: " + total + " 
subscribers <font color='green'>(up " + diff + " in the last 3 months)</font>"
+                                       if (diff < 0) {
+                                               text = "Currently: " + total + 
" subscribers <font color='red'>(down " + diff + " in the last 3 months)</font>"
+                                               if (d[1] != "private" && d[1] 
!= "security" && d[1] != "commits") {
+                                                       addLine(pmc, " - " + 
mlname + ": ")
+                                                       addLine(pmc, "    - " + 
total + " subscribers (down " + diff + " in the last 3 months)" + add)
+                                                       addLine(pmc)
+                                               }
+                                       } else {
+                                               if (d[1] != "private" && d[1] 
!= "security" && d[1] != "commits") {
+                                                       addLine(pmc, " - " + 
mlname + ": ")
+                                                       addLine(pmc, "    - " + 
total + " subscribers (up " + diff + " in the last 3 months)" + add)
+                                                       addLine(pmc)
+                                               }
+                                       }
+
+                                       if (json.delivery[pmc] && 
json.delivery[pmc][lookup]) {
+                                               text += " (" + 
json.delivery[pmc][lookup].quarterly[0] + " emails sent in the past 3 months, " 
+ json.delivery[pmc][lookup].quarterly[1] + " in the previous cycle)"
+                                       }
+
+                                       var p = document.createElement('li');
+                                       p.innerHTML = "<h5>" + mlname + 
":</h5>" + text
+                                       p.appendChild(div)
+                                       ul.appendChild(p)
+                               }
+                       }
+               }
+               addLine(pmc)
+
+               // Add btn for nav
+               if (f > 0) {
+                       var btn = document.createElement('li');
+                       btn.setAttribute("id", "btn_" + pmc)
+                       btn.setAttribute("class", "tab-title")
+                       btn.setAttribute("onclick", 
"$('#tabcontents').animate({scrollTop: -99999}, 500)");
+                       btn.innerHTML = "<a href='#' name='tab_" + pmc + "'>" + 
pmc + "</a>"
+                       panellist.appendChild(btn)
+                       if (sproject && sproject == pmc) {
+                               $('#btn_' + pmc).click();
+                               $('#' + pmc).addClass("active");
+                       }
+
+               }
+
+
+
+
+               if (json.jira[pmc][0] > 0 || json.jira[pmc][1] > 0) {
+                       renderJIRA(pmc)
+               }
+
+
+               // Reporting example
+               var template = buildPanel(pmc, "Report template");
+               template.innerHTML += "<pre style='border: 2px dotted #444; 
padding: 10px; background: #FFD;' contenteditable='true'>" + templates[pmc] + 
"</pre>"
+
+               // Fetch from JIRA dialog
+               var dialog = document.createElement('div');
+               dialog.setAttribute("id", "dialog_" + pmc);
+               dialog.setAttribute("title", "Fetch data from JIRA")
+               dialog.setAttribute("style", "display: none;")
+               dialog.innerHTML = "<form><b>JIRA Project:</b><input 
type='text' name='jira' placeholder='FOO'><br/><b>Optional prepend:</b> <input 
name='prepend' type='text' placeholder='Foo'/><br><input type='button' 
value='Fetch from JIRA' onclick='fetchJIRA(\"" + pmc + "\", 
this.form[\"jira\"].value, this.form[\"prepend\"].value);'></form><p>If you 
have multiple JIRA projects and they only have the version number in their 
release versions, please enter the component name in the 'prepend' field.</p>"
+               document.getElementById('tab_' + pmc).appendChild(dialog)
+               
+               // Manually add release dialog
+               var rdialog = document.createElement('div');
+               rdialog.setAttribute("id", "rdialog_" + pmc);
+               rdialog.setAttribute("title", "Add a release")
+               rdialog.setAttribute("style", "display: none;")
+               rdialog.innerHTML = "<form><b>Version:</b><input type='text' 
name='version' placeholder='1.2.3'><br/><b>Date:</b> <input name='date' 
type='text' placeholder='YYYY-MM-DD'/><br><input type='button' value='Add 
release' onclick='addRelease(\"" + pmc + "\", this.form[\"version\"].value, 
this.form[\"date\"].value);'></form>"
+               document.getElementById('tab_' + pmc).appendChild(rdialog)
+
+       }
+       if (json.pmcs.length == 0) {
+               container.innerHTML = "You are not a member of any top level 
project PMC, sorry!"
+       }
+
+       $("#tabcontents").find("[id^='tab']").hide();
+
+
+
+       $('#tabs a').click(function(e) {
+               e.preventDefault();
+               if ($(this).closest("li").attr("id") == "current") {
+                       return;
+               } else {
+                       $("#tabcontents").find("[id^='tab_']").hide();
+                       $("#tabs li").attr("id", "");
+                       $(this).parent().attr("id", "current");
+                       $('#' + $(this).attr('name')).fadeIn();
+               }
+       });
+
+       var project = nproject ? nproject : document.location.search.substr(1);
+
+       if (project && project.length > 0) {
+               $("#tabcontents #tab_" + project).fadeIn();
+               $("#tabs #btn_" + project).attr('id', 'current');
+       }
+       if (json.all && json.all.length > 0) {
+               var btn = document.createElement('li');
+               btn.setAttribute("style", "margin-left: 48px;")
+               btn.setAttribute("id", "btn_all")
+               btn.setAttribute("class", "tab-title")
+               if (json.all.indexOf("-----------------------") == -1) {
+                       json.all.sort()
+                       json.all.unshift("-----------------------")
+                       json.all.unshift("Members-only Quick-nav:")
+               }
+               
+               var sel = makeSelect("project", json.all, [])
+               sel.setAttribute("style", "height: 32px !important; padding: 
0px !important; margin: 0px !important; margin-left: 32px !important;")
+               sel.style = "break-before: never; break-after: never; float: 
left"
+               sel.setAttribute("onchange", "GetAsyncJSON('/getjson.py?only='+ 
this.value, this.value, mergeData);")
+               btn.appendChild(sel)
+               panellist.appendChild(btn)
+
+       }
+
+
+
+}
+
+function mergeData(json, pmc) {
+       if (jsdata.pmcs.indexOf(pmc) >= 0) {
+               return
+       }
+       if (nproject && nproject.length > 0) {
+               for (i in jsdata.pmcs) {
+                       if (jsdata.pmcs[i] == nproject) {
+                               jsdata.pmcs.splice(i,1);
+                               break
+                       }
+               }
+       }
+       
+       var todo = new Array('count', 'mail', 'delivery', 'jira', 'changes', 
'pdata', 'releases', 'keys', 'health')
+       for (i in todo) {
+               var key = todo[i]
+               jsdata[key][pmc] = json[key][pmc];
+       }
+       jsdata.pmcs.push(pmc)
+       nproject = pmc
+       renderFrontPage(jsdata)
+}
+
+
+function renderJIRA(pmc) {
+       var obj = buildPanel(pmc, "JIRA Statistics")
+
+       addLine(pmc, "## JIRA activity:")
+       addLine(pmc)
+       addLine(pmc, " - " + jsdata.jira[pmc][0] + " JIRA tickets created in 
the last 3 months");
+       addLine(pmc, " - " + jsdata.jira[pmc][1] + " JIRA tickets 
closed/resolved in the last 3 months");
+       addLine(pmc)
+       obj.innerHTML += jsdata.jira[pmc][0] + " JIRA tickets created in the 
last 3 months<br/>";
+       obj.innerHTML += jsdata.jira[pmc][1] + " JIRA tickets closed/resolved 
in the last 3 months<br/>";
+       if (jsdata.keys[pmc]) {
+               obj.innerHTML += "Keys used: <kbd>" + jsdata.keys[pmc].join(", 
") + "</kbd>"
+       }
+
+}
+
+
+function renderChart(json, name, container, delivery) {
+
+       var chartDiv = document.createElement('div')
+       chartDiv.setAttribute("id", name + "_chart")
+       var dates = []
+       var noweekly = 0;
+       for (date in json[name]) {
+               dates.push(date)
+       }
+       for (date in delivery) noweekly++;
+       var d = name.split(".org-");
+       var mlname = d[1] + "@" + d[0] + ".org"
+       dates.sort();
+       var cu = 0;
+       narr = []
+       hitFirst = false
+
+       var dp = new Date();
+       dp.setMonth(dp.getMonth() - 3);
+
+       var odp = new Date();
+       odp.setMonth(odp.getMonth() - 6);
+
+       difference = 0
+       for (i in dates) {
+               var date = dates[i];
+               var dateString = new Date(parseInt(date) * 1000);
+               if (dateString > dp) {
+                       difference += json[name][date]
+               }
+               cu = cu + json[name][date];
+               if (cu > 0) {
+                       hitFirst = true
+               }
+               if ((cu > 0 || hitFirst) && dateString >= odp) {
+                       if (noweekly > 0) {
+                               narr.push([dateString, cu, delivery[date] ? 
delivery[date] : 0])
+                       } else {
+                               narr.push([dateString, cu])
+                       }
+               }
+
+       }
+
+       var data = new google.visualization.DataTable();
+       data.addColumn('date', 'Date');
+       data.addColumn('number', "List members");
+       if (noweekly > 0) {
+               data.addColumn('number', "Emails sent per week");
+       }
+
+       data.addRows(narr);
+
+
+       var options = {
+               title: 'Mailing list stats for ' + mlname,
+               backgroundColor: 'transparent',
+               width: 900,
+               height: 260,
+               legend: {
+                       position: 'none',
+                       maxLines: 3
+               },
+               vAxis: {
+                       format: "#"
+               },
+               vAxes: (noweekly > 0) ? [
+
+                       {
+                               title: 'Emails per week',
+                               titleTextStyle: {
+                                       color: '#DD0000'
+                               }
+                       }, {
+                               title: 'Subscribers',
+                               titleTextStyle: {
+                                       color: '#0000DD'
+                               }
+                       },
+               ] : [{
+                               title: 'Subscribers',
+                               titleTextStyle: {
+                                       color: '#0000DD'
+                               }
+                       },
+               ],
+               series: {
+                       0: {
+                               type: "line",
+                               pointSize: 4,
+                               lineWidth: 2,
+                               targetAxisIndex: (noweekly > 0) ? 1 : null
+                       },
+                       1: {
+                               type: "bars",
+                               targetAxisIndex: (noweekly > 0) ? 0 : [0, 1]
+                       }
+               },
+               seriesType: "bars",
+               tooltip: {
+                       isHtml: true
+               },
+       };
+
+       var chart = new google.visualization.ComboChart(chartDiv);
+
+       chart.draw(data, options);
+       return [cu, difference, chartDiv];
+
+}
+
+
+
+function renderReleaseChart(releases, name, container) {
+
+
+       var chartDiv;
+       if (document.getElementById(name + "_releasechart")) {
+               chartDiv = document.getElementById(name + "_releasechart")
+       } else {
+               chartDiv = document.createElement('div')
+               chartDiv.setAttribute("id", name + "_releasechart")
+       }
+
+       var narr = []
+       var maxLen = 1;
+       for (version in releases) {
+               var x = version.match(/(\d+)\.(\d+)/)
+               if (x && x[2].length > maxLen) {
+                       maxLen = x[2].length;
+               }
+       }
+       for (version in releases) {
+               if (new Date(releases[version] * 1000).getFullYear() >= 1999) {
+                       var major = parseFloat(version) ? parseFloat(version) : 
1
+                       var x = version.match(/(\d+)\.(\d+)/)
+                       if (x) {
+                               while (x[2].length < maxLen) {
+                                       x[2] = "0" + x[2]
+                               }
+                               major = parseFloat(x[1] + "." + x[2])
+                       }
+                       narr.push([new Date(releases[version] * 1000), major, 
version + " - " + new Date(releases[version] * 1000).toDateString()])
+               }
+
+       }
+
+       var data = new google.visualization.DataTable();
+
+       data.addColumn('datetime', 'Date');
+       data.addColumn('number', 'Version')
+       data.addColumn('string', 'tooltip');
+       data.setColumnProperty(2, 'role', 'tooltip');
+
+       data.addRows(narr);
+
+
+       var options = {
+               title: 'Release timeline for ' + name,
+               height: 240,
+               width: 800,
+               backgroundColor: 'transparent',
+               series: [{
+                               pointSize: 15
+                       },
+               ],
+               pointShape: {
+                       type: 'star',
+                       sides: 5
+               }
+       };
+
+       var chart = new google.visualization.ScatterChart(chartDiv);
+       chartDiv.style.marginLeft = "50px";
+
+       chart.draw(data, options);
+       return chartDiv
+}
+
+function fetchJIRA(pmc, project, prepend) {
+       if (project && project.length > 1) {
+               GetAsyncJSON("/jiraversions.py?project=" + pmc + "&jiraname=" + 
project + "&prepend=" + prepend, null, function(json) {
+                       if (json && json.versions) {
+                               var n = 0;
+                               for (version in json.versions) {
+                                       n++;
+                                       jsdata.releases[pmc][version] = 
json.versions[version]
+                               }
+                               $('#dialog_' + pmc).dialog("close")
+                               var nproject = pmc
+                               alert("Fetched " + n + " releases from JIRA!")
+                               renderFrontPage(jsdata)
+
+                       } else {
+                               alert("Couldn't find any release data :(")
+                       }
+               })
+       }
+
+}
+
+function addRelease(pmc, version, date) {
+       if (version && version.length > 1 && 
date.match(/^(\d\d\d\d)-(\d\d)-(\d\d)$/)) {
+               var x = date.split("-");
+               var y = new Date(x[0],parseInt(x[1])-1,parseInt(x[2]));
+               var nn = parseInt(y.getTime()/1000);
+               GetAsyncJSON("/addrelease.py?json=true&project=" + pmc + 
"&version=" + escape(version) + "&date=" + nn, null, function(json) {
+                       if (json && json.versions) {
+                               var n = 0;
+                               for (version in json.versions) {
+                                       n++;
+                                       jsdata.releases[pmc][version] = 
json.versions[version]
+                               }
+                               $('#rdialog_' + pmc).dialog("close")
+                               var nproject = pmc
+                               alert("Release added!")
+                               renderFrontPage(jsdata)
+
+                       } else {
+                               alert("Couldn't add release data :(")
+                       }
+               })
+       }
+
+}
\ No newline at end of file

Propchange: comdev/reporter.apache.org/tags/test/site/render.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: comdev/reporter.apache.org/tags/test/site/reportingcycles.json
URL: 
http://svn.apache.org/viewvc/comdev/reporter.apache.org/tags/test/site/reportingcycles.json?rev=1689512&view=auto
==============================================================================
--- comdev/reporter.apache.org/tags/test/site/reportingcycles.json (added)
+++ comdev/reporter.apache.org/tags/test/site/reportingcycles.json Mon Jul  6 
22:11:25 2015
@@ -0,0 +1 @@
+{"camel": ["March", "June", "September", "December"], "bookkeeper": 
["February", "May", "August", "November"], "curator": ["March", "June", 
"September", "December"], "oozie": ["February", "May", "August", "November"], 
"tika": ["January", "April", "July", "October"], "james": ["January", "April", 
"July", "October"], "sis": ["February", "May", "August", "November"], "lucy": 
["January", "April", "July", "October"], "cordova": ["March", "June", 
"September", "December"], "ctakes": ["March", "June", "September", "December"], 
"tez": ["January", "April", "July", "October"], "jmeter": ["January", "April", 
"July", "October"], "tiles": ["March", "June", "September", "December"], 
"wicket": ["March", "June", "September", "December"], "perl": ["February", 
"May", "August", "November"], "flink": ["March", "June", "September", 
"December"], "http server": ["February", "May", "August", "November"], "onami": 
["January", "April", "July", "October"], "cocoon": ["February", "May", 
"August", "November"], "
 nutch": ["January", "April", "July", "October"], "stanbol": ["March", "June", 
"September", "December"], "maven": ["January", "April", "July", "October"], 
"spamassassin": ["March", "June", "September", "December"], "openjpa": 
["January", "April", "July", "October"], "xalan": ["February", "May", "August", 
"November"], "jena": ["January", "April", "July", "October"], "mrunit": 
["March", "June", "September", "December"], "sqoop": ["January", "April", 
"July", "October"], "directory": ["January", "April", "July", "October"], 
"creadur": ["February", "May", "August", "November"], "olingo": ["March", 
"June", "September", "December"], "helix": ["March", "June", "September", 
"December"], "spark": ["February", "May", "August", "November"], "webservices": 
["January", "April", "July", "October"], "web services": ["January", "April", 
"July", "October"], "oltu": ["February", "May", "August", "November"], "db": 
["January", "April", "July", "October"], "etch": ["February", "May", "August", 
"November"
 ], "activemq": ["January", "April", "July", "October"], "shiro": ["March", 
"June", "September", "December"], "climate": ["February", "May", "August", 
"November"], "cayenne": ["March", "June", "September", "December"], "portals": 
["March", "June", "September", "December"], "httpd": ["February", "May", 
"August", "November"], "lucene.net": ["March", "June", "September", 
"December"], "opennlp": ["March", "June", "September", "December"], "chukwa": 
["January", "April", "July", "October"], "xmlgraphics": ["February", "May", 
"August", "November"], "hadoop": ["January", "April", "July", "October"], 
"oodt": ["March", "June", "September", "December"], "gump": ["March", "June", 
"September", "December"], "openmeetings": ["January", "April", "July", 
"October"], "tomee": ["January", "April", "July", "October"], "giraph": 
["February", "May", "August", "November"], "hama": ["February", "May", 
"August", "November"], "roller": ["February", "May", "August", "November"], 
"commons": ["March", "June", "S
 eptember", "December"], "zookeeper": ["March", "June", "September", 
"December"], "pdfbox": ["January", "April", "July", "October"], "whirr": 
["March", "June", "September", "December"], "openoffice": ["January", "April", 
"July", "October"], "libcloud": ["February", "May", "August", "November"], 
"jclouds": ["January", "April", "July", "October"], "deltaspike": ["February", 
"May", "August", "November"], "kafka": ["February", "May", "August", 
"November"], "labs": ["March", "June", "September", "December"], "ace": 
["January", "April", "July", "October"], "ambari": ["February", "May", 
"August", "November"], "stratos": ["February", "May", "August", "November"], 
"river": ["February", "May", "August", "November"], "avro": ["January", 
"April", "July", "October"], "wookie": ["January", "April", "July", "October"], 
"synapse": ["March", "June", "September", "December"], "celix": ["January", 
"April", "July", "October"], "directmemory": ["February", "May", "August", 
"November"], "axis": ["March", 
 "June", "September", "December"], "servicemix": ["March", "June", "September", 
"December"], "xml graphics": ["February", "May", "August", "November"], 
"lucene": ["March", "June", "September", "December"], "gora": ["February", 
"May", "August", "November"], "sling": ["March", "June", "September", 
"December"], "isis": ["January", "April", "July", "October"], "xerces": 
["February", "May", "August", "November"], "tajo": ["March", "June", 
"September", "December"], "archiva": ["March", "June", "September", 
"December"], "jspwiki": ["January", "April", "July", "October"], "crunch": 
["January", "April", "July", "October"], "trafficserver": ["January", "April", 
"July", "October"], "phoenix": ["February", "May", "August", "November"], 
"wink": ["March", "June", "September", "December"], "qpid": ["February", "May", 
"August", "November"], "clerezza": ["February", "May", "August", "November"], 
"subversion": ["February", "May", "August", "November"], "traffic server": 
["January", "April", "July", "O
 ctober"], "any23": ["March", "June", "September", "December"], "syncope": 
["February", "May", "August", "November"], "continuum": ["February", "May", 
"August", "November"], "ofbiz": ["March", "June", "September", "December"], 
"flume": ["February", "May", "August", "November"], "aries": ["January", 
"April", "July", "October"], "empire-db": ["February", "May", "August", 
"November"], "cxf": ["January", "April", "July", "October"], "portable 
runtime": ["March", "June", "September", "December"], "steve": ["January", 
"April", "July", "October"], "accumulo": ["January", "April", "July", 
"October"], "lenya": ["February", "May", "August", "November"], "tcl": 
["January", "April", "July", "October"], "storm": ["March", "June", 
"September", "December"], "jackrabbit": ["March", "June", "September", 
"December"], "open climate workbench": ["February", "May", "August", 
"November"], "shindig": ["January", "April", "July", "October"], "mesos": 
["January", "April", "July", "October"], "couchdb": ["Feb
 ruary", "May", "August", "November"], "devicemap": ["February", "May", 
"August", "November"], "community development": ["February", "May", "August", 
"November"], "marmotta": ["February", "May", "August", "November"], 
"chemistry": ["March", "June", "September", "December"], "httpcomponents": 
["February", "May", "August", "November"], "uima": ["March", "June", 
"September", "December"], "pivot": ["March", "June", "September", "December"], 
"metamodel": ["February", "May", "August", "November"], "tuscany": ["February", 
"May", "August", "November"], "buildr": ["February", "May", "August", 
"November"], "hbase": ["January", "April", "July", "October"], "forrest": 
["February", "May", "August", "November"], "pig": ["March", "June", 
"September", "December"], "mina": ["January", "April", "July", "October"], 
"drill": ["February", "May", "August", "November"], "vcl": ["March", "June", 
"September", "December"], "bigtop": ["March", "June", "September", "December"], 
"velocity": ["February", "May", "
 August", "November"], "turbine": ["February", "May", "August", "November"], 
"rave": ["January", "April", "July", "October"], "tapestry": ["January", 
"April", "July", "October"], "ant": ["February", "May", "August", "November"], 
"deltacloud": ["January", "April", "July", "October"], "attic": ["January", 
"April", "July", "October"], "myfaces": ["January", "April", "July", 
"October"], "manifoldcf": ["February", "May", "August", "November"], 
"cloudstack": ["March", "June", "September", "December"], "knox": ["February", 
"May", "August", "November"], "tomcat": ["March", "June", "September", 
"December"], "openwebbeans": ["March", "June", "September", "December"], 
"abdera": ["February", "May", "August", "November"], "cassandra": ["February", 
"May", "August", "November"], "airavata": ["January", "April", "July", 
"October"], "geronimo": ["January", "April", "July", "October"], "felix": 
["March", "June", "September", "December"], "vxquery": ["January", "April", 
"July", "October"], "flex": ["Ma
 rch", "June", "September", "December"], "santuario": ["February", "May", 
"August", "November"], "bloodhound": ["March", "June", "September", 
"December"], "juddi": ["February", "May", "August", "November"], "ode": 
["January", "April", "July", "October"], "karaf": ["March", "June", 
"September", "December"], "poi": ["February", "May", "August", "November"], 
"logging": ["February", "May", "August", "November"], "thrift": ["January", 
"April", "July", "October"], "struts": ["January", "April", "July", "October"], 
"allura": ["March", "June", "September", "December"], "bval": ["March", "June", 
"September", "December"], "hive": ["March", "June", "September", "December"], 
"falcon": ["March", "June", "September", "December"], "mahout": ["January", 
"April", "July", "October"]}
\ No newline at end of file


Reply via email to