bigbrother/docs/uberdoc.html

3219 lines
199 KiB
HTML
Raw Permalink Normal View History

2015-02-17 10:40:29 +00:00
<!DOCTYPE html>
<html><head><meta charset="utf-8" content="text/html" http-equiv="Content-Type" /><meta content="Periodically send metrics" name="description" /><style type="text/css">/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
.syntaxhighlighter a,
.syntaxhighlighter div,
.syntaxhighlighter code,
.syntaxhighlighter table,
.syntaxhighlighter table td,
.syntaxhighlighter table tr,
.syntaxhighlighter table tbody,
.syntaxhighlighter table thead,
.syntaxhighlighter table caption,
.syntaxhighlighter textarea {
-moz-border-radius: 0 0 0 0 !important;
-webkit-border-radius: 0 0 0 0 !important;
background: none !important;
border: 0 !important;
bottom: auto !important;
float: none !important;
height: auto !important;
left: auto !important;
line-height: 1.1em !important;
/* margin: 0 !important; */
outline: 0 !important;
overflow: visible !important;
padding: 0 !important;
position: static !important;
right: auto !important;
text-align: left !important;
top: auto !important;
vertical-align: baseline !important;
width: auto !important;
box-sizing: content-box !important;
font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important;
font-weight: normal !important;
font-style: normal !important;
min-height: inherit !important;
min-height: auto !important;
}
.syntaxhighlighter {
/* width: 100% !important; */
margin: 1em 0 1em 0 !important;
position: relative !important;
overflow: auto !important;
}
.syntaxhighlighter.source {
overflow: hidden !important;
}
.syntaxhighlighter .bold {
font-weight: bold !important;
}
.syntaxhighlighter .italic {
font-style: italic !important;
}
.syntaxhighlighter .line {
white-space: pre !important;
}
.syntaxhighlighter table {
/* width: 100% !important;*/
}
.syntaxhighlighter table caption {
text-align: left !important;
padding: .5em 0 0.5em 1em !important;
}
.syntaxhighlighter table td.code {
width: 100% !important;
}
.syntaxhighlighter table td.code .container {
position: relative !important;
}
.syntaxhighlighter table td.code .container textarea {
box-sizing: border-box !important;
position: absolute !important;
left: 0 !important;
top: 0 !important;
width: 100% !important;
height: 100% !important;
border: none !important;
background: white !important;
padding-left: 1em !important;
overflow: hidden !important;
white-space: pre !important;
}
.syntaxhighlighter table td.gutter .line {
text-align: right !important;
padding: 0 0.5em 0 1em !important;
}
.syntaxhighlighter table td.code .line {
padding: 0 1em !important;
}
.syntaxhighlighter.nogutter td.code .container textarea, .syntaxhighlighter.nogutter td.code .line {
padding-left: 0em !important;
}
.syntaxhighlighter.show {
display: block !important;
}
.syntaxhighlighter.collapsed table {
display: none !important;
}
.syntaxhighlighter.collapsed .toolbar {
display: none;
/* padding: 0.1em 0.8em 0em 0.8em !important;
font-size: 1em !important;
position: static !important;
width: auto !important;
height: auto !important;*/
}
.syntaxhighlighter.collapsed .toolbar span {
display: inline !important;
margin-right: 1em !important;
}
.syntaxhighlighter.collapsed .toolbar span a {
padding: 0 !important;
display: none !important;
}
.syntaxhighlighter.collapsed .toolbar span a.expandSource {
display: inline !important;
}
.syntaxhighlighter .toolbar {
display: none;
/* position: absolute !important;
right: 1px !important;
top: 1px !important;
width: 11px !important;
height: 11px !important;
font-size: 10px !important;
z-index: 10 !important;*/
}
.syntaxhighlighter .toolbar span.title {
display: inline !important;
}
.syntaxhighlighter .toolbar a {
display: block !important;
text-align: center !important;
text-decoration: none !important;
padding-top: 1px !important;
}
.syntaxhighlighter .toolbar a.expandSource {
display: none !important;
}
.syntaxhighlighter.ie {
font-size: .9em !important;
padding: 1px 0 1px 0 !important;
}
.syntaxhighlighter.ie .toolbar {
line-height: 8px !important;
}
.syntaxhighlighter.ie .toolbar a {
padding-top: 0px !important;
}
.syntaxhighlighter.printing .line.alt1 .content,
.syntaxhighlighter.printing .line.alt2 .content,
.syntaxhighlighter.printing .line.highlighted .number,
.syntaxhighlighter.printing .line.highlighted.alt1 .content,
.syntaxhighlighter.printing .line.highlighted.alt2 .content {
background: none !important;
}
.syntaxhighlighter.printing .line .number {
color: #bbbbbb !important;
}
.syntaxhighlighter.printing .line .content {
color: black !important;
}
.syntaxhighlighter.printing .toolbar {
display: none !important;
}
.syntaxhighlighter.printing a {
text-decoration: none !important;
}
.syntaxhighlighter.printing .plain, .syntaxhighlighter.printing .plain a {
color: black !important;
}
.syntaxhighlighter.printing .comments, .syntaxhighlighter.printing .comments a {
color: #008200 !important;
}
.syntaxhighlighter.printing .string, .syntaxhighlighter.printing .string a {
color: blue !important;
}
.syntaxhighlighter.printing .keyword {
color: #006699 !important;
font-weight: bold !important;
}
.syntaxhighlighter.printing .preprocessor {
color: gray !important;
}
.syntaxhighlighter.printing .variable {
color: #aa7700 !important;
}
.syntaxhighlighter.printing .value {
color: #009900 !important;
}
.syntaxhighlighter.printing .functions {
color: #ff1493 !important;
}
.syntaxhighlighter.printing .constants {
color: #0066cc !important;
}
.syntaxhighlighter.printing .script {
font-weight: bold !important;
}
.syntaxhighlighter.printing .color1, .syntaxhighlighter.printing .color1 a {
color: gray !important;
}
.syntaxhighlighter.printing .color2, .syntaxhighlighter.printing .color2 a {
color: #ff1493 !important;
}
.syntaxhighlighter.printing .color3, .syntaxhighlighter.printing .color3 a {
color: red !important;
}
.syntaxhighlighter.printing .break, .syntaxhighlighter.printing .break a {
color: black !important;
}
</style><style type="text/css">.syntaxhighlighter{overflow:hidden !important;}</style><style type="text/css">/**
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
.syntaxhighlighter {
background-color: transparent !important;
}
.syntaxhighlighter .line.alt1 {
background-color: transparent !important;
}
.syntaxhighlighter .line.alt2 {
background-color: transparent !important;
}
.syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 {
background-color: #c3defe !important;
}
.syntaxhighlighter .line.highlighted.number {
color: white !important;
}
.syntaxhighlighter table caption {
color: black !important;
}
.syntaxhighlighter .gutter {
color: #787878 !important;
}
.syntaxhighlighter .gutter .line {
border-right: 3px solid #d4d0c8 !important;
}
.syntaxhighlighter .gutter .line.highlighted {
background-color: #d4d0c8 !important;
color: white !important;
}
.syntaxhighlighter.printing .line .content {
border: none !important;
}
.syntaxhighlighter.collapsed {
overflow: visible !important;
}
.syntaxhighlighter.collapsed .toolbar {
color: #3f5fbf !important;
background: white !important;
border: 1px solid #d4d0c8 !important;
}
.syntaxhighlighter.collapsed .toolbar a {
color: #3f5fbf !important;
}
.syntaxhighlighter.collapsed .toolbar a:hover {
color: #aa7700 !important;
}
.syntaxhighlighter .toolbar {
color: #a0a0a0 !important;
background: #d4d0c8 !important;
border: none !important;
}
.syntaxhighlighter .toolbar a {
color: #a0a0a0 !important;
}
.syntaxhighlighter .toolbar a:hover {
color: red !important;
}
.syntaxhighlighter .plain, .syntaxhighlighter .plain a {
color: black !important;
}
.syntaxhighlighter .comments, .syntaxhighlighter .comments a {
color: #3f5fbf !important;
}
.syntaxhighlighter .string, .syntaxhighlighter .string a {
color: #2a00ff !important;
}
.syntaxhighlighter .keyword {
color: #7f0055 !important;
}
.syntaxhighlighter .preprocessor {
color: #646464 !important;
}
.syntaxhighlighter .variable {
color: #aa7700 !important;
}
.syntaxhighlighter .value {
color: #009900 !important;
}
.syntaxhighlighter .functions {
color: #ff1493 !important;
}
.syntaxhighlighter .constants {
color: #0066cc !important;
}
.syntaxhighlighter .script {
font-weight: bold !important;
color: #7f0055 !important;
background-color: none !important;
}
.syntaxhighlighter .color1, .syntaxhighlighter .color1 a {
color: gray !important;
}
.syntaxhighlighter .color2, .syntaxhighlighter .color2 a {
color: #ff1493 !important;
}
.syntaxhighlighter .color3, .syntaxhighlighter .color3 a {
color: red !important;
}
.syntaxhighlighter .xml .keyword {
color: #3f7f7f !important;
font-weight: normal !important;
}
.syntaxhighlighter .xml .color1, .syntaxhighlighter .xml .color1 a {
color: #7f007f !important;
}
.syntaxhighlighter .xml .string {
font-style: italic !important;
color: #2a00ff !important;
}
.clojure.syntaxhighlighter .invalid {
background-color: #FAA !important;
}
.clojure.syntaxhighlighter .quoted {
font-style: italic !important;
}
.syntaxhighlighter .clojure.variable,
.syntaxhighlighter .clojure.symbol,
.syntaxhighlighter .clojure.value
{
color: #006060 !important;
}
.syntaxhighlighter .clojure.string {
color: #55B !important;
}
.syntaxhighlighter .clojure.functions {
color: black !important;
}
.syntaxhighlighter .clojure.color1 {
color: #666 !important;
}
.syntaxhighlighter .clojure.color3 {
color: #900 !important;
}
.syntaxhighlighter .clojure.constants {
color: #1A734D !important;
}
</style><style type="text/css">html{padding:0;margin:0;}h1{padding:0;margin:0;}h2{padding:0;margin:0;}h3{padding:0;margin:0;}h4{padding:0;margin:0;}a{color:#261A3B;}a:visited{color:#261A3B;}</style><style type="text/css">.header{margin-top:30px;}h1.project-name{font-size:34px;display:inline;}h2.project-version{font-size:18px;margin-left:10px;margin-top:0;display:inline;}.toc-link{color:#252519;font-size:12px;margin-left:10px;text-decoration:none;}.toc-link:hover{color:#5050A6;}.toc h1{font-size:34px;margin:0;}.docs-header{padding-bottom:10px;margin-bottom:25px;border-bottom:dotted #aaa 1px;}.toc h1{font-size:24px;}.toc{margin-bottom:40px;border-bottom:solid #bbb 1px;}.toc ul{margin-left:20px;margin-top:0;padding-top:0;padding-left:0px;}.toc li{list-style-type:none;padding-left:0;}.dependencies{}.dependencies table{font-size:16px;margin-left:20px;width:99.99%;border:none;}.dependencies td{white-space:nowrap;padding-right:20px;;}.dependencies .dotted{width:99%;}.dependencies .dotted hr{border-right:none;color:transparent;background-color:transparent;noshade:noshade;border-left:none;border-top:none;margin-bottom:-6px;height:0;border-bottom:dotted #bbb 1px;}.dependencies .dep-version{text-align:right;}.plugins ul{margin-left:20px;margin-top:0;padding-top:0;padding-left:0px;}.plugins li{list-style-type:none;padding-left:0;}.header p{margin-left:20px;}</style><style type="text/css">#floating-toc{text-align:right;top:10px;overflow:hidden;right:20px;position:fixed;height:20px;}#floating-toc li{list-style-type:none;padding:0;margin:0;}</style><style type="text/css">body{color:#252519;font-size:16px;background-color:#F5F5FF;padding:0;font-family:'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;;margin:0;}h1{font-size:20px;margin-top:0;}h2{font-size:18px;}h3{font-size:16px;}a.anchor{color:#252519;text-decoration:none;}a.anchor:hover{color:#5050A6;}table{border-spacing:0;margin-bottom:10px;border-bottom:solid #ddd 1px;;}code{display:inline;}p{margin-top:8px;}tr{padding:0px;margin:0px;}td.docs{vertical-align:top;background-color:#FFF;width:410px;max-width:410px;padding-right:20px;padding-left:55px;border:none;margin:0px;}td.docs pre{font-size:12px;overflow:hidden;}td.codes{vertical-align:top;font-size:10pt;overflow:hidden;background-color:#F5F5FF;width:55%;border-left:solid #E5E5EE 1px;padding-left:20px;border:none;margin:0px;}td.spacer{padding-bottom:40px;}pre code{padding:4px;display:block;}code{font-size:14px;background-color:ghostWhite;padding-right:3px;padding-left:3px;border:solid #DEDEDE 1px;}.syntaxhighlighter code{font-size:13px;}.footer{text-align:center;}</style><script type="text/javascript">/*! jQuery v1.7.1 jquery.com | jquery.org/license */
(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.ou
f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=[],j,k,l,m,n,o,p,q,r,s,t;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click")){m=f(this),m.context=this.ownerDocument||this;for(l=c.target;l!=this;l=l.parentNode||this){o={},q=[],m[0]=l;for(j=0;j<e;j++)r=d[j],s=r.selector,o[s]===b&&(o[s]=r.quick?H(l,r.quick):m.is(s)),o[s]&&q.push(r);q.length&&i.push({elem:l,matches:q})}}d.length>e&&i.push({elem:this,matches:d.slice(e)});for(j=0;j<i.length&&!c.isPropagationStopped();j++){p=i[j],c.currentTarget=p.
{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bp)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.leng
</script><script type="text/javascript">//XRegExp 1.5.0 <xregexp.com> MIT License
var XRegExp;if(XRegExp){throw Error("can't load XRegExp twice in the same frame")}(function(){XRegExp=function(w,r){var q=[],u=XRegExp.OUTSIDE_CLASS,x=0,p,s,v,t,y;if(XRegExp.isRegExp(w)){if(r!==undefined){throw TypeError("can't supply flags when constructing one RegExp from another")}return j(w)}if(g){throw Error("can't call the XRegExp constructor within token definition functions")}r=r||"";p={hasNamedCapture:false,captureNames:[],hasFlag:function(z){return r.indexOf(z)>-1},setFlag:function(z){r+=z}};while(x<w.length){s=o(w,x,u,p);if(s){q.push(s.output);x+=(s.match[0].length||1)}else{if(v=m.exec.call(i[u],w.slice(x))){q.push(v[0]);x+=v[0].length}else{t=w.charAt(x);if(t==="["){u=XRegExp.INSIDE_CLASS}else{if(t==="]"){u=XRegExp.OUTSIDE_CLASS}}q.push(t);x++}}}y=RegExp(q.join(""),m.replace.call(r,h,""));y._xregexp={source:w,captureNames:p.hasNamedCapture?p.captureNames:null};return y};XRegExp.version="1.5.0";XRegExp.INSIDE_CLASS=1;XRegExp.OUTSIDE_CLASS=2;var c=/\$(?:(\d\d?|[$&`'])|{([$\w]+)})/g,h=/[^gimy]+|([\s\S])(?=[\s\S]*\1)/g,n=/^(?:[?*+]|{\d+(?:,\d*)?})\??/,g=false,k=[],m={exec:RegExp.prototype.exec,test:RegExp.prototype.test,match:String.prototype.match,replace:String.prototype.replace,split:String.prototype.split},a=m.exec.call(/()??/,"")[1]===undefined,e=function(){var p=/^/g;m.test.call(p,"");return !p.lastIndex}(),f=function(){var p=/x/g;m.replace.call("x",p,"");return !p.lastIndex}(),b=RegExp.prototype.sticky!==undefined,i={};i[XRegExp.INSIDE_CLASS]=/^(?:\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S]))/;i[XRegExp.OUTSIDE_CLASS]=/^(?:\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9]\d*|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|c[A-Za-z]|[\s\S])|\(\?[:=!]|[?*+]\?|{\d+(?:,\d*)?}\??)/;XRegExp.addToken=function(s,r,q,p){k.push({pattern:j(s,"g"+(b?"y":"")),handler:r,scope:q||XRegExp.OUTSIDE_CLASS,trigger:p||null})};XRegExp.cache=function(r,p){var q=r+"/"+(p||"");return XRegExp.cache[q]||(XRegExp.cache[q]=XRegExp(r,p))};XRegExp.copyAsGlobal=function(p){return j(p,"g")};XRegExp.escape=function(p){return p.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&")};XRegExp.execAt=function(s,r,t,q){r=j(r,"g"+((q&&b)?"y":""));r.lastIndex=t=t||0;var p=r.exec(s);if(q){return(p&&p.index===t)?p:null}else{return p}};XRegExp.freezeTokens=function(){XRegExp.addToken=function(){throw Error("can't run addToken after freezeTokens")}};XRegExp.isRegExp=function(p){return Object.prototype.toString.call(p)==="[object RegExp]"};XRegExp.iterate=function(u,p,v,s){var t=j(p,"g"),r=-1,q;while(q=t.exec(u)){v.call(s,q,++r,u,t);if(t.lastIndex===q.index){t.lastIndex++}}if(p.global){p.lastIndex=0}};XRegExp.matchChain=function(q,p){return function r(s,x){var v=p[x].regex?p[x]:{regex:p[x]},u=j(v.regex,"g"),w=[],t;for(t=0;t<s.length;t++){XRegExp.iterate(s[t],u,function(y){w.push(v.backref?(y[v.backref]||""):y[0])})}return((x===p.length-1)||!w.length)?w:r(w,x+1)}([q],0)};RegExp.prototype.apply=function(q,p){return this.exec(p[0])};RegExp.prototype.call=function(p,q){return this.exec(q)};RegExp.prototype.exec=function(t){var r=m.exec.apply(this,arguments),q,p;if(r){if(!a&&r.length>1&&l(r,"")>-1){p=RegExp(this.source,m.replace.call(d(this),"g",""));m.replace.call(t.slice(r.index),p,function(){for(var u=1;u<arguments.length-2;u++){if(arguments[u]===undefined){r[u]=undefined}}})}if(this._xregexp&&this._xregexp.captureNames){for(var s=1;s<r.length;s++){q=this._xregexp.captureNames[s-1];if(q){r[q]=r[s]}}}if(!e&&this.global&&!r[0].length&&(this.lastIndex>r.index)){this.lastIndex--}}return r};if(!e){RegExp.prototype.test=function(q){var p=m.exec.call(this,q);if(p&&this.global&&!p[0].length&&(this.lastIndex>p.index)){this.lastIndex--}return !!p}}String.prototype.match=function(q){if(!XRegExp.isRegExp(q)){q=RegExp(q)}if(q.global){var p=m.match.apply(this,arguments);q.lastIndex=0;return p}return q.exec(this)};String.prototype.replace=function(r,s){var t=XRegExp.isRegExp(r),q,p,u;if(t&&typeof s.valueOf()==="string"&&s.indexOf("${")===-1&&f){return m.replace.apply(this,arguments)}if(!t){r=r+""}else{if(r._xregexp){q=r._xregexp.captureNames}}if(typeof s==="function"
</script><script type="text/javascript">/**
* SyntaxHighlighter
* http://alexgorbatchev.com/SyntaxHighlighter
*
* SyntaxHighlighter is donationware. If you are using it, please donate.
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
*
* @version
* 3.0.83 (July 02 2010)
*
* @copyright
* Copyright (C) 2004-2010 Alex Gorbatchev.
*
* @license
* Dual licensed under the MIT and GPL licenses.
*/
//
// Begin anonymous function. This is used to contain local scope variables without polutting global scope.
//
var SyntaxHighlighter = function() {
// CommonJS
if (typeof(require) != 'undefined' && typeof(XRegExp) == 'undefined')
{
XRegExp = require('XRegExp').XRegExp;
}
// Shortcut object which will be assigned to the SyntaxHighlighter variable.
// This is a shorthand for local reference in order to avoid long namespace
// references to SyntaxHighlighter.whatever...
var sh = {
defaults : {
/** Additional CSS class names to be added to highlighter elements. */
'class-name' : '',
/** First line number. */
'first-line' : 1,
/**
* Pads line numbers. Possible values are:
*
* false - don't pad line numbers.
* true - automaticaly pad numbers with minimum required number of leading zeroes.
* [int] - length up to which pad line numbers.
*/
'pad-line-numbers' : false,
/** Lines to highlight. */
'highlight' : null,
/** Title to be displayed above the code block. */
'title' : null,
/** Enables or disables smart tabs. */
'smart-tabs' : true,
/** Gets or sets tab size. */
'tab-size' : 4,
/** Enables or disables gutter. */
'gutter' : true,
/** Enables or disables toolbar. */
'toolbar' : true,
/** Enables quick code copy and paste from double click. */
'quick-code' : true,
/** Forces code view to be collapsed. */
'collapse' : false,
/** Enables or disables automatic links. */
'auto-links' : true,
/** Gets or sets light mode. Equavalent to turning off gutter and toolbar. */
'light' : false,
'html-script' : false
},
config : {
space : '&nbsp;',
/** Enables use of <SCRIPT type="syntaxhighlighter" /> tags. */
useScriptTags : true,
/** Blogger mode flag. */
bloggerMode : false,
stripBrs : false,
/** Name of the tag that SyntaxHighlighter will automatically look for. */
tagName : 'pre',
strings : {
expandSource : 'expand source',
help : '?',
alert: 'SyntaxHighlighter\n\n',
noBrush : 'Can\'t find brush for: ',
brushNotHtmlScript : 'Brush wasn\'t configured for html-script option: ',
// this is populated by the build script
aboutDialog : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>About SyntaxHighlighter</title></head><body style="font-family:Geneva,Arial,Helvetica,sans-serif;background-color:#fff;color:#000;font-size:1em;text-align:center;"><div style="text-align:center;margin-top:1.5em;"><div style="font-size:xx-large;">SyntaxHighlighter</div><div style="font-size:.75em;margin-bottom:3em;"><div>version 3.0.83 (July 02 2010)</div><div><a href="http://alexgorbatchev.com/SyntaxHighlighter" target="_blank" style="color:#005896">http://alexgorbatchev.com/SyntaxHighlighter</a></div><div>JavaScript code syntax highlighter.</div><div>Copyright 2004-2010 Alex Gorbatchev.</div></div><div>If you like this script, please <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=2930402" style="color:#005896">donate</a> to <br/>keep development active!</div></div></body></html>'
}
},
/** Internal 'global' variables. */
vars : {
discoveredBrushes : null,
highlighters : {}
},
/** This object is populated by user included external brush files. */
brushes : {},
/** Common regular expressions. */
regexLib : {
multiLineCComments : /\/\*[\s\S]*?\*\//gm,
singleLineCComments : /\/\/.*$/gm,
singleLinePerlComments : /#.*$/gm,
doubleQuotedString : /"([^\\"\n]|\\.)*"/g,
singleQuotedString : /'([^\\'\n]|\\.)*'/g,
multiLineDoubleQuotedString : new XRegExp('"([^\\\\"]|\\\\.)*"', 'gs'),
multiLineSingleQuotedString : new XRegExp("'([^\\\\']|\\\\.)*'", 'gs'),
xmlComments : /(&lt;|<)!--[\s\S]*?--(&gt;|>)/gm,
url : /\w+:\/\/[\w-.\/?%&=:@;]*/g,
/** <?= ?> tags. */
phpScriptTags : { left: /(&lt;|<)\?=?/g, right: /\?(&gt;|>)/g },
/** <%= %> tags. */
aspScriptTags : { left: /(&lt;|<)%=?/g, right: /%(&gt;|>)/g },
scriptScriptTags : { left: /(&lt;|<)\s*script.*?(&gt;|>)/gi, right: /(&lt;|<)\/\s*script\s*(&gt;|>)/gi }
},
toolbar: {
/**
* Generates HTML markup for the toolbar.
* @param {Highlighter} highlighter Highlighter instance.
* @return {String} Returns HTML markup.
*/
getHtml: function(highlighter)
{
var html = '<div class="toolbar">',
items = sh.toolbar.items,
list = items.list
;
function defaultGetHtml(highlighter, name)
{
return sh.toolbar.getButtonHtml(highlighter, name, sh.config.strings[name]);
};
for (var i = 0; i < list.length; i++)
html += (items[list[i]].getHtml || defaultGetHtml)(highlighter, list[i]);
html += '</div>';
return html;
},
/**
* Generates HTML markup for a regular button in the toolbar.
* @param {Highlighter} highlighter Highlighter instance.
* @param {String} commandName Command name that would be executed.
* @param {String} label Label text to display.
* @return {String} Returns HTML markup.
*/
getButtonHtml: function(highlighter, commandName, label)
{
return '<span><a href="#" class="toolbar_item'
+ ' command_' + commandName
+ ' ' + commandName
+ '">' + label + '</a></span>'
;
},
/**
* Event handler for a toolbar anchor.
*/
handler: function(e)
{
var target = e.target,
className = target.className || ''
;
function getValue(name)
{
var r = new RegExp(name + '_(\\w+)'),
match = r.exec(className)
;
return match ? match[1] : null;
};
var highlighter = getHighlighterById(findParentElement(target, '.syntaxhighlighter').id),
commandName = getValue('command')
;
// execute the toolbar command
if (highlighter && commandName)
sh.toolbar.items[commandName].execute(highlighter);
// disable default A click behaviour
e.preventDefault();
},
/** Collection of toolbar items. */
items : {
// Ordered lis of items in the toolbar. Can't expect `for (var n in items)` to be consistent.
list: ['expandSource', 'help'],
expandSource: {
getHtml: function(highlighter)
{
if (highlighter.getParam('collapse') != true)
return '';
var title = highlighter.getParam('title');
return sh.toolbar.getButtonHtml(highlighter, 'expandSource', title ? title : sh.config.strings.expandSource);
},
execute: function(highlighter)
{
var div = getHighlighterDivById(highlighter.id);
removeClass(div, 'collapsed');
}
},
/** Command to display the about dialog window. */
help: {
execute: function(highlighter)
{
var wnd = popup('', '_blank', 500, 250, 'scrollbars=0'),
doc = wnd.document
;
doc.write(sh.config.strings.aboutDialog);
doc.close();
wnd.focus();
}
}
}
},
/**
* Finds all elements on the page which should be processes by SyntaxHighlighter.
*
* @param {Object} globalParams Optional parameters which override element's
* parameters. Only used if element is specified.
*
* @param {Object} element Optional element to highlight. If none is
* provided, all elements in the current document
* are returned which qualify.
*
* @return {Array} Returns list of <code>{ target: DOMElement, params: Object }</code> objects.
*/
findElements: function(globalParams, element)
{
var elements = element ? [element] : toArray(document.getElementsByTagName(sh.config.tagName)),
conf = sh.config,
result = []
;
// support for <SCRIPT TYPE="syntaxhighlighter" /> feature
if (conf.useScriptTags)
elements = elements.concat(getSyntaxHighlighterScriptTags());
if (elements.length === 0)
return result;
for (var i = 0; i < elements.length; i++)
{
var item = {
target: elements[i],
// local params take precedence over globals
params: merge(globalParams, parseParams(elements[i].className))
};
if (item.params['brush'] == null)
continue;
result.push(item);
}
return result;
},
/**
* Shorthand to highlight all elements on the page that are marked as
* SyntaxHighlighter source code.
*
* @param {Object} globalParams Optional parameters which override element's
* parameters. Only used if element is specified.
*
* @param {Object} element Optional element to highlight. If none is
* provided, all elements in the current document
* are highlighted.
*/
highlight: function(globalParams, element)
{
var elements = this.findElements(globalParams, element),
propertyName = 'innerHTML',
highlighter = null,
conf = sh.config
;
if (elements.length === 0)
return;
for (var i = 0; i < elements.length; i++)
{
var element = elements[i],
target = element.target,
params = element.params,
brushName = params.brush,
code
;
if (brushName == null)
continue;
// Instantiate a brush
if (params['html-script'] == 'true' || sh.defaults['html-script'] == true)
{
highlighter = new sh.HtmlScript(brushName);
brushName = 'htmlscript';
}
else
{
var brush = findBrush(brushName);
if (brush)
highlighter = new brush();
else
continue;
}
code = target[propertyName];
// remove CDATA from <SCRIPT/> tags if it's present
if (conf.useScriptTags)
code = stripCData(code);
// Inject title if the attribute is present
if ((target.title || '') != '')
params.title = target.title;
params['brush'] = brushName;
highlighter.init(params);
element = highlighter.getDiv(code);
// carry over ID
if ((target.id || '') != '')
element.id = target.id;
target.parentNode.replaceChild(element, target);
}
},
/**
* Main entry point for the SyntaxHighlighter.
* @param {Object} params Optional params to apply to all highlighted elements.
*/
all: function(params)
{
attachEvent(
window,
'load',
function() { sh.highlight(params); }
);
}
}; // end of sh
sh['all'] = sh.all;
sh['highlight'] = sh.highlight;
/**
* Checks if target DOM elements has specified CSS class.
* @param {DOMElement} target Target DOM element to check.
* @param {String} className Name of the CSS class to check for.
* @return {Boolean} Returns true if class name is present, false otherwise.
*/
function hasClass(target, className)
{
return target.className.indexOf(className) != -1;
};
/**
* Adds CSS class name to the target DOM element.
* @param {DOMElement} target Target DOM element.
* @param {String} className New CSS class to add.
*/
function addClass(target, className)
{
if (!hasClass(target, className))
target.className += ' ' + className;
};
/**
* Removes CSS class name from the target DOM element.
* @param {DOMElement} target Target DOM element.
* @param {String} className CSS class to remove.
*/
function removeClass(target, className)
{
target.className = target.className.replace(className, '');
};
/**
* Converts the source to array object. Mostly used for function arguments and
* lists returned by getElementsByTagName() which aren't Array objects.
* @param {List} source Source list.
* @return {Array} Returns array.
*/
function toArray(source)
{
var result = [];
for (var i = 0; i < source.length; i++)
result.push(source[i]);
return result;
};
/**
* Splits block of text into lines.
* @param {String} block Block of text.
* @return {Array} Returns array of lines.
*/
function splitLines(block)
{
return block.split('\n');
}
/**
* Generates HTML ID for the highlighter.
* @param {String} highlighterId Highlighter ID.
* @return {String} Returns HTML ID.
*/
function getHighlighterId(id)
{
var prefix = 'highlighter_';
return id.indexOf(prefix) == 0 ? id : prefix + id;
};
/**
* Finds Highlighter instance by ID.
* @param {String} highlighterId Highlighter ID.
* @return {Highlighter} Returns instance of the highlighter.
*/
function getHighlighterById(id)
{
return sh.vars.highlighters[getHighlighterId(id)];
};
/**
* Finds highlighter's DIV container.
* @param {String} highlighterId Highlighter ID.
* @return {Element} Returns highlighter's DIV element.
*/
function getHighlighterDivById(id)
{
return document.getElementById(getHighlighterId(id));
};
/**
* Stores highlighter so that getHighlighterById() can do its thing. Each
* highlighter must call this method to preserve itself.
* @param {Highilghter} highlighter Highlighter instance.
*/
function storeHighlighter(highlighter)
{
sh.vars.highlighters[getHighlighterId(highlighter.id)] = highlighter;
};
/**
* Looks for a child or parent node which has specified classname.
* Equivalent to jQuery's $(container).find(".className")
* @param {Element} target Target element.
* @param {String} search Class name or node name to look for.
* @param {Boolean} reverse If set to true, will go up the node tree instead of down.
* @return {Element} Returns found child or parent element on null.
*/
function findElement(target, search, reverse /* optional */)
{
if (target == null)
return null;
var nodes = reverse != true ? target.childNodes : [ target.parentNode ],
propertyToFind = { '#' : 'id', '.' : 'className' }[search.substr(0, 1)] || 'nodeName',
expectedValue,
found
;
expectedValue = propertyToFind != 'nodeName'
? search.substr(1)
: search.toUpperCase()
;
// main return of the found node
if ((target[propertyToFind] || '').indexOf(expectedValue) != -1)
return target;
for (var i = 0; nodes && i < nodes.length && found == null; i++)
found = findElement(nodes[i], search, reverse);
return found;
};
/**
* Looks for a parent node which has specified classname.
* This is an alias to <code>findElement(container, className, true)</code>.
* @param {Element} target Target element.
* @param {String} className Class name to look for.
* @return {Element} Returns found parent element on null.
*/
function findParentElement(target, className)
{
return findElement(target, className, true);
};
/**
* Finds an index of element in the array.
* @ignore
* @param {Object} searchElement
* @param {Number} fromIndex
* @return {Number} Returns index of element if found; -1 otherwise.
*/
function indexOf(array, searchElement, fromIndex)
{
fromIndex = Math.max(fromIndex || 0, 0);
for (var i = fromIndex; i < array.length; i++)
if(array[i] == searchElement)
return i;
return -1;
};
/**
* Generates a unique element ID.
*/
function guid(prefix)
{
return (prefix || '') + Math.round(Math.random() * 1000000).toString();
};
/**
* Merges two objects. Values from obj2 override values in obj1.
* Function is NOT recursive and works only for one dimensional objects.
* @param {Object} obj1 First object.
* @param {Object} obj2 Second object.
* @return {Object} Returns combination of both objects.
*/
function merge(obj1, obj2)
{
var result = {}, name;
for (name in obj1)
result[name] = obj1[name];
for (name in obj2)
result[name] = obj2[name];
return result;
};
/**
* Attempts to convert string to boolean.
* @param {String} value Input string.
* @return {Boolean} Returns true if input was "true", false if input was "false" and value otherwise.
*/
function toBoolean(value)
{
var result = { "true" : true, "false" : false }[value];
return result == null ? value : result;
};
/**
* Opens up a centered popup window.
* @param {String} url URL to open in the window.
* @param {String} name Popup name.
* @param {int} width Popup width.
* @param {int} height Popup height.
* @param {String} options window.open() options.
* @return {Window} Returns window instance.
*/
function popup(url, name, width, height, options)
{
var x = (screen.width - width) / 2,
y = (screen.height - height) / 2
;
options += ', left=' + x +
', top=' + y +
', width=' + width +
', height=' + height
;
options = options.replace(/^,/, '');
var win = window.open(url, name, options);
win.focus();
return win;
};
/**
* Adds event handler to the target object.
* @param {Object} obj Target object.
* @param {String} type Name of the event.
* @param {Function} func Handling function.
*/
function attachEvent(obj, type, func, scope)
{
function handler(e)
{
e = e || window.event;
if (!e.target)
{
e.target = e.srcElement;
e.preventDefault = function()
{
this.returnValue = false;
};
}
func.call(scope || window, e);
};
if (obj.attachEvent)
{
obj.attachEvent('on' + type, handler);
}
else
{
obj.addEventListener(type, handler, false);
}
};
/**
* Displays an alert.
* @param {String} str String to display.
*/
function alert(str)
{
window.alert(sh.config.strings.alert + str);
};
/**
* Finds a brush by its alias.
*
* @param {String} alias Brush alias.
* @param {Boolean} showAlert Suppresses the alert if false.
* @return {Brush} Returns bursh constructor if found, null otherwise.
*/
function findBrush(alias, showAlert)
{
var brushes = sh.vars.discoveredBrushes,
result = null
;
if (brushes == null)
{
brushes = {};
// Find all brushes
for (var brush in sh.brushes)
{
var info = sh.brushes[brush],
aliases = info.aliases
;
if (aliases == null)
continue;
// keep the brush name
info.brushName = brush.toLowerCase();
for (var i = 0; i < aliases.length; i++)
brushes[aliases[i]] = brush;
}
sh.vars.discoveredBrushes = brushes;
}
result = sh.brushes[brushes[alias]];
if (result == null && showAlert != false)
alert(sh.config.strings.noBrush + alias);
return result;
};
/**
* Executes a callback on each line and replaces each line with result from the callback.
* @param {Object} str Input string.
* @param {Object} callback Callback function taking one string argument and returning a string.
*/
function eachLine(str, callback)
{
var lines = splitLines(str);
for (var i = 0; i < lines.length; i++)
lines[i] = callback(lines[i], i);
return lines.join('\n');
};
/**
* This is a special trim which only removes first and last empty lines
* and doesn't affect valid leading space on the first line.
*
* @param {String} str Input string
* @return {String} Returns string without empty first and last lines.
*/
function trimFirstAndLastLines(str)
{
return str.replace(/^[ ]*[\n]+|[\n]*[ ]*$/g, '');
};
/**
* Parses key/value pairs into hash object.
*
* Understands the following formats:
* - name: word;
* - name: [word, word];
* - name: "string";
* - name: 'string';
*
* For example:
* name1: value; name2: [value, value]; name3: 'value'
*
* @param {String} str Input string.
* @return {Object} Returns deserialized object.
*/
function parseParams(str)
{
var match,
result = {},
arrayRegex = new XRegExp("^\\[(?<values>(.*?))\\]$"),
regex = new XRegExp(
"(?<name>[\\w-]+)" +
"\\s*:\\s*" +
"(?<value>" +
"[\\w-%#]+|" + // word
"\\[.*?\\]|" + // [] array
'".*?"|' + // "" string
"'.*?'" + // '' string
")\\s*;?",
"g"
)
;
while ((match = regex.exec(str)) != null)
{
var value = match.value
.replace(/^['"]|['"]$/g, '') // strip quotes from end of strings
;
// try to parse array value
if (value != null && arrayRegex.test(value))
{
var m = arrayRegex.exec(value);
value = m.values.length > 0 ? m.values.split(/\s*,\s*/) : [];
}
result[match.name] = value;
}
return result;
};
/**
* Wraps each line of the string into <code/> tag with given style applied to it.
*
* @param {String} str Input string.
* @param {String} css Style name to apply to the string.
* @return {String} Returns input string with each line surrounded by <span/> tag.
*/
function wrapLinesWithCode(str, css)
{
if (str == null || str.length == 0 || str == '\n')
return str;
str = str.replace(/</g, '&lt;');
// Replace two or more sequential spaces with &nbsp; leaving last space untouched.
str = str.replace(/ {2,}/g, function(m)
{
var spaces = '';
for (var i = 0; i < m.length - 1; i++)
spaces += sh.config.space;
return spaces + ' ';
});
// Split each line and apply <span class="...">...</span> to them so that
// leading spaces aren't included.
if (css != null)
str = eachLine(str, function(line)
{
if (line.length == 0)
return '';
var spaces = '';
line = line.replace(/^(&nbsp;| )+/, function(s)
{
spaces = s;
return '';
});
if (line.length == 0)
return spaces;
return spaces + '<code class="' + css + '">' + line + '</code>';
});
return str;
};
/**
* Pads number with zeros until it's length is the same as given length.
*
* @param {Number} number Number to pad.
* @param {Number} length Max string length with.
* @return {String} Returns a string padded with proper amount of '0'.
*/
function padNumber(number, length)
{
var result = number.toString();
while (result.length < length)
result = '0' + result;
return result;
};
/**
* Replaces tabs with spaces.
*
* @param {String} code Source code.
* @param {Number} tabSize Size of the tab.
* @return {String} Returns code with all tabs replaces by spaces.
*/
function processTabs(code, tabSize)
{
var tab = '';
for (var i = 0; i < tabSize; i++)
tab += ' ';
return code.replace(/\t/g, tab);
};
/**
* Replaces tabs with smart spaces.
*
* @param {String} code Code to fix the tabs in.
* @param {Number} tabSize Number of spaces in a column.
* @return {String} Returns code with all tabs replaces with roper amount of spaces.
*/
function processSmartTabs(code, tabSize)
{
var lines = splitLines(code),
tab = '\t',
spaces = ''
;
// Create a string with 1000 spaces to copy spaces from...
// It's assumed that there would be no indentation longer than that.
for (var i = 0; i < 50; i++)
spaces += ' '; // 20 spaces * 50
// This function inserts specified amount of spaces in the string
// where a tab is while removing that given tab.
function insertSpaces(line, pos, count)
{
return line.substr(0, pos)
+ spaces.substr(0, count)
+ line.substr(pos + 1, line.length) // pos + 1 will get rid of the tab
;
};
// Go through all the lines and do the 'smart tabs' magic.
code = eachLine(code, function(line)
{
if (line.indexOf(tab) == -1)
return line;
var pos = 0;
while ((pos = line.indexOf(tab)) != -1)
{
// This is pretty much all there is to the 'smart tabs' logic.
// Based on the position within the line and size of a tab,
// calculate the amount of spaces we need to insert.
var spaces = tabSize - pos % tabSize;
line = insertSpaces(line, pos, spaces);
}
return line;
});
return code;
};
/**
* Performs various string fixes based on configuration.
*/
function fixInputString(str)
{
var br = /<br\s*\/?>|&lt;br\s*\/?&gt;/gi;
if (sh.config.bloggerMode == true)
str = str.replace(br, '\n');
if (sh.config.stripBrs == true)
str = str.replace(br, '');
return str;
};
/**
* Removes all white space at the begining and end of a string.
*
* @param {String} str String to trim.
* @return {String} Returns string without leading and following white space characters.
*/
function trim(str)
{
return str.replace(/^\s+|\s+$/g, '');
};
/**
* Unindents a block of text by the lowest common indent amount.
* @param {String} str Text to unindent.
* @return {String} Returns unindented text block.
*/
function unindent(str)
{
var lines = splitLines(fixInputString(str)),
indents = new Array(),
regex = /^\s*/,
min = 1000
;
// go through every line and check for common number of indents
for (var i = 0; i < lines.length && min > 0; i++)
{
var line = lines[i];
if (trim(line).length == 0)
continue;
var matches = regex.exec(line);
// In the event that just one line doesn't have leading white space
// we can't unindent anything, so bail completely.
if (matches == null)
return str;
min = Math.min(matches[0].length, min);
}
// trim minimum common number of white space from the begining of every line
if (min > 0)
for (var i = 0; i < lines.length; i++)
lines[i] = lines[i].substr(min);
return lines.join('\n');
};
/**
* Callback method for Array.sort() which sorts matches by
* index position and then by length.
*
* @param {Match} m1 Left object.
* @param {Match} m2 Right object.
* @return {Number} Returns -1, 0 or -1 as a comparison result.
*/
function matchesSortCallback(m1, m2)
{
// sort matches by index first
if(m1.index < m2.index)
return -1;
else if(m1.index > m2.index)
return 1;
else
{
// if index is the same, sort by length
if(m1.length < m2.length)
return -1;
else if(m1.length > m2.length)
return 1;
}
return 0;
};
/**
* Executes given regular expression on provided code and returns all
* matches that are found.
*
* @param {String} code Code to execute regular expression on.
* @param {Object} regex Regular expression item info from <code>regexList</code> collection.
* @return {Array} Returns a list of Match objects.
*/
function getMatches(code, regexInfo)
{
function defaultAdd(match, regexInfo)
{
return match[0];
};
var index = 0,
match = null,
matches = [],
func = regexInfo.func ? regexInfo.func : defaultAdd
;
while((match = regexInfo.regex.exec(code)) != null)
{
var resultMatch = func(match, regexInfo);
if (typeof(resultMatch) == 'string')
resultMatch = [new sh.Match(resultMatch, match.index, regexInfo.css)];
matches = matches.concat(resultMatch);
}
return matches;
};
/**
* Turns all URLs in the code into <a/> tags.
* @param {String} code Input code.
* @return {String} Returns code with </a> tags.
*/
function processUrls(code)
{
var gt = /(.*)((&gt;|&lt;).*)/;
return code.replace(sh.regexLib.url, function(m)
{
var suffix = '',
match = null
;
// We include &lt; and &gt; in the URL for the common cases like <http://google.com>
// The problem is that they get transformed into &lt;http://google.com&gt;
// Where as &gt; easily looks like part of the URL string.
if (match = gt.exec(m))
{
m = match[1];
suffix = match[2];
}
return '<a href="' + m + '">' + m + '</a>' + suffix;
});
};
/**
* Finds all <SCRIPT TYPE="syntaxhighlighter" /> elementss.
* @return {Array} Returns array of all found SyntaxHighlighter tags.
*/
function getSyntaxHighlighterScriptTags()
{
var tags = document.getElementsByTagName('script'),
result = []
;
for (var i = 0; i < tags.length; i++)
if (tags[i].type == 'syntaxhighlighter')
result.push(tags[i]);
return result;
};
/**
* Strips <![CDATA[]]> from <SCRIPT /> content because it should be used
* there in most cases for XHTML compliance.
* @param {String} original Input code.
* @return {String} Returns code without leading <![CDATA[]]> tags.
*/
function stripCData(original)
{
var left = '<![CDATA[',
right = ']]>',
// for some reason IE inserts some leading blanks here
copy = trim(original),
changed = false,
leftLength = left.length,
rightLength = right.length
;
if (copy.indexOf(left) == 0)
{
copy = copy.substring(leftLength);
changed = true;
}
var copyLength = copy.length;
if (copy.indexOf(right) == copyLength - rightLength)
{
copy = copy.substring(0, copyLength - rightLength);
changed = true;
}
return changed ? copy : original;
};
/**
* Quick code mouse double click handler.
*/
function quickCodeHandler(e)
{
var target = e.target,
highlighterDiv = findParentElement(target, '.syntaxhighlighter'),
container = findParentElement(target, '.container'),
textarea = document.createElement('textarea'),
highlighter
;
if (!container || !highlighterDiv || findElement(container, 'textarea'))
return;
highlighter = getHighlighterById(highlighterDiv.id);
// add source class name
addClass(highlighterDiv, 'source');
// Have to go over each line and grab it's text, can't just do it on the
// container because Firefox loses all \n where as Webkit doesn't.
var lines = container.childNodes,
code = []
;
for (var i = 0; i < lines.length; i++)
code.push(lines[i].innerText || lines[i].textContent);
// using \r instead of \r or \r\n makes this work equally well on IE, FF and Webkit
code = code.join('\r');
// inject <textarea/> tag
textarea.appendChild(document.createTextNode(code));
container.appendChild(textarea);
// preselect all text
textarea.focus();
textarea.select();
// set up handler for lost focus
attachEvent(textarea, 'blur', function(e)
{
textarea.parentNode.removeChild(textarea);
removeClass(highlighterDiv, 'source');
});
};
/**
* Match object.
*/
sh.Match = function(value, index, css)
{
this.value = value;
this.index = index;
this.length = value.length;
this.css = css;
this.brushName = null;
};
sh.Match.prototype.toString = function()
{
return this.value;
};
/**
* Simulates HTML code with a scripting language embedded.
*
* @param {String} scriptBrushName Brush name of the scripting language.
*/
sh.HtmlScript = function(scriptBrushName)
{
var brushClass = findBrush(scriptBrushName),
scriptBrush,
xmlBrush = new sh.brushes.Xml(),
bracketsRegex = null,
ref = this,
methodsToExpose = 'getDiv getHtml init'.split(' ')
;
if (brushClass == null)
return;
scriptBrush = new brushClass();
for(var i = 0; i < methodsToExpose.length; i++)
// make a closure so we don't lose the name after i changes
(function() {
var name = methodsToExpose[i];
ref[name] = function()
{
return xmlBrush[name].apply(xmlBrush, arguments);
};
})();
if (scriptBrush.htmlScript == null)
{
alert(sh.config.strings.brushNotHtmlScript + scriptBrushName);
return;
}
xmlBrush.regexList.push(
{ regex: scriptBrush.htmlScript.code, func: process }
);
function offsetMatches(matches, offset)
{
for (var j = 0; j < matches.length; j++)
matches[j].index += offset;
}
function process(match, info)
{
var code = match.code,
matches = [],
regexList = scriptBrush.regexList,
offset = match.index + match.left.length,
htmlScript = scriptBrush.htmlScript,
result
;
// add all matches from the code
for (var i = 0; i < regexList.length; i++)
{
result = getMatches(code, regexList[i]);
offsetMatches(result, offset);
matches = matches.concat(result);
}
// add left script bracket
if (htmlScript.left != null && match.left != null)
{
result = getMatches(match.left, htmlScript.left);
offsetMatches(result, match.index);
matches = matches.concat(result);
}
// add right script bracket
if (htmlScript.right != null && match.right != null)
{
result = getMatches(match.right, htmlScript.right);
offsetMatches(result, match.index + match[0].lastIndexOf(match.right));
matches = matches.concat(result);
}
for (var j = 0; j < matches.length; j++)
matches[j].brushName = brushClass.brushName;
return matches;
}
};
/**
* Main Highlither class.
* @constructor
*/
sh.Highlighter = function()
{
// not putting any code in here because of the prototype inheritance
};
sh.Highlighter.prototype = {
/**
* Returns value of the parameter passed to the highlighter.
* @param {String} name Name of the parameter.
* @param {Object} defaultValue Default value.
* @return {Object} Returns found value or default value otherwise.
*/
getParam: function(name, defaultValue)
{
var result = this.params[name];
return toBoolean(result == null ? defaultValue : result);
},
/**
* Shortcut to document.createElement().
* @param {String} name Name of the element to create (DIV, A, etc).
* @return {HTMLElement} Returns new HTML element.
*/
create: function(name)
{
return document.createElement(name);
},
/**
* Applies all regular expression to the code and stores all found
* matches in the `this.matches` array.
* @param {Array} regexList List of regular expressions.
* @param {String} code Source code.
* @return {Array} Returns list of matches.
*/
findMatches: function(regexList, code)
{
var result = [];
if (regexList != null)
for (var i = 0; i < regexList.length; i++)
// BUG: length returns len+1 for array if methods added to prototype chain (oising@gmail.com)
if (typeof (regexList[i]) == "object")
result = result.concat(getMatches(code, regexList[i]));
// sort and remove nested the matches
return this.removeNestedMatches(result.sort(matchesSortCallback));
},
/**
* Checks to see if any of the matches are inside of other matches.
* This process would get rid of highligted strings inside comments,
* keywords inside strings and so on.
*/
removeNestedMatches: function(matches)
{
// Optimized by Jose Prado (http://joseprado.com)
for (var i = 0; i < matches.length; i++)
{
if (matches[i] === null)
continue;
var itemI = matches[i],
itemIEndPos = itemI.index + itemI.length
;
for (var j = i + 1; j < matches.length && matches[i] !== null; j++)
{
var itemJ = matches[j];
if (itemJ === null)
continue;
else if (itemJ.index > itemIEndPos)
break;
else if (itemJ.index == itemI.index && itemJ.length > itemI.length)
matches[i] = null;
else if (itemJ.index >= itemI.index && itemJ.index < itemIEndPos)
matches[j] = null;
}
}
return matches;
},
/**
* Creates an array containing integer line numbers starting from the 'first-line' param.
* @return {Array} Returns array of integers.
*/
figureOutLineNumbers: function(code)
{
var lines = [],
firstLine = parseInt(this.getParam('first-line'))
;
eachLine(code, function(line, index)
{
lines.push(index + firstLine);
});
return lines;
},
/**
* Determines if specified line number is in the highlighted list.
*/
isLineHighlighted: function(lineNumber)
{
var list = this.getParam('highlight', []);
if (typeof(list) != 'object' && list.push == null)
list = [ list ];
return indexOf(list, lineNumber.toString()) != -1;
},
/**
* Generates HTML markup for a single line of code while determining alternating line style.
* @param {Integer} lineNumber Line number.
* @param {String} code Line HTML markup.
* @return {String} Returns HTML markup.
*/
getLineHtml: function(lineIndex, lineNumber, code)
{
var classes = [
'line',
'number' + lineNumber,
'index' + lineIndex,
'alt' + (lineNumber % 2 == 0 ? 1 : 2).toString()
];
if (this.isLineHighlighted(lineNumber))
classes.push('highlighted');
if (lineNumber == 0)
classes.push('break');
return '<div class="' + classes.join(' ') + '">' + code + '</div>';
},
/**
* Generates HTML markup for line number column.
* @param {String} code Complete code HTML markup.
* @param {Array} lineNumbers Calculated line numbers.
* @return {String} Returns HTML markup.
*/
getLineNumbersHtml: function(code, lineNumbers)
{
var html = '',
count = splitLines(code).length,
firstLine = parseInt(this.getParam('first-line')),
pad = this.getParam('pad-line-numbers')
;
if (pad == true)
pad = (firstLine + count - 1).toString().length;
else if (isNaN(pad) == true)
pad = 0;
for (var i = 0; i < count; i++)
{
var lineNumber = lineNumbers ? lineNumbers[i] : firstLine + i,
code = lineNumber == 0 ? sh.config.space : padNumber(lineNumber, pad)
;
html += this.getLineHtml(i, lineNumber, code);
}
return html;
},
/**
* Splits block of text into individual DIV lines.
* @param {String} code Code to highlight.
* @param {Array} lineNumbers Calculated line numbers.
* @return {String} Returns highlighted code in HTML form.
*/
getCodeLinesHtml: function(html, lineNumbers)
{
html = trim(html);
var lines = splitLines(html),
padLength = this.getParam('pad-line-numbers'),
firstLine = parseInt(this.getParam('first-line')),
html = '',
brushName = this.getParam('brush')
;
for (var i = 0; i < lines.length; i++)
{
var line = lines[i],
indent = /^(&nbsp;|\s)+/.exec(line),
spaces = null,
lineNumber = lineNumbers ? lineNumbers[i] : firstLine + i;
;
if (indent != null)
{
spaces = indent[0].toString();
line = line.substr(spaces.length);
spaces = spaces.replace(' ', sh.config.space);
}
line = trim(line);
if (line.length == 0)
line = sh.config.space;
html += this.getLineHtml(
i,
lineNumber,
(spaces != null ? '<code class="' + brushName + ' spaces">' + spaces + '</code>' : '') + line
);
}
return html;
},
/**
* Returns HTML for the table title or empty string if title is null.
*/
getTitleHtml: function(title)
{
return title ? '<caption>' + title + '</caption>' : '';
},
/**
* Finds all matches in the source code.
* @param {String} code Source code to process matches in.
* @param {Array} matches Discovered regex matches.
* @return {String} Returns formatted HTML with processed mathes.
*/
getMatchesHtml: function(code, matches)
{
var pos = 0,
result = '',
brushName = this.getParam('brush', '')
;
function getBrushNameCss(match)
{
var result = match ? (match.brushName || brushName) : brushName;
return result ? result + ' ' : '';
};
// Finally, go through the final list of matches and pull the all
// together adding everything in between that isn't a match.
for (var i = 0; i < matches.length; i++)
{
var match = matches[i],
matchBrushName
;
if (match === null || match.length === 0)
continue;
matchBrushName = getBrushNameCss(match);
result += wrapLinesWithCode(code.substr(pos, match.index - pos), matchBrushName + 'plain')
+ wrapLinesWithCode(match.value, matchBrushName + match.css)
;
pos = match.index + match.length + (match.offset || 0);
}
// don't forget to add whatever's remaining in the string
result += wrapLinesWithCode(code.substr(pos), getBrushNameCss() + 'plain');
return result;
},
/**
* Generates HTML markup for the whole syntax highlighter.
* @param {String} code Source code.
* @return {String} Returns HTML markup.
*/
getHtml: function(code)
{
var html = '',
classes = [ 'syntaxhighlighter' ],
tabSize,
matches,
lineNumbers
;
// process light mode
if (this.getParam('light') == true)
this.params.toolbar = this.params.gutter = false;
className = 'syntaxhighlighter';
if (this.getParam('collapse') == true)
classes.push('collapsed');
if ((gutter = this.getParam('gutter')) == false)
classes.push('nogutter');
// add custom user style name
classes.push(this.getParam('class-name'));
// add brush alias to the class name for custom CSS
classes.push(this.getParam('brush'));
code = trimFirstAndLastLines(code)
.replace(/\r/g, ' ') // IE lets these buggers through
;
tabSize = this.getParam('tab-size');
// replace tabs with spaces
code = this.getParam('smart-tabs') == true
? processSmartTabs(code, tabSize)
: processTabs(code, tabSize)
;
// unindent code by the common indentation
code = unindent(code);
if (gutter)
lineNumbers = this.figureOutLineNumbers(code);
// find matches in the code using brushes regex list
matches = this.findMatches(this.regexList, code);
// processes found matches into the html
html = this.getMatchesHtml(code, matches);
// finally, split all lines so that they wrap well
html = this.getCodeLinesHtml(html, lineNumbers);
// finally, process the links
if (this.getParam('auto-links'))
html = processUrls(html);
if (typeof(navigator) != 'undefined' && navigator.userAgent && navigator.userAgent.match(/MSIE/))
classes.push('ie');
html =
'<div id="' + getHighlighterId(this.id) + '" class="' + classes.join(' ') + '">'
+ (this.getParam('toolbar') ? sh.toolbar.getHtml(this) : '')
+ '<table border="0" cellpadding="0" cellspacing="0">'
+ this.getTitleHtml(this.getParam('title'))
+ '<tbody>'
+ '<tr>'
+ (gutter ? '<td class="gutter">' + this.getLineNumbersHtml(code) + '</td>' : '')
+ '<td class="code">'
+ '<div class="container">'
+ html
+ '</div>'
+ '</td>'
+ '</tr>'
+ '</tbody>'
+ '</table>'
+ '</div>'
;
return html;
},
/**
* Highlights the code and returns complete HTML.
* @param {String} code Code to highlight.
* @return {Element} Returns container DIV element with all markup.
*/
getDiv: function(code)
{
if (code === null)
code = '';
this.code = code;
var div = this.create('div');
// create main HTML
div.innerHTML = this.getHtml(code);
// set up click handlers
if (this.getParam('toolbar'))
attachEvent(findElement(div, '.toolbar'), 'click', sh.toolbar.handler);
if (this.getParam('quick-code'))
attachEvent(findElement(div, '.code'), 'dblclick', quickCodeHandler);
return div;
},
/**
* Initializes the highlighter/brush.
*
* Constructor isn't used for initialization so that nothing executes during necessary
* `new SyntaxHighlighter.Highlighter()` call when setting up brush inheritence.
*
* @param {Hash} params Highlighter parameters.
*/
init: function(params)
{
this.id = guid();
// register this instance in the highlighters list
storeHighlighter(this);
// local params take precedence over defaults
this.params = merge(sh.defaults, params || {})
// process light mode
if (this.getParam('light') == true)
this.params.toolbar = this.params.gutter = false;
},
/**
* Converts space separated list of keywords into a regular expression string.
* @param {String} str Space separated keywords.
* @return {String} Returns regular expression string.
*/
getKeywords: function(str)
{
str = str
.replace(/^\s+|\s+$/g, '')
.replace(/\s+/g, '|')
;
return '\\b(?:' + str + ')\\b';
},
/**
* Makes a brush compatible with the `html-script` functionality.
* @param {Object} regexGroup Object containing `left` and `right` regular expressions.
*/
forHtmlScript: function(regexGroup)
{
this.htmlScript = {
left : { regex: regexGroup.left, css: 'script' },
right : { regex: regexGroup.right, css: 'script' },
code : new XRegExp(
"(?<left>" + regexGroup.left.source + ")" +
"(?<code>.*?)" +
"(?<right>" + regexGroup.right.source + ")",
"sgi"
)
};
}
}; // end of Highlighter
return sh;
}(); // end of anonymous function
// CommonJS
typeof(exports) != 'undefined' ? exports['SyntaxHighlighter'] = SyntaxHighlighter : null;
</script><script type="text/javascript">// (inc clojure-brush) ;; an improved SyntaxHighlighter brush for clojure
//
// Copyright (C) 2011 Andrew Brehaut
//
// Distributed under the Eclipse Public License, the same as Clojure.
//
// https://github.com/brehaut/inc-clojure-brush
//
// Written by Andrew Brehaut
// V0.9.1, November 2011
if (typeof net == "undefined") net = {};
if (!(net.brehaut)) net.brehaut = {};
net.brehaut.ClojureTools = (function (SH) {
"use strict";
// utiliies
if (!Object.create) Object.create = function object(o) {
function F() {};
F.prototype = o;
return new F();
};
// data
function Token(value, index, tag, length) {
this.value = value;
this.index = index;
this.length = length || value.length;
this.tag = tag;
this.secondary_tags = {};
}
// null_token exists so that LispNodes that have not had a closing tag attached
// can have a dummy token to simplify annotation
var null_token = new Token("", -1, "null", -1);
/* LispNodes are aggregate nodes for sexpressions.
*
*/
function LispNode(tag, children, opening) {
this.tag = tag; // current metadata for syntax inference
this.parent = null; // the parent expression
this.list = children; // all the child forms in order
this.opening = opening; // the token that opens this form.
this.closing = null_token; // the token that closes this form.
this.meta = null; // metadata nodes will be attached here if they are found
}
var null_lispnode = new LispNode("null", [], null_token);
function PrefixNode(tag, token, attached_node) {
this.tag = tag;
this.token = token;
this.attached_node = attached_node;
this.parent = null;
}
// tokenize
function tokenize(code) {
var tokens = [];
var tn = 0;
var zero = "0".charCodeAt(0);
var nine = "9".charCodeAt(0);
var lower_a = "a".charCodeAt(0);
var lower_f = "f".charCodeAt(0);
var upper_a = "A".charCodeAt(0);
var upper_f = "F".charCodeAt(0);
var dispatch = false; // have we just seen a # character?
// i tracks the start of the current window
// extent is the window for slicing
for (var i = 0,
extent = i,
j = code.length;
i < j && extent <= j;) {
var c = code[i];
// we care about capturing the whole token when dispatch is used, so back up the
// starting index by 1
if (dispatch) i--;
switch (c) {
// dispatch alters the value of the next thing read
case "#":
dispatch = true;
i++;
extent++;
continue;
case " ": // ignore whitespace
case "\t":
case "\n":
case "\r":
case ",":
extent++
break;
// simple terms
case "^":
case "`":
case ")":
case "[":
case "]":
case "}":
case "@":
tokens[tn++] = new Token(c, i, c, ++extent - i);
break;
case "'":
tokens[tn++] = new Token(code.slice(i, ++extent), i, dispatch ? "#'" : "'", extent - i);
break
case "(":
tokens[tn++] = new Token(code.slice(i, ++extent), i, "(", extent - i);
break;
case "{":
tokens[tn++] = new Token(code.slice(i, ++extent), i, dispatch ? "#{" : "{", extent - i);
break;
case "\\":
if (code.slice(i + 1, i + 8) === "newline") {
tokens[tn++] = new Token("\\newline", i, "value", 8);
extent = i + 9;
}
else if (code.slice(i + 1, i + 6) === "space") {
tokens[tn++] = new Token("\\space", i, "value", 6);
extent = i + 6;
}
else if (code.slice(i + 1, i + 4) === "tab") {
tokens[tn++] = new Token("\\tab", i, "value", 4);
extent = i + 5;
} // work around fun bug with &,>,< in character literals
else if (code.slice(i + 1, i + 6) === "&amp;") {
tokens[tn++] = new Token("\\&amp;", i, "value", 6);
extent = i + 6;
}
else if (code.slice(i + 1, i + 5) === "&lt;") {
tokens[tn++] = new Token("\\&lt;", i, "value", 5);
extent = i + 5;
}
else if (code.slice(i + 1, i + 5) === "&gt;") {
tokens[tn++] = new Token("\\&gt;", i, "value", 5);
extent = i + 5;
}
else {
extent += 2;
tokens[tn++] = new Token(code.slice(i, extent), i, "value", 2);
}
break;
case "~": // slice
if (code[i + 1] === "@") {
extent += 2;
tokens[tn++] = new Token(code.slice(i, extent), i, "splice", 2);
}
else {
tokens[tn++] = new Token(code.slice(i, ++extent), i, "unquote", 2);
}
break;
// complicated terms
case "\"": // strings and regexps
for (extent++; extent <= j; extent++) {
if (code[extent] === "\\") extent++;
else if (code[extent] === "\"") break;
}
tokens[tn++] = new Token(code.slice(i, ++extent), i, dispatch ? "regexp" : "string", extent - i);
break;
case ";":
for (; extent <= j && code[extent] !== "\n" && code[extent] !== "\r"; extent++);
tokens[tn++] = new Token(code.slice(i, ++extent), i, "comments", extent - i);
break;
case "+": // numbers; fall through to symbol for + and - not prefixing a number
case "-":
case "0":
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
// todo: exponents, hex
// http://my.safaribooksonline.com/9781449310387/14?reader=pf&readerfullscreen=&readerleftmenu=1
var c2 = code.charCodeAt(i + 1);
if (((c === "+" || c === "-") && (c2 >= zero && c2 <= nine)) // prefixes
|| (c !== "+" && c !== "-")) {
if (c === "+" || c === "-") extent++;
for (; extent <= j; extent++) {
var charCode = code.charCodeAt(extent);
if (charCode < zero || charCode > nine) break;
}
c = code[extent];
c2 = code.charCodeAt(extent + 1);
if ((c === "r" || c === "R" || c === "/" || c === ".") // interstitial characters
&& (c2 >= zero && c2 <= nine)) {
for (extent++; extent <= j; extent++) {
var charCode = code.charCodeAt(extent);
if (charCode < zero || charCode > nine) break;
}
}
c = code[extent];
c2 = code.charCodeAt(extent + 1);
if ((c === "x" || c === "X") &&
((c2 >= zero && c2 <= nine)
|| (c2 >= lower_a && c2 <= lower_f)
|| (c2 >= upper_a && c2 <= upper_f))) {
for (extent++; extent <= j; extent++) {
var charCode = code.charCodeAt(extent);
if (((charCode >= zero && charCode <= nine)
|| (charCode >= lower_a && charCode <= lower_f)
|| (charCode >= upper_a && charCode <= upper_f))) continue;
break;
}
}
c = code[extent];
c2 = code.charCodeAt(extent + 1);
if ((c === "e" || c === "E")
&& (c2 >= zero && c2 <= nine)) {
for (extent++; extent <= j; extent++) {
var charCode = code.charCodeAt(extent);
if (charCode < zero || charCode > nine) break;
}
}
c = code[extent];
if (c === "N" || c === "M") extent++;
tokens[tn++] = new Token(code.slice(i, extent), i, "value", extent - i);
break;
}
case "_":
if (dispatch && c === "_") {
tokens[tn++] = new Token(code.slice(i, ++extent), i, "skip", extent - i);
break;
} // if not a skip, fall through to symbols
// Allow just about any other symbol as a symbol. This is far more permissive than
// clojure actually allows, but should catch any weirdo crap that accidentally gets
// into the code.
default:
for (extent++; extent <= j; extent++) {
switch (code[extent]) {
case " ":
case "\t":
case "\n":
case "\r":
case "\\":
case ",":
case "{":
case "}":
case "(":
case ")":
case "[":
case "]":
case "^":
case "`":
case "@":
break;
case ";":
// theres a weird bug via syntax highligher that gives us escaped entities.
// need to watch out for these
if (code.slice(extent-3, extent+1) === "&lt;"
||code.slice(extent-3, extent+1) === "&gt;"
||code.slice(extent-4, extent+1) === "&amp;") {
continue;
}
break;
default:
continue;
}
break;
}
var value = code.slice(i, extent);
var tag = "symbol";
if (value[0] == ":") {
tag = "keyword";
}
else if (value === "true" || value === "false" || value === "nil") {
tag = "value";
}
tokens[tn++] = new Token(value, i, tag, extent - i);
}
dispatch = false;
i = extent;
}
return tokens;
}
function build_tree(tokens) {
var toplevel = {
list: [],
tag: "toplevel",
parent: null,
opening: null,
closing: null,
depth: -1
};
// loop variables hoisted out as semi globals to track position in token stream
var i = -1;
var j = tokens.length;
function parse_one(t) {
// ignore special tokens and forms that dont belong in the tree
for (; t && (t.tag === "comments" || t.tag === "invalid" || t.tag == "skip") && i < j; ) {
if (t.tag === "skip") {
t.tag = "preprocessor";
annotate_comment(parse_one(tokens[++i]));
}
t = tokens[++i];
}
if (!t) return {}; // hackity hack
switch (t.tag) {
case "{":
return build_aggregate(new LispNode("map", [], t), "}");
case "(":
return build_aggregate(new LispNode("list", [], t), ")");
case "#{":
return build_aggregate(new LispNode("set", [], t), "}");
case "[":
return build_aggregate(new LispNode("vector", [], t), "]");
case "'":
return new PrefixNode("quote", t, parse_one(tokens[++i]));
case "#'":
return new PrefixNode("varquote", t, parse_one(tokens[++i]));
case "@":
return new PrefixNode("deref", t, parse_one(tokens[++i]));
case "`":
return new PrefixNode("quasiquote", t, parse_one(tokens[++i]));
case "unquote":
return new PrefixNode("unquote", t, parse_one(tokens[++i]));
case "splice":
return new PrefixNode("splice", t, parse_one(tokens[++i]));
case "^":
t.tag = "meta";
var meta = parse_one(tokens[++i]);
var next = parse_one(tokens[++i]);
next.meta = meta;
return next;
}
return t;
}
// build_aggregate collects to ether sub forms for one aggregate for.
function build_aggregate(current, expected_closing) {
for (i++; i < j; i++) {
var t = tokens[i];
if (t.tag === "}" || t.tag === ")" || t.tag === "]") {
if (t.tag !== expected_closing) t.tag = "invalid";
current.closing = t;
if (expected_closing) return current;
}
var node = parse_one(t);
node.parent = current;
current.list[current.list.length] = node;
}
return current;
}
build_aggregate(toplevel, null);
return toplevel;
}
// annotation rules to apply to a form based on its head
var show_locals = true; // HACK. would rather not use a (semi)-global.
/* annotate_comment is a special case annotation.
* in addition to its role in styling specific forms, it is called by parse_one to
* ignore any forms skipped with #_
*/
function annotate_comment(exp) {
exp.tag = "comments";
if (exp.list) {
exp.opening.tag = "comments";
exp.closing.tag = "comments";
for (var i = 0; i < exp.list.length; i++) {
var child = exp.list[i];
if (child.list) {
annotate_comment(child);
}
if (child.attached_node) {
annotate_comment(child.attached_node);
}
else {
child.tag = "comments";
}
}
}
}
/* custom annotation rules are stored here */
var annotation_rules = {};
// this function is exposed to allow ad hoc extension of the customisation rules
function register_annotation_rule(names, rule) {
for (var i = 0; i < names.length; i++) {
annotation_rules[names[i]] = rule;
}
}
function annotate_destructuring (exp, scope) {
if (exp.list) {
if (exp.tag === "vector") {
for (var i = 0; i < exp.list.length; i++) {
annotate_destructuring(exp.list[i], scope);
}
}
else if (exp.tag === "map") {
for (var i = 0; i < exp.list.length; i += 2) {
var key = exp.list[i];
var val = exp.list[i + 1];
if (key.tag === "keyword" && val.tag === "vector") {
for (var ii = 0, jj = val.list.length; ii < jj; ii++) {
if (val.list[ii].tag !== "symbol") continue;
val.list[ii].tag = "variable";
scope[val.list[ii].value] = true;
}
}
else {
annotate_destructuring(key, scope);
annotate_expressions(val, scope);
}
}
}
}
else if (exp.tag === "symbol" && (exp.value !== "&" && exp.value !== "&amp;")){
exp.tag = "variable";
scope[exp.value] = true;
}
}
function _annotate_binding_vector (exp, scope) {
if (exp.tag !== "vector") return;
var bindings = exp.list;
if (bindings.length % 2 === 1) return;
for (var i = 0; i < bindings.length; i += 2) {
annotate_destructuring(bindings[i], scope);
annotate_expressions(bindings[i + 1], scope);
}
}
function annotate_binding (exp, scope) {
var bindings = exp.list[1];
if (!show_locals) return; // HACK
if (bindings) {
scope = Object.create(scope);
_annotate_binding_vector(bindings, scope);
}
for (var i = 2; i < exp.list.length; i++) {
annotate_expressions(exp.list[i], scope);
}
}
function _annotate_function_body (exp, scope, start_idx) {
var argvec = exp.list[start_idx];
if (argvec.tag !== "vector") return;
scope = Object.create(scope);
for (var i = 0, j = argvec.list.length; i < j; i++) {
annotate_destructuring(argvec.list[i], scope);
}
for (var i = start_idx, j = exp.list.length; i < j; i++) {
annotate_expressions(exp.list[i], scope);
}
}
function annotate_function (exp, scope) {
for (var i = 1, j = exp.list.length; i < j; i++) {
var child = exp.list[i];
if (child.tag === "vector") {
_annotate_function_body (exp, scope, i);
return;
}
else if (child.tag === "list") {
_annotate_function_body(child, scope, 0)
}
}
}
function annotate_letfn (exp, scope) {
scope = Object.create(scope);
var bindings = exp.list[1];
var fn;
for (var i = 0, j = bindings.list.length; i < j; i++) {
fn = bindings.list[i];
if (!fn.list[0]) continue;
fn.list[0].tag = "variable";
scope[fn.list[0].value] = true;
}
for (i = 0, j = bindings.list.length; i < j; i++) {
var fn = bindings.list[i];
annotate_function(fn, scope);
}
for (i = 2, j = exp.list.length; i < j; i++) {
annotate_expressions(exp.list[i], scope);
}
}
register_annotation_rule(
["comment"],
annotate_comment
);
register_annotation_rule(
["let", "when-let", "if-let", "binding", "doseq", "for", "dotimes", "let*"],
annotate_binding
);
register_annotation_rule(
["defn", "defn-", "fn", "bound-fn", "defmacro", "fn*", "defmethod"],
annotate_function
);
register_annotation_rule(
["letfn"],
annotate_letfn
);
// standard annotations
function _annotate_metadata_recursive(meta, scope) {
if (!meta) return;
if (meta.list !== undefined && meta.list !== null) {
for (var i = 0, j = meta.list.length; i < j; i++) {
meta.opening.secondary_tags.meta = true
meta.closing.secondary_tags.meta = true
_annotate_metadata_recursive(meta.list[i], scope);
}
}
else if (meta.attached_node) {
meta.token.secondary_tags.meta = true;
_annotate_metadata_recursive(meta.attached_node, scope);
}
else {
meta.secondary_tags.meta = true;
}
}
function annotate_metadata(exp) {
if (!(exp && exp.meta)) return;
var meta = exp.meta;
annotate_expressions(meta, {});
_annotate_metadata_recursive(meta, {});
}
function annotate_quoted(exp, scope) {
if (!exp) return;
if (exp.list !== undefined && exp.list !== null) {
for (var i = 0, j = exp.list.length; i < j; i++) {
exp.opening.secondary_tags.quoted = true
exp.closing.secondary_tags.quoted = true
annotate_quoted(exp.list[i], scope);
}
}
else if (exp.attached_node) {
if (exp.tag === "unquote" || exp.tag === "splice") return;
exp.token.secondary_tags.quoted = true;
annotate_quoted(exp.attached_node, scope);
}
else {
exp.secondary_tags.quoted = true;
}
}
function annotate_expressions(exp, scope) {
annotate_metadata(exp);
switch (exp.tag) {
case "toplevel":
for (var i = 0; i < exp.list.length; i++) {
annotate_expressions(exp.list[i], scope);
}
break;
case "list": // functions, macros, special forms, comments
var head = exp.list[0];
if (head) {
if (head.tag === "list" || head.tag === "vector"
|| head.tag === "map" || head.tag === "set") {
annotate_expressions(head, scope);
}
else if (head.attached_node) {
annotate_expressions(head.attached_node, scope);
}
else {
head.tag = (head.value.match(/(^\.)|(\.$)|[A-Z].*\//)
? "method"
: "function");
}
// apply specific rules
if (annotation_rules.hasOwnProperty(head.value)) {
annotation_rules[head.value](exp, scope);
}
else {
for (var i = 1; i < exp.list.length; i++) {
annotate_expressions(exp.list[i], scope);
}
}
}
else { // empty list
exp.opening.tag = "value";
exp.closing.tag = "value";
}
break;
case "vector": // data
case "map":
case "set":
for (var i = 0; i < exp.list.length; i++) {
annotate_expressions(exp.list[i], scope);
}
break;
case "symbol":
if (exp.value.match(/[A-Z].*\/[A-Z_]+/)) {
exp.tag = "constant";
}
else if (show_locals && scope[exp.value]) {
exp.tag = "variable";
}
else if (exp.tag === "symbol" && exp.value.match(/([A-Z].*\/)?[A-Z_]+/)) {
exp.tag = "type";
}
break;
case "quote":
case "quasiquote":
annotate_quoted(exp.attached_node, scope);
default:
if (exp.attached_node) annotate_expressions(exp.attached_node, scope);
}
}
// translation of tag to css:
var css_translation = {
"constant": "constants",
"keyword": "constants",
"method": "color1",
"type": "color3",
"function": "functions",
"string": "string",
"regexp": "string",
"value": "value",
"comments": "comments",
"symbol": "symbol",
"variable": "variable",
"splice": "preprocessor",
"unquote": "preprocessor",
"preprocessor": "preprocessor",
"meta": "preprocessor",
"'": "preprocessor",
"#'": "preprocessor",
"(": "plain",
")": "plain",
"{": "keyword",
"}": "keyword",
"#{": "keyword",
"[": "keyword",
"]": "keyword",
"invalid": "invalid",
"@": "plain"
};
function translate_tags_to_css(tokens) {
for (var i = 0, j = tokens.length; i < j; i++) {
var token = tokens[i];
token.css = css_translation[token.tag];
for (var k in token.secondary_tags) if (token.secondary_tags.hasOwnProperty(k))
token.css += " " + k ;
};
}
// create the new brush
SH.brushes.Clojure = function () {};
SH.brushes.Clojure.prototype = new SyntaxHighlighter.Highlighter();
SH.brushes.Clojure.prototype.findMatches = function find_matches (regexpList, code) {
// this is a nasty global hack. need to resolve this
if (this.params && this.params.locals) {
show_locals = this.params.locals === true || this.params.locals === "true";
}
else {
show_locals = true;
}
var tokens = tokenize(code);
annotate_expressions(build_tree(tokens), {});
translate_tags_to_css(tokens);
return tokens;
};
SH.brushes.Clojure.aliases = ['clojure', 'Clojure', 'clj'];
SH.brushes.Clojure.register_annotation_rule = register_annotation_rule;
return {
tokenize: tokenize,
build_tree: build_tree
};
})(SyntaxHighlighter);
</script><title>bigbrother -- Marginalia</title></head><body><table><tr><td class="docs"><div class="header"><h1 class="project-name"><a href="http://github.com/yogsototh/bigbrother">bigbrother</a></h1><h2 class="project-version">0.1.0-SNAPSHOT</h2><br /><p>Periodically send metrics</p>
</div><div class="dependencies"><h3>dependencies</h3><table><tr><td class="dep-name">org.clojure/clojure</td><td class="dotted"><hr /></td><td class="dep-version">1.6.0</td></tr><tr><td class="dep-name">org.clojure/data.json</td><td class="dotted"><hr /></td><td class="dep-version">0.2.5</td></tr><tr><td class="dep-name">org.clojure/tools.logging</td><td class="dotted"><hr /></td><td class="dep-version">0.3.1</td></tr><tr><td class="dep-name">org.clojure/algo.generic</td><td class="dotted"><hr /></td><td class="dep-version">0.1.2</td></tr><tr><td class="dep-name">org.clojure/test.check</td><td class="dotted"><hr /></td><td class="dep-version">0.7.0</td></tr><tr><td class="dep-name">riemann-clojure-client</td><td class="dotted"><hr /></td><td class="dep-version">0.3.2</td></tr><tr><td class="dep-name">overtone/at-at</td><td class="dotted"><hr /></td><td class="dep-version">1.2.0</td></tr></table></div></td><td class="codes" style="text-align: center; vertical-align: middle;color: #666;padding-right:20px"><br /><br /><br />(this space intentionally left almost blank)</td></tr><tr><td class="docs"><div class="toc"><a name="toc"><h3>namespaces</h3></a><ul><li><a href="#bigbrother.core">bigbrother.core</a></li><li><a href="#bigbrother.counter">bigbrother.counter</a></li><li><a href="#bigbrother.max-metrics">bigbrother.max-metrics</a></li><li><a href="#bigbrother.metrics">bigbrother.metrics</a></li><li><a href="#bigbrother.timer">bigbrother.timer</a></li></ul></div></td><td class="codes">&nbsp;</td></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#bigbrother.core" name="bigbrother.core"><h1 class="project-name">bigbrother.core</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs"><p>This file provide helpers to manage time spend in functions</p>
</td><td class="codes"><pre class="brush: clojure">(ns bigbrother.core
(:require [clojure.tools.logging :as log]
[clojure.data.json :as json]
[overtone.at-at :refer [every mk-pool]]
[riemann.client :as r]
[clojure.algo.generic.functor :refer [fmap]]
[bigbrother.timer :as timer]
[bigbrother.counter :as counter]
[bigbrother.metrics :as metrics]
[bigbrother.max-metrics :as max-metrics]))</pre></td></tr><tr><td class="docs"><p>Atoms</p>
</td><td class="codes"><pre class="brush: clojure">(def pool (atom nil)) ;; pool for async</pre></td></tr><tr><td class="docs"><p>pool for async</p>
</td><td class="codes"><pre class="brush: clojure">(def default-map (atom #{}))
(def riemann-conn (atom nil))
(def riemann-service (atom &quot;supercell&quot;))
(def level-by-key (atom nil))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(def n (atom 0)) ;; a number</pre></td></tr><tr><td class="docs"><p>a number</p>
</td><td class="codes"></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(def log-time timer/log-time)
(def log-counter counter/log-counter)
(def log-metric metrics/log-metric)
(def log-mmetric max-metrics/log-mmetric)</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn timer-loop-finished []
;; increment the number of loop
(swap! n inc)
(timer/finish-timer-loop)
(max-metrics/loop-finished)
(metrics/loop-finished)
(counter/loop-finished))</pre></td></tr><tr><td class="docs"><p>Starting the timer</p>
<p>---- aliases</p>
<p>Starting the timer</p>
</td><td class="codes"><pre class="brush: clojure">(defn big-brother-is-watching-you []
(timer/log-time :start))
(def telescreen-on big-brother-is-watching-you)</pre></td></tr><tr><td class="docs"><p>End the timer chrono</p>
<p>End the timer chrono</p>
</td><td class="codes"><pre class="brush: clojure">(def welcome-in-miniluv timer-loop-finished)
(def telescreen-off timer-loop-finished)</pre></td></tr><tr><td class="docs"><p><hr />
Riemann Warn Level</p>
</td><td class="codes"></td></tr><tr><td class="docs"><p>warn level between two numbers</p>
</td><td class="codes"><pre class="brush: clojure">(defn warn-level
[warn crit]
(fn [v] (cond (neg? v) &quot;critical&quot;
(&gt;= v crit) &quot;critical&quot;
(&gt;= v warn) &quot;warning&quot;
:else &quot;ok&quot;)))
(defn rev-warn-level
[warn crit]
(fn [v] (cond (&lt;= v crit) &quot;critical&quot;
(&lt;= v warn) &quot;warning&quot;
:else &quot;ok&quot;)))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn ok [] (fn [_] &quot;ok&quot;))
(defn warning [] (fn [_] &quot;warning&quot;))
(defn critical [] (fn [_] &quot;critical&quot;))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn- to-riemann-event [[k v]]
(when (number? v)
(let [lvl-fn (get @level-by-key k)
level (if lvl-fn (lvl-fn v) &quot;ok&quot;)]
{:service (str @riemann-service &quot; &quot; (name k) (subs (str k) 1))
:state level
:metric v})))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn send-to-riemann [m]
(let [result-map (into @default-map m)
metric-data {:service @riemann-service
:state &quot;ok&quot;}
events (remove nil? (map to-riemann-event result-map))
]
(when @riemann-conn
(r/send-events @riemann-conn events))))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn reset-accumulators! []
(counter/reset-acc!)
(metrics/reset-acc!)
(max-metrics/reset-acc!)
(timer/reset-acc!)
(reset! n 0))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn reset-all-atoms! []
(reset! timer/times [])
(reset! metrics/metrics {})
(reset! max-metrics/mmetrics {})
(reset! counter/counters {})
(reset-accumulators!))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn resume-map [nb-ms]
(let [n-by-sec (float (/ @n (/ nb-ms 1000)))
basic {:nb n-by-sec}]
(reduce into basic [(metrics/resume @n)
(max-metrics/resume)
(timer/resume)
(counter/resume nb-ms)])))</pre></td></tr><tr><td class="docs"><p>display the time at most every 10s</p>
</td><td class="codes"><pre class="brush: clojure">(defn display-time
[nb-ms]
(let [result (resume-map nb-ms)]
(log/info (json/write-str result))
(send-to-riemann result)
(reset-accumulators!)))</pre></td></tr><tr><td class="docs"><h2>init-metrics</h2>
<pre><code>init-map :: Map Keyword (v -&gt; ERROR_LEVEL)
</code></pre>
</td><td class="codes"><pre class="brush: clojure">(defn init-metrics
[init-map nb-ms-metrics riemann-host riemann-service-name]
(reset! default-map (reduce into {}
(map (fn [k] {k -1} )
(conj (keys init-map) :total))))
(reset! level-by-key init-map)
(reset! pool (mk-pool))
(reset! riemann-service riemann-service-name)
(when riemann-host
(reset! riemann-conn (r/tcp-client {:host riemann-host})))
(every nb-ms-metrics (fn [] (display-time nb-ms-metrics)) @pool))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#bigbrother.counter" name="bigbrother.counter"><h1 class="project-name">bigbrother.counter</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(ns bigbrother.counter
(:require
[clojure.algo.generic.functor :refer [fmap]]))</pre></td></tr><tr><td class="docs"><p><hr />
COUNTERS</p>
</td><td class="codes"></td></tr><tr><td class="docs"><h2>Monoid instance of `sumcounter`</h2>
<p>a sum time is a list of couple <code>{name nb}</code></p>
</td><td class="codes"><pre class="brush: clojure">(def empty-sumcounter {})
(defn add-sumcounter [st st2]
(merge-with + st st2))</pre></td></tr><tr><td class="docs"><p>Counters atoms</p>
</td><td class="codes"><pre class="brush: clojure">(def counters (atom {}))
(def sumcounters (atom empty-sumcounter))</pre></td></tr><tr><td class="docs"><p>Counters (the mean is given by default)</p>
<p>declare a specific counters (not time)</p>
<p>declare a specific counters (not time) and returns the first parameter</p>
</td><td class="codes"><pre class="brush: clojure">(defn- set-counter! [k v] (swap! counters add-sumcounter {k v}))
(defn log-counter
([k] (set-counter! k 1))
([k v] (set-counter! k v)))
(defn log-counter-&gt;
[x k v]
(log-counter k v)
x)</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn loop-finished []
;; aggreate sumcounter
(swap! sumcounters add-sumcounter @counters)
(reset! counters {}))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn reset-acc! []
(reset! sumcounters empty-sumcounter))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn resume [nb-ms]
(fmap #(float (/ % (/ nb-ms 1000))) @sumcounters))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#bigbrother.max-metrics" name="bigbrother.max-metrics"><h1 class="project-name">bigbrother.max-metrics</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(ns bigbrother.max-metrics)</pre></td></tr><tr><td class="docs"><p><hr />
Max Metrics</p>
</td><td class="codes"></td></tr><tr><td class="docs"><h2>Monoid instance of `maxmetrics`</h2>
<p>a sum time is a list of couple <code>{name metric-value}</code></p>
</td><td class="codes"><pre class="brush: clojure">(def empty-maxmetric {})
(defn add-maxmetrics [st st2]
(merge-with max st st2))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(def mmetrics (atom {})) ;; timestamps</pre></td></tr><tr><td class="docs"><p>timestamps</p>
</td><td class="codes"><pre class="brush: clojure">(def maxmetrics (atom empty-maxmetric)) ;; time spent by type</pre></td></tr><tr><td class="docs"><p>time spent by type</p>
</td><td class="codes"></td></tr><tr><td class="docs"><p>Max Metrics (metrics to do a max between them instead of a mean)</p>
<p>declare a specific max metrics (not time)</p>
<p>declare a specific max metrics (not time) and returns the first parameter</p>
</td><td class="codes"><pre class="brush: clojure">(defn- set-mmetric! [k v] (swap! mmetrics add-maxmetrics {k v}))
(defn log-mmetric
[k v]
(set-mmetric! k v))
(defn log-mmetric-&gt;
[x k v]
(log-mmetric k v)
x)</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn loop-finished []
;; aggreate maxmetrics
(swap! maxmetrics add-maxmetrics @mmetrics)
(reset! mmetrics {}))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn reset-acc! []
(reset! maxmetrics empty-maxmetric))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn resume [] @maxmetrics)</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#bigbrother.metrics" name="bigbrother.metrics"><h1 class="project-name">bigbrother.metrics</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(ns bigbrother.metrics
(:require [clojure.algo.generic.functor :refer [fmap]]))</pre></td></tr><tr><td class="docs"><p><hr />
Sum Metrics</p>
</td><td class="codes"></td></tr><tr><td class="docs"><h2>Monoid instance of `summetrics`</h2>
<p>a sum time is a list of couple <code>{name metric-value}</code></p>
</td><td class="codes"><pre class="brush: clojure">(def empty-summetric {})
(defn add-summetrics [st st2]
(merge-with + st st2))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(def metrics (atom {})) ;; timestamps</pre></td></tr><tr><td class="docs"><p>timestamps</p>
</td><td class="codes"><pre class="brush: clojure">(def summetrics (atom empty-summetric)) ;; time spent by type</pre></td></tr><tr><td class="docs"><p>time spent by type</p>
</td><td class="codes"></td></tr><tr><td class="docs"><p>Metrics (the mean is given by default)</p>
<p>declare a specific metrics (not time)</p>
<p>declare a specific metrics (not time) and returns the first parameter</p>
</td><td class="codes"><pre class="brush: clojure">(defn- set-metric! [k v] (swap! metrics add-summetrics {k v}))
(defn log-metric
[k v]
(set-metric! k v))
(defn log-metric-&gt;
[x k v]
(log-metric k v)
x)</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn loop-finished []
;; aggreate summetrics
(swap! summetrics add-summetrics @metrics)
(reset! metrics {}))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn reset-acc! []
(reset! summetrics empty-summetric))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn resume [n]
(fmap #(float (/ % n)) @summetrics))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#bigbrother.timer" name="bigbrother.timer"><h1 class="project-name">bigbrother.timer</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(ns bigbrother.timer)</pre></td></tr><tr><td class="docs"><p><hr />
TIMERS</p>
</td><td class="codes"></td></tr><tr><td class="docs"><h2>Monoid instance of `sumtimes`</h2>
<p>a sum time is a list of couple <code>[name [timespent nb]]</code></p>
</td><td class="codes"><pre class="brush: clojure">(defn ts-name [x] (first x))
(defn ts-timespent [x] (first (second x)))
(defn ts-nb [x] (second (second x)))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(def empty-sumtime [])
(defn- add-one-sumtime [st st2]
[(ts-name st) [(+ (ts-timespent st) (ts-timespent st2))
(+ (ts-nb st) (ts-nb st2))]])
(defn add-sumtimes [st st2]
(cond (empty? st) st2
(empty? st2) st
:else (map add-one-sumtime st st2)))
(defn fmap-sumtimes [f st]
(map (fn [v] [(first v) [(f (ts-timespent v))
(ts-nb v)]]) st))</pre></td></tr><tr><td class="docs"><p>Given a <code>sumtimes</code> returns a map <code>{key timespent}</code>'</p>
</td><td class="codes"><pre class="brush: clojure">(defn normalized-map-from-sumtimes
[st]
(reduce #(merge-with + %1 %2) {}
(map (fn [v] {(ts-name v)
(/ (ts-timespent v)
(ts-nb v))}) st)))</pre></td></tr><tr><td class="docs"><p>timers atoms</p>
</td><td class="codes"><pre class="brush: clojure">(def times (atom [])) ;; timestamps</pre></td></tr><tr><td class="docs"><p>timestamps</p>
</td><td class="codes"><pre class="brush: clojure">(def sumtimes (atom empty-sumtime)) ;; time spent by type</pre></td></tr><tr><td class="docs"><p>time spent by type</p>
</td><td class="codes"></td></tr><tr><td class="docs"><p>Timer</p>
<p>declare the action named <code>k</code> finished</p>
<p>declare the action named <code>k</code> finished and returned object <code>x</code></p>
</td><td class="codes"><pre class="brush: clojure">(defn- set-value! [k v] (swap! times conj [k v]))
(defn log-time
[k]
(set-value! k (System/nanoTime)))
(defn log-time-&gt;
[x k]
(log-time k)
x)</pre></td></tr><tr><td class="docs"><p>get time spent during one step</p>
</td><td class="codes"><pre class="brush: clojure">(defn- show-one-step
[x]
(if (&lt; (count x) 2)
{:nothing 0}
(let [from (second (first x))
k (first (second x))
to (second (second x))]
[k [(- to from) 1]])))</pre></td></tr><tr><td class="docs"><p>from a list of timestamp generate a sumtime</p>
</td><td class="codes"><pre class="brush: clojure">(defn timespent
[times-array]
(map show-one-step (partition 2 1 times-array)))</pre></td></tr><tr><td class="docs"><p>from a list of timestamp generate the total time spent</p>
</td><td class="codes"><pre class="brush: clojure">(defn total-time
[times-array]
(- (second (last times-array))
(second (first times-array))))</pre></td></tr><tr><td class="docs"><p>convert from nanoseconds to milliseconds</p>
</td><td class="codes"><pre class="brush: clojure">(defn to-milliseconds
[times-array]
(fmap-sumtimes #(float (/ % 1000000)) times-array))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn finish-timer-loop []
;; Convert actual timestamps to sumtimes and aggregate them
(if (&gt; (count @times) 1)
(let [difftime (timespent @times)
total (total-time @times)
res (to-milliseconds (conj difftime [:total [total 1]]))]
(swap! sumtimes add-sumtimes res)))
(reset! times []))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn reset-acc! []
(reset! sumtimes empty-sumtime))</pre></td></tr><tr><td class="docs">
</td><td class="codes"><pre class="brush: clojure">(defn resume []
(normalized-map-from-sumtimes @sumtimes))</pre></td></tr><tr><td class="spacer docs">&nbsp;</td><td class="codes" /></tr></table><div class="footer">Generated by <a href="https://github.com/gdeer81/marginalia">Marginalia</a>.&nbsp;&nbsp;Syntax highlighting provided by Alex Gorbatchev's <a href="http://alexgorbatchev.com/SyntaxHighlighter/">SyntaxHighlighter</a><div id="floating-toc"><ul><li class="floating-toc-li" id="floating-toc_bigbrother.core">bigbrother.core</li><li class="floating-toc-li" id="floating-toc_bigbrother.counter">bigbrother.counter</li><li class="floating-toc-li" id="floating-toc_bigbrother.max-metrics">bigbrother.max-metrics</li><li class="floating-toc-li" id="floating-toc_bigbrother.metrics">bigbrother.metrics</li><li class="floating-toc-li" id="floating-toc_bigbrother.timer">bigbrother.timer</li></ul></div></div><script type="text/javascript">SyntaxHighlighter.defaults['gutter'] = false;
SyntaxHighlighter.all();
// hackity hack
$(window).load(function() {
var ft = $("#floating-toc");
var ul = ft.find('ul');
var lis = ft.find('li');
var liHeight = $(lis.first()).height();
ul.css('margin', '0px');
ft.css('height', liHeight + 'px');
showNs = function(ns) {
var index = 0;
for(i in nsPositions.nss) {
if(ns == nsPositions.nss[i]) index = i;
}
if(index != lastNsIndex) {
lastNsIndex = index;
ul.animate({marginTop: (-1 * liHeight * index) + 'px'},
300);
}
}
var calcNsPositions = function() {
var hheight = $('.docs-header').first().height();
var nss = [];
var anchors = [];
var positions = [];
$.each(lis, function(i, el) {
var ns = $(el).attr('id').split('_')[1];
nss.push(ns);
var a = $("a[name='"+ns+"']");
anchors.push(a);
positions.push(a.offset().top - hheight);
// console.log(a.offset().top)
});
return {nss: nss, positions: positions};
}
var nsPositions = calcNsPositions();
// console.log(nsPositions)
var lastNsIndex = -1;
var $window = $(window);
var currentSection = function(nsp) {
var ps = nsp.positions;
var scroll = $window.scrollTop();
var nsIndex = -1;
for(var i = 0, length = ps.length; i < length; i++) {
if(ps[i] >= scroll) {
nsIndex = i-1;
break;
}
}
if(nsIndex == -1) {
if(scroll >= ps[0]) {
nsIndex = ps.length - 1;
} else {
nsIndex = 0;
}
}
return nsp.nss[nsIndex];
}
$(window).scroll(function(e) {
showNs(currentSection(nsPositions));
});
});
</script></body></html>