/ docs / uberdoc.html
uberdoc.html
   1  <!DOCTYPE html>
   2  <html><head><meta charset="utf-8" content="text/html" http-equiv="Content-Type" /><meta content="Django style templates for Clojure" name="description" /><style type="text/css">/**
   3   * SyntaxHighlighter
   4   * http://alexgorbatchev.com/SyntaxHighlighter
   5   *
   6   * SyntaxHighlighter is donationware. If you are using it, please donate.
   7   * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
   8   *
   9   * @version
  10   * 3.0.83 (July 02 2010)
  11   *
  12   * @copyright
  13   * Copyright (C) 2004-2010 Alex Gorbatchev.
  14   *
  15   * @license
  16   * Dual licensed under the MIT and GPL licenses.
  17   */
  18  .syntaxhighlighter a,
  19  .syntaxhighlighter div,
  20  .syntaxhighlighter code,
  21  .syntaxhighlighter table,
  22  .syntaxhighlighter table td,
  23  .syntaxhighlighter table tr,
  24  .syntaxhighlighter table tbody,
  25  .syntaxhighlighter table thead,
  26  .syntaxhighlighter table caption,
  27  .syntaxhighlighter textarea {
  28    -moz-border-radius: 0 0 0 0 !important;
  29    -webkit-border-radius: 0 0 0 0 !important;
  30    background: none !important;
  31    border: 0 !important;
  32    bottom: auto !important;
  33    float: none !important;
  34    height: auto !important;
  35    left: auto !important;
  36    line-height: 1.1em !important;
  37  /*  margin: 0 !important; */
  38    outline: 0 !important;
  39    overflow: visible !important;
  40    padding: 0 !important;
  41    position: static !important;
  42    right: auto !important;
  43    text-align: left !important;
  44    top: auto !important;
  45    vertical-align: baseline !important;
  46    width: auto !important;
  47    box-sizing: content-box !important;
  48    font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important;
  49    font-weight: normal !important;
  50    font-style: normal !important;
  51    min-height: inherit !important;
  52    min-height: auto !important;
  53  }
  54  
  55  .syntaxhighlighter {
  56  /*  width: 100% !important; */
  57    margin: 1em 0 1em 0 !important;
  58    position: relative !important;
  59    overflow: auto !important;
  60  }
  61  .syntaxhighlighter.source {
  62    overflow: hidden !important;
  63  }
  64  .syntaxhighlighter .bold {
  65    font-weight: bold !important;
  66  }
  67  .syntaxhighlighter .italic {
  68    font-style: italic !important;
  69  }
  70  .syntaxhighlighter .line {
  71    white-space: pre !important;
  72  }
  73  .syntaxhighlighter table {
  74  /*    width: 100% !important;*/
  75  }
  76  .syntaxhighlighter table caption {
  77    text-align: left !important;
  78    padding: .5em 0 0.5em 1em !important;
  79  }
  80  .syntaxhighlighter table td.code {
  81    width: 100% !important;
  82  }
  83  .syntaxhighlighter table td.code .container {
  84    position: relative !important;
  85  }
  86  .syntaxhighlighter table td.code .container textarea {
  87    box-sizing: border-box !important;
  88    position: absolute !important;
  89    left: 0 !important;
  90    top: 0 !important;
  91    width: 100% !important;
  92    height: 100% !important;
  93    border: none !important;
  94    background: white !important;
  95    padding-left: 1em !important;
  96    overflow: hidden !important;
  97    white-space: pre !important;
  98  }
  99  .syntaxhighlighter table td.gutter .line {
 100    text-align: right !important;
 101    padding: 0 0.5em 0 1em !important;
 102  }
 103  .syntaxhighlighter table td.code .line {
 104    padding: 0 1em !important;
 105  }
 106  .syntaxhighlighter.nogutter td.code .container textarea, .syntaxhighlighter.nogutter td.code .line {
 107    padding-left: 0em !important;
 108  }
 109  .syntaxhighlighter.show {
 110    display: block !important;
 111  }
 112  .syntaxhighlighter.collapsed table {
 113    display: none !important;
 114  }
 115  .syntaxhighlighter.collapsed .toolbar {
 116      display: none;
 117  /*  padding: 0.1em 0.8em 0em 0.8em !important;
 118    font-size: 1em !important;
 119    position: static !important;
 120    width: auto !important;
 121    height: auto !important;*/
 122  }
 123  .syntaxhighlighter.collapsed .toolbar span {
 124    display: inline !important;
 125    margin-right: 1em !important;
 126  }
 127  .syntaxhighlighter.collapsed .toolbar span a {
 128    padding: 0 !important;
 129    display: none !important;
 130  }
 131  .syntaxhighlighter.collapsed .toolbar span a.expandSource {
 132    display: inline !important;
 133  }
 134  .syntaxhighlighter .toolbar {
 135      display: none;
 136  /*  position: absolute !important;
 137    right: 1px !important;
 138    top: 1px !important;
 139    width: 11px !important;
 140    height: 11px !important;
 141    font-size: 10px !important;
 142    z-index: 10 !important;*/
 143  }
 144  .syntaxhighlighter .toolbar span.title {
 145    display: inline !important;
 146  }
 147  .syntaxhighlighter .toolbar a {
 148    display: block !important;
 149    text-align: center !important;
 150    text-decoration: none !important;
 151    padding-top: 1px !important;
 152  }
 153  .syntaxhighlighter .toolbar a.expandSource {
 154    display: none !important;
 155  }
 156  .syntaxhighlighter.ie {
 157    font-size: .9em !important;
 158    padding: 1px 0 1px 0 !important;
 159  }
 160  .syntaxhighlighter.ie .toolbar {
 161    line-height: 8px !important;
 162  }
 163  .syntaxhighlighter.ie .toolbar a {
 164    padding-top: 0px !important;
 165  }
 166  .syntaxhighlighter.printing .line.alt1 .content,
 167  .syntaxhighlighter.printing .line.alt2 .content,
 168  .syntaxhighlighter.printing .line.highlighted .number,
 169  .syntaxhighlighter.printing .line.highlighted.alt1 .content,
 170  .syntaxhighlighter.printing .line.highlighted.alt2 .content {
 171    background: none !important;
 172  }
 173  .syntaxhighlighter.printing .line .number {
 174    color: #bbbbbb !important;
 175  }
 176  .syntaxhighlighter.printing .line .content {
 177    color: black !important;
 178  }
 179  .syntaxhighlighter.printing .toolbar {
 180    display: none !important;
 181  }
 182  .syntaxhighlighter.printing a {
 183    text-decoration: none !important;
 184  }
 185  .syntaxhighlighter.printing .plain, .syntaxhighlighter.printing .plain a {
 186    color: black !important;
 187  }
 188  .syntaxhighlighter.printing .comments, .syntaxhighlighter.printing .comments a {
 189    color: #008200 !important;
 190  }
 191  .syntaxhighlighter.printing .string, .syntaxhighlighter.printing .string a {
 192    color: blue !important;
 193  }
 194  .syntaxhighlighter.printing .keyword {
 195    color: #006699 !important;
 196    font-weight: bold !important;
 197  }
 198  .syntaxhighlighter.printing .preprocessor {
 199    color: gray !important;
 200  }
 201  .syntaxhighlighter.printing .variable {
 202    color: #aa7700 !important;
 203  }
 204  .syntaxhighlighter.printing .value {
 205    color: #009900 !important;
 206  }
 207  .syntaxhighlighter.printing .functions {
 208    color: #ff1493 !important;
 209  }
 210  .syntaxhighlighter.printing .constants {
 211    color: #0066cc !important;
 212  }
 213  .syntaxhighlighter.printing .script {
 214    font-weight: bold !important;
 215  }
 216  .syntaxhighlighter.printing .color1, .syntaxhighlighter.printing .color1 a {
 217    color: gray !important;
 218  }
 219  .syntaxhighlighter.printing .color2, .syntaxhighlighter.printing .color2 a {
 220    color: #ff1493 !important;
 221  }
 222  .syntaxhighlighter.printing .color3, .syntaxhighlighter.printing .color3 a {
 223    color: red !important;
 224  }
 225  .syntaxhighlighter.printing .break, .syntaxhighlighter.printing .break a {
 226    color: black !important;
 227  }
 228  </style><style type="text/css">.syntaxhighlighter{overflow:hidden !important;}</style><style type="text/css">/**
 229   * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
 230   *
 231   * @version
 232   * 3.0.83 (July 02 2010)
 233   *
 234   * @copyright
 235   * Copyright (C) 2004-2010 Alex Gorbatchev.
 236   *
 237   * @license
 238   * Dual licensed under the MIT and GPL licenses.
 239   */
 240  .syntaxhighlighter {
 241    background-color: transparent !important;
 242  }
 243  .syntaxhighlighter .line.alt1 {
 244    background-color: transparent !important;
 245  }
 246  .syntaxhighlighter .line.alt2 {
 247    background-color: transparent !important;
 248  }
 249  .syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 {
 250    background-color: #c3defe !important;
 251  }
 252  .syntaxhighlighter .line.highlighted.number {
 253    color: white !important;
 254  }
 255  .syntaxhighlighter table caption {
 256    color: black !important;
 257  }
 258  .syntaxhighlighter .gutter {
 259    color: #787878 !important;
 260  }
 261  .syntaxhighlighter .gutter .line {
 262    border-right: 3px solid #d4d0c8 !important;
 263  }
 264  .syntaxhighlighter .gutter .line.highlighted {
 265    background-color: #d4d0c8 !important;
 266    color: white !important;
 267  }
 268  .syntaxhighlighter.printing .line .content {
 269    border: none !important;
 270  }
 271  .syntaxhighlighter.collapsed {
 272    overflow: visible !important;
 273  }
 274  .syntaxhighlighter.collapsed .toolbar {
 275    color: #3f5fbf !important;
 276    background: white !important;
 277    border: 1px solid #d4d0c8 !important;
 278  }
 279  .syntaxhighlighter.collapsed .toolbar a {
 280    color: #3f5fbf !important;
 281  }
 282  .syntaxhighlighter.collapsed .toolbar a:hover {
 283    color: #aa7700 !important;
 284  }
 285  .syntaxhighlighter .toolbar {
 286    color: #a0a0a0 !important;
 287    background: #d4d0c8 !important;
 288    border: none !important;
 289  }
 290  .syntaxhighlighter .toolbar a {
 291    color: #a0a0a0 !important;
 292  }
 293  .syntaxhighlighter .toolbar a:hover {
 294    color: red !important;
 295  }
 296  .syntaxhighlighter .plain, .syntaxhighlighter .plain a {
 297    color: black !important;
 298  }
 299  .syntaxhighlighter .comments, .syntaxhighlighter .comments a {
 300    color: #3f5fbf !important;
 301  }
 302  .syntaxhighlighter .string, .syntaxhighlighter .string a {
 303    color: #2a00ff !important;
 304  }
 305  .syntaxhighlighter .keyword {
 306    color: #7f0055 !important;
 307  }
 308  .syntaxhighlighter .preprocessor {
 309    color: #646464 !important;
 310  }
 311  .syntaxhighlighter .variable {
 312    color: #aa7700 !important;
 313  }
 314  .syntaxhighlighter .value {
 315    color: #009900 !important;
 316  }
 317  .syntaxhighlighter .functions {
 318    color: #ff1493 !important;
 319  }
 320  .syntaxhighlighter .constants {
 321    color: #0066cc !important;
 322  }
 323  .syntaxhighlighter .script {
 324    font-weight: bold !important;
 325    color: #7f0055 !important;
 326    background-color: none !important;
 327  }
 328  .syntaxhighlighter .color1, .syntaxhighlighter .color1 a {
 329    color: gray !important;
 330  }
 331  .syntaxhighlighter .color2, .syntaxhighlighter .color2 a {
 332    color: #ff1493 !important;
 333  }
 334  .syntaxhighlighter .color3, .syntaxhighlighter .color3 a {
 335    color: red !important;
 336  }
 337  
 338  .syntaxhighlighter .xml .keyword {
 339    color: #3f7f7f !important;
 340    font-weight: normal !important;
 341  }
 342  .syntaxhighlighter .xml .color1, .syntaxhighlighter .xml .color1 a {
 343    color: #7f007f !important;
 344  }
 345  .syntaxhighlighter .xml .string {
 346    font-style: italic !important;
 347    color: #2a00ff !important;
 348  }
 349  
 350  .clojure.syntaxhighlighter .invalid {
 351     background-color: #FAA !important;
 352  }
 353  
 354  .clojure.syntaxhighlighter .quoted {
 355      font-style: italic !important;
 356  }
 357  
 358  .syntaxhighlighter .clojure.variable,
 359  .syntaxhighlighter .clojure.symbol,
 360  .syntaxhighlighter .clojure.value
 361  {
 362      color: #006060 !important;
 363  }
 364  
 365  .syntaxhighlighter .clojure.string {
 366      color: #55B !important;
 367  }
 368  
 369  .syntaxhighlighter .clojure.functions {
 370      color: black !important;
 371  }
 372  
 373  .syntaxhighlighter .clojure.color1 {
 374      color: #666 !important;
 375  }
 376  
 377  .syntaxhighlighter .clojure.color3 {
 378      color: #900 !important;
 379  }
 380  
 381  .syntaxhighlighter .clojure.constants {
 382      color: #1A734D !important;
 383  }
 384  
 385  </style><style type="text/css">html{margin:0;padding:0;}h1{margin:0;padding:0;}h2{margin:0;padding:0;}h3{margin:0;padding:0;}h4{margin:0;padding: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-top:0;display:inline;margin-left:10px;}.toc-link{font-size:12px;margin-left:10px;color:#252519;text-decoration:none;}.toc-link:hover{color:#5050A6;}.toc h1{font-size:34px;margin:0;}.docs-header{border-bottom:dotted #aaa 1px;padding-bottom:10px;margin-bottom:25px;}.toc h1{font-size:24px;}.toc{border-bottom:solid #bbb 1px;margin-bottom:40px;}.toc ul{margin-left:20px;padding-left:0px;padding-top:0;margin-top:0;}.toc li{list-style-type:none;padding-left:0;}.dependencies{}.dependencies table{font-size:16px;width:99.99%;border:none;margin-left:20px;}.dependencies td{padding-right:20px;;white-space:nowrap;}.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;padding-left:0px;padding-top:0;margin-top:0;}.plugins li{list-style-type:none;padding-left:0;}.header p{margin-left:20px;}</style><style type="text/css">#floating-toc{position:fixed;top:10px;right:20px;height:20px;overflow:hidden;text-align:right;}#floating-toc li{list-style-type:none;margin:0;padding:0;}</style><style type="text/css">body{margin:0;padding:0;font-family:'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;;font-size:16px;color:#252519;background-color:#F5F5FF;}h1{font-size:20px;margin-top:0;}h2{font-size:18px;}h3{font-size:16px;}a.anchor{text-decoration:none;color:#252519;}a.anchor:hover{color:#5050A6;}table{border-spacing:0;border-bottom:solid #ddd 1px;;margin-bottom:10px;}code{display:inline;}p{margin-top:8px;}tr{margin:0px;padding:0px;}td.docs{width:410px;max-width:410px;vertical-align:top;margin:0px;padding-left:55px;padding-right:20px;border:none;background-color:#FFF;}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{display:block;padding:4px;}code{background-color:ghostWhite;border:solid #DEDEDE 1px;padding-left:3px;padding-right:3px;font-size:14px;}.syntaxhighlighter code{font-size:13px;}.footer{text-align:center;}</style><script type="text/javascript">/*! jQuery v1.7.1 jquery.com | jquery.org/license */
 386  (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.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
 387  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.elem;for(k=0;k<p.matches.length&&!c.isImmediatePropagationStopped();k++){r=p.matches[k];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=((f.event.special[r.origType]||{}).handle||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.POS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function()
 388  {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.length)=="number")for(i=0;i<r;i++)bn(k[i]);else bn(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bq=/alpha\([^)]*\)/i,br=/opacity=([^)]*)/,bs=/([A-Z]|^ms)/g,bt=/^-?\d+(?:px)?$/i,bu=/^-?\d/,bv=/^([\-+])=([\-+.\de]+)/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bv.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bC(a,b,d);f.swap(a,bw,function(){e=bC(a,b,d)});return e}},set:function(a,b){if(!bt.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cv(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cn.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=co.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cr||cs(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cp&&(cp=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cr||cs(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cp),cp=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
 389  </script><script type="text/javascript">//XRegExp 1.5.0 <xregexp.com> MIT License
 390  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"){p=m.replace.call(this,r,function(){if(q){arguments[0]=new String(arguments[0]);for(var v=0;v<q.length;v++){if(q[v]){arguments[0][q[v]]=arguments[v+1]}}}if(t&&r.global){r.lastIndex=arguments[arguments.length-2]+arguments[0].length}return s.apply(null,arguments)})}else{u=this+"";p=m.replace.call(u,r,function(){var v=arguments;return m.replace.call(s,c,function(x,w,A){if(w){switch(w){case"$":return"$";case"&":return v[0];case"`":return v[v.length-1].slice(0,v[v.length-2]);case"'":return v[v.length-1].slice(v[v.length-2]+v[0].length);default:var y="";w=+w;if(!w){return x}while(w>v.length-3){y=String.prototype.slice.call(w,-1)+y;w=Math.floor(w/10)}return(w?v[w]||"":"$")+y}}else{var z=+A;if(z<=v.length-3){return v[z]}z=q?l(q,A):-1;return z>-1?v[z+1]:x}})})}if(t&&r.global){r.lastIndex=0}return p};String.prototype.split=function(u,p){if(!XRegExp.isRegExp(u)){return m.split.apply(this,arguments)}var w=this+"",r=[],v=0,t,q;if(p===undefined||+p<0){p=Infinity}else{p=Math.floor(+p);if(!p){return[]}}u=XRegExp.copyAsGlobal(u);while(t=u.exec(w)){if(u.lastIndex>v){r.push(w.slice(v,t.index));if(t.length>1&&t.index<w.length){Array.prototype.push.apply(r,t.slice(1))}q=t[0].length;v=u.lastIndex;if(r.length>=p){break}}if(u.lastIndex===t.index){u.lastIndex++}}if(v===w.length){if(!m.test.call(u,"")||q){r.push("")}}else{r.push(w.slice(v))}return r.length>p?r.slice(0,p):r};function j(r,q){if(!XRegExp.isRegExp(r)){throw TypeError("type RegExp expected")}var p=r._xregexp;r=XRegExp(r.source,d(r)+(q||""));if(p){r._xregexp={source:p.source,captureNames:p.captureNames?p.captureNames.slice(0):null}}return r}function d(p){return(p.global?"g":"")+(p.ignoreCase?"i":"")+(p.multiline?"m":"")+(p.extended?"x":"")+(p.sticky?"y":"")}function o(v,u,w,p){var r=k.length,y,s,x;g=true;try{while(r--){x=k[r];if((w&x.scope)&&(!x.trigger||x.trigger.call(p))){x.pattern.lastIndex=u;s=x.pattern.exec(v);if(s&&s.index===u){y={output:x.handler.call(p,s,w),match:s};break}}}}catch(q){throw q}finally{g=false}return y}function l(s,q,r){if(Array.prototype.indexOf){return s.indexOf(q,r)}for(var p=r||0;p<s.length;p++){if(s[p]===q){return p}}return -1}XRegExp.addToken(/\(\?#[^)]*\)/,function(p){return m.test.call(n,p.input.slice(p.index+p[0].length))?"":"(?:)"});XRegExp.addToken(/\((?!\?)/,function(){this.captureNames.push(null);return"("});XRegExp.addToken(/\(\?<([$\w]+)>/,function(p){this.captureNames.push(p[1]);this.hasNamedCapture=true;return"("});XRegExp.addToken(/\\k<([\w$]+)>/,function(q){var p=l(this.captureNames,q[1]);return p>-1?"\\"+(p+1)+(isNaN(q.input.charAt(q.index+q[0].length))?"":"(?:)"):q[0]});XRegExp.addToken(/\[\^?]/,function(p){return p[0]==="[]"?"\\b\\B":"[\\s\\S]"});XRegExp.addToken(/^\(\?([imsx]+)\)/,function(p){this.setFlag(p[1]);return""});XRegExp.addToken(/(?:\s+|#.*)+/,function(p){return m.test.call(n,p.input.slice(p.index+p[0].length))?"":"(?:)"},XRegExp.OUTSIDE_CLASS,function(){return this.hasFlag("x")});XRegExp.addToken(/\./,function(){return"[\\s\\S]"},XRegExp.OUTSIDE_CLASS,function(){return this.hasFlag("s")})})();
 391  </script><script type="text/javascript">/**
 392   * SyntaxHighlighter
 393   * http://alexgorbatchev.com/SyntaxHighlighter
 394   *
 395   * SyntaxHighlighter is donationware. If you are using it, please donate.
 396   * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
 397   *
 398   * @version
 399   * 3.0.83 (July 02 2010)
 400   *
 401   * @copyright
 402   * Copyright (C) 2004-2010 Alex Gorbatchev.
 403   *
 404   * @license
 405   * Dual licensed under the MIT and GPL licenses.
 406   */
 407  //
 408  // Begin anonymous function. This is used to contain local scope variables without polutting global scope.
 409  //
 410  var SyntaxHighlighter = function() {
 411  
 412  // CommonJS
 413  if (typeof(require) != 'undefined' && typeof(XRegExp) == 'undefined')
 414  {
 415  	XRegExp = require('XRegExp').XRegExp;
 416  }
 417  
 418  // Shortcut object which will be assigned to the SyntaxHighlighter variable.
 419  // This is a shorthand for local reference in order to avoid long namespace
 420  // references to SyntaxHighlighter.whatever...
 421  var sh = {
 422  	defaults : {
 423  		/** Additional CSS class names to be added to highlighter elements. */
 424  		'class-name' : '',
 425  
 426  		/** First line number. */
 427  		'first-line' : 1,
 428  
 429  		/**
 430  		 * Pads line numbers. Possible values are:
 431  		 *
 432  		 *   false - don't pad line numbers.
 433  		 *   true  - automaticaly pad numbers with minimum required number of leading zeroes.
 434  		 *   [int] - length up to which pad line numbers.
 435  		 */
 436  		'pad-line-numbers' : false,
 437  
 438  		/** Lines to highlight. */
 439  		'highlight' : null,
 440  
 441  		/** Title to be displayed above the code block. */
 442  		'title' : null,
 443  
 444  		/** Enables or disables smart tabs. */
 445  		'smart-tabs' : true,
 446  
 447  		/** Gets or sets tab size. */
 448  		'tab-size' : 4,
 449  
 450  		/** Enables or disables gutter. */
 451  		'gutter' : true,
 452  
 453  		/** Enables or disables toolbar. */
 454  		'toolbar' : true,
 455  
 456  		/** Enables quick code copy and paste from double click. */
 457  		'quick-code' : true,
 458  
 459  		/** Forces code view to be collapsed. */
 460  		'collapse' : false,
 461  
 462  		/** Enables or disables automatic links. */
 463  		'auto-links' : true,
 464  
 465  		/** Gets or sets light mode. Equavalent to turning off gutter and toolbar. */
 466  		'light' : false,
 467  
 468  		'html-script' : false
 469  	},
 470  
 471  	config : {
 472  		space : '&nbsp;',
 473  
 474  		/** Enables use of <SCRIPT type="syntaxhighlighter" /> tags. */
 475  		useScriptTags : true,
 476  
 477  		/** Blogger mode flag. */
 478  		bloggerMode : false,
 479  
 480  		stripBrs : false,
 481  
 482  		/** Name of the tag that SyntaxHighlighter will automatically look for. */
 483  		tagName : 'pre',
 484  
 485  		strings : {
 486  			expandSource : 'expand source',
 487  			help : '?',
 488  			alert: 'SyntaxHighlighter\n\n',
 489  			noBrush : 'Can\'t find brush for: ',
 490  			brushNotHtmlScript : 'Brush wasn\'t configured for html-script option: ',
 491  
 492  			// this is populated by the build script
 493  			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>'
 494  		}
 495  	},
 496  
 497  	/** Internal 'global' variables. */
 498  	vars : {
 499  		discoveredBrushes : null,
 500  		highlighters : {}
 501  	},
 502  
 503  	/** This object is populated by user included external brush files. */
 504  	brushes : {},
 505  
 506  	/** Common regular expressions. */
 507  	regexLib : {
 508  		multiLineCComments			: /\/\*[\s\S]*?\*\//gm,
 509  		singleLineCComments			: /\/\/.*$/gm,
 510  		singleLinePerlComments		: /#.*$/gm,
 511  		doubleQuotedString			: /"([^\\"\n]|\\.)*"/g,
 512  		singleQuotedString			: /'([^\\'\n]|\\.)*'/g,
 513  		multiLineDoubleQuotedString	: new XRegExp('"([^\\\\"]|\\\\.)*"', 'gs'),
 514  		multiLineSingleQuotedString	: new XRegExp("'([^\\\\']|\\\\.)*'", 'gs'),
 515  		xmlComments					: /(&lt;|<)!--[\s\S]*?--(&gt;|>)/gm,
 516  		url							: /\w+:\/\/[\w-.\/?%&=:@;]*/g,
 517  
 518  		/** <?= ?> tags. */
 519  		phpScriptTags 				: { left: /(&lt;|<)\?=?/g, right: /\?(&gt;|>)/g },
 520  
 521  		/** <%= %> tags. */
 522  		aspScriptTags				: { left: /(&lt;|<)%=?/g, right: /%(&gt;|>)/g },
 523  
 524  		scriptScriptTags			: { left: /(&lt;|<)\s*script.*?(&gt;|>)/gi, right: /(&lt;|<)\/\s*script\s*(&gt;|>)/gi }
 525  	},
 526  
 527  	toolbar: {
 528  		/**
 529  		 * Generates HTML markup for the toolbar.
 530  		 * @param {Highlighter} highlighter Highlighter instance.
 531  		 * @return {String} Returns HTML markup.
 532  		 */
 533  		getHtml: function(highlighter)
 534  		{
 535  			var html = '<div class="toolbar">',
 536  				items = sh.toolbar.items,
 537  				list = items.list
 538  				;
 539  
 540  			function defaultGetHtml(highlighter, name)
 541  			{
 542  				return sh.toolbar.getButtonHtml(highlighter, name, sh.config.strings[name]);
 543  			};
 544  
 545  			for (var i = 0; i < list.length; i++)
 546  				html += (items[list[i]].getHtml || defaultGetHtml)(highlighter, list[i]);
 547  
 548  			html += '</div>';
 549  
 550  			return html;
 551  		},
 552  
 553  		/**
 554  		 * Generates HTML markup for a regular button in the toolbar.
 555  		 * @param {Highlighter} highlighter Highlighter instance.
 556  		 * @param {String} commandName		Command name that would be executed.
 557  		 * @param {String} label			Label text to display.
 558  		 * @return {String}					Returns HTML markup.
 559  		 */
 560  		getButtonHtml: function(highlighter, commandName, label)
 561  		{
 562  			return '<span><a href="#" class="toolbar_item'
 563  				+ ' command_' + commandName
 564  				+ ' ' + commandName
 565  				+ '">' + label + '</a></span>'
 566  				;
 567  		},
 568  
 569  		/**
 570  		 * Event handler for a toolbar anchor.
 571  		 */
 572  		handler: function(e)
 573  		{
 574  			var target = e.target,
 575  				className = target.className || ''
 576  				;
 577  
 578  			function getValue(name)
 579  			{
 580  				var r = new RegExp(name + '_(\\w+)'),
 581  					match = r.exec(className)
 582  					;
 583  
 584  				return match ? match[1] : null;
 585  			};
 586  
 587  			var highlighter = getHighlighterById(findParentElement(target, '.syntaxhighlighter').id),
 588  				commandName = getValue('command')
 589  				;
 590  
 591  			// execute the toolbar command
 592  			if (highlighter && commandName)
 593  				sh.toolbar.items[commandName].execute(highlighter);
 594  
 595  			// disable default A click behaviour
 596  			e.preventDefault();
 597  		},
 598  
 599  		/** Collection of toolbar items. */
 600  		items : {
 601  			// Ordered lis of items in the toolbar. Can't expect `for (var n in items)` to be consistent.
 602  			list: ['expandSource', 'help'],
 603  
 604  			expandSource: {
 605  				getHtml: function(highlighter)
 606  				{
 607  					if (highlighter.getParam('collapse') != true)
 608  						return '';
 609  
 610  					var title = highlighter.getParam('title');
 611  					return sh.toolbar.getButtonHtml(highlighter, 'expandSource', title ? title : sh.config.strings.expandSource);
 612  				},
 613  
 614  				execute: function(highlighter)
 615  				{
 616  					var div = getHighlighterDivById(highlighter.id);
 617  					removeClass(div, 'collapsed');
 618  				}
 619  			},
 620  
 621  			/** Command to display the about dialog window. */
 622  			help: {
 623  				execute: function(highlighter)
 624  				{
 625  					var wnd = popup('', '_blank', 500, 250, 'scrollbars=0'),
 626  						doc = wnd.document
 627  						;
 628  
 629  					doc.write(sh.config.strings.aboutDialog);
 630  					doc.close();
 631  					wnd.focus();
 632  				}
 633  			}
 634  		}
 635  	},
 636  
 637  	/**
 638  	 * Finds all elements on the page which should be processes by SyntaxHighlighter.
 639  	 *
 640  	 * @param {Object} globalParams		Optional parameters which override element's
 641  	 * 									parameters. Only used if element is specified.
 642  	 *
 643  	 * @param {Object} element	Optional element to highlight. If none is
 644  	 * 							provided, all elements in the current document
 645  	 * 							are returned which qualify.
 646  	 *
 647  	 * @return {Array}	Returns list of <code>{ target: DOMElement, params: Object }</code> objects.
 648  	 */
 649  	findElements: function(globalParams, element)
 650  	{
 651  		var elements = element ? [element] : toArray(document.getElementsByTagName(sh.config.tagName)),
 652  			conf = sh.config,
 653  			result = []
 654  			;
 655  
 656  		// support for <SCRIPT TYPE="syntaxhighlighter" /> feature
 657  		if (conf.useScriptTags)
 658  			elements = elements.concat(getSyntaxHighlighterScriptTags());
 659  
 660  		if (elements.length === 0)
 661  			return result;
 662  
 663  		for (var i = 0; i < elements.length; i++)
 664  		{
 665  			var item = {
 666  				target: elements[i],
 667  				// local params take precedence over globals
 668  				params: merge(globalParams, parseParams(elements[i].className))
 669  			};
 670  
 671  			if (item.params['brush'] == null)
 672  				continue;
 673  
 674  			result.push(item);
 675  		}
 676  
 677  		return result;
 678  	},
 679  
 680  	/**
 681  	 * Shorthand to highlight all elements on the page that are marked as
 682  	 * SyntaxHighlighter source code.
 683  	 *
 684  	 * @param {Object} globalParams		Optional parameters which override element's
 685  	 * 									parameters. Only used if element is specified.
 686  	 *
 687  	 * @param {Object} element	Optional element to highlight. If none is
 688  	 * 							provided, all elements in the current document
 689  	 * 							are highlighted.
 690  	 */
 691  	highlight: function(globalParams, element)
 692  	{
 693  		var elements = this.findElements(globalParams, element),
 694  			propertyName = 'innerHTML',
 695  			highlighter = null,
 696  			conf = sh.config
 697  			;
 698  
 699  		if (elements.length === 0)
 700  			return;
 701  
 702  		for (var i = 0; i < elements.length; i++)
 703  		{
 704  			var element = elements[i],
 705  				target = element.target,
 706  				params = element.params,
 707  				brushName = params.brush,
 708  				code
 709  				;
 710  
 711  			if (brushName == null)
 712  				continue;
 713  
 714  			// Instantiate a brush
 715  			if (params['html-script'] == 'true' || sh.defaults['html-script'] == true)
 716  			{
 717  				highlighter = new sh.HtmlScript(brushName);
 718  				brushName = 'htmlscript';
 719  			}
 720  			else
 721  			{
 722  				var brush = findBrush(brushName);
 723  
 724  				if (brush)
 725  					highlighter = new brush();
 726  				else
 727  					continue;
 728  			}
 729  
 730  			code = target[propertyName];
 731  
 732  			// remove CDATA from <SCRIPT/> tags if it's present
 733  			if (conf.useScriptTags)
 734  				code = stripCData(code);
 735  
 736  			// Inject title if the attribute is present
 737  			if ((target.title || '') != '')
 738  				params.title = target.title;
 739  
 740  			params['brush'] = brushName;
 741  			highlighter.init(params);
 742  			element = highlighter.getDiv(code);
 743  
 744  			// carry over ID
 745  			if ((target.id || '') != '')
 746  				element.id = target.id;
 747  
 748  			target.parentNode.replaceChild(element, target);
 749  		}
 750  	},
 751  
 752  	/**
 753  	 * Main entry point for the SyntaxHighlighter.
 754  	 * @param {Object} params Optional params to apply to all highlighted elements.
 755  	 */
 756  	all: function(params)
 757  	{
 758  		attachEvent(
 759  			window,
 760  			'load',
 761  			function() { sh.highlight(params); }
 762  		);
 763  	}
 764  }; // end of sh
 765  
 766  sh['all']			= sh.all;
 767  sh['highlight']		= sh.highlight;
 768  
 769  /**
 770   * Checks if target DOM elements has specified CSS class.
 771   * @param {DOMElement} target Target DOM element to check.
 772   * @param {String} className Name of the CSS class to check for.
 773   * @return {Boolean} Returns true if class name is present, false otherwise.
 774   */
 775  function hasClass(target, className)
 776  {
 777  	return target.className.indexOf(className) != -1;
 778  };
 779  
 780  /**
 781   * Adds CSS class name to the target DOM element.
 782   * @param {DOMElement} target Target DOM element.
 783   * @param {String} className New CSS class to add.
 784   */
 785  function addClass(target, className)
 786  {
 787  	if (!hasClass(target, className))
 788  		target.className += ' ' + className;
 789  };
 790  
 791  /**
 792   * Removes CSS class name from the target DOM element.
 793   * @param {DOMElement} target Target DOM element.
 794   * @param {String} className CSS class to remove.
 795   */
 796  function removeClass(target, className)
 797  {
 798  	target.className = target.className.replace(className, '');
 799  };
 800  
 801  /**
 802   * Converts the source to array object. Mostly used for function arguments and
 803   * lists returned by getElementsByTagName() which aren't Array objects.
 804   * @param {List} source Source list.
 805   * @return {Array} Returns array.
 806   */
 807  function toArray(source)
 808  {
 809  	var result = [];
 810  
 811  	for (var i = 0; i < source.length; i++)
 812  		result.push(source[i]);
 813  
 814  	return result;
 815  };
 816  
 817  /**
 818   * Splits block of text into lines.
 819   * @param {String} block Block of text.
 820   * @return {Array} Returns array of lines.
 821   */
 822  function splitLines(block)
 823  {
 824  	return block.split('\n');
 825  }
 826  
 827  /**
 828   * Generates HTML ID for the highlighter.
 829   * @param {String} highlighterId Highlighter ID.
 830   * @return {String} Returns HTML ID.
 831   */
 832  function getHighlighterId(id)
 833  {
 834  	var prefix = 'highlighter_';
 835  	return id.indexOf(prefix) == 0 ? id : prefix + id;
 836  };
 837  
 838  /**
 839   * Finds Highlighter instance by ID.
 840   * @param {String} highlighterId Highlighter ID.
 841   * @return {Highlighter} Returns instance of the highlighter.
 842   */
 843  function getHighlighterById(id)
 844  {
 845  	return sh.vars.highlighters[getHighlighterId(id)];
 846  };
 847  
 848  /**
 849   * Finds highlighter's DIV container.
 850   * @param {String} highlighterId Highlighter ID.
 851   * @return {Element} Returns highlighter's DIV element.
 852   */
 853  function getHighlighterDivById(id)
 854  {
 855  	return document.getElementById(getHighlighterId(id));
 856  };
 857  
 858  /**
 859   * Stores highlighter so that getHighlighterById() can do its thing. Each
 860   * highlighter must call this method to preserve itself.
 861   * @param {Highilghter} highlighter Highlighter instance.
 862   */
 863  function storeHighlighter(highlighter)
 864  {
 865  	sh.vars.highlighters[getHighlighterId(highlighter.id)] = highlighter;
 866  };
 867  
 868  /**
 869   * Looks for a child or parent node which has specified classname.
 870   * Equivalent to jQuery's $(container).find(".className")
 871   * @param {Element} target Target element.
 872   * @param {String} search Class name or node name to look for.
 873   * @param {Boolean} reverse If set to true, will go up the node tree instead of down.
 874   * @return {Element} Returns found child or parent element on null.
 875   */
 876  function findElement(target, search, reverse /* optional */)
 877  {
 878  	if (target == null)
 879  		return null;
 880  
 881  	var nodes			= reverse != true ? target.childNodes : [ target.parentNode ],
 882  		propertyToFind	= { '#' : 'id', '.' : 'className' }[search.substr(0, 1)] || 'nodeName',
 883  		expectedValue,
 884  		found
 885  		;
 886  
 887  	expectedValue = propertyToFind != 'nodeName'
 888  		? search.substr(1)
 889  		: search.toUpperCase()
 890  		;
 891  
 892  	// main return of the found node
 893  	if ((target[propertyToFind] || '').indexOf(expectedValue) != -1)
 894  		return target;
 895  
 896  	for (var i = 0; nodes && i < nodes.length && found == null; i++)
 897  		found = findElement(nodes[i], search, reverse);
 898  
 899  	return found;
 900  };
 901  
 902  /**
 903   * Looks for a parent node which has specified classname.
 904   * This is an alias to <code>findElement(container, className, true)</code>.
 905   * @param {Element} target Target element.
 906   * @param {String} className Class name to look for.
 907   * @return {Element} Returns found parent element on null.
 908   */
 909  function findParentElement(target, className)
 910  {
 911  	return findElement(target, className, true);
 912  };
 913  
 914  /**
 915   * Finds an index of element in the array.
 916   * @ignore
 917   * @param {Object} searchElement
 918   * @param {Number} fromIndex
 919   * @return {Number} Returns index of element if found; -1 otherwise.
 920   */
 921  function indexOf(array, searchElement, fromIndex)
 922  {
 923  	fromIndex = Math.max(fromIndex || 0, 0);
 924  
 925  	for (var i = fromIndex; i < array.length; i++)
 926  		if(array[i] == searchElement)
 927  			return i;
 928  
 929  	return -1;
 930  };
 931  
 932  /**
 933   * Generates a unique element ID.
 934   */
 935  function guid(prefix)
 936  {
 937  	return (prefix || '') + Math.round(Math.random() * 1000000).toString();
 938  };
 939  
 940  /**
 941   * Merges two objects. Values from obj2 override values in obj1.
 942   * Function is NOT recursive and works only for one dimensional objects.
 943   * @param {Object} obj1 First object.
 944   * @param {Object} obj2 Second object.
 945   * @return {Object} Returns combination of both objects.
 946   */
 947  function merge(obj1, obj2)
 948  {
 949  	var result = {}, name;
 950  
 951  	for (name in obj1)
 952  		result[name] = obj1[name];
 953  
 954  	for (name in obj2)
 955  		result[name] = obj2[name];
 956  
 957  	return result;
 958  };
 959  
 960  /**
 961   * Attempts to convert string to boolean.
 962   * @param {String} value Input string.
 963   * @return {Boolean} Returns true if input was "true", false if input was "false" and value otherwise.
 964   */
 965  function toBoolean(value)
 966  {
 967  	var result = { "true" : true, "false" : false }[value];
 968  	return result == null ? value : result;
 969  };
 970  
 971  /**
 972   * Opens up a centered popup window.
 973   * @param {String} url		URL to open in the window.
 974   * @param {String} name		Popup name.
 975   * @param {int} width		Popup width.
 976   * @param {int} height		Popup height.
 977   * @param {String} options	window.open() options.
 978   * @return {Window}			Returns window instance.
 979   */
 980  function popup(url, name, width, height, options)
 981  {
 982  	var x = (screen.width - width) / 2,
 983  		y = (screen.height - height) / 2
 984  		;
 985  
 986  	options +=	', left=' + x +
 987  				', top=' + y +
 988  				', width=' + width +
 989  				', height=' + height
 990  		;
 991  	options = options.replace(/^,/, '');
 992  
 993  	var win = window.open(url, name, options);
 994  	win.focus();
 995  	return win;
 996  };
 997  
 998  /**
 999   * Adds event handler to the target object.
1000   * @param {Object} obj		Target object.
1001   * @param {String} type		Name of the event.
1002   * @param {Function} func	Handling function.
1003   */
1004  function attachEvent(obj, type, func, scope)
1005  {
1006  	function handler(e)
1007  	{
1008  		e = e || window.event;
1009  
1010  		if (!e.target)
1011  		{
1012  			e.target = e.srcElement;
1013  			e.preventDefault = function()
1014  			{
1015  				this.returnValue = false;
1016  			};
1017  		}
1018  
1019  		func.call(scope || window, e);
1020  	};
1021  
1022  	if (obj.attachEvent)
1023  	{
1024  		obj.attachEvent('on' + type, handler);
1025  	}
1026  	else
1027  	{
1028  		obj.addEventListener(type, handler, false);
1029  	}
1030  };
1031  
1032  /**
1033   * Displays an alert.
1034   * @param {String} str String to display.
1035   */
1036  function alert(str)
1037  {
1038  	window.alert(sh.config.strings.alert + str);
1039  };
1040  
1041  /**
1042   * Finds a brush by its alias.
1043   *
1044   * @param {String} alias		Brush alias.
1045   * @param {Boolean} showAlert	Suppresses the alert if false.
1046   * @return {Brush}				Returns bursh constructor if found, null otherwise.
1047   */
1048  function findBrush(alias, showAlert)
1049  {
1050  	var brushes = sh.vars.discoveredBrushes,
1051  		result = null
1052  		;
1053  
1054  	if (brushes == null)
1055  	{
1056  		brushes = {};
1057  
1058  		// Find all brushes
1059  		for (var brush in sh.brushes)
1060  		{
1061  			var info = sh.brushes[brush],
1062  				aliases = info.aliases
1063  				;
1064  
1065  			if (aliases == null)
1066  				continue;
1067  
1068  			// keep the brush name
1069  			info.brushName = brush.toLowerCase();
1070  
1071  			for (var i = 0; i < aliases.length; i++)
1072  				brushes[aliases[i]] = brush;
1073  		}
1074  
1075  		sh.vars.discoveredBrushes = brushes;
1076  	}
1077  
1078  	result = sh.brushes[brushes[alias]];
1079  
1080  	if (result == null && showAlert != false)
1081  		alert(sh.config.strings.noBrush + alias);
1082  
1083  	return result;
1084  };
1085  
1086  /**
1087   * Executes a callback on each line and replaces each line with result from the callback.
1088   * @param {Object} str			Input string.
1089   * @param {Object} callback		Callback function taking one string argument and returning a string.
1090   */
1091  function eachLine(str, callback)
1092  {
1093  	var lines = splitLines(str);
1094  
1095  	for (var i = 0; i < lines.length; i++)
1096  		lines[i] = callback(lines[i], i);
1097  
1098  	return lines.join('\n');
1099  };
1100  
1101  /**
1102   * This is a special trim which only removes first and last empty lines
1103   * and doesn't affect valid leading space on the first line.
1104   *
1105   * @param {String} str   Input string
1106   * @return {String}      Returns string without empty first and last lines.
1107   */
1108  function trimFirstAndLastLines(str)
1109  {
1110  	return str.replace(/^[ ]*[\n]+|[\n]*[ ]*$/g, '');
1111  };
1112  
1113  /**
1114   * Parses key/value pairs into hash object.
1115   *
1116   * Understands the following formats:
1117   * - name: word;
1118   * - name: [word, word];
1119   * - name: "string";
1120   * - name: 'string';
1121   *
1122   * For example:
1123   *   name1: value; name2: [value, value]; name3: 'value'
1124   *
1125   * @param {String} str    Input string.
1126   * @return {Object}       Returns deserialized object.
1127   */
1128  function parseParams(str)
1129  {
1130  	var match,
1131  		result = {},
1132  		arrayRegex = new XRegExp("^\\[(?<values>(.*?))\\]$"),
1133  		regex = new XRegExp(
1134  			"(?<name>[\\w-]+)" +
1135  			"\\s*:\\s*" +
1136  			"(?<value>" +
1137  				"[\\w-%#]+|" +		// word
1138  				"\\[.*?\\]|" +		// [] array
1139  				'".*?"|' +			// "" string
1140  				"'.*?'" +			// '' string
1141  			")\\s*;?",
1142  			"g"
1143  		)
1144  		;
1145  
1146  	while ((match = regex.exec(str)) != null)
1147  	{
1148  		var value = match.value
1149  			.replace(/^['"]|['"]$/g, '') // strip quotes from end of strings
1150  			;
1151  
1152  		// try to parse array value
1153  		if (value != null && arrayRegex.test(value))
1154  		{
1155  			var m = arrayRegex.exec(value);
1156  			value = m.values.length > 0 ? m.values.split(/\s*,\s*/) : [];
1157  		}
1158  
1159  		result[match.name] = value;
1160  	}
1161  
1162  	return result;
1163  };
1164  
1165  /**
1166   * Wraps each line of the string into <code/> tag with given style applied to it.
1167   *
1168   * @param {String} str   Input string.
1169   * @param {String} css   Style name to apply to the string.
1170   * @return {String}      Returns input string with each line surrounded by <span/> tag.
1171   */
1172  function wrapLinesWithCode(str, css)
1173  {
1174  	if (str == null || str.length == 0 || str == '\n')
1175  		return str;
1176  
1177  	str = str.replace(/</g, '&lt;');
1178  
1179  	// Replace two or more sequential spaces with &nbsp; leaving last space untouched.
1180  	str = str.replace(/ {2,}/g, function(m)
1181  	{
1182  		var spaces = '';
1183  
1184  		for (var i = 0; i < m.length - 1; i++)
1185  			spaces += sh.config.space;
1186  
1187  		return spaces + ' ';
1188  	});
1189  
1190  	// Split each line and apply <span class="...">...</span> to them so that
1191  	// leading spaces aren't included.
1192  	if (css != null)
1193  		str = eachLine(str, function(line)
1194  		{
1195  			if (line.length == 0)
1196  				return '';
1197  
1198  			var spaces = '';
1199  
1200  			line = line.replace(/^(&nbsp;| )+/, function(s)
1201  			{
1202  				spaces = s;
1203  				return '';
1204  			});
1205  
1206  			if (line.length == 0)
1207  				return spaces;
1208  
1209  			return spaces + '<code class="' + css + '">' + line + '</code>';
1210  		});
1211  
1212  	return str;
1213  };
1214  
1215  /**
1216   * Pads number with zeros until it's length is the same as given length.
1217   *
1218   * @param {Number} number	Number to pad.
1219   * @param {Number} length	Max string length with.
1220   * @return {String}			Returns a string padded with proper amount of '0'.
1221   */
1222  function padNumber(number, length)
1223  {
1224  	var result = number.toString();
1225  
1226  	while (result.length < length)
1227  		result = '0' + result;
1228  
1229  	return result;
1230  };
1231  
1232  /**
1233   * Replaces tabs with spaces.
1234   *
1235   * @param {String} code		Source code.
1236   * @param {Number} tabSize	Size of the tab.
1237   * @return {String}			Returns code with all tabs replaces by spaces.
1238   */
1239  function processTabs(code, tabSize)
1240  {
1241  	var tab = '';
1242  
1243  	for (var i = 0; i < tabSize; i++)
1244  		tab += ' ';
1245  
1246  	return code.replace(/\t/g, tab);
1247  };
1248  
1249  /**
1250   * Replaces tabs with smart spaces.
1251   *
1252   * @param {String} code    Code to fix the tabs in.
1253   * @param {Number} tabSize Number of spaces in a column.
1254   * @return {String}        Returns code with all tabs replaces with roper amount of spaces.
1255   */
1256  function processSmartTabs(code, tabSize)
1257  {
1258  	var lines = splitLines(code),
1259  		tab = '\t',
1260  		spaces = ''
1261  		;
1262  
1263  	// Create a string with 1000 spaces to copy spaces from...
1264  	// It's assumed that there would be no indentation longer than that.
1265  	for (var i = 0; i < 50; i++)
1266  		spaces += '                    '; // 20 spaces * 50
1267  
1268  	// This function inserts specified amount of spaces in the string
1269  	// where a tab is while removing that given tab.
1270  	function insertSpaces(line, pos, count)
1271  	{
1272  		return line.substr(0, pos)
1273  			+ spaces.substr(0, count)
1274  			+ line.substr(pos + 1, line.length) // pos + 1 will get rid of the tab
1275  			;
1276  	};
1277  
1278  	// Go through all the lines and do the 'smart tabs' magic.
1279  	code = eachLine(code, function(line)
1280  	{
1281  		if (line.indexOf(tab) == -1)
1282  			return line;
1283  
1284  		var pos = 0;
1285  
1286  		while ((pos = line.indexOf(tab)) != -1)
1287  		{
1288  			// This is pretty much all there is to the 'smart tabs' logic.
1289  			// Based on the position within the line and size of a tab,
1290  			// calculate the amount of spaces we need to insert.
1291  			var spaces = tabSize - pos % tabSize;
1292  			line = insertSpaces(line, pos, spaces);
1293  		}
1294  
1295  		return line;
1296  	});
1297  
1298  	return code;
1299  };
1300  
1301  /**
1302   * Performs various string fixes based on configuration.
1303   */
1304  function fixInputString(str)
1305  {
1306  	var br = /<br\s*\/?>|&lt;br\s*\/?&gt;/gi;
1307  
1308  	if (sh.config.bloggerMode == true)
1309  		str = str.replace(br, '\n');
1310  
1311  	if (sh.config.stripBrs == true)
1312  		str = str.replace(br, '');
1313  
1314  	return str;
1315  };
1316  
1317  /**
1318   * Removes all white space at the begining and end of a string.
1319   *
1320   * @param {String} str   String to trim.
1321   * @return {String}      Returns string without leading and following white space characters.
1322   */
1323  function trim(str)
1324  {
1325  	return str.replace(/^\s+|\s+$/g, '');
1326  };
1327  
1328  /**
1329   * Unindents a block of text by the lowest common indent amount.
1330   * @param {String} str   Text to unindent.
1331   * @return {String}      Returns unindented text block.
1332   */
1333  function unindent(str)
1334  {
1335  	var lines = splitLines(fixInputString(str)),
1336  		indents = new Array(),
1337  		regex = /^\s*/,
1338  		min = 1000
1339  		;
1340  
1341  	// go through every line and check for common number of indents
1342  	for (var i = 0; i < lines.length && min > 0; i++)
1343  	{
1344  		var line = lines[i];
1345  
1346  		if (trim(line).length == 0)
1347  			continue;
1348  
1349  		var matches = regex.exec(line);
1350  
1351  		// In the event that just one line doesn't have leading white space
1352  		// we can't unindent anything, so bail completely.
1353  		if (matches == null)
1354  			return str;
1355  
1356  		min = Math.min(matches[0].length, min);
1357  	}
1358  
1359  	// trim minimum common number of white space from the begining of every line
1360  	if (min > 0)
1361  		for (var i = 0; i < lines.length; i++)
1362  			lines[i] = lines[i].substr(min);
1363  
1364  	return lines.join('\n');
1365  };
1366  
1367  /**
1368   * Callback method for Array.sort() which sorts matches by
1369   * index position and then by length.
1370   *
1371   * @param {Match} m1	Left object.
1372   * @param {Match} m2    Right object.
1373   * @return {Number}     Returns -1, 0 or -1 as a comparison result.
1374   */
1375  function matchesSortCallback(m1, m2)
1376  {
1377  	// sort matches by index first
1378  	if(m1.index < m2.index)
1379  		return -1;
1380  	else if(m1.index > m2.index)
1381  		return 1;
1382  	else
1383  	{
1384  		// if index is the same, sort by length
1385  		if(m1.length < m2.length)
1386  			return -1;
1387  		else if(m1.length > m2.length)
1388  			return 1;
1389  	}
1390  
1391  	return 0;
1392  };
1393  
1394  /**
1395   * Executes given regular expression on provided code and returns all
1396   * matches that are found.
1397   *
1398   * @param {String} code    Code to execute regular expression on.
1399   * @param {Object} regex   Regular expression item info from <code>regexList</code> collection.
1400   * @return {Array}         Returns a list of Match objects.
1401   */
1402  function getMatches(code, regexInfo)
1403  {
1404  	function defaultAdd(match, regexInfo)
1405  	{
1406  		return match[0];
1407  	};
1408  
1409  	var index = 0,
1410  		match = null,
1411  		matches = [],
1412  		func = regexInfo.func ? regexInfo.func : defaultAdd
1413  		;
1414  
1415  	while((match = regexInfo.regex.exec(code)) != null)
1416  	{
1417  		var resultMatch = func(match, regexInfo);
1418  
1419  		if (typeof(resultMatch) == 'string')
1420  			resultMatch = [new sh.Match(resultMatch, match.index, regexInfo.css)];
1421  
1422  		matches = matches.concat(resultMatch);
1423  	}
1424  
1425  	return matches;
1426  };
1427  
1428  /**
1429   * Turns all URLs in the code into <a/> tags.
1430   * @param {String} code Input code.
1431   * @return {String} Returns code with </a> tags.
1432   */
1433  function processUrls(code)
1434  {
1435  	var gt = /(.*)((&gt;|&lt;).*)/;
1436  
1437  	return code.replace(sh.regexLib.url, function(m)
1438  	{
1439  		var suffix = '',
1440  			match = null
1441  			;
1442  
1443  		// We include &lt; and &gt; in the URL for the common cases like <http://google.com>
1444  		// The problem is that they get transformed into &lt;http://google.com&gt;
1445  		// Where as &gt; easily looks like part of the URL string.
1446  
1447  		if (match = gt.exec(m))
1448  		{
1449  			m = match[1];
1450  			suffix = match[2];
1451  		}
1452  
1453  		return '<a href="' + m + '">' + m + '</a>' + suffix;
1454  	});
1455  };
1456  
1457  /**
1458   * Finds all <SCRIPT TYPE="syntaxhighlighter" /> elementss.
1459   * @return {Array} Returns array of all found SyntaxHighlighter tags.
1460   */
1461  function getSyntaxHighlighterScriptTags()
1462  {
1463  	var tags = document.getElementsByTagName('script'),
1464  		result = []
1465  		;
1466  
1467  	for (var i = 0; i < tags.length; i++)
1468  		if (tags[i].type == 'syntaxhighlighter')
1469  			result.push(tags[i]);
1470  
1471  	return result;
1472  };
1473  
1474  /**
1475   * Strips <![CDATA[]]> from <SCRIPT /> content because it should be used
1476   * there in most cases for XHTML compliance.
1477   * @param {String} original	Input code.
1478   * @return {String} Returns code without leading <![CDATA[]]> tags.
1479   */
1480  function stripCData(original)
1481  {
1482  	var left = '<![CDATA[',
1483  		right = ']]>',
1484  		// for some reason IE inserts some leading blanks here
1485  		copy = trim(original),
1486  		changed = false,
1487  		leftLength = left.length,
1488  		rightLength = right.length
1489  		;
1490  
1491  	if (copy.indexOf(left) == 0)
1492  	{
1493  		copy = copy.substring(leftLength);
1494  		changed = true;
1495  	}
1496  
1497  	var copyLength = copy.length;
1498  
1499  	if (copy.indexOf(right) == copyLength - rightLength)
1500  	{
1501  		copy = copy.substring(0, copyLength - rightLength);
1502  		changed = true;
1503  	}
1504  
1505  	return changed ? copy : original;
1506  };
1507  
1508  
1509  /**
1510   * Quick code mouse double click handler.
1511   */
1512  function quickCodeHandler(e)
1513  {
1514  	var target = e.target,
1515  		highlighterDiv = findParentElement(target, '.syntaxhighlighter'),
1516  		container = findParentElement(target, '.container'),
1517  		textarea = document.createElement('textarea'),
1518  		highlighter
1519  		;
1520  
1521  	if (!container || !highlighterDiv || findElement(container, 'textarea'))
1522  		return;
1523  
1524  	highlighter = getHighlighterById(highlighterDiv.id);
1525  
1526  	// add source class name
1527  	addClass(highlighterDiv, 'source');
1528  
1529  	// Have to go over each line and grab it's text, can't just do it on the
1530  	// container because Firefox loses all \n where as Webkit doesn't.
1531  	var lines = container.childNodes,
1532  		code = []
1533  		;
1534  
1535  	for (var i = 0; i < lines.length; i++)
1536  		code.push(lines[i].innerText || lines[i].textContent);
1537  
1538  	// using \r instead of \r or \r\n makes this work equally well on IE, FF and Webkit
1539  	code = code.join('\r');
1540  
1541  	// inject <textarea/> tag
1542  	textarea.appendChild(document.createTextNode(code));
1543  	container.appendChild(textarea);
1544  
1545  	// preselect all text
1546  	textarea.focus();
1547  	textarea.select();
1548  
1549  	// set up handler for lost focus
1550  	attachEvent(textarea, 'blur', function(e)
1551  	{
1552  		textarea.parentNode.removeChild(textarea);
1553  		removeClass(highlighterDiv, 'source');
1554  	});
1555  };
1556  
1557  /**
1558   * Match object.
1559   */
1560  sh.Match = function(value, index, css)
1561  {
1562  	this.value = value;
1563  	this.index = index;
1564  	this.length = value.length;
1565  	this.css = css;
1566  	this.brushName = null;
1567  };
1568  
1569  sh.Match.prototype.toString = function()
1570  {
1571  	return this.value;
1572  };
1573  
1574  /**
1575   * Simulates HTML code with a scripting language embedded.
1576   *
1577   * @param {String} scriptBrushName Brush name of the scripting language.
1578   */
1579  sh.HtmlScript = function(scriptBrushName)
1580  {
1581  	var brushClass = findBrush(scriptBrushName),
1582  		scriptBrush,
1583  		xmlBrush = new sh.brushes.Xml(),
1584  		bracketsRegex = null,
1585  		ref = this,
1586  		methodsToExpose = 'getDiv getHtml init'.split(' ')
1587  		;
1588  
1589  	if (brushClass == null)
1590  		return;
1591  
1592  	scriptBrush = new brushClass();
1593  
1594  	for(var i = 0; i < methodsToExpose.length; i++)
1595  		// make a closure so we don't lose the name after i changes
1596  		(function() {
1597  			var name = methodsToExpose[i];
1598  
1599  			ref[name] = function()
1600  			{
1601  				return xmlBrush[name].apply(xmlBrush, arguments);
1602  			};
1603  		})();
1604  
1605  	if (scriptBrush.htmlScript == null)
1606  	{
1607  		alert(sh.config.strings.brushNotHtmlScript + scriptBrushName);
1608  		return;
1609  	}
1610  
1611  	xmlBrush.regexList.push(
1612  		{ regex: scriptBrush.htmlScript.code, func: process }
1613  	);
1614  
1615  	function offsetMatches(matches, offset)
1616  	{
1617  		for (var j = 0; j < matches.length; j++)
1618  			matches[j].index += offset;
1619  	}
1620  
1621  	function process(match, info)
1622  	{
1623  		var code = match.code,
1624  			matches = [],
1625  			regexList = scriptBrush.regexList,
1626  			offset = match.index + match.left.length,
1627  			htmlScript = scriptBrush.htmlScript,
1628  			result
1629  			;
1630  
1631  		// add all matches from the code
1632  		for (var i = 0; i < regexList.length; i++)
1633  		{
1634  			result = getMatches(code, regexList[i]);
1635  			offsetMatches(result, offset);
1636  			matches = matches.concat(result);
1637  		}
1638  
1639  		// add left script bracket
1640  		if (htmlScript.left != null && match.left != null)
1641  		{
1642  			result = getMatches(match.left, htmlScript.left);
1643  			offsetMatches(result, match.index);
1644  			matches = matches.concat(result);
1645  		}
1646  
1647  		// add right script bracket
1648  		if (htmlScript.right != null && match.right != null)
1649  		{
1650  			result = getMatches(match.right, htmlScript.right);
1651  			offsetMatches(result, match.index + match[0].lastIndexOf(match.right));
1652  			matches = matches.concat(result);
1653  		}
1654  
1655  		for (var j = 0; j < matches.length; j++)
1656  			matches[j].brushName = brushClass.brushName;
1657  
1658  		return matches;
1659  	}
1660  };
1661  
1662  /**
1663   * Main Highlither class.
1664   * @constructor
1665   */
1666  sh.Highlighter = function()
1667  {
1668  	// not putting any code in here because of the prototype inheritance
1669  };
1670  
1671  sh.Highlighter.prototype = {
1672  	/**
1673  	 * Returns value of the parameter passed to the highlighter.
1674  	 * @param {String} name				Name of the parameter.
1675  	 * @param {Object} defaultValue		Default value.
1676  	 * @return {Object}					Returns found value or default value otherwise.
1677  	 */
1678  	getParam: function(name, defaultValue)
1679  	{
1680  		var result = this.params[name];
1681  		return toBoolean(result == null ? defaultValue : result);
1682  	},
1683  
1684  	/**
1685  	 * Shortcut to document.createElement().
1686  	 * @param {String} name		Name of the element to create (DIV, A, etc).
1687  	 * @return {HTMLElement}	Returns new HTML element.
1688  	 */
1689  	create: function(name)
1690  	{
1691  		return document.createElement(name);
1692  	},
1693  
1694  	/**
1695  	 * Applies all regular expression to the code and stores all found
1696  	 * matches in the `this.matches` array.
1697  	 * @param {Array} regexList		List of regular expressions.
1698  	 * @param {String} code			Source code.
1699  	 * @return {Array}				Returns list of matches.
1700  	 */
1701  	findMatches: function(regexList, code)
1702  	{
1703  		var result = [];
1704  
1705  		if (regexList != null)
1706  			for (var i = 0; i < regexList.length; i++)
1707  				// BUG: length returns len+1 for array if methods added to prototype chain (oising@gmail.com)
1708  				if (typeof (regexList[i]) == "object")
1709  					result = result.concat(getMatches(code, regexList[i]));
1710  
1711  		// sort and remove nested the matches
1712  		return this.removeNestedMatches(result.sort(matchesSortCallback));
1713  	},
1714  
1715  	/**
1716  	 * Checks to see if any of the matches are inside of other matches.
1717  	 * This process would get rid of highligted strings inside comments,
1718  	 * keywords inside strings and so on.
1719  	 */
1720  	removeNestedMatches: function(matches)
1721  	{
1722  		// Optimized by Jose Prado (http://joseprado.com)
1723  		for (var i = 0; i < matches.length; i++)
1724  		{
1725  			if (matches[i] === null)
1726  				continue;
1727  
1728  			var itemI = matches[i],
1729  				itemIEndPos = itemI.index + itemI.length
1730  				;
1731  
1732  			for (var j = i + 1; j < matches.length && matches[i] !== null; j++)
1733  			{
1734  				var itemJ = matches[j];
1735  
1736  				if (itemJ === null)
1737  					continue;
1738  				else if (itemJ.index > itemIEndPos)
1739  					break;
1740  				else if (itemJ.index == itemI.index && itemJ.length > itemI.length)
1741  					matches[i] = null;
1742  				else if (itemJ.index >= itemI.index && itemJ.index < itemIEndPos)
1743  					matches[j] = null;
1744  			}
1745  		}
1746  
1747  		return matches;
1748  	},
1749  
1750  	/**
1751  	 * Creates an array containing integer line numbers starting from the 'first-line' param.
1752  	 * @return {Array} Returns array of integers.
1753  	 */
1754  	figureOutLineNumbers: function(code)
1755  	{
1756  		var lines = [],
1757  			firstLine = parseInt(this.getParam('first-line'))
1758  			;
1759  
1760  		eachLine(code, function(line, index)
1761  		{
1762  			lines.push(index + firstLine);
1763  		});
1764  
1765  		return lines;
1766  	},
1767  
1768  	/**
1769  	 * Determines if specified line number is in the highlighted list.
1770  	 */
1771  	isLineHighlighted: function(lineNumber)
1772  	{
1773  		var list = this.getParam('highlight', []);
1774  
1775  		if (typeof(list) != 'object' && list.push == null)
1776  			list = [ list ];
1777  
1778  		return indexOf(list, lineNumber.toString()) != -1;
1779  	},
1780  
1781  	/**
1782  	 * Generates HTML markup for a single line of code while determining alternating line style.
1783  	 * @param {Integer} lineNumber	Line number.
1784  	 * @param {String} code Line	HTML markup.
1785  	 * @return {String}				Returns HTML markup.
1786  	 */
1787  	getLineHtml: function(lineIndex, lineNumber, code)
1788  	{
1789  		var classes = [
1790  			'line',
1791  			'number' + lineNumber,
1792  			'index' + lineIndex,
1793  			'alt' + (lineNumber % 2 == 0 ? 1 : 2).toString()
1794  		];
1795  
1796  		if (this.isLineHighlighted(lineNumber))
1797  		 	classes.push('highlighted');
1798  
1799  		if (lineNumber == 0)
1800  			classes.push('break');
1801  
1802  		return '<div class="' + classes.join(' ') + '">' + code + '</div>';
1803  	},
1804  
1805  	/**
1806  	 * Generates HTML markup for line number column.
1807  	 * @param {String} code			Complete code HTML markup.
1808  	 * @param {Array} lineNumbers	Calculated line numbers.
1809  	 * @return {String}				Returns HTML markup.
1810  	 */
1811  	getLineNumbersHtml: function(code, lineNumbers)
1812  	{
1813  		var html = '',
1814  			count = splitLines(code).length,
1815  			firstLine = parseInt(this.getParam('first-line')),
1816  			pad = this.getParam('pad-line-numbers')
1817  			;
1818  
1819  		if (pad == true)
1820  			pad = (firstLine + count - 1).toString().length;
1821  		else if (isNaN(pad) == true)
1822  			pad = 0;
1823  
1824  		for (var i = 0; i < count; i++)
1825  		{
1826  			var lineNumber = lineNumbers ? lineNumbers[i] : firstLine + i,
1827  				code = lineNumber == 0 ? sh.config.space : padNumber(lineNumber, pad)
1828  				;
1829  
1830  			html += this.getLineHtml(i, lineNumber, code);
1831  		}
1832  
1833  		return html;
1834  	},
1835  
1836  	/**
1837  	 * Splits block of text into individual DIV lines.
1838  	 * @param {String} code			Code to highlight.
1839  	 * @param {Array} lineNumbers	Calculated line numbers.
1840  	 * @return {String}				Returns highlighted code in HTML form.
1841  	 */
1842  	getCodeLinesHtml: function(html, lineNumbers)
1843  	{
1844  		html = trim(html);
1845  
1846  		var lines = splitLines(html),
1847  			padLength = this.getParam('pad-line-numbers'),
1848  			firstLine = parseInt(this.getParam('first-line')),
1849  			html = '',
1850  			brushName = this.getParam('brush')
1851  			;
1852  
1853  		for (var i = 0; i < lines.length; i++)
1854  		{
1855  			var line = lines[i],
1856  				indent = /^(&nbsp;|\s)+/.exec(line),
1857  				spaces = null,
1858  				lineNumber = lineNumbers ? lineNumbers[i] : firstLine + i;
1859  				;
1860  
1861  			if (indent != null)
1862  			{
1863  				spaces = indent[0].toString();
1864  				line = line.substr(spaces.length);
1865  				spaces = spaces.replace(' ', sh.config.space);
1866  			}
1867  
1868  			line = trim(line);
1869  
1870  			if (line.length == 0)
1871  				line = sh.config.space;
1872  
1873  			html += this.getLineHtml(
1874  				i,
1875  				lineNumber,
1876  				(spaces != null ? '<code class="' + brushName + ' spaces">' + spaces + '</code>' : '') + line
1877  			);
1878  		}
1879  
1880  		return html;
1881  	},
1882  
1883  	/**
1884  	 * Returns HTML for the table title or empty string if title is null.
1885  	 */
1886  	getTitleHtml: function(title)
1887  	{
1888  		return title ? '<caption>' + title + '</caption>' : '';
1889  	},
1890  
1891  	/**
1892  	 * Finds all matches in the source code.
1893  	 * @param {String} code		Source code to process matches in.
1894  	 * @param {Array} matches	Discovered regex matches.
1895  	 * @return {String} Returns formatted HTML with processed mathes.
1896  	 */
1897  	getMatchesHtml: function(code, matches)
1898  	{
1899  		var pos = 0,
1900  			result = '',
1901  			brushName = this.getParam('brush', '')
1902  			;
1903  
1904  		function getBrushNameCss(match)
1905  		{
1906  			var result = match ? (match.brushName || brushName) : brushName;
1907  			return result ? result + ' ' : '';
1908  		};
1909  
1910  		// Finally, go through the final list of matches and pull the all
1911  		// together adding everything in between that isn't a match.
1912  		for (var i = 0; i < matches.length; i++)
1913  		{
1914  			var match = matches[i],
1915  				matchBrushName
1916  				;
1917  
1918  			if (match === null || match.length === 0)
1919  				continue;
1920  
1921  			matchBrushName = getBrushNameCss(match);
1922  
1923  			result += wrapLinesWithCode(code.substr(pos, match.index - pos), matchBrushName + 'plain')
1924  					+ wrapLinesWithCode(match.value, matchBrushName + match.css)
1925  					;
1926  
1927  			pos = match.index + match.length + (match.offset || 0);
1928  		}
1929  
1930  		// don't forget to add whatever's remaining in the string
1931  		result += wrapLinesWithCode(code.substr(pos), getBrushNameCss() + 'plain');
1932  
1933  		return result;
1934  	},
1935  
1936  	/**
1937  	 * Generates HTML markup for the whole syntax highlighter.
1938  	 * @param {String} code Source code.
1939  	 * @return {String} Returns HTML markup.
1940  	 */
1941  	getHtml: function(code)
1942  	{
1943  		var html = '',
1944  			classes = [ 'syntaxhighlighter' ],
1945  			tabSize,
1946  			matches,
1947  			lineNumbers
1948  			;
1949  
1950  		// process light mode
1951  		if (this.getParam('light') == true)
1952  			this.params.toolbar = this.params.gutter = false;
1953  
1954  		className = 'syntaxhighlighter';
1955  
1956  		if (this.getParam('collapse') == true)
1957  			classes.push('collapsed');
1958  
1959  		if ((gutter = this.getParam('gutter')) == false)
1960  			classes.push('nogutter');
1961  
1962  		// add custom user style name
1963  		classes.push(this.getParam('class-name'));
1964  
1965  		// add brush alias to the class name for custom CSS
1966  		classes.push(this.getParam('brush'));
1967  
1968  		code = trimFirstAndLastLines(code)
1969  			.replace(/\r/g, ' ') // IE lets these buggers through
1970  			;
1971  
1972  		tabSize = this.getParam('tab-size');
1973  
1974  		// replace tabs with spaces
1975  		code = this.getParam('smart-tabs') == true
1976  			? processSmartTabs(code, tabSize)
1977  			: processTabs(code, tabSize)
1978  			;
1979  
1980  		// unindent code by the common indentation
1981  		code = unindent(code);
1982  
1983  		if (gutter)
1984  			lineNumbers = this.figureOutLineNumbers(code);
1985  
1986  		// find matches in the code using brushes regex list
1987  		matches = this.findMatches(this.regexList, code);
1988  		// processes found matches into the html
1989  		html = this.getMatchesHtml(code, matches);
1990  		// finally, split all lines so that they wrap well
1991  		html = this.getCodeLinesHtml(html, lineNumbers);
1992  
1993  		// finally, process the links
1994  		if (this.getParam('auto-links'))
1995  			html = processUrls(html);
1996  
1997  		if (typeof(navigator) != 'undefined' && navigator.userAgent && navigator.userAgent.match(/MSIE/))
1998  			classes.push('ie');
1999  
2000  		html =
2001  			'<div id="' + getHighlighterId(this.id) + '" class="' + classes.join(' ') + '">'
2002  				+ (this.getParam('toolbar') ? sh.toolbar.getHtml(this) : '')
2003  				+ '<table border="0" cellpadding="0" cellspacing="0">'
2004  					+ this.getTitleHtml(this.getParam('title'))
2005  					+ '<tbody>'
2006  						+ '<tr>'
2007  							+ (gutter ? '<td class="gutter">' + this.getLineNumbersHtml(code) + '</td>' : '')
2008  							+ '<td class="code">'
2009  								+ '<div class="container">'
2010  									+ html
2011  								+ '</div>'
2012  							+ '</td>'
2013  						+ '</tr>'
2014  					+ '</tbody>'
2015  				+ '</table>'
2016  			+ '</div>'
2017  			;
2018  
2019  		return html;
2020  	},
2021  
2022  	/**
2023  	 * Highlights the code and returns complete HTML.
2024  	 * @param {String} code     Code to highlight.
2025  	 * @return {Element}        Returns container DIV element with all markup.
2026  	 */
2027  	getDiv: function(code)
2028  	{
2029  		if (code === null)
2030  			code = '';
2031  
2032  		this.code = code;
2033  
2034  		var div = this.create('div');
2035  
2036  		// create main HTML
2037  		div.innerHTML = this.getHtml(code);
2038  
2039  		// set up click handlers
2040  		if (this.getParam('toolbar'))
2041  			attachEvent(findElement(div, '.toolbar'), 'click', sh.toolbar.handler);
2042  
2043  		if (this.getParam('quick-code'))
2044  			attachEvent(findElement(div, '.code'), 'dblclick', quickCodeHandler);
2045  
2046  		return div;
2047  	},
2048  
2049  	/**
2050  	 * Initializes the highlighter/brush.
2051  	 *
2052  	 * Constructor isn't used for initialization so that nothing executes during necessary
2053  	 * `new SyntaxHighlighter.Highlighter()` call when setting up brush inheritence.
2054  	 *
2055  	 * @param {Hash} params Highlighter parameters.
2056  	 */
2057  	init: function(params)
2058  	{
2059  		this.id = guid();
2060  
2061  		// register this instance in the highlighters list
2062  		storeHighlighter(this);
2063  
2064  		// local params take precedence over defaults
2065  		this.params = merge(sh.defaults, params || {})
2066  
2067  		// process light mode
2068  		if (this.getParam('light') == true)
2069  			this.params.toolbar = this.params.gutter = false;
2070  	},
2071  
2072  	/**
2073  	 * Converts space separated list of keywords into a regular expression string.
2074  	 * @param {String} str    Space separated keywords.
2075  	 * @return {String}       Returns regular expression string.
2076  	 */
2077  	getKeywords: function(str)
2078  	{
2079  		str = str
2080  			.replace(/^\s+|\s+$/g, '')
2081  			.replace(/\s+/g, '|')
2082  			;
2083  
2084  		return '\\b(?:' + str + ')\\b';
2085  	},
2086  
2087  	/**
2088  	 * Makes a brush compatible with the `html-script` functionality.
2089  	 * @param {Object} regexGroup Object containing `left` and `right` regular expressions.
2090  	 */
2091  	forHtmlScript: function(regexGroup)
2092  	{
2093  		this.htmlScript = {
2094  			left : { regex: regexGroup.left, css: 'script' },
2095  			right : { regex: regexGroup.right, css: 'script' },
2096  			code : new XRegExp(
2097  				"(?<left>" + regexGroup.left.source + ")" +
2098  				"(?<code>.*?)" +
2099  				"(?<right>" + regexGroup.right.source + ")",
2100  				"sgi"
2101  				)
2102  		};
2103  	}
2104  }; // end of Highlighter
2105  
2106  return sh;
2107  }(); // end of anonymous function
2108  
2109  // CommonJS
2110  typeof(exports) != 'undefined' ? exports['SyntaxHighlighter'] = SyntaxHighlighter : null;
2111  </script><script type="text/javascript">// (inc clojure-brush) ;; an improved SyntaxHighlighter brush for clojure
2112  //
2113  // Copyright (C) 2011 Andrew Brehaut
2114  //
2115  // Distributed under the Eclipse Public License, the same as Clojure.
2116  //
2117  // https://github.com/brehaut/inc-clojure-brush
2118  //
2119  // Written by Andrew Brehaut
2120  // V0.9.1, November 2011
2121  
2122  if (typeof net == "undefined") net = {};
2123  if (!(net.brehaut)) net.brehaut = {};
2124  
2125  net.brehaut.ClojureTools = (function (SH) {
2126    "use strict";
2127    // utiliies
2128    if (!Object.create) Object.create = function object(o) {
2129      function F() {};
2130      F.prototype = o;
2131      return new F();
2132    };
2133  
2134    // data
2135  
2136    function Token(value, index, tag, length) {
2137      this.value = value;
2138      this.index = index;
2139      this.length = length || value.length;
2140      this.tag = tag;
2141      this.secondary_tags = {};
2142    }
2143  
2144    // null_token exists so that LispNodes that have not had a closing tag attached
2145    // can have a dummy token to simplify annotation
2146    var null_token = new Token("", -1, "null", -1);
2147  
2148    /* LispNodes are aggregate nodes for sexpressions.
2149     *
2150     */
2151    function LispNode(tag, children, opening) {
2152      this.tag = tag;            // current metadata for syntax inference
2153      this.parent = null;        // the parent expression
2154      this.list = children;      // all the child forms in order
2155      this.opening = opening;    // the token that opens this form.
2156      this.closing = null_token; // the token that closes this form.
2157      this.meta = null;          // metadata nodes will be attached here if they are found
2158    }
2159  
2160    var null_lispnode = new LispNode("null", [], null_token);
2161  
2162  
2163    function PrefixNode(tag, token, attached_node) {
2164      this.tag = tag;
2165      this.token = token;
2166      this.attached_node = attached_node;
2167      this.parent = null;
2168    }
2169  
2170  
2171  
2172    // tokenize
2173  
2174    function tokenize(code) {
2175      var tokens = [];
2176      var tn = 0;
2177  
2178      var zero = "0".charCodeAt(0);
2179      var nine = "9".charCodeAt(0);
2180      var lower_a = "a".charCodeAt(0);
2181      var lower_f = "f".charCodeAt(0);
2182      var upper_a = "A".charCodeAt(0);
2183      var upper_f = "F".charCodeAt(0);
2184  
2185      var dispatch = false; // have we just seen a # character?
2186  
2187      // i tracks the start of the current window
2188      // extent is the window for slicing
2189  
2190      for (var i = 0,
2191               extent = i,
2192               j = code.length;
2193               i < j && extent <= j;) {
2194  
2195        var c = code[i];
2196  
2197        // we care about capturing the whole token when dispatch is used, so back up the
2198        // starting index by 1
2199        if (dispatch) i--;
2200  
2201        switch (c) {
2202          // dispatch alters the value of the next thing read
2203          case "#":
2204            dispatch = true;
2205            i++;
2206            extent++;
2207            continue;
2208  
2209          case " ":    // ignore whitespace
2210          case "\t":
2211          case "\n":
2212          case "\r":
2213          case ",":
2214            extent++
2215            break;
2216  
2217          // simple terms
2218          case "^":
2219          case "`":
2220          case ")":
2221          case "[":
2222          case "]":
2223          case "}":
2224          case "@":
2225            tokens[tn++] = new Token(c, i, c, ++extent - i);
2226            break;
2227  
2228          case "'":
2229            tokens[tn++] = new Token(code.slice(i, ++extent), i, dispatch ? "#'" : "'", extent - i);
2230            break
2231  
2232          case "(":
2233            tokens[tn++] = new Token(code.slice(i, ++extent), i, "(", extent - i);
2234            break;
2235  
2236          case "{":
2237            tokens[tn++] = new Token(code.slice(i, ++extent), i, dispatch ? "#{" : "{", extent - i);
2238            break;
2239  
2240          case "\\":
2241            if (code.slice(i + 1, i + 8) === "newline") {
2242              tokens[tn++] = new Token("\\newline", i, "value", 8);
2243              extent = i + 9;
2244            }
2245            else if (code.slice(i + 1, i + 6) === "space") {
2246              tokens[tn++] = new Token("\\space", i, "value", 6);
2247              extent = i + 6;
2248            }
2249            else if (code.slice(i + 1, i + 4) === "tab") {
2250              tokens[tn++] = new Token("\\tab", i, "value", 4);
2251              extent = i + 5;
2252            } // work around fun bug with &,>,< in character literals
2253            else if (code.slice(i + 1, i + 6) === "&amp;") {
2254              tokens[tn++] = new Token("\\&amp;", i, "value", 6);
2255              extent = i + 6;
2256            }
2257            else if (code.slice(i + 1, i + 5) === "&lt;") {
2258              tokens[tn++] = new Token("\\&lt;", i, "value", 5);
2259              extent = i + 5;
2260            }
2261            else if (code.slice(i + 1, i + 5) === "&gt;") {
2262              tokens[tn++] = new Token("\\&gt;", i, "value", 5);
2263              extent = i + 5;
2264            }
2265  
2266            else {
2267              extent += 2;
2268              tokens[tn++] = new Token(code.slice(i, extent), i, "value", 2);
2269            }
2270            break;
2271  
2272          case "~": // slice
2273            if (code[i + 1] === "@") {
2274              extent += 2;
2275              tokens[tn++] = new Token(code.slice(i, extent), i, "splice", 2);
2276            }
2277            else {
2278              tokens[tn++] = new Token(code.slice(i, ++extent), i, "unquote", 2);
2279            }
2280            break;
2281  
2282          // complicated terms
2283          case "\"": // strings and regexps
2284            for (extent++; extent <= j; extent++) {
2285              if (code[extent] === "\\") extent++;
2286              else if (code[extent] === "\"") break;
2287            }
2288            tokens[tn++] = new Token(code.slice(i, ++extent), i, dispatch ? "regexp" : "string", extent - i);
2289            break;
2290  
2291          case ";":
2292            for (; extent <= j && code[extent] !== "\n" && code[extent] !== "\r"; extent++);
2293            tokens[tn++] = new Token(code.slice(i, ++extent), i, "comments", extent - i);
2294            break;
2295  
2296          case "+": // numbers; fall through to symbol for + and - not prefixing a number
2297          case "-":
2298          case "0":
2299          case "1":
2300          case "2":
2301          case "3":
2302          case "4":
2303          case "5":
2304          case "6":
2305          case "7":
2306          case "8":
2307          case "9":
2308          // todo: exponents, hex
2309          // http://my.safaribooksonline.com/9781449310387/14?reader=pf&readerfullscreen=&readerleftmenu=1
2310            var c2 = code.charCodeAt(i + 1);
2311            if (((c === "+" || c === "-") && (c2 >= zero && c2 <= nine)) // prefixes
2312                || (c !== "+" && c !== "-")) {
2313              if (c === "+" || c === "-") extent++;
2314              for (; extent <= j; extent++) {
2315                var charCode = code.charCodeAt(extent);
2316                if (charCode < zero || charCode > nine) break;
2317              }
2318  
2319              c = code[extent];
2320              c2 = code.charCodeAt(extent + 1);
2321              if ((c === "r" || c === "R" || c === "/" || c === ".") // interstitial characters
2322                  && (c2 >= zero && c2 <= nine)) {
2323                for (extent++; extent <= j; extent++) {
2324                  var charCode = code.charCodeAt(extent);
2325                  if (charCode < zero || charCode > nine) break;
2326                }
2327              }
2328  
2329              c = code[extent];
2330              c2 = code.charCodeAt(extent + 1);
2331              if ((c === "x" || c === "X") &&
2332                  ((c2 >= zero && c2 <= nine)
2333                   || (c2 >= lower_a && c2 <= lower_f)
2334                   || (c2 >= upper_a && c2 <= upper_f))) {
2335                for (extent++; extent <= j; extent++) {
2336                  var charCode = code.charCodeAt(extent);
2337                  if (((charCode >= zero && charCode <= nine)
2338                      || (charCode >= lower_a && charCode <= lower_f)
2339                      || (charCode >= upper_a && charCode <= upper_f))) continue;
2340                  break;
2341                }
2342              }
2343  
2344              c = code[extent];
2345              c2 = code.charCodeAt(extent + 1);
2346              if ((c === "e" || c === "E")
2347                  && (c2 >= zero && c2 <= nine)) {
2348                for (extent++; extent <= j; extent++) {
2349                  var charCode = code.charCodeAt(extent);
2350                  if (charCode < zero || charCode > nine) break;
2351                }
2352              }
2353  
2354              c = code[extent];
2355              if (c === "N" || c === "M") extent++;
2356  
2357              tokens[tn++] = new Token(code.slice(i, extent), i, "value", extent - i);
2358              break;
2359            }
2360  
2361          case "_":
2362            if (dispatch && c === "_") {
2363              tokens[tn++] = new Token(code.slice(i, ++extent), i, "skip", extent - i);
2364              break;
2365            } // if not a skip, fall through to symbols
2366  
2367          // Allow just about any other symbol as a symbol. This is far more permissive than
2368          // clojure actually allows, but should catch any weirdo crap that accidentally gets
2369          // into the code.
2370          default:
2371            for (extent++; extent <= j; extent++) {
2372              switch (code[extent]) {
2373                case " ":
2374                case "\t":
2375                case "\n":
2376                case "\r":
2377                case "\\":
2378                case ",":
2379                case "{":
2380                case "}":
2381                case "(":
2382                case ")":
2383                case "[":
2384                case "]":
2385                case "^":
2386                case "`":
2387                case "@":
2388                  break;
2389                case ";":
2390                  // theres a weird bug via syntax highligher that gives us escaped entities.
2391                  // need to watch out for these
2392                  if (code.slice(extent-3, extent+1) === "&lt;"
2393                      ||code.slice(extent-3, extent+1) === "&gt;"
2394                      ||code.slice(extent-4, extent+1) === "&amp;") {
2395                    continue;
2396                  }
2397                  break;
2398                default:
2399                  continue;
2400              }
2401              break;
2402            }
2403  
2404            var value = code.slice(i, extent);
2405            var tag = "symbol";
2406            if (value[0] == ":") {
2407              tag = "keyword";
2408            }
2409            else if (value === "true" || value === "false" || value === "nil") {
2410              tag = "value";
2411            }
2412            tokens[tn++] = new Token(value, i, tag, extent - i);
2413        }
2414  
2415        dispatch = false;
2416        i = extent;
2417      }
2418  
2419      return tokens;
2420    }
2421  
2422  
2423    function build_tree(tokens) {
2424      var toplevel = {
2425        list: [],
2426        tag: "toplevel",
2427        parent: null,
2428        opening: null,
2429        closing: null,
2430        depth: -1
2431      };
2432  
2433      // loop variables hoisted out as semi globals to track position in token stream
2434      var i = -1;
2435      var j = tokens.length;
2436  
2437      function parse_one(t) {
2438        // ignore special tokens and forms that dont belong in the tree
2439        for (; t && (t.tag === "comments" || t.tag === "invalid" || t.tag == "skip") && i < j; ) {
2440          if (t.tag === "skip") {
2441            t.tag = "preprocessor";
2442            annotate_comment(parse_one(tokens[++i]));
2443          }
2444          t = tokens[++i];
2445        }
2446  
2447        if (!t) return {}; // hackity hack
2448  
2449        switch (t.tag) {
2450          case "{":
2451            return build_aggregate(new LispNode("map", [], t), "}");
2452          case "(":
2453            return build_aggregate(new LispNode("list", [], t), ")");
2454          case "#{":
2455            return build_aggregate(new LispNode("set", [], t), "}");
2456          case "[":
2457            return build_aggregate(new LispNode("vector", [], t), "]");
2458          case "'":
2459            return new PrefixNode("quote", t, parse_one(tokens[++i]));
2460          case "#'":
2461            return new PrefixNode("varquote", t, parse_one(tokens[++i]));
2462          case "@":
2463            return new PrefixNode("deref", t, parse_one(tokens[++i]));
2464          case "`":
2465            return new PrefixNode("quasiquote", t, parse_one(tokens[++i]));
2466          case "unquote":
2467            return new PrefixNode("unquote", t, parse_one(tokens[++i]));
2468          case "splice":
2469            return new PrefixNode("splice", t, parse_one(tokens[++i]));
2470          case "^":
2471            t.tag = "meta";
2472            var meta = parse_one(tokens[++i]);
2473            var next = parse_one(tokens[++i]);
2474            next.meta = meta;
2475            return next;
2476        }
2477  
2478        return t;
2479      }
2480  
2481      // build_aggregate collects to ether sub forms for one aggregate for.
2482      function build_aggregate(current, expected_closing) {
2483        for (i++; i < j; i++) {
2484          var t = tokens[i];
2485  
2486          if (t.tag === "}" || t.tag === ")" || t.tag === "]") {
2487            if (t.tag !== expected_closing) t.tag = "invalid";
2488            current.closing = t;
2489            if (expected_closing) return current;
2490          }
2491          var node = parse_one(t);
2492  
2493          node.parent = current;
2494          current.list[current.list.length] = node;
2495        }
2496  
2497        return current;
2498      }
2499  
2500      build_aggregate(toplevel, null);
2501  
2502      return toplevel;
2503    }
2504  
2505    // annotation rules to apply to a form based on its head
2506  
2507    var show_locals = true;  // HACK. would rather not use a (semi)-global.
2508  
2509    /* annotate_comment is a special case annotation.
2510     * in addition to its role in styling specific forms, it is called by parse_one to
2511     * ignore any forms skipped with #_
2512     */
2513    function annotate_comment(exp) {
2514      exp.tag = "comments";
2515  
2516      if (exp.list) {
2517        exp.opening.tag = "comments";
2518        exp.closing.tag = "comments";
2519  
2520        for (var i = 0; i < exp.list.length; i++) {
2521          var child = exp.list[i];
2522          if (child.list) {
2523            annotate_comment(child);
2524          }
2525          if (child.attached_node) {
2526            annotate_comment(child.attached_node);
2527          }
2528          else {
2529            child.tag = "comments";
2530          }
2531        }
2532      }
2533    }
2534  
2535    /* custom annotation rules are stored here */
2536    var annotation_rules = {};
2537  
2538    // this function is exposed to allow ad hoc extension of the customisation rules
2539    function register_annotation_rule(names, rule) {
2540      for (var i = 0; i < names.length; i++) {
2541        annotation_rules[names[i]] = rule;
2542      }
2543    }
2544  
2545  
2546    function annotate_destructuring (exp, scope) {
2547      if (exp.list) {
2548        if (exp.tag === "vector") {
2549          for (var i = 0; i < exp.list.length; i++) {
2550            annotate_destructuring(exp.list[i], scope);
2551          }
2552        }
2553        else if (exp.tag === "map") {
2554          for (var i = 0; i < exp.list.length; i += 2) {
2555            var key = exp.list[i];
2556            var val = exp.list[i + 1];
2557  
2558            if (key.tag === "keyword" && val.tag === "vector") {
2559              for (var ii = 0, jj = val.list.length; ii < jj; ii++) {
2560                if (val.list[ii].tag !== "symbol") continue;
2561                val.list[ii].tag = "variable";
2562                scope[val.list[ii].value] = true;
2563              }
2564            }
2565            else {
2566              annotate_destructuring(key, scope);
2567              annotate_expressions(val, scope);
2568            }
2569          }
2570        }
2571      }
2572      else if (exp.tag === "symbol" && (exp.value !== "&" && exp.value !== "&amp;")){
2573        exp.tag = "variable";
2574        scope[exp.value] = true;
2575      }
2576    }
2577  
2578    function _annotate_binding_vector (exp, scope) {
2579      if (exp.tag !== "vector") return;
2580  
2581      var bindings = exp.list;
2582  
2583      if (bindings.length % 2 === 1) return;
2584  
2585      for (var i = 0; i < bindings.length; i += 2) {
2586        annotate_destructuring(bindings[i], scope);
2587        annotate_expressions(bindings[i + 1], scope);
2588      }
2589    }
2590  
2591    function annotate_binding (exp, scope) {
2592      var bindings = exp.list[1];
2593      if (!show_locals) return; // HACK
2594  
2595      if (bindings) {
2596        scope = Object.create(scope);
2597        _annotate_binding_vector(bindings, scope);
2598      }
2599      for (var i = 2; i < exp.list.length; i++) {
2600        annotate_expressions(exp.list[i], scope);
2601      }
2602    }
2603  
2604    function _annotate_function_body (exp, scope, start_idx) {
2605      var argvec = exp.list[start_idx];
2606      if (argvec.tag !== "vector") return;
2607  
2608      scope = Object.create(scope);
2609  
2610      for (var i = 0, j = argvec.list.length; i < j; i++) {
2611        annotate_destructuring(argvec.list[i], scope);
2612      }
2613  
2614      for (var i = start_idx, j = exp.list.length; i < j; i++) {
2615        annotate_expressions(exp.list[i], scope);
2616      }
2617    }
2618  
2619    function annotate_function (exp, scope) {
2620      for (var i = 1, j = exp.list.length; i < j; i++) {
2621        var child = exp.list[i];
2622  
2623        if (child.tag === "vector") {
2624          _annotate_function_body (exp, scope, i);
2625          return;
2626        }
2627        else if (child.tag === "list") {
2628          _annotate_function_body(child, scope, 0)
2629        }
2630      }
2631    }
2632  
2633    function annotate_letfn (exp, scope) {
2634      scope = Object.create(scope);
2635      var bindings = exp.list[1];
2636  
2637      var fn;
2638      for (var i = 0, j = bindings.list.length; i < j; i++) {
2639        fn = bindings.list[i];
2640        if (!fn.list[0]) continue;
2641        fn.list[0].tag = "variable";
2642        scope[fn.list[0].value] = true;
2643      }
2644  
2645      for (i = 0, j = bindings.list.length; i < j; i++) {
2646        var fn = bindings.list[i];
2647        annotate_function(fn, scope);
2648      }
2649  
2650      for (i = 2, j = exp.list.length; i < j; i++) {
2651        annotate_expressions(exp.list[i], scope);
2652      }
2653    }
2654  
2655    register_annotation_rule(
2656      ["comment"],
2657      annotate_comment
2658    );
2659  
2660    register_annotation_rule(
2661      ["let", "when-let", "if-let", "binding", "doseq", "for", "dotimes", "let*"],
2662      annotate_binding
2663    );
2664  
2665    register_annotation_rule(
2666      ["defn", "defn-", "fn", "bound-fn", "defmacro", "fn*", "defmethod"],
2667      annotate_function
2668    );
2669  
2670    register_annotation_rule(
2671      ["letfn"],
2672      annotate_letfn
2673    );
2674  
2675    // standard annotations
2676  
2677    function _annotate_metadata_recursive(meta, scope) {
2678      if (!meta) return;
2679  
2680      if (meta.list !== undefined && meta.list !== null) {
2681        for (var i = 0, j = meta.list.length; i < j; i++) {
2682          meta.opening.secondary_tags.meta = true
2683          meta.closing.secondary_tags.meta = true
2684          _annotate_metadata_recursive(meta.list[i], scope);
2685        }
2686      }
2687      else if (meta.attached_node) {
2688        meta.token.secondary_tags.meta = true;
2689        _annotate_metadata_recursive(meta.attached_node, scope);
2690      }
2691      else {
2692        meta.secondary_tags.meta = true;
2693      }
2694    }
2695  
2696    function annotate_metadata(exp) {
2697      if (!(exp && exp.meta)) return;
2698      var meta = exp.meta;
2699  
2700       annotate_expressions(meta, {});
2701      _annotate_metadata_recursive(meta, {});
2702    }
2703  
2704  
2705    function annotate_quoted(exp, scope) {
2706      if (!exp) return;
2707  
2708      if (exp.list !== undefined && exp.list !== null) {
2709        for (var i = 0, j = exp.list.length; i < j; i++) {
2710          exp.opening.secondary_tags.quoted = true
2711          exp.closing.secondary_tags.quoted = true
2712          annotate_quoted(exp.list[i], scope);
2713        }
2714      }
2715      else if (exp.attached_node) {
2716        if (exp.tag === "unquote" || exp.tag === "splice") return;
2717        exp.token.secondary_tags.quoted = true;
2718        annotate_quoted(exp.attached_node, scope);
2719      }
2720      else {
2721        exp.secondary_tags.quoted = true;
2722      }
2723    }
2724  
2725  
2726    function annotate_expressions(exp, scope) {
2727      annotate_metadata(exp);
2728  
2729      switch (exp.tag) {
2730        case "toplevel":
2731          for (var i = 0; i < exp.list.length; i++) {
2732            annotate_expressions(exp.list[i], scope);
2733          }
2734          break;
2735  
2736        case "list": // functions, macros, special forms, comments
2737          var head = exp.list[0];
2738  
2739          if (head) {
2740            if (head.tag === "list" || head.tag === "vector"
2741             || head.tag === "map" || head.tag === "set") {
2742              annotate_expressions(head, scope);
2743            }
2744            else if (head.attached_node) {
2745              annotate_expressions(head.attached_node, scope);
2746            }
2747            else {
2748              head.tag = (head.value.match(/(^\.)|(\.$)|[A-Z].*\//)
2749                          ? "method"
2750                          : "function");
2751            }
2752  
2753            // apply specific rules
2754            if (annotation_rules.hasOwnProperty(head.value)) {
2755              annotation_rules[head.value](exp, scope);
2756            }
2757            else {
2758              for (var i = 1; i < exp.list.length; i++) {
2759                annotate_expressions(exp.list[i], scope);
2760              }
2761            }
2762          }
2763          else { // empty list
2764            exp.opening.tag = "value";
2765            exp.closing.tag = "value";
2766          }
2767  
2768          break;
2769  
2770        case "vector": // data
2771        case "map":
2772        case "set":
2773          for (var i = 0; i < exp.list.length; i++) {
2774            annotate_expressions(exp.list[i], scope);
2775          }
2776          break;
2777  
2778        case "symbol":
2779          if (exp.value.match(/[A-Z].*\/[A-Z_]+/)) {
2780            exp.tag = "constant";
2781          }
2782          else if (show_locals && scope[exp.value]) {
2783            exp.tag = "variable";
2784          }
2785          else if (exp.tag === "symbol" && exp.value.match(/([A-Z].*\/)?[A-Z_]+/)) {
2786            exp.tag = "type";
2787          }
2788          break;
2789  
2790        case "quote":
2791        case "quasiquote":
2792          annotate_quoted(exp.attached_node, scope);
2793  
2794        default:
2795          if (exp.attached_node) annotate_expressions(exp.attached_node, scope);
2796      }
2797    }
2798  
2799    // translation of tag to css:
2800    var css_translation = {
2801      "constant":     "constants",
2802      "keyword":      "constants",
2803      "method":       "color1",
2804      "type":         "color3",
2805      "function":     "functions",
2806      "string":       "string",
2807      "regexp":       "string",
2808      "value":        "value",
2809      "comments":     "comments",
2810      "symbol":       "symbol",
2811      "variable":     "variable",
2812      "splice":       "preprocessor",
2813      "unquote":      "preprocessor",
2814      "preprocessor": "preprocessor",
2815      "meta":         "preprocessor",
2816      "'":            "preprocessor",
2817      "#'":           "preprocessor",
2818      "(":            "plain",
2819      ")":            "plain",
2820      "{":            "keyword",
2821      "}":            "keyword",
2822      "#{":           "keyword",
2823      "[":            "keyword",
2824      "]":            "keyword",
2825      "invalid":      "invalid",
2826      "@":            "plain"
2827    };
2828  
2829    function translate_tags_to_css(tokens) {
2830      for (var i = 0, j = tokens.length; i < j; i++) {
2831        var token = tokens[i];
2832        token.css = css_translation[token.tag];
2833        for (var k in token.secondary_tags) if (token.secondary_tags.hasOwnProperty(k))
2834          token.css += " " + k ;
2835      };
2836    }
2837  
2838  
2839    // create the new brush
2840  
2841    SH.brushes.Clojure = function () {};
2842    SH.brushes.Clojure.prototype = new SyntaxHighlighter.Highlighter();
2843  
2844    SH.brushes.Clojure.prototype.findMatches = function find_matches (regexpList, code) {
2845      // this is a nasty global hack. need to resolve this
2846      if (this.params && this.params.locals) {
2847        show_locals = this.params.locals === true || this.params.locals === "true";
2848      }
2849      else {
2850        show_locals = true;
2851      }
2852  
2853      var tokens = tokenize(code);
2854      annotate_expressions(build_tree(tokens), {});
2855      translate_tags_to_css(tokens);
2856  
2857      return tokens;
2858    };
2859  
2860    SH.brushes.Clojure.aliases = ['clojure', 'Clojure', 'clj'];
2861    SH.brushes.Clojure.register_annotation_rule = register_annotation_rule;
2862  
2863    return {
2864      tokenize: tokenize,
2865      build_tree: build_tree
2866    };
2867  })(SyntaxHighlighter);
2868  </script><title>selmer -- Marginalia</title></head><body><table><tr><td class="docs"><div class="header"><h1 class="project-name"><a href="https://github.com/yogthos/Selmer">selmer</a></h1><h2 class="project-version">1.11.1</h2><br /><p>Django style templates for Clojure</p>
2869  </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.7.0</td></tr><tr><td class="dep-name">criterium</td><td class="dotted"><hr /></td><td class="dep-version">0.4.4</td></tr><tr><td class="dep-name">joda-time</td><td class="dotted"><hr /></td><td class="dep-version">2.9.6</td></tr><tr><td class="dep-name">commons-codec</td><td class="dotted"><hr /></td><td class="dep-version">1.10</td></tr><tr><td class="dep-name">json-html</td><td class="dotted"><hr /></td><td class="dep-version">0.4.0</td></tr><tr><td class="dep-name">cheshire</td><td class="dotted"><hr /></td><td class="dep-version">5.6.3</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="#selmer.filter-parser">selmer.filter-parser</a></li><li><a href="#selmer.filters">selmer.filters</a></li><li><a href="#selmer.middleware">selmer.middleware</a></li><li><a href="#selmer.node">selmer.node</a></li><li><a href="#selmer.parser">selmer.parser</a></li><li><a href="#selmer.tags">selmer.tags</a></li><li><a href="#selmer.template-parser">selmer.template-parser</a></li><li><a href="#selmer.util">selmer.util</a></li><li><a href="#selmer.validator">selmer.validator</a></li></ul></div></td><td class="codes">&nbsp;</td></tr><tr><td class="docs"><div class="docs-header"><a class="anchor" href="#selmer.filter-parser" name="selmer.filter-parser"><h1 class="project-name">selmer.filter-parser</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs"><p>Accessors are separated by dots like {{ foo.bar.0 }}
2870  which gets translated into (get-in context-map [:foo :bar 0]). So you
2871  can nest vectors and maps in your context-map.</p>
2872  
2873  <p>Filters can be applied by separating then from the accessor
2874  with pipes: {{ foo|lower|capitalize }}. They are applied one after
2875  the other from left to right. Arguments can be passed to a filter
2876  separated by colons: {{ foo|pluralize:y:ies }}. If an argument includes
2877  spaces you can enclose it with doublequotes or colons: {{ foo|join:", " }}.</p>
2878  
2879  <p>You can escape doublequotes inside doublequotes. And you can put colons
2880  inside doublequotes which will be ignored for the purpose of separating
2881  arguments.</p>
2882  </td><td class="codes"><pre class="brush: clojure">(ns selmer.filter-parser
2883    (:require [selmer.filters :refer [get-filter]]
2884              [selmer.util :refer [exception *escape-variables*]]
2885              [clojure.string :as s]))</pre></td></tr><tr><td class="docs"><p>More Utils</p>
2886  </td><td class="codes"><pre class="brush: clojure">(defn escape-html*
2887    [^String s]
2888    &quot;HTML-escapes the given string. Escapes the same characters as django's escape.&quot;
2889    ;; This method is &quot;Java in Clojure&quot; for serious speedups.
2890    ;; Stolen from davidsantiago/quoin and modified.
2891    (if *escape-variables*
2892      (let [sb (StringBuilder.)
2893            slength (count s)]
2894        (loop [idx 0]
2895          (if (&gt;= idx slength)
2896            (.toString sb)
2897            (let [c (char (.charAt s idx))]
2898              (case c
2899                \&amp; (.append sb &quot;&amp;amp;&quot;)
2900                \&lt; (.append sb &quot;&amp;lt;&quot;)
2901                \&gt; (.append sb &quot;&amp;gt;&quot;)
2902                \&quot; (.append sb &quot;&amp;quot;&quot;)
2903                \' (.append sb &quot;&amp;#39;&quot;)
2904                (.append sb c))
2905              (recur (inc idx))))))
2906      s))</pre></td></tr><tr><td class="docs"><p>Removes doublequotes from the start and end of a string if any.</p>
2907  </td><td class="codes"><pre class="brush: clojure">(defn strip-doublequotes
2908    [^String s]
2909    (if (and (&gt; (count s) 1)
2910             (= \&quot; (first s) (.charAt s (dec (count s)))))
2911      (.substring s 1 (dec (count s)))
2912      s))</pre></td></tr><tr><td class="docs"><p>Must have the form [:safe safe-string] to prevent escaping. Alternatively,
2913    you can call selmer.util/turn-off-escaping! to turn it off completely.</p>
2914  </td><td class="codes"><pre class="brush: clojure">(defn escape-html
2915    [x]
2916    (if (and (vector? x)
2917             (= :safe (first x)))
2918      (second x)
2919      (let [s (str x)]
2920        (escape-html* s))))</pre></td></tr><tr><td class="docs"><p>Turns strings into keywords and strings like "0" into Longs
2921  so it can access vectors as well as maps.</p>
2922  
2923  <p>Compile filters</p>
2924  </td><td class="codes"><pre class="brush: clojure">(defn fix-accessor
2925    [ks]
2926    (mapv (fn [^String s]
2927            (try (Long/valueOf s)
2928                 (catch NumberFormatException _
2929                   (keyword s))))
2930          ks))</pre></td></tr><tr><td class="docs"><p>Split accessors like foo.bar.baz by the dot.
2931     But if there is a double dot '..' then it will leave it</p>
2932  </td><td class="codes"><pre class="brush: clojure">(defn split-filter-val
2933    [s]
2934    (let [ks (clojure.string/split s #&quot;(?&lt;!\.)\.(?!\.)&quot;)
2935          kss (map
2936                (fn [s] (clojure.string/replace s &quot;..&quot; &quot;.&quot;)) ks)] ;we remove the double dot here
2937      (fix-accessor kss)))</pre></td></tr><tr><td class="docs"><p>Map any sort of needed fixes to the arguments before passing them
2938  to the filters. Only strips enclosing doublequotes for now.</p>
2939  </td><td class="codes"><pre class="brush: clojure">(defn fix-filter-args
2940    [args]
2941    ;; TODO - figure out what kind of extra args filters can take
2942    (map (fn [^String s]
2943           (strip-doublequotes s))
2944         args))</pre></td></tr><tr><td class="docs"><p>Given a context map, return a function that accepts a filter
2945    argument and if it begins with @, return the value from the
2946    context map instead of treating it as a literal.</p>
2947  </td><td class="codes"><pre class="brush: clojure">(defn lookup-args
2948    [context-map]
2949    (fn [^String arg]
2950      (if (and (&gt; (count arg) 1) (.startsWith arg &quot;@&quot;))
2951        (let [accessor (split-filter-val (subs arg 1))]
2952          (get-in context-map accessor arg))
2953        arg)))</pre></td></tr><tr><td class="docs"><p>Turns a filter string like "pluralize:y:ies" into a function that
2954  expects a value obtained from a context map or from a previously
2955  applied filter.</p>
2956  </td><td class="codes"><pre class="brush: clojure">(defn filter-str-&gt;fn
2957    [s]
2958    (let [[filter-name &amp; args]
2959          ;; Ignore colons inside doublequotes
2960          (re-seq #&quot;(?:[^:\&quot;]|\&quot;[^\&quot;]*\&quot;)+&quot; s)
2961          args (fix-filter-args args)
2962          filter (get-filter filter-name)]
2963      (if filter
2964        (fn [x context-map]
2965          (apply filter x (map (lookup-args context-map) args)))
2966        (exception &quot;No filter defined with the name '&quot; filter-name &quot;'&quot;))))</pre></td></tr><tr><td class="docs">
2967  </td><td class="codes"><pre class="brush: clojure">(def safe-filter ::selmer-safe-filter)</pre></td></tr><tr><td class="docs">
2968  </td><td class="codes"><pre class="brush: clojure">(defn- literal? [^String val]
2969    (or
2970      (and (.startsWith val &quot;\) (.endsWith val &quot;\))
2971      (re-matches #&quot;[0-9]+&quot; val)))</pre></td></tr><tr><td class="docs">
2972  </td><td class="codes"><pre class="brush: clojure">(defn- parse-literal [^String val]
2973    (if (.startsWith val &quot;\)
2974      (subs val 1 (dec (count val)))
2975      val))</pre></td></tr><tr><td class="docs">
2976  </td><td class="codes"><pre class="brush: clojure">(defn- apply-filters [val s filter-strs filters context-map]
2977    (reduce
2978      (fn [acc [filter-str filter]]
2979        (try (filter acc context-map)
2980             (catch Exception e
2981               (exception
2982                 &quot;On filter body '&quot; s &quot;' and filter '&quot; filter-str &quot;' this error occurred:&quot; (.getMessage e)))))
2983      val
2984      (map vector filter-strs filters)))</pre></td></tr><tr><td class="docs">
2985  </td><td class="codes"><pre class="brush: clojure">(defn get-accessor [m k]
2986    &quot;Returns the value of `k` from map `m`, either as a keyword or string lookup.&quot;
2987    (or (get m k)
2988        (when (keyword? k)
2989          (if-let [n (namespace k)]
2990            (get m (str n &quot;/&quot; (name k)))
2991            (get m (name k))))))</pre></td></tr><tr><td class="docs"><p>Turns a string like foo|filter1:x|filter2:y into a fn that expects a
2992   context-map and will apply the filters one after the other to the value
2993   from the map. It will escape the end result unless the last
2994   filter is "safe" or when it's called with escape? equal to true,
2995   which is the default behavior.</p>
2996  </td><td class="codes"><pre class="brush: clojure">(defn compile-filter-body
2997    ([s] (compile-filter-body s true))
2998    ([s escape?]
2999     (let [[val &amp; filter-strs] (-&gt;&gt; s
3000                                    (s/trim)
3001                                    ;; Ignore pipes and allow escaped doublequotes inside doublequotes
3002                                    (re-seq #&quot;(?:[^|\&quot;]|\&quot;[^\&quot;]*\&quot;)+&quot;))
3003           accessor (split-filter-val val)
3004           filters (map filter-str-&gt;fn filter-strs)]
3005       (if (literal? val)
3006         (fn [context-map]
3007           (apply-filters
3008             (parse-literal val)
3009             s
3010             filter-strs
3011             filters
3012             context-map))
3013         (fn [context-map]
3014           (let [val (reduce get-accessor context-map accessor)]
3015             (when (or val (and selmer.util/*filter-missing-values* (seq filters)))
3016               (let [x (apply-filters
3017                         val
3018                         s
3019                         filter-strs
3020                         filters
3021                         context-map)]
3022                 ;; Escape by default unless the last filter is 'safe' or safe-filter is set in the context-map
3023                 (cond
3024                   (safe-filter context-map) x
3025                   escape? (escape-html x)
3026                   :else x)))))))))</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="#selmer.filters" name="selmer.filters"><h1 class="project-name">selmer.filters</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs"><p>To create a filter use the function add-filter! which takes a name and a fn.
3027  The first argument to the fn is always the value obtained from the context
3028  map. The rest of the arguments are optional and are always strings.</p>
3029  </td><td class="codes"><pre class="brush: clojure">(ns selmer.filters
3030    (:require [clojure.string :as s]
3031              [cheshire.core :as json :only [generate-string]]
3032              [selmer.util :refer [exception]])
3033    (:import java.util.Locale
3034             org.joda.time.DateTime
3035             java.text.NumberFormat
3036             [org.joda.time.format DateTimeFormat DateTimeFormatter]
3037             [org.apache.commons.codec.digest DigestUtils]))</pre></td></tr><tr><td class="docs">
3038  </td><td class="codes"><pre class="brush: clojure">(def valid-date-formats
3039    {&quot;shortDate&quot;      (DateTimeFormat/shortDate)
3040     &quot;shortTime&quot;      (DateTimeFormat/shortTime)
3041     &quot;shortDateTime&quot;  (DateTimeFormat/shortDateTime)
3042     &quot;mediumDate&quot;     (DateTimeFormat/mediumDate)
3043     &quot;mediumTime&quot;     (DateTimeFormat/mediumTime)
3044     &quot;mediumDateTime&quot; (DateTimeFormat/mediumDateTime)
3045     &quot;longDate&quot;       (DateTimeFormat/longDate)
3046     &quot;longTime&quot;       (DateTimeFormat/longTime)
3047     &quot;longDateTime&quot;   (DateTimeFormat/longDateTime)
3048     &quot;fullDate&quot;       (DateTimeFormat/fullDate)
3049     &quot;fullTime&quot;       (DateTimeFormat/fullTime)
3050     &quot;fullDateTime&quot;   (DateTimeFormat/fullDateTime)
3051     })</pre></td></tr><tr><td class="docs">
3052  </td><td class="codes"><pre class="brush: clojure">(defn ^DateTime fix-date [d]
3053    (cond (instance? DateTime d) d
3054          (instance? java.util.Date d) (DateTime. d)
3055          :else
3056          (try (DateTime. d)
3057               (catch Exception _
3058                 (throw (IllegalArgumentException. (str d &quot; is not a valid date format.&quot;)))))))</pre></td></tr><tr><td class="docs"><p>Throws an exception with the given msg when (seq x) will fail (excluding nil)</p>
3059  
3060  <p>Used in filters when we are expecting a collection but instead got nil or a number
3061  or something else just as useless.
3062  Some clojure functions silently do the wrong thing when given invalid arguments. This
3063  aims to prevent that.</p>
3064  </td><td class="codes"><pre class="brush: clojure">(defn throw-when-expecting-seqable
3065    [x &amp; [msg]]
3066    (let [is-seqable  (and (not (nil? x))
3067                           (or (seq? x)
3068                               (instance? clojure.lang.Seqable x)
3069                               (string? x)
3070                               (instance? Iterable x)
3071                               (-&gt; ^Object x .getClass .isArray)
3072                               (instance? java.util.Map x)))
3073          ^String msg (if msg msg (str &quot;Expected '&quot; (if (nil? x) &quot;nil&quot; (str x)) &quot;' to be a collection of some sort.&quot;))]
3074      (when-not is-seqable
3075        (exception msg))))</pre></td></tr><tr><td class="docs"><p>Similar to the above only with numbers</p>
3076  </td><td class="codes"><pre class="brush: clojure">(defn throw-when-expecting-number
3077    [x &amp; [msg]]
3078    (let [^String msg (if msg msg (str &quot;Expected '&quot; (if (nil? x) &quot;nil&quot; (str x)) &quot;' to be a number.&quot;))]
3079      (when-not (number? x)
3080        (exception msg))))</pre></td></tr><tr><td class="docs">
3081  </td><td class="codes"><pre class="brush: clojure">(defonce filters
3082           (atom
3083             {;;; Useful for doing crazy stuff like {{ foo|length-is:3|join:&quot;/&quot; }}
3084              ;;; Without blowing up I guess
3085              :str
3086              str
3087              ;;; Try to add the arguments as numbers
3088              ;;; If it fails concatenate them as strings
3089              :add
3090              (fn [x y &amp; rest]
3091                (let [args (conj rest y (str x))]
3092                  (try (apply +
3093                              (map #(Long/valueOf ^String %) args))
3094                       (catch NumberFormatException _
3095                         (apply str args)))))
3096              ;;; Add backslashes to quotes
3097              :addslashes
3098              (fn [s]
3099                (-&gt;&gt; s
3100                     (str)
3101                     (mapcat (fn [c]
3102                               (if (or (= \&quot; c) (= \' c))
3103                                 [\\ c]
3104                                 [c])))
3105                     (apply str)))
3106              ;;; Center a string given a width
3107              :center
3108              (fn [s w]
3109                (let [s (str s)
3110                      w (Long/valueOf (s/trim w))
3111                      c (count s)
3112                      l (Math/ceil (/ (- w c) 2))
3113                      r (Math/floor (/ (- w c) 2))]
3114                  (str
3115                    (apply str (repeat l \space))
3116                    s
3117                    (apply str (repeat r \space)))))
3118              :currency-format
3119              (fn [n &amp; [locale country]]
3120                (throw-when-expecting-number n)
3121                (let [n               (double n)
3122                      locale          (cond
3123                                        (and locale country) (Locale. locale country)
3124                                        locale (Locale. locale)
3125                                        :else (Locale/getDefault))
3126                      currency-format (java.text.NumberFormat/getCurrencyInstance locale)]
3127                  (.format ^NumberFormat currency-format n)))
3128              :number-format
3129              (fn [n fmt &amp; [locale]]
3130                (throw-when-expecting-number n)
3131                (let [locale (if locale (java.util.Locale. locale)
3132                                        (Locale/getDefault))]
3133                  (String/format locale fmt (into-array Object [n]))))
3134              ;;; Formats a date with default locale, expects an instance of DateTime (Joda Time) or Date.
3135              ;;; The format can be a key from valid-date-formats or a manually defined format
3136              ;;; Look in
3137              ;;; http://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html
3138              ;;; for formatting help.
3139              ;;; You can also format time with this.
3140              ;;; An optional locale for formatting can be given as second parameter
3141              :date
3142              (fn [d fmt &amp; [locale]]
3143                (when d
3144                  (let [fixed-date             (fix-date d)
3145                        locale                 (if locale (java.util.Locale. locale)
3146                                                          (Locale/getDefault))
3147                        ^DateTimeFormatter fmt (.withLocale
3148                                                 (or ^DateTimeFormatter (valid-date-formats fmt)
3149                                                     ^DateTimeFormatter (DateTimeFormat/forPattern fmt)) locale)]
3150                    (.print fmt fixed-date))))
3151              ;;; Default if x is falsey
3152              :default
3153              (fn [x default]
3154                (if x
3155                  x
3156                  default))
3157              ;;; Default if coll is empty
3158              :default-if-empty
3159              (fn [coll default]
3160                (try
3161                  (cond
3162                    (nil? coll) default
3163                    (empty? coll) default
3164                    :else coll)
3165                  (catch Exception _
3166                    (throw-when-expecting-seqable coll))))
3167              ;;; With no decimal places it rounds to 1 decimal place
3168              :double-format
3169              (fn [n &amp; [decimal-places]]
3170                (throw-when-expecting-number n)
3171                (let [n (double n)]
3172                  (format (str &quot;%.&quot; (if decimal-places decimal-places &quot;1&quot;) &quot;f&quot;)
3173                          n)))
3174              :first
3175              (fn [coll]
3176                (throw-when-expecting-seqable coll)
3177                (first coll))
3178              :take
3179              (fn [coll n]
3180                (throw-when-expecting-seqable coll)
3181                (vec (take (Long/valueOf ^String n) coll)))
3182              :drop
3183              (fn [coll n]
3184                (throw-when-expecting-seqable coll)
3185                (vec (drop (Long/valueOf ^String n) coll)))
3186              ;;; Get the ith digit of a number
3187              ;;; 1 is the rightmost digit
3188              ;;; Returns the number if the index is out of bounds
3189              :get-digit
3190              (fn [n i]
3191                (let [nv (vec (str n))
3192                      i  (Long/valueOf ^String i)
3193                      i  (- (count nv) i)]
3194                  (if (or (&lt; i 0) (&gt;= i (count nv)))
3195                    n
3196                    (let [d (nv i)]
3197                      (if (= \. d)
3198                        (nv (dec i))
3199                        d)))))
3200              :hash
3201              (fn [s hash]
3202                (let [s (str s)]
3203                  (case hash
3204                    &quot;md5&quot; (DigestUtils/md5Hex s)
3205                    &quot;sha&quot; (DigestUtils/shaHex s)
3206                    &quot;sha256&quot; (DigestUtils/sha256Hex s)
3207                    &quot;sha384&quot; (DigestUtils/sha384Hex s)
3208                    &quot;sha512&quot; (DigestUtils/sha512Hex s)
3209                    (throw (IllegalArgumentException. (str &quot;'&quot; hash &quot;' is not a valid hash algorithm.&quot;))))))
3210              :join
3211              (fn [coll &amp; [sep]]
3212                (throw-when-expecting-seqable coll)
3213                (if sep (s/join sep coll) (s/join coll)))
3214              :empty?
3215              empty?
3216              :not-empty
3217              not-empty
3218              :json
3219              (fn [x] (json/generate-string x))
3220              :last
3221              (fn [coll]
3222                (throw-when-expecting-seqable coll)
3223                (if (vector? coll)
3224                  (coll (dec (count coll)))
3225                  (last coll)))
3226              ;;; Exception to the rule: nil counts to 0
3227              :length
3228              (fn [coll]
3229                (if (nil? coll)
3230                  0
3231                  (do
3232                    (throw-when-expecting-seqable coll)
3233                    (count coll))))
3234              ;;; Exception to the rule: nil counts to 0
3235              :count
3236              (fn [coll]
3237                (if (nil? coll)
3238                  0
3239                  (do
3240                    (throw-when-expecting-seqable coll)
3241                    (count coll))))
3242              ;;; Return true when the count of the coll matches the argument
3243              :length-is
3244              (fn [coll n]
3245                (when-not (nil? coll)
3246                  (throw-when-expecting-seqable coll))
3247                (let [n (Long/valueOf ^String n)]
3248                  (= n (count coll))))
3249              :count-is
3250              (fn [coll n]
3251                (when-not (nil? coll)
3252                  (throw-when-expecting-seqable coll))
3253                (let [n (Long/valueOf ^String n)]
3254                  (= n (count coll))))
3255              ;;; Single newlines become &lt;br /&gt;, double newlines mean new paragraph
3256              :linebreaks
3257              (fn [s]
3258                (let [s  (str s)
3259                      br (s/replace s #&quot;\n&quot; &quot;&lt;br /&gt;&quot;)
3260                      p  (s/replace br #&quot;&lt;br /&gt;&lt;br /&gt;&quot; &quot;&lt;/p&gt;&lt;p&gt;&quot;)
3261                      c  (s/replace p #&quot;&lt;p&gt;$&quot; )]
3262                  (if (re-seq #&quot;&lt;/p&gt;$&quot; c)
3263                    (str &quot;&lt;p&gt;&quot; c)
3264                    (str &quot;&lt;p&gt;&quot; c &quot;&lt;/p&gt;&quot;))))
3265              :linebreaks-br
3266              (fn [s]
3267                (let [s (str s)]
3268                  (s/replace s #&quot;\n&quot; &quot;&lt;br /&gt;&quot;)))
3269              ;;; Display text with line numbers
3270              :linenumbers
3271              (fn [s]
3272                (let [s (str s)]
3273                  (-&gt;&gt; (s/split s #&quot;\n&quot;)
3274                       (map-indexed
3275                         (fn [i line]
3276                           (str (inc i) &quot;. &quot; line)))
3277                       (s/join &quot;\n&quot;))))
3278              :rand-nth
3279              (fn [coll]
3280                (throw-when-expecting-seqable coll)
3281                (rand-nth coll))
3282              ;;; Turns the to-remove string into a set of chars
3283              ;;; That are removed from the context string
3284              :remove
3285              (fn [s to-remove]
3286                (let [s         (str s)
3287                      to-remove (set to-remove)]
3288                  (apply str (remove to-remove s))))
3289              ;;; Use like the following:
3290              ;;; You have {{ num-cherries }} cherr{{ num-cherries|pluralize:y:ies }}
3291              ;;; You have {{ num-walruses }} walrus{{ num-walruses|pluralize:es }}
3292              ;;; You have {{ num-messages }} message{{ num-messages|pluralize }}
3293              :pluralize
3294              (fn [n-or-coll &amp; opts]
3295                (let [n        (if (number? n-or-coll) n-or-coll
3296                                                       (do (throw-when-expecting-seqable n-or-coll)
3297                                                           (count n-or-coll)))
3298                      plural   (case (count opts)
3299                                 0 &quot;s&quot;
3300                                 1 (first opts)
3301                                 2 (second opts))
3302                      singular (case (count opts)
3303                                 (list 0 1)
3304                                 2 (first opts))]
3305                  (if (== 1 n)
3306                    singular
3307                    plural)))
3308              ;;; Do not escape html
3309              :safe
3310              (fn [s] [:safe s])
3311              :urlescape
3312              (fn [s] (java.net.URLEncoder/encode s))
3313              :lower
3314              (fn [s] (s/lower-case (str s)))
3315              :upper
3316              (fn [s] (s/upper-case (str s)))
3317              :capitalize
3318              (fn [s] (s/capitalize (str s)))
3319              ;; Capitalize every word
3320              :title
3321              (fn [s] (-&gt;&gt; (s/split (str s) #&quot; &quot;)
3322                           (map s/capitalize)
3323                           (s/join &quot; &quot;)))
3324              :sort
3325              (fn [coll]
3326                (throw-when-expecting-seqable coll)
3327                (sort coll))
3328              ;;; Sort by a keyword
3329              :sort-by
3330              (fn [coll k]
3331                (throw-when-expecting-seqable coll)
3332                (sort-by (keyword k) coll))
3333              :sort-by-reversed
3334              (fn [coll k]
3335                (throw-when-expecting-seqable coll)
3336                (sort-by (keyword k) (comp - compare) coll))
3337              :sort-reversed
3338              (fn [coll]
3339                (throw-when-expecting-seqable coll)
3340                (sort (comp - compare) coll))
3341              ;;; Remove tags
3342              ;;; Use like {{ value|remove-tags:b:span }}
3343              :remove-tags
3344              (fn [s &amp; tags]
3345                (if-not tags
3346                  s
3347                  (let [s       (str s)
3348                        tags    (str &quot;(&quot; (s/join &quot;|&quot; tags) &quot;)&quot;)
3349                        opening (re-pattern (str &quot;(?i)&lt;&quot; tags &quot;(/?&gt;|(\\s+[^&gt;]*&gt;))&quot;))
3350                        closing (re-pattern (str &quot;(?i)&lt;/&quot; tags &quot;&gt;&quot;))]
3351                    (-&gt; s
3352                        (s/replace opening )
3353                        (s/replace closing )))))
3354              :name
3355              name}))</pre></td></tr><tr><td class="docs">
3356  </td><td class="codes"><pre class="brush: clojure">(defn get-filter
3357    [name]
3358    (get @filters (keyword name)))</pre></td></tr><tr><td class="docs">
3359  </td><td class="codes"><pre class="brush: clojure">(defn call-filter
3360    [name &amp; args]
3361    (apply (get-filter name) args))</pre></td></tr><tr><td class="docs">
3362  </td><td class="codes"><pre class="brush: clojure">(defn add-filter!
3363    [name f]
3364    (swap! filters assoc (keyword name) f))</pre></td></tr><tr><td class="docs">
3365  </td><td class="codes"><pre class="brush: clojure">(defn remove-filter!
3366    [name]
3367    (swap! filters dissoc (keyword name)))</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="#selmer.middleware" name="selmer.middleware"><h1 class="project-name">selmer.middleware</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
3368  </td><td class="codes"><pre class="brush: clojure">(ns selmer.middleware
3369    (:require [selmer.parser :as parser]))</pre></td></tr><tr><td class="docs"><p>development middleware for rendering a friendly error page when a parsing error occurs</p>
3370  </td><td class="codes"><pre class="brush: clojure">(defn wrap-error-page
3371    [handler]
3372    (fn [request]
3373      (try
3374        (handler request)
3375        (catch clojure.lang.ExceptionInfo ex
3376          (let [{:keys [type error-template] :as data} (ex-data ex)]
3377            (if (= :selmer-validation-error type)
3378              {:status 500
3379               :headers {&quot;Content-Type&quot; &quot;text/html; charset=utf-8&quot;}
3380               :body (parser/render error-template data)}
3381              (throw ex)))))))</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="#selmer.node" name="selmer.node"><h1 class="project-name">selmer.node</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs"><p> Node protocol for the objects that get accum'd in the post-parse vector.
3382    Same vector that will be processed by the runtime context-aware renderer.
3383    Currently only TextNodes and FunctionNodes. Anything that requires action
3384    upon context map data at runtime is handled by a generated anonymous function. </p>
3385  </td><td class="codes"><pre class="brush: clojure">(ns selmer.node
3386    (:gen-class))</pre></td></tr><tr><td class="docs"><p>Generic INode protocol</p>
3387  </td><td class="codes"></td></tr><tr><td class="docs">
3388  </td><td class="codes"><pre class="brush: clojure">(defprotocol INode
3389    (render-node [this context-map] &quot;Renders the context&quot;))</pre></td></tr><tr><td class="docs"><p>Implements fn handler for the context map. fn handlers can
3390  access any data in the context map.</p>
3391  </td><td class="codes"></td></tr><tr><td class="docs">
3392  </td><td class="codes"><pre class="brush: clojure">(deftype FunctionNode [handler]
3393    INode
3394    (render-node [this context-map]
3395      (handler context-map))
3396    clojure.lang.IMeta
3397    (meta [this]
3398      (meta handler)))</pre></td></tr><tr><td class="docs"><p>Implements dumb text content injection at runtime.</p>
3399  </td><td class="codes"></td></tr><tr><td class="docs">
3400  </td><td class="codes"><pre class="brush: clojure">(deftype TextNode [text]
3401    INode
3402    (render-node [this context-map]
3403      (str text))
3404    (toString [_]
3405      (str text)))</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="#selmer.parser" name="selmer.parser"><h1 class="project-name">selmer.parser</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs"><p> Parsing and handling of compile-time vs.
3406    run-time. Avoiding unnecessary work by pre-processing
3407    the template structure and content and reacting to
3408    the runtime context map with a prepared data structure
3409    instead of a raw template. Anything other than a raw tag
3410    value injection is a runtime dispatch fn. Compile-time here
3411    means the first time we see a template <em>at runtime</em>, not the
3412    implementation's compile-time. </p>
3413  </td><td class="codes"><pre class="brush: clojure">(ns selmer.parser
3414    (:require [selmer.template-parser :refer [preprocess-template]]
3415              [selmer.filters :refer [filters]]
3416              [selmer.filter-parser :refer [compile-filter-body]]
3417              [selmer.tags :refer :all]
3418              [selmer.util :refer :all]
3419              [selmer.validator :refer [validation-error]]
3420              selmer.node)
3421    (:import [selmer.node INode TextNode FunctionNode]))</pre></td></tr><tr><td class="docs"><p>Ahead decl because some fns call into each other.</p>
3422  </td><td class="codes"></td></tr><tr><td class="docs">
3423  </td><td class="codes"><pre class="brush: clojure">(declare parse parse-input parse-file tag-content)</pre></td></tr><tr><td class="docs"><p>Memoization atom for templates. If you pass a filepath instead
3424  of a string, we'll use the last-modified timestamp to cache the
3425  template. Works fine for active local development and production.</p>
3426  </td><td class="codes"></td></tr><tr><td class="docs">
3427  </td><td class="codes"><pre class="brush: clojure">(defonce templates (atom {}))</pre></td></tr><tr><td class="docs"><p>Can be overridden by closure/argument 'cache</p>
3428  </td><td class="codes"><pre class="brush: clojure">(defonce cache? (atom true))</pre></td></tr><tr><td class="docs">
3429  </td><td class="codes"><pre class="brush: clojure">(defn cache-on! []
3430    (reset! cache? true))</pre></td></tr><tr><td class="docs">
3431  </td><td class="codes"><pre class="brush: clojure">(defn cache-off! []
3432    (reset! cache? false))</pre></td></tr><tr><td class="docs"><p>append '/' to the given string unless it already ends with a slash</p>
3433  </td><td class="codes"><pre class="brush: clojure">(defn- append-slash
3434    [^String s]
3435    (if (or (nil? s)
3436            (.endsWith s &quot;/&quot;))
3437      s
3438      (str s &quot;/&quot;)))</pre></td></tr><tr><td class="docs">
3439  </td><td class="codes"><pre class="brush: clojure">(defn- make-resource-path
3440    [path]
3441    (cond
3442      (nil? path)
3443        nil
3444      (instance? java.net.URL path)
3445        (append-slash (str path))
3446      :else
3447        (append-slash
3448         (try
3449           (str (java.net.URL. path))
3450           (catch java.net.MalformedURLException err
3451             (str &quot;file:///&quot; path))))))</pre></td></tr><tr><td class="docs"><p>set custom location, where templates are being searched for. path
3452    may be a java.net.URL instance or a string. If it's a string, we
3453    first try to convert it to a java.net.URL instance and if it doesn't
3454    work it's interpreted as a path in the local filesystem.</p>
3455  </td><td class="codes"><pre class="brush: clojure">(defn set-resource-path!
3456    [path]
3457    (set-custom-resource-path! (make-resource-path path)))</pre></td></tr><tr><td class="docs">
3458  </td><td class="codes"><pre class="brush: clojure">(defn update-tag [tag-map tag tags]
3459    (assoc tag-map tag (concat (get tag-map tag) tags)))</pre></td></tr><tr><td class="docs">
3460  </td><td class="codes"><pre class="brush: clojure">(defn set-closing-tags! [&amp; tags]
3461    (loop [[tag &amp; tags] tags]
3462      (when tag
3463        (swap! selmer.tags/closing-tags update-tag tag tags)
3464        (recur tags))))</pre></td></tr><tr><td class="docs"><p> tag name, fn handler, and maybe tags </p>
3465  
3466  <p>add-tag! is a hella nifty macro. Example use:
3467  (add-tag! :joined (fn [args context-map] (clojure.string/join "," args)))</p>
3468  </td><td class="codes"><pre class="brush: clojure">(defmacro add-tag!
3469    [k handler &amp; tags]
3470    `(do
3471       (set-closing-tags! ~k ~@tags)
3472       (swap! selmer.tags/expr-tags assoc ~k (tag-handler ~handler ~k ~@tags))))</pre></td></tr><tr><td class="docs">
3473  </td><td class="codes"><pre class="brush: clojure">(defn remove-tag!
3474    [k]
3475    (swap! expr-tags dissoc k)
3476    (swap! closing-tags dissoc k))</pre></td></tr><tr><td class="docs"><p>render-template renders at runtime, accepts
3477  post-parsing vectors of INode elements.</p>
3478  </td><td class="codes"></td></tr><tr><td class="docs">
3479  </td><td class="codes"><pre class="brush: clojure">(defn render-template [template context-map]
3480    &quot; vector of ^selmer.node.INodes and a context map.&quot;
3481    (let [buf (StringBuilder.)]
3482      (doseq [^selmer.node.INode element template]
3483          (if-let [value (.render-node element context-map)]
3484            (.append buf value)
3485            (.append buf (*missing-value-formatter* (:tag (meta element)) context-map))))
3486      (.toString buf)))</pre></td></tr><tr><td class="docs">
3487  </td><td class="codes"><pre class="brush: clojure">(defn render [s context-map &amp; [opts]]
3488    &quot; render takes the string, the context-map and possibly also opts. &quot;
3489    (render-template (parse parse-input (java.io.StringReader. s) opts) context-map))</pre></td></tr><tr><td class="docs"><p>Primary fn you interact with as a user, you pass a path that
3490  exists somewhere in your class-path, typically something like
3491  resources/templates/template_name.html. You also pass a context
3492  map and potentially opts. Smart (last-modified timestamp)
3493  auto-memoization of compiler output.</p>
3494  </td><td class="codes"></td></tr><tr><td class="docs">
3495  </td><td class="codes"><pre class="brush: clojure">(defn render-file [filename-or-url context-map &amp; [{:keys [cache custom-resource-path]
3496                                              :or  {cache @cache?
3497                                                    custom-resource-path *custom-resource-path*}
3498                                              :as opts}]]
3499    &quot; Parses files if there isn't a memoized post-parse vector ready to go,
3500    renders post-parse vector with passed context-map regardless. Double-checks
3501    last-modified on files. Uses classpath for filename-or-url path &quot;
3502    (binding [*custom-resource-path* (make-resource-path custom-resource-path)]
3503      (if-let [resource (resource-path filename-or-url)]
3504        (let [{:keys [template last-modified]} (get @templates resource)
3505              ;;for some resources, such as ones inside a jar, it's
3506              ;;not possible to check the last modified timestamp
3507              last-modified-time (if (or (nil? last-modified) (pos? last-modified))
3508                                   (resource-last-modified resource) -1)]
3509          (check-template-exists resource)
3510          (if (and cache last-modified (= last-modified last-modified-time))
3511            (render-template template context-map)
3512            (let [template (parse parse-file filename-or-url opts)]
3513              (swap! templates assoc resource {:template template
3514                                               :last-modified last-modified-time})
3515              (render-template template context-map))))
3516        (validation-error
3517         (str &quot;resource-path for &quot; filename-or-url &quot; returned nil, typically means the file doesn't exist in your classpath.&quot;)
3518         nil nil nil))))</pre></td></tr><tr><td class="docs"><p>For a given tag, get the fn handler for the tag type,
3519  pass it the arguments, tag-content, render-template fn,
3520  and reader.</p>
3521  </td><td class="codes"></td></tr><tr><td class="docs">
3522  </td><td class="codes"><pre class="brush: clojure">(defn expr-tag [{:keys [tag-name args] :as tag} rdr]
3523    (if-let [handler (tag-name @expr-tags)]
3524      (handler args tag-content render-template rdr)
3525      (exception &quot;unrecognized tag: &quot; tag-name &quot; - did you forget to close a tag?&quot;)))</pre></td></tr><tr><td class="docs"><p>Same as a vanilla data tag with a value, but composes
3526  the filter fns. Like, {{ data-var | upper | safe }}
3527  (-> {:data-var "woohoo"} upper safe) => "WOOHOO"
3528  Happens at compile-time.</p>
3529  </td><td class="codes"></td></tr><tr><td class="docs">
3530  </td><td class="codes"><pre class="brush: clojure">(defn filter-tag [{:keys [tag-value]}]
3531    &quot; Compile-time parser of var tag filters. &quot;
3532    (compile-filter-body tag-value))</pre></td></tr><tr><td class="docs"><p>Generally either a filter tag, if tag, ifequal,
3533  or for. filter-tags are conflated with vanilla tag</p>
3534  </td><td class="codes"></td></tr><tr><td class="docs">
3535  </td><td class="codes"><pre class="brush: clojure">(defn parse-tag [{:keys [tag-type] :as tag} rdr]
3536    (with-meta
3537      (if (= :filter tag-type)
3538        (filter-tag tag)
3539        (expr-tag tag rdr))
3540      {:tag tag}))</pre></td></tr><tr><td class="docs"><p>Parses and detects tags which turn into
3541  FunctionNode call-sites or TextNode content. open-tag? fn returns
3542  true or false based on character lookahead to see if it's {{ or {%</p>
3543  </td><td class="codes"></td></tr><tr><td class="docs">
3544  </td><td class="codes"><pre class="brush: clojure">(defn append-node [content tag ^StringBuilder buf rdr]
3545    (-&gt; content
3546      (conj (TextNode. (.toString buf)))
3547      (conj (FunctionNode. (parse-tag tag rdr)))))</pre></td></tr><tr><td class="docs">
3548  </td><td class="codes"><pre class="brush: clojure">(defn update-tags [tag tags content args ^StringBuilder buf]
3549    (assoc tags tag
3550           {:args args
3551            :content (conj content (TextNode. (.toString buf)))}))</pre></td></tr><tr><td class="docs">
3552  </td><td class="codes"><pre class="brush: clojure">(defn tag-content [rdr start-tag &amp; end-tags]
3553    (let [buf (StringBuilder.)]
3554      (loop [ch       (read-char rdr)
3555             tags     {}
3556             content  []
3557             cur-tag  start-tag
3558             end-tags end-tags]
3559        (cond
3560          (and (nil? ch) (not-empty end-tags))
3561          (exception &quot;No closing tag found for &quot; start-tag)
3562          (nil? ch)
3563          tags
3564          (open-tag? ch rdr)
3565          (let [{:keys [tag-name args] :as tag} (read-tag-info rdr)]
3566            (if-let [open-tag  (and tag-name (some #{tag-name} end-tags))]
3567                (let [tags     (update-tags cur-tag tags content args buf)
3568                      end-tags (next (drop-while #(not= tag-name %) end-tags))]
3569                  (.setLength buf 0)
3570                  (recur (when-not (empty? end-tags) (read-char rdr)) tags [] open-tag end-tags))
3571                (let [content (append-node content tag buf rdr)]
3572                  (.setLength buf 0)
3573                  (recur (read-char rdr) tags content cur-tag end-tags))))
3574          :else
3575          (do
3576            (.append buf ch)
3577            (recur (read-char rdr) tags content cur-tag end-tags))))))</pre></td></tr><tr><td class="docs">
3578  </td><td class="codes"><pre class="brush: clojure">(defn skip-short-comment-tag [template rdr]
3579    (loop [ch1 (read-char rdr)
3580           ch2 (read-char rdr)]
3581      (cond
3582        (nil? ch2)
3583        (exception &quot;short-form comment tag was not closed&quot;)
3584        (and (= *short-comment-second* ch1) (= *tag-close* ch2))
3585        template
3586        :else (recur ch2 (read-char rdr)))))</pre></td></tr><tr><td class="docs"><p>Compile-time parsing of tags. Accumulates a transient vector
3587  before returning the persistent vector of INodes (TextNode, FunctionNode)</p>
3588  </td><td class="codes"></td></tr><tr><td class="docs">
3589  </td><td class="codes"><pre class="brush: clojure">(defn add-node [template buf rdr]
3590    (let [template (if-let [text (not-empty (.toString ^StringBuilder buf))]
3591                     (conj! template (TextNode. text))
3592                     template)]
3593      (.setLength ^StringBuilder buf 0)
3594      (conj! template (FunctionNode. (parse-tag (read-tag-info rdr) rdr)))))</pre></td></tr><tr><td class="docs">
3595  </td><td class="codes"><pre class="brush: clojure">(defn parse* [input]
3596    (with-open [rdr (clojure.java.io/reader input)]
3597        (let [buf      (StringBuilder.)]
3598          (loop [template (transient [])
3599                 ch (read-char rdr)]
3600            (if ch
3601              (cond
3602                ;; We hit a tag so we append the buffer content to the template
3603                ;; and empty the buffer, then we proceed to parse the tag
3604                (and (open-tag? ch rdr) (some #{(peek-rdr rdr)} [*tag-second* *filter-open*]))
3605                (recur (add-node template buf rdr) (read-char rdr))
3606                ;; Short comment tags are dropped
3607                (open-short-comment? ch rdr)
3608                (recur (skip-short-comment-tag template rdr) (read-char rdr))
3609                ;; Default case, here we append the character and
3610                ;; read the next char
3611                :else
3612                (do
3613                  (.append buf ch)
3614                  (recur template (read-char rdr))))
3615              ;; Add the leftover content of the buffer and return the template
3616              (-&gt;&gt; buf (.toString) (TextNode.) (conj! template) persistent!))))))</pre></td></tr><tr><td class="docs"><p>Primary compile-time parse routine. Work we don't want happening after
3617  first template render. Vector output from parse* gets memoized by render-file.</p>
3618  </td><td class="codes"></td></tr><tr><td class="docs">
3619  </td><td class="codes"><pre class="brush: clojure">(defn parse-input [input &amp; [{:keys [custom-tags custom-filters]}]]
3620    (swap! expr-tags merge custom-tags)
3621    (swap! filters merge custom-filters)
3622    (parse* input))</pre></td></tr><tr><td class="docs"><p>File-aware parse wrapper.</p>
3623  </td><td class="codes"></td></tr><tr><td class="docs">
3624  </td><td class="codes"><pre class="brush: clojure">(defn parse-file [file params]
3625    (-&gt; file preprocess-template (java.io.StringReader.) (parse-input params)))</pre></td></tr><tr><td class="docs">
3626  </td><td class="codes"><pre class="brush: clojure">(defn parse [parse-fn input &amp; [{:keys [tag-open tag-close filter-open filter-close tag-second short-comment-second]
3627                                  :or   {tag-open             *tag-open*
3628                                         tag-close            *tag-close*
3629                                         filter-open          *filter-open*
3630                                         filter-close         *filter-close*
3631                                         tag-second           *tag-second*
3632                                         short-comment-second *short-comment-second*}
3633                                  :as   params}]]
3634    (binding [*tag-open*             tag-open
3635              *tag-close*            tag-close
3636              *filter-open*          filter-open
3637              *filter-close*         filter-close
3638              *tag-second*           tag-second
3639              *short-comment-second* short-comment-second
3640              *tag-second-pattern*   (pattern tag-second)
3641              *filter-open-pattern*  (pattern &quot;\\&quot; tag-open &quot;\\&quot; filter-open &quot;\\s*&quot;)
3642              *filter-close-pattern* (pattern &quot;\\s*\\&quot; filter-close &quot;\\&quot; tag-close)
3643              *filter-pattern*       (pattern &quot;\\&quot; tag-open &quot;\\&quot; filter-open &quot;\\s*.*\\s*\\&quot; filter-close &quot;\\&quot; tag-close)
3644              *tag-open-pattern*     (pattern &quot;\\&quot; tag-open &quot;\\&quot; tag-second &quot;\\s*&quot;)
3645              *tag-close-pattern*    (pattern &quot;\\s*\\&quot; tag-second &quot;\\&quot;  tag-close)
3646              *tag-pattern*          (pattern &quot;\\&quot; tag-open &quot;\\&quot; tag-second &quot;\\s*.*\\s*\\&quot; tag-second &quot;\\&quot; tag-close)
3647              *include-pattern*      (pattern &quot;\\&quot; tag-open &quot;\\&quot; tag-second &quot;\\s*include.*&quot;)
3648              *extends-pattern*      (pattern &quot;\\&quot; tag-open &quot;\\&quot; tag-second &quot;\\s*extends.*&quot;)
3649              *block-pattern*        (pattern &quot;\\&quot; tag-open &quot;\\&quot; tag-second &quot;\\s*block.*&quot;)
3650              *block-super-pattern*  (pattern &quot;\\&quot; tag-open &quot;\\&quot; filter-open &quot;\\s*block.super\\s*\\&quot; filter-close &quot;\\&quot; tag-close)
3651              *endblock-pattern*     (pattern &quot;\\&quot; tag-open &quot;\\&quot; tag-second &quot;\\s*endblock.*&quot;)]
3652      (parse-fn input params)))</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="#selmer.tags" name="selmer.tags"><h1 class="project-name">selmer.tags</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
3653  </td><td class="codes"><pre class="brush: clojure">(ns selmer.tags
3654    (:require selmer.node
3655              [selmer.filter-parser :refer [split-filter-val safe-filter compile-filter-body fix-accessor get-accessor]]
3656              [selmer.filters :refer [filters]]
3657              [selmer.util :refer :all]
3658              [json-html.core :refer [edn-&gt;html]])
3659    (:import [selmer.node INode TextNode FunctionNode]))</pre></td></tr><tr><td class="docs"><p>A tag can modify the context map for its body
3660  It has full control of its body which means that it has to
3661  take care of its compilation.</p>
3662  </td><td class="codes"><pre class="brush: clojure">(defn parse-arg [^String arg]
3663    (fix-accessor (.split arg &quot;\\.&quot;)))</pre></td></tr><tr><td class="docs">
3664  </td><td class="codes"><pre class="brush: clojure">(defn create-value-mappings [context-map ids value]
3665    (if (= 1 (count ids))
3666      (assoc-in context-map (first ids) value)
3667      (reduce
3668        (fn [m [path value]] (assoc-in m path value))
3669        context-map (map vector ids value))))</pre></td></tr><tr><td class="docs">
3670  </td><td class="codes"><pre class="brush: clojure">(defn aggregate-args [args]
3671    (-&gt;&gt; args
3672         (map #(.split ^String % &quot;,&quot;))
3673         (apply concat)
3674         (split-with (partial not= &quot;in&quot;))))</pre></td></tr><tr><td class="docs">
3675  </td><td class="codes"><pre class="brush: clojure">(defn compile-filters [items filter-names]
3676    (map #(compile-filter-body (str items &quot;|&quot; %) false) filter-names))</pre></td></tr><tr><td class="docs">
3677  </td><td class="codes"><pre class="brush: clojure">(defn apply-filters [item filters context-map items]
3678    (reduce
3679      (fn [value filter]
3680        (filter (assoc context-map
3681                       (keyword items) value
3682                       (name items) value)))
3683      item filters))</pre></td></tr><tr><td class="docs">
3684  </td><td class="codes"><pre class="brush: clojure">(defn for-handler [args tag-content render rdr]
3685    (let [content       (tag-content rdr :for :empty :endfor)
3686          for-content   (get-in content [:for :content])
3687          empty-content (get-in content [:empty :content])
3688          [ids [_ items]] (aggregate-args args)
3689          ids           (map parse-arg ids)
3690          [items &amp; filter-names] (if items (.split ^String items &quot;\\|&quot;))
3691          filters       (compile-filters items filter-names)
3692          item-keys     (parse-arg items)]
3693      (fn [context-map]
3694        (let [buf    (StringBuilder.)
3695              items  (-&gt; (reduce get-accessor context-map item-keys)
3696                         (apply-filters filters context-map items))
3697              length (count items)]
3698          (if (and empty-content (empty? items))
3699            (.append buf (render empty-content context-map))
3700            (doseq [[counter value] (map-indexed vector items)]
3701              (let [loop-info
3702                    {:length      length
3703                     :counter0    counter
3704                     :counter     (inc counter)
3705                     :revcounter  (- length (inc counter))
3706                     :revcounter0 (- length counter)
3707                     :first       (= counter 0)
3708                     :last        (= counter (dec length))}]
3709                (-&gt;&gt; (assoc (create-value-mappings context-map ids value)
3710                       :forloop loop-info
3711                       :parentloop loop-info)
3712                     (render for-content)
3713                     (.append buf)))))
3714          (.toString buf)))))</pre></td></tr><tr><td class="docs">
3715  </td><td class="codes"><pre class="brush: clojure">(defn render-if [render context-map condition first-block second-block]
3716    (render
3717      (cond
3718        (and condition first-block)
3719        (:content first-block)
3720        (and (not condition) first-block)
3721        (:content second-block)
3722        condition
3723        (:content second-block)
3724        :else [(TextNode. )])
3725      context-map))</pre></td></tr><tr><td class="docs">
3726  </td><td class="codes"><pre class="brush: clojure">(defn if-result [value]
3727    (condp = value
3728      nil false
3729       false
3730      &quot;false&quot; false
3731      false false
3732      true))</pre></td></tr><tr><td class="docs">
3733  </td><td class="codes"><pre class="brush: clojure">(defn if-default-handler [[condition1 condition2] if-tags else-tags render]
3734    &quot; Handler of if-condition tags. Expects conditions, enclosed
3735    tag-content, render boolean. Returns anonymous fn that will expect
3736    runtime context-map. (Separate from compile-time) &quot;
3737    (let [not?      (and condition1 condition2 (= condition1 &quot;not&quot;))
3738          condition (compile-filter-body (or condition2 condition1))]
3739      (fn [context-map]
3740        (let [condition (if-result (condition context-map))]
3741          (render-if render context-map (if not? (not condition) condition) if-tags else-tags)))))</pre></td></tr><tr><td class="docs">
3742  </td><td class="codes"><pre class="brush: clojure">(defn match-comparator [op]
3743    (condp = op &quot;&gt;&quot; &gt; &quot;&lt;&quot; &lt; &quot;=&quot; == &quot;&gt;=&quot; &gt;= &quot;&lt;=&quot; &lt;=
3744                (exception &quot;Unrecognized operator in 'if' statement: &quot; op)))</pre></td></tr><tr><td class="docs">
3745  </td><td class="codes"><pre class="brush: clojure">(defn- num? [v]
3746    (re-matches #&quot;[0-9]*\.?[0-9]+&quot; v))</pre></td></tr><tr><td class="docs">
3747  </td><td class="codes"><pre class="brush: clojure">(defn- parse-double [v]
3748    (java.lang.Double/parseDouble v))</pre></td></tr><tr><td class="docs">
3749  </td><td class="codes"><pre class="brush: clojure">(defn parse-numeric-params [p1 op p2]
3750    (let [comparator (match-comparator op)]
3751      (cond
3752        (and (not (num? p1)) (not (num? p2)))
3753        [#(comparator (parse-double %1) (parse-double %2)) p1 p2]
3754        (num? p1)
3755        [#(comparator (parse-double p1) (parse-double %)) nil p2]
3756        (num? p2)
3757        [#(comparator (parse-double %) (parse-double p2)) p1 nil])))</pre></td></tr><tr><td class="docs">
3758  </td><td class="codes"><pre class="brush: clojure">(defn render-if-numeric [render negate? [comparator context-key1 context-key2] context-map if-tags else-tags]
3759    (render
3760      (let [[value1 value2]
3761            (cond
3762              (and context-key1 context-key2)
3763              [(not-empty ((compile-filter-body context-key1) context-map))
3764               (not-empty ((compile-filter-body context-key2) context-map))]
3765              context-key1
3766              [(not-empty ((compile-filter-body context-key1) context-map))]
3767              context-key2
3768              [(not-empty ((compile-filter-body context-key2) context-map))])
3769            result (cond
3770                     (and value1 value2)
3771                     (comparator value1 value2)
3772                     value1
3773                     (comparator value1)
3774                     value2
3775                     (comparator value2))]
3776        (or (:content (if (if negate? (not result) result) if-tags else-tags))
3777            [(TextNode. )]))
3778      context-map))</pre></td></tr><tr><td class="docs">
3779  </td><td class="codes"><pre class="brush: clojure">(defn if-numeric-handler [[p1 p2 p3 p4 :as params] if-tags else-tags render]
3780    (cond
3781      (and p4 (not= p1 &quot;not&quot;))
3782      (exception &quot;invalid params for if-tag: &quot; params)
3783      (= &quot;not&quot; p1)
3784      #(render-if-numeric render true (parse-numeric-params p2 p3 p4) % if-tags else-tags)
3785      :else
3786      #(render-if-numeric render false (parse-numeric-params p1 p2 p3) % if-tags else-tags)))</pre></td></tr><tr><td class="docs">
3787  </td><td class="codes"><pre class="brush: clojure">(defn render-if-any-all [not? op params if-tags else-tags render]
3788    (let [filters (map compile-filter-body params)]
3789      (fn [context-map]
3790        (render-if
3791          render
3792          context-map
3793          (let [test (op #{true} (map #(if-result (% context-map)) filters))]
3794            (if not? (not test) test))
3795          if-tags else-tags))))</pre></td></tr><tr><td class="docs">
3796  </td><td class="codes"><pre class="brush: clojure">(defn if-handler [params tag-content render rdr]
3797    (let [{if-tags :if else-tags :else} (tag-content rdr :if :else :endif)]
3798      (cond
3799        (some #{&quot;any&quot; &quot;all&quot;} (take 2 params))
3800        (let [[not? op] (if (= &quot;not&quot; (first params))
3801                          [true (second params)]
3802                          [false (first params)])
3803              params (if not? (drop 2 params) (rest params))]
3804          (render-if-any-all not? (if (= &quot;any&quot; op) some every?) params if-tags else-tags render))
3805        (&lt; (count params) 3)
3806        (if-default-handler params if-tags else-tags render)
3807        :else
3808        (if-numeric-handler params if-tags else-tags render))))</pre></td></tr><tr><td class="docs">
3809  </td><td class="codes"><pre class="brush: clojure">(defn compare-tag [args comparator render success failure]
3810    (fn [context-map]
3811      (let [condition (apply comparator (map #(if (fn? %) (% context-map) %) args))]
3812        (render-if render context-map condition success failure))))</pre></td></tr><tr><td class="docs">
3813  </td><td class="codes"><pre class="brush: clojure">(defn parse-eq-args [args]
3814    (for [^String arg args]
3815      (cond
3816        (= \&quot; (first arg))
3817        (.substring arg 1 (dec (.length arg)))
3818        (= \: (first arg))
3819        arg
3820        :else
3821        (compile-filter-body arg))))</pre></td></tr><tr><td class="docs">
3822  </td><td class="codes"><pre class="brush: clojure">(defn ifequal-handler [args tag-content render rdr]
3823    (let [{:keys [ifequal else]} (tag-content rdr :ifequal :else :endifequal)
3824          args (parse-eq-args args)]
3825      (compare-tag args = render ifequal else)))</pre></td></tr><tr><td class="docs">
3826  </td><td class="codes"><pre class="brush: clojure">(defn ifunequal-handler [args tag-content render rdr]
3827    (let [{:keys [ifunequal else]} (tag-content rdr :ifunequal :else :endifunequal)
3828          args (parse-eq-args args)]
3829      (compare-tag args not= render ifunequal else)))</pre></td></tr><tr><td class="docs">
3830  </td><td class="codes"><pre class="brush: clojure">(defn block-handler [args tag-content render rdr]
3831    (let [content (get-in (tag-content rdr :block :endblock) [:block :content])]
3832      (fn [context-map] (render content context-map))))</pre></td></tr><tr><td class="docs">
3833  </td><td class="codes"><pre class="brush: clojure">(defn sum-handler [args _ _ _]
3834    (fn [context-map]
3835      (reduce + (map (fn [val]
3836                       (let [accessor (split-filter-val val)]
3837                         (get-in context-map accessor))) args))))</pre></td></tr><tr><td class="docs">
3838  </td><td class="codes"><pre class="brush: clojure">(defn now-handler [args _ _ _]
3839    (fn [context-map]
3840      ((:date @filters) (java.util.Date.) (clojure.string/join &quot; &quot; args))))</pre></td></tr><tr><td class="docs">
3841  </td><td class="codes"><pre class="brush: clojure">(defn comment-handler [args tag-content render rdr]
3842    (let [content (tag-content rdr :comment :endcomment)]
3843      (fn [_]
3844        (render (filter (partial instance? selmer.node.TextNode) content) {}))))</pre></td></tr><tr><td class="docs">
3845  </td><td class="codes"><pre class="brush: clojure">(defn first-of-handler [args _ _ _]
3846    (let [args (map compile-filter-body args)]
3847      (fn [context-map]
3848        (let [first-true (-&gt;&gt; args (map #(% context-map)) (remove empty?) (drop-while false?) first)]
3849          (or first-true )))))</pre></td></tr><tr><td class="docs">
3850  </td><td class="codes"><pre class="brush: clojure">(defn read-verbatim [rdr]
3851    (-&gt;buf [buf]
3852           (loop [ch (read-char rdr)]
3853             (when ch
3854               (cond
3855                 (open-tag? ch rdr)
3856                 (let [tag (read-tag-content rdr)]
3857                   (if-not (re-matches #&quot;\{\%\s*endverbatim\s*\%\}&quot; tag)
3858                     (do (.append buf tag)
3859                         (recur (read-char rdr)))))
3860                 :else
3861                 (do
3862                   (.append buf ch)
3863                   (recur (read-char rdr))))))))</pre></td></tr><tr><td class="docs">
3864  </td><td class="codes"><pre class="brush: clojure">(defn verbatim-handler [args _ render rdr]
3865    (let [content (read-verbatim rdr)]
3866      (fn [context-map] content)))</pre></td></tr><tr><td class="docs">
3867  </td><td class="codes"><pre class="brush: clojure">(defn compile-args [args]
3868    (when-not (even? (count args))
3869      (exception &quot;invalid arguments passed to 'with' tag: &quot; args))
3870    (for [[id value] (partition 2 args)]
3871      [(keyword id) (compile-filter-body value false)]))</pre></td></tr><tr><td class="docs">
3872  </td><td class="codes"><pre class="brush: clojure">(defn with-handler [args tag-content render rdr]
3873    (let [content (get-in (tag-content rdr :with :endwith) [:with :content])
3874          args    (-&gt;&gt; args
3875                       (mapcat #(.split ^String % &quot;=&quot;))
3876                       (remove #{&quot;=&quot;})
3877                       (compile-args))]
3878      (fn [context-map]
3879        (render content
3880                (reduce
3881                  (fn [context-map [k v]]
3882                    (assoc context-map k (v context-map)))
3883                  context-map args)))))</pre></td></tr><tr><td class="docs"><p>Accepts <code>uri</code> passed in as first argument to {% script %} or {% style %} tag
3884    and context map. Returns string - new URI built with value of
3885    <code>selmer/context</code> context parameter in mind. <code>uri</code> can be a string literal or
3886    name of context parameter (filters also supported).</p>
3887  </td><td class="codes"><pre class="brush: clojure">(defn- build-uri-for-script-or-style-tag
3888    [^String uri {:keys [selmer/context] :as context-map}]
3889    (let [literal? (and (.startsWith uri &quot;\&quot;&quot;) (.endsWith uri &quot;\&quot;&quot;))
3890          uri
3891          (if literal?
3892            (.replace uri &quot;\&quot;&quot; &quot;&quot;)     ; case of {% style &quot;/css/foo.css&quot; %}
3893            (-&gt; uri                    ; case of {% style context-param|some-filter:arg1:arg2 %}
3894                (compile-filter-body)
3895                (apply [context-map])))]
3896      (-&gt; selmer/context (str uri) (.replace &quot;//&quot; &quot;/&quot;))))</pre></td></tr><tr><td class="docs"><p>Returns function that renders HTML <code>&lt;SCRIPT/&gt;</code> tag. Accepts <code>uri</code> that would
3897    be used to build value for 'src' attribute of generated tag and variable
3898    number of optional arguments. Value for 'src' attribute is built accounting
3899    value of <code>selmer/context</code> context parameter and <code>uri</code> can be a string literal
3900    or name of context parameter (filters also supported). Optional arguments are:
3901    * <code>async</code> - when evaluates to logical true then 'async' attribute would be
3902      added to generated tag.</p>
3903  </td><td class="codes"><pre class="brush: clojure">(defn script-handler
3904    [[^String uri &amp; args] _ _ _]
3905    (let [args
3906          (-&gt;&gt; args
3907               (mapcat #(.split ^String % &quot;=&quot;))
3908               (remove #{&quot;=&quot;})
3909               (compile-args))]
3910      (fn [{:keys [selmer/context] :as context-map}]
3911        (let [args
3912              (reduce
3913               (fn [context-map [k v]]
3914                 (assoc context-map k (v context-map)))
3915               context-map
3916               args)
3917              async-attr (when (:async args) &quot;async &quot;)
3918              src-attr-val (build-uri-for-script-or-style-tag uri context-map)]
3919          (str &quot;&lt;script &quot; async-attr &quot;src=\&quot;&quot; src-attr-val &quot;\&quot; type=\&quot;text/javascript\&quot;&gt;&lt;/script&gt;&quot;)))))</pre></td></tr><tr><td class="docs"><p>Returns function that renders HTML <code>&lt;LINK/&gt;</code> tag. Accepts <code>uri</code> that would
3920    be used to build value for 'href' attribute of generated tag. Value for 'href'
3921    attribute is built accounting value of <code>selmer/context</code> context parameter and
3922    <code>uri</code> can be a string literal or name of context parameter (filters also
3923    supported).</p>
3924  </td><td class="codes"><pre class="brush: clojure">(defn style-handler
3925    [[^String uri] _ _ _]
3926    (fn [{:keys [selmer/context] :as context-map}]
3927      (let [href-attr-val (build-uri-for-script-or-style-tag uri context-map)]
3928        (str &quot;&lt;link href=\&quot;&quot; href-attr-val &quot;\&quot; rel=\&quot;stylesheet\&quot; type=\&quot;text/css\&quot; /&gt;&quot;))))</pre></td></tr><tr><td class="docs">
3929  </td><td class="codes"><pre class="brush: clojure">(defn cycle-handler [args _ _ _]
3930    (let [fields (vec args)
3931          length (dec (count fields))
3932          i      (int-array [0])]
3933      (fn [_]
3934        (let [cur-i (aget i 0)
3935              val   (fields cur-i)]
3936          (aset i 0 (if (&lt; cur-i length) (inc cur-i) 0))
3937          val))))</pre></td></tr><tr><td class="docs">
3938  </td><td class="codes"><pre class="brush: clojure">(defn safe-handler [args tag-content render rdr]
3939    (let [content (get-in (tag-content rdr :safe :endsafe) [:safe :content])]
3940      (fn [context-map]
3941        (render content (assoc context-map safe-filter true)))))</pre></td></tr><tr><td class="docs">
3942  </td><td class="codes"><pre class="brush: clojure">(defn debug-handler [_ _ _ _]
3943    (fn [context-map]
3944      (str
3945        &quot;&lt;style&gt;&quot;
3946        (-&gt; &quot;json.human.css&quot; clojure.java.io/resource slurp)
3947        &quot;&lt;/style&gt;&quot;
3948        (edn-&gt;html context-map))))</pre></td></tr><tr><td class="docs"><p>expr-tags are {% if ... %}, {% ifequal ... %},
3949  {% for ... %}, and {% block blockname %}</p>
3950  </td><td class="codes"></td></tr><tr><td class="docs">
3951  </td><td class="codes"><pre class="brush: clojure">(defonce expr-tags
3952           (atom {:if        if-handler
3953                  :ifequal   ifequal-handler
3954                  :ifunequal ifunequal-handler
3955                  :sum       sum-handler
3956                  :for       for-handler
3957                  :block     block-handler
3958                  :cycle     cycle-handler
3959                  :now       now-handler
3960                  :comment   comment-handler
3961                  :firstof   first-of-handler
3962                  :verbatim  verbatim-handler
3963                  :with      with-handler
3964                  :script    script-handler
3965                  :style     style-handler
3966                  :safe      safe-handler
3967                  :debug     debug-handler
3968                  :extends   nil
3969                  :include   nil}))</pre></td></tr><tr><td class="docs">
3970  </td><td class="codes"><pre class="brush: clojure">(defonce closing-tags
3971           (atom {:if        [:else :endif]
3972                  :else      [:endif :endifequal :endifunequal]
3973                  :ifequal   [:else :endifequal]
3974                  :ifunequal [:else :endifunequal]
3975                  :block     [:endblock]
3976                  :for       [:empty :endfor]
3977                  :empty     [:endfor]
3978                  :comment   [:endcomment]
3979                  :safe      [:endsafe]
3980                  :verbatim  [:endverbatim]
3981                  :with      [:endwith]}))</pre></td></tr><tr><td class="docs"><p>helpers for custom tag definition</p>
3982  </td><td class="codes"><pre class="brush: clojure">(defn render-tags [context-map tags]
3983    (into {}
3984          (for [[tag content] tags]
3985            [tag
3986             (update-in content [:content]
3987                        (fn [^selmer.node.INode node]
3988                          (clojure.string/join (map #(.render-node ^selmer.node.INode % context-map) node))))])))</pre></td></tr><tr><td class="docs">
3989  </td><td class="codes"><pre class="brush: clojure">(defn tag-handler [handler &amp; tags]
3990    (fn [args tag-content render rdr]
3991      (if-let [content (if (&gt; (count tags) 1) (apply (partial tag-content rdr) tags))]
3992        (fn [context-map]
3993          (render
3994            [(-&gt;&gt; content (render-tags context-map) (handler args context-map) (TextNode.))]
3995            context-map))
3996        (fn [context-map]
3997          (handler args context-map)))))</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="#selmer.template-parser" name="selmer.template-parser"><h1 class="project-name">selmer.template-parser</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs"><p> Where we preprocess the inheritance and mixin components of the templates.
3998    These are presumed to be static and we only aggregate them on the first
3999    template render. The compile-time tag parsing routines happen on a flat string
4000    composed from the result of <code>extends</code> inheritance and <code>include</code> mixins. </p>
4001  </td><td class="codes"><pre class="brush: clojure">(ns selmer.template-parser
4002    (:require [clojure.java.io :refer [reader]]
4003              [selmer.util :refer :all]
4004              [clojure.string :as s :refer [split trim]]
4005              [selmer.validator :as validator])
4006    (:import java.io.StringReader))</pre></td></tr><tr><td class="docs">
4007  </td><td class="codes"><pre class="brush: clojure">(declare consume-block preprocess-template)</pre></td></tr><tr><td class="docs">
4008  </td><td class="codes"><pre class="brush: clojure">(defn get-tag-params [tag-id block-str]
4009    (let [tag-id (re-pattern (str &quot;^.+?&quot; tag-id &quot;\\s*&quot;))]
4010      (-&gt; block-str (s/replace tag-id ) (split *tag-second-pattern*) first trim)))</pre></td></tr><tr><td class="docs">
4011  </td><td class="codes"><pre class="brush: clojure">(defn parse-defaults [defaults]
4012    (when defaults
4013      (-&gt;&gt; defaults
4014           (interpose &quot; &quot;)
4015           (apply str)
4016           split-by-args
4017           (partition 2)
4018           (map vec)
4019           (into {}))))</pre></td></tr><tr><td class="docs">
4020  </td><td class="codes"><pre class="brush: clojure">(defn split-include-tag [^String tag-str]
4021    (seq (.split ^String (get-tag-params &quot;include&quot; (.replace tag-str &quot;\\&quot; &quot;/&quot;)) &quot; &quot;)))</pre></td></tr><tr><td class="docs">
4022  </td><td class="codes"><pre class="brush: clojure">(defn string-&gt;reader [string]
4023    (reader (StringReader. string)))</pre></td></tr><tr><td class="docs"><p>parse any included templates and splice them in replacing the include tags</p>
4024  </td><td class="codes"><pre class="brush: clojure">(defn insert-includes
4025    [template]
4026    ;; We really need to split out the &quot;gather all parent templates recursively&quot;
4027    ;; and separate that from the buffer appending so we can gather the template
4028    ;; hierarchy for smarter cache invalidation - will eliminate almost all
4029    ;; existing reasons for cache-off!
4030    (-&gt;buf [buf]
4031           (with-open [rdr (reader (StringReader. template))]
4032             (loop [ch (read-char rdr)]
4033               (when ch
4034                 (if (and (= *tag-open* ch) (= *tag-second* (peek-rdr rdr)))
4035                   (let [tag-str (read-tag-content rdr)]
4036                     (.append buf
4037                              (if (re-matches *include-pattern* tag-str)
4038                                (let [params   (split-include-tag tag-str)
4039                                      source   (.replaceAll ^String (first params) &quot;\&quot;&quot; &quot;&quot;)
4040                                      defaults (parse-defaults (nnext params))]
4041                                  (preprocess-template source {} defaults))
4042                                tag-str)))
4043                   (.append buf ch))
4044                 (recur (read-char rdr)))))))</pre></td></tr><tr><td class="docs">
4045  </td><td class="codes"><pre class="brush: clojure">(defn get-parent [tag-str]
4046    (let [template (get-tag-params &quot;extends&quot; tag-str)]
4047      (.substring ^String template 1 (dec (.length ^String template)))))</pre></td></tr><tr><td class="docs">
4048  </td><td class="codes"><pre class="brush: clojure">(defn write-tag? [buf super-tag? existing-block blocks-to-close omit-close-tag?]
4049    (and buf
4050         (or super-tag?
4051             (and
4052               (not existing-block)
4053               (&gt; blocks-to-close (if omit-close-tag? 1 0))))))</pre></td></tr><tr><td class="docs">
4054  </td><td class="codes"><pre class="brush: clojure">(defn consume-block [rdr &amp; [^StringBuilder buf blocks omit-close-tag?]]
4055    (loop [blocks-to-close 1
4056           has-super? false]
4057      (if (and (pos? blocks-to-close) (peek-rdr rdr))
4058        (let [ch (read-char rdr)]
4059          (if (open-tag? ch rdr)
4060            (let [tag-str        (read-tag-content rdr)
4061                  block?         (re-matches *block-pattern* tag-str)
4062                  block-name     (if block? (get-tag-params &quot;block&quot; tag-str))
4063                  super-tag?     (re-matches *block-super-pattern* tag-str)
4064                  existing-block (if block-name (get-in blocks [block-name :content]))]
4065              ;;check if we wish to write the closing tag for the block. If we're
4066              ;;injecting block.super, then we want to omit it
4067              (when (write-tag? buf super-tag? existing-block blocks-to-close omit-close-tag?)
4068                (.append buf tag-str))
4069              (recur
4070                (long
4071                  (cond
4072                    existing-block
4073                    (do
4074                      (consume-block rdr)
4075                      (consume-block
4076                        (StringReader. existing-block) buf (dissoc blocks block-name))
4077                      blocks-to-close)
4078                    block?
4079                    (inc blocks-to-close)
4080                    (re-matches *endblock-pattern* tag-str)
4081                    (dec blocks-to-close)
4082                    :else blocks-to-close))
4083                (or has-super? super-tag?)))
4084            (do
4085              (when buf (.append buf ch))
4086              (recur blocks-to-close has-super?))))
4087        (boolean has-super?))))</pre></td></tr><tr><td class="docs">
4088  </td><td class="codes"><pre class="brush: clojure">(defn rewrite-super [block parent-content]
4089    (clojure.string/replace block *block-super-pattern* parent-content))</pre></td></tr><tr><td class="docs">
4090  </td><td class="codes"><pre class="brush: clojure">(defn read-block [rdr block-tag blocks]
4091    (let [block-name     (get-tag-params &quot;block&quot; block-tag)
4092          existing-block (get blocks block-name)]
4093      (cond
4094        ;;we have a child block with a {{block.super}} tag, we'll need to
4095        ;;grab the contents of the parent and inject them in the child
4096        (:super existing-block)
4097        (let [child-content  (:content existing-block)
4098              parent-content (StringBuilder.)
4099              has-super?     (consume-block rdr parent-content blocks true)]
4100          (assoc blocks block-name
4101                 {:super has-super?
4102                  :content (rewrite-super child-content (.toString parent-content))}))
4103        ;;we've got a child block without a super tag, the parent will be replaced
4104        existing-block
4105        (do (consume-block rdr) blocks)
4106        ;;this is the first occurance of the block and we simply add it to the
4107        ;;map of blocks we've already seen
4108        :else
4109        (let [buf        (doto (StringBuilder.) (.append block-tag))
4110              has-super? (consume-block rdr buf blocks)]
4111          (assoc blocks block-name
4112                 {:super has-super?
4113                  :content (.toString buf)})))))</pre></td></tr><tr><td class="docs">
4114  </td><td class="codes"><pre class="brush: clojure">(defn process-block [rdr buf block-tag blocks]
4115    (let [block-name (get-tag-params &quot;block&quot; block-tag)]
4116      (if-let [child-content (get-in blocks [block-name :content])]
4117        (.append ^StringBuilder buf
4118                 (rewrite-super
4119                   child-content
4120                   (-&gt;buf [buf] (consume-block rdr buf blocks true))))
4121        (do
4122          (.append ^StringBuilder buf block-tag)
4123          (consume-block rdr buf blocks)))))</pre></td></tr><tr><td class="docs">
4124  </td><td class="codes"><pre class="brush: clojure">(defn wrap-in-expression-tag [string]
4125    (str *tag-open* *tag-second* string *tag-second* *tag-close*))</pre></td></tr><tr><td class="docs">
4126  </td><td class="codes"><pre class="brush: clojure">(defn wrap-in-variable-tag [string]
4127    (str *tag-open* *filter-open* string *filter-close* *tag-close*))</pre></td></tr><tr><td class="docs">
4128  </td><td class="codes"><pre class="brush: clojure">(defn trim-regex [string &amp; regexes]
4129    (reduce #(clojure.string/replace %1 %2 ) string regexes))</pre></td></tr><tr><td class="docs">
4130  </td><td class="codes"><pre class="brush: clojure">(defn trim-variable-tag [string]
4131    (trim-regex string *filter-open-pattern* *filter-close-pattern*))</pre></td></tr><tr><td class="docs">
4132  </td><td class="codes"><pre class="brush: clojure">(defn trim-expression-tag [string]
4133    (trim-regex string *tag-open-pattern* *tag-close-pattern*))</pre></td></tr><tr><td class="docs">
4134  </td><td class="codes"><pre class="brush: clojure">(defn to-expression-string [tag-name args]
4135    (let [tag-name' (name tag-name)
4136          args' (clojure.string/join \space args)
4137          joined (if (seq args) (str tag-name' \space args') tag-name')]
4138      (wrap-in-expression-tag joined)))</pre></td></tr><tr><td class="docs">
4139  </td><td class="codes"><pre class="brush: clojure">(defn add-default [identifier default]
4140    (str identifier &quot;|default:&quot; \&quot; default \&quot;))</pre></td></tr><tr><td class="docs">
4141  </td><td class="codes"><pre class="brush: clojure">(defn try-add-default [identifier defaults]
4142    (if-let [default (get defaults identifier)]
4143      (add-default identifier default)
4144      identifier))</pre></td></tr><tr><td class="docs">
4145  </td><td class="codes"><pre class="brush: clojure">(defn add-defaults-to-variable-tag [tag-str defaults]
4146    (let [tag-name (trim-variable-tag tag-str)]
4147      (wrap-in-variable-tag (try-add-default tag-name defaults))))</pre></td></tr><tr><td class="docs">
4148  </td><td class="codes"><pre class="brush: clojure">(defn add-defaults-to-expression-tag [tag-str defaults]
4149    (let [tag-str' (-&gt;&gt; (trim-expression-tag tag-str)
4150                        ;; NOTE: we add a character here since read-tag-info
4151                        ;; consumes the first character before parsing.
4152                        (str *tag-second*))
4153          {:keys [tag-name args]} (read-tag-info (string-&gt;reader tag-str')) ]
4154      (to-expression-string tag-name (map #(try-add-default % defaults) args))))</pre></td></tr><tr><td class="docs">
4155  </td><td class="codes"><pre class="brush: clojure">(defn get-template-path [template]
4156    (resource-path template))</pre></td></tr><tr><td class="docs">
4157  </td><td class="codes"><pre class="brush: clojure">(defn read-template [template blocks defaults]
4158    (let [path (resource-path template)]
4159      (when-not path
4160        (validator/validation-error
4161          (str &quot;resource-path for &quot; template &quot; returned nil, typically means the file doesn't exist in your classpath.&quot;)
4162          nil nil nil))
4163      (validator/validate path)
4164      (check-template-exists (get-template-path template))
4165      (let [buf (StringBuilder.)
4166            [parent blocks]
4167            (with-open [rdr (reader path)]
4168              (loop [blocks (or blocks {})
4169                     ch     (read-char rdr)
4170                     parent nil]
4171                (cond
4172                  (nil? ch) [parent blocks]
4173                  (open-tag? ch rdr)
4174                  (let [tag-str (read-tag-content rdr)]
4175                    (cond
4176                      (and defaults
4177                           (re-matches *filter-pattern* tag-str))
4178                      (do (.append buf (add-defaults-to-variable-tag tag-str defaults))
4179                          (recur blocks (read-char rdr) parent))
4180                      (and defaults
4181                           (re-matches *tag-pattern* tag-str))
4182                      (do (.append buf (add-defaults-to-expression-tag tag-str defaults))
4183                          (recur blocks (read-char rdr) parent))
4184                      ;;if the template extends another it's not the root
4185                      ;;this template is allowed to only contain blocks
4186                      (re-matches *extends-pattern* tag-str)
4187                      (recur blocks (read-char rdr) (get-parent tag-str))
4188                      ;;if we have a parent then we simply want to add the
4189                      ;;block to the block map if it hasn't been added already
4190                      (and parent (re-matches *block-pattern* tag-str))
4191                      (recur (read-block rdr tag-str blocks) (read-char rdr) parent)
4192                      ;;if the template has blocks, but no parent it's the root
4193                      ;;we either replace the block with an existing one from a child
4194                      ;;template or read the block from this template
4195                      (re-matches *block-pattern* tag-str)
4196                      (do
4197                        (process-block rdr buf tag-str blocks)
4198                        (recur blocks (read-char rdr) parent))
4199                      ;;if we are in the root template we'll accumulate the content
4200                      ;;into a buffer, this will be the resulting template string
4201                      (nil? parent)
4202                      (do
4203                        (.append buf tag-str)
4204                        (recur blocks (read-char rdr) parent))))
4205                  :else
4206                  (do
4207                    (if (nil? parent) (.append buf ch))
4208                    (recur blocks (read-char rdr) parent)))))]
4209        (if parent (recur parent blocks defaults) (.toString buf)))))</pre></td></tr><tr><td class="docs">
4210  </td><td class="codes"><pre class="brush: clojure">(defn preprocess-template [template &amp; [blocks defaults]]
4211    (insert-includes (read-template template blocks defaults)))</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="#selmer.util" name="selmer.util"><h1 class="project-name">selmer.util</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
4212  </td><td class="codes"><pre class="brush: clojure">(ns selmer.util
4213    (:import java.io.StringReader
4214             java.util.regex.Pattern))</pre></td></tr><tr><td class="docs">
4215  </td><td class="codes"><pre class="brush: clojure">(defmacro exception [&amp; [param &amp; more :as params]]
4216    (if (class? param)
4217      `(throw (new ~param (str ~@more)))
4218      `(throw (Exception. (str ~@params)))))</pre></td></tr><tr><td class="docs">
4219  </td><td class="codes"><pre class="brush: clojure">(def ^:dynamic *custom-resource-path* nil)</pre></td></tr><tr><td class="docs">
4220  </td><td class="codes"><pre class="brush: clojure">(defn set-custom-resource-path!
4221    [path]
4222    (alter-var-root #'*custom-resource-path* (constantly path))
4223    (when (thread-bound? #'*custom-resource-path*)
4224      (set! *custom-resource-path* path)))</pre></td></tr><tr><td class="docs">
4225  </td><td class="codes"><pre class="brush: clojure">(def ^:dynamic *escape-variables* true)</pre></td></tr><tr><td class="docs">
4226  </td><td class="codes"><pre class="brush: clojure">(defn turn-off-escaping! []
4227    (alter-var-root #'*escape-variables*
4228                    (constantly false)))</pre></td></tr><tr><td class="docs">
4229  </td><td class="codes"><pre class="brush: clojure">(defn turn-on-escaping! []
4230    (alter-var-root #'*escape-variables*
4231                    (constantly true)))</pre></td></tr><tr><td class="docs">
4232  </td><td class="codes"><pre class="brush: clojure">(defmacro with-escaping [&amp; body]
4233    `(binding [*escape-variables* true]
4234       ~@body))</pre></td></tr><tr><td class="docs">
4235  </td><td class="codes"><pre class="brush: clojure">(defmacro without-escaping [&amp; body]
4236    `(binding [*escape-variables* false]
4237       ~@body))</pre></td></tr><tr><td class="docs">
4238  </td><td class="codes"><pre class="brush: clojure">(defn pattern [&amp; content]
4239    (re-pattern (clojure.string/join content)))</pre></td></tr><tr><td class="docs">
4240  </td><td class="codes"><pre class="brush: clojure">(defn read-char [^java.io.Reader rdr]
4241    (let [ch (.read rdr)]
4242      (if-not (== -1 ch) (char ch))))</pre></td></tr><tr><td class="docs"><p>Works best for small collections seemingly.</p>
4243  </td><td class="codes"><pre class="brush: clojure">(defn assoc-in*
4244    [m ks v]
4245    (let [k (first ks)]
4246      (if (zero? (count ks))
4247        (assoc m k (assoc-in* (get m k) (next ks) v))
4248        (assoc m k v))))</pre></td></tr><tr><td class="docs"><p>default tag characters</p>
4249  </td><td class="codes"><pre class="brush: clojure">(def ^:dynamic ^Character *tag-open* \{)
4250  (def ^:dynamic ^Character *tag-close* \})
4251  (def ^:dynamic ^Character *filter-open* \{)
4252  (def ^:dynamic ^Character *filter-close* \})
4253  (def ^:dynamic ^Character *tag-second* \%)
4254  (def ^:dynamic ^Character *short-comment-second* \#)</pre></td></tr><tr><td class="docs"><p>tag regex patterns</p>
4255  </td><td class="codes"><pre class="brush: clojure">(def ^:dynamic ^Pattern *tag-second-pattern* nil)
4256  (def ^:dynamic ^Pattern *filter-open-pattern* nil)
4257  (def ^:dynamic ^Pattern *filter-close-pattern* nil)
4258  (def ^:dynamic ^Pattern *filter-pattern* nil)
4259  (def ^:dynamic ^Pattern *tag-open-pattern* nil)
4260  (def ^:dynamic ^Pattern *tag-close-pattern* nil)
4261  (def ^:dynamic ^Pattern *tag-pattern* nil)
4262  (def ^:dynamic ^Pattern *include-pattern* nil)
4263  (def ^:dynamic ^Pattern *extends-pattern* nil)
4264  (def ^:dynamic ^Pattern *block-pattern* nil)
4265  (def ^:dynamic ^Pattern *block-super-pattern* nil)
4266  (def ^:dynamic ^Pattern *endblock-pattern* nil)</pre></td></tr><tr><td class="docs">
4267  </td><td class="codes"><pre class="brush: clojure">(def match-unquoted &quot; *(?=(?:[^\&quot;]*\&quot;[^\&quot;]*\&quot;)*[^\&quot;]*$)&quot;)</pre></td></tr><tr><td class="docs">
4268  </td><td class="codes"><pre class="brush: clojure">(defn check-tag-args [args]
4269    (if (even? (count (filter #{\&quot;} args)))
4270      args (exception &quot;malformed tag arguments in &quot; args)))</pre></td></tr><tr><td class="docs">
4271  </td><td class="codes"><pre class="brush: clojure">(defn read-tag-info [rdr]
4272    (let [buf      (StringBuilder.)
4273          tag-type (if (= *filter-open* (read-char rdr)) :filter :expr)]
4274      (loop [ch1 (read-char rdr)
4275             ch2 (read-char rdr)]
4276        (when-not (or (nil? ch1)
4277                      (and (or (= *filter-close* ch1) (= *tag-second* ch1))
4278                           (= *tag-close* ch2)))
4279          (.append buf ch1)
4280          (recur ch2 (read-char rdr))))
4281      (let [content (-&gt;&gt; (.toString buf)
4282                         (check-tag-args)
4283                         (re-seq #&quot;(?:[^\s\&quot;]|\&quot;[^\&quot;]*\&quot;)+&quot;)
4284                         (remove empty?)
4285                         (map (fn [^String s] (.trim s))))]
4286        (merge {:tag-type tag-type}
4287               (if (= :filter tag-type)
4288                 {:tag-value (first content)}
4289                 {:tag-name (keyword (first content))
4290                  :args     (next content)})))))</pre></td></tr><tr><td class="docs">
4291  </td><td class="codes"><pre class="brush: clojure">(defn peek-rdr [^java.io.Reader rdr]
4292    (.mark rdr 1)
4293    (let [result (read-char rdr)]
4294      (.reset rdr)
4295      result))</pre></td></tr><tr><td class="docs">
4296  </td><td class="codes"><pre class="brush: clojure">(defmacro -&gt;buf [[buf] &amp; body]
4297    `(let [~buf (StringBuilder.)]
4298       (do ~@body)
4299       (.toString ~buf)))</pre></td></tr><tr><td class="docs">
4300  </td><td class="codes"><pre class="brush: clojure">(defn read-tag-content [rdr]
4301    (-&gt;buf [buf]
4302           (let [next-ch (peek-rdr rdr)
4303                 filter? (not= *tag-second* next-ch)]
4304             (.append buf *tag-open*)
4305             (when next-ch
4306               (loop [ch (read-char rdr)]
4307                 (.append buf ch)
4308                 (when (and (not= *tag-close* ch) (not= *filter-close* ch))
4309                   (recur (read-char rdr))))
4310               (when filter?
4311                 (.append buf (read-char rdr)))))))</pre></td></tr><tr><td class="docs">
4312  </td><td class="codes"><pre class="brush: clojure">(defn open-tag? [ch rdr]
4313    (and (= *tag-open* ch)
4314         (let [next-ch (peek-rdr rdr)]
4315           (or (= *filter-open* next-ch)
4316               (= *tag-second* next-ch)))))</pre></td></tr><tr><td class="docs">
4317  </td><td class="codes"><pre class="brush: clojure">(defn open-short-comment? [ch rdr]
4318    (and (= *tag-open* ch)
4319         (let [next-ch (peek-rdr rdr)]
4320           (= *short-comment-second* next-ch))))</pre></td></tr><tr><td class="docs">
4321  </td><td class="codes"><pre class="brush: clojure">(defn split-by-args [s]
4322    (let [rdr (StringReader. s)
4323          buf (StringBuilder.)]
4324      (loop [items []
4325             ch    (read-char rdr)
4326             open? false]
4327        (cond
4328          (nil? ch) items
4329          (and open? (= ch \&quot;))
4330          (let [value (.trim (.toString buf))]
4331            (.setLength buf 0)
4332            (recur (conj items value) (read-char rdr) false))
4333          (= ch \&quot;)
4334          (recur items (read-char rdr) true)
4335          (and (not open?) (= ch \=))
4336          (let [id (.trim (.toString buf))]
4337            (.setLength buf 0)
4338            (recur (conj items id) (read-char rdr) open?))
4339          :else
4340          (do
4341            (.append buf ch)
4342            (recur items (read-char rdr) open?))))))</pre></td></tr><tr><td class="docs">
4343  </td><td class="codes"><pre class="brush: clojure">(defn get-resource [resource]
4344    (-&gt; (Thread/currentThread)
4345        (.getContextClassLoader)
4346        (.getResource resource)))</pre></td></tr><tr><td class="docs">
4347  </td><td class="codes"><pre class="brush: clojure">(defn resource-path [template]
4348    (if (instance? java.net.URL template)
4349      template
4350      (if-let [path *custom-resource-path*]
4351        (java.net.URL. (str path template))
4352        (get-resource template))))</pre></td></tr><tr><td class="docs">
4353  </td><td class="codes"><pre class="brush: clojure">(defn resource-last-modified [^java.net.URL resource]
4354    (let [path (.getPath resource)]
4355      (try
4356        (.lastModified (java.io.File. ^String path))
4357        (catch NullPointerException _ -1))))</pre></td></tr><tr><td class="docs">
4358  </td><td class="codes"><pre class="brush: clojure">(defn check-template-exists [^java.net.URL resource]
4359    (when-not resource
4360      (exception &quot;template: \ (.getPath ^java.net.URL resource) &quot;\&quot; not found&quot;)))</pre></td></tr><tr><td class="docs">
4361  </td><td class="codes"><pre class="brush: clojure">(def default-missing-value-formatter (constantly ))</pre></td></tr><tr><td class="docs">
4362  </td><td class="codes"><pre class="brush: clojure">(def ^:dynamic *missing-value-formatter* default-missing-value-formatter)
4363  (def ^:dynamic *filter-missing-values* true)</pre></td></tr><tr><td class="docs"><p>Takes a function of two arguments which is called on a missing value.
4364     The function should return the value to be output in place of an empty string
4365     (which is the default from 'default-missing-value-formatter').</p>
4366  
4367  <p>   Call with named argument :filter-missing-values true to force filtering of missing
4368     values (although for most use cases this will not make sense).</p>
4369  
4370  <p>   Arguments to missing-value-fn:
4371     tag - map with data for the tag being evaluated.
4372           Contains the key :tag-type with the value :filter or :expr (for filter or expression tag types.
4373           For :filter:
4374              tag-value - the contents of the filter tag as a string.
4375           For :expr:
4376              tag-name - the name of the expression.
4377              args - the args provided to the expression.
4378     context-map - the context-map provided to the render function.</p>
4379  </td><td class="codes"><pre class="brush: clojure">(defn set-missing-value-formatter!
4380    [missing-value-fn &amp; {:keys [filter-missing-values] :or {filter-missing-values false}}]
4381    (alter-var-root #'*missing-value-formatter* (constantly missing-value-fn))
4382    (alter-var-root #'*filter-missing-values* (constantly filter-missing-values)))</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="#selmer.validator" name="selmer.validator"><h1 class="project-name">selmer.validator</h1><a class="toc-link" href="#toc">toc</a></a></div></td><td class="codes" /></tr><tr><td class="docs">
4383  </td><td class="codes"><pre class="brush: clojure">(ns selmer.validator
4384   (:use selmer.tags
4385         selmer.filters
4386         selmer.util
4387         [clojure.set :only [difference]]
4388         [clojure.java.io :only [reader]]))</pre></td></tr><tr><td class="docs">
4389  </td><td class="codes"><pre class="brush: clojure">(def error-template
4390    (slurp (get-resource &quot;selmer-error-template.html&quot;)))</pre></td></tr><tr><td class="docs">
4391  </td><td class="codes"><pre class="brush: clojure">(def validate? (atom true))</pre></td></tr><tr><td class="docs">
4392  </td><td class="codes"><pre class="brush: clojure">(defn validate-on! [] (reset! validate? true))</pre></td></tr><tr><td class="docs">
4393  </td><td class="codes"><pre class="brush: clojure">(defn validate-off! [] (reset! validate? false))</pre></td></tr><tr><td class="docs">
4394  </td><td class="codes"><pre class="brush: clojure">(defn format-tag [{:keys [tag-name tag-value tag-type args]}]
4395    (condp = tag-type
4396      :expr (str *tag-open* *tag-second* &quot; &quot; (name tag-name) &quot; &quot; (if args (str (clojure.string/join args) &quot; &quot;)) *tag-second* *tag-close*)
4397      :filter (str *tag-open* *filter-open* (name tag-value) *filter-close* *tag-close*)
4398      (str tag-name &quot; &quot; tag-value &quot; &quot; tag-type &quot; &quot; args)))</pre></td></tr><tr><td class="docs">
4399  </td><td class="codes"><pre class="brush: clojure">(defn validation-error
4400    ([error tag line template]
4401     (validation-error
4402       (str error
4403            (if tag (str &quot; &quot; (format-tag tag)))
4404            (if line (str &quot; on line &quot; line))
4405            (if template (str &quot; for template &quot; template)))
4406       error line [{:tag tag :line line}] template))
4407    ([long-error short-error line error-tags template]
4408     (throw
4409       (ex-info long-error
4410                {:type           :selmer-validation-error
4411                 :error          short-error
4412                 :error-template error-template
4413                 :line           line
4414                 :template       template
4415                 :validation-errors
4416                 (for [error error-tags]
4417                   (update-in error [:tag] format-tag))}))))</pre></td></tr><tr><td class="docs">
4418  </td><td class="codes"><pre class="brush: clojure">(defn validate-filters [template line {:keys [tag-value] :as tag}]
4419    (let [tag-filters (map
4420                    #(-&gt; ^String % (.split &quot;:&quot;) first keyword)
4421                    (-&gt; tag-value name (.split &quot;\\|&quot;) rest))]
4422      (if-not (empty? (difference (set tag-filters) (set (keys @filters))))
4423        (validation-error (str &quot;Unrecognized filter &quot; tag-value &quot; found inside the tag&quot;) tag line template))))</pre></td></tr><tr><td class="docs">
4424  </td><td class="codes"><pre class="brush: clojure">(defn close-tags []
4425    (apply concat (vals @closing-tags)))</pre></td></tr><tr><td class="docs">
4426  </td><td class="codes"><pre class="brush: clojure">(defn valide-tag [template line tags {:keys [tag-name args tag-value tag-type] :as tag}]
4427   (condp = tag-type
4428     :expr
4429     (let [last-tag (last tags)
4430           end-tags (get @closing-tags (:tag-name last-tag))]
4431       (doseq [arg args] (validate-filters template line (assoc tag :tag-value arg)))
4432       (cond
4433         (nil? tag-name)
4434         (validation-error &quot;No tag name supplied for the tag&quot; tag line template)
4435         (not-any? #{tag-name} (concat (close-tags) (keys @expr-tags)))
4436         (validation-error &quot;Unrecognized tag found&quot; tag line template)
4437         ;; check if we have closing tag
4438         ;; handle the case where it's an intermediate tag
4439         ;; throw an exception if it doesn't belong to the last open tag
4440         (some #{tag-name} (close-tags))
4441         (let [tags (vec (butlast tags))]
4442           (if (some #{tag-name} end-tags)
4443             (if (not-empty (get @closing-tags tag-name))
4444               (conj tags (assoc tag :line line)) tags)
4445             (validation-error &quot;No closing tag found for the tag&quot; last-tag (:line last-tag) template)))
4446         (not-empty (get @closing-tags tag-name))
4447         (conj tags (assoc tag :line line))
4448         (some #{tag-name} (close-tags))
4449         (validation-error &quot;Found an orphan closing tag&quot; tag line template)
4450         :else tags))
4451     :filter
4452     (do (validate-filters template line tag) tags)))</pre></td></tr><tr><td class="docs">
4453  </td><td class="codes"><pre class="brush: clojure">(defn skip-verbatim-tags [tag-info rdr line template]
4454    (if (= :verbatim (:tag-name tag-info))
4455      (loop [ch (read-char rdr)]
4456        (if ch
4457          (if-not (and
4458                   (open-tag? ch rdr)
4459                   (= :endverbatim (:tag-name (read-tag-info rdr))))
4460            (recur (read-char rdr)))))
4461      tag-info))</pre></td></tr><tr><td class="docs">
4462  </td><td class="codes"><pre class="brush: clojure">(defn read-tag [rdr line template]
4463    (try
4464      (-&gt; (read-tag-info rdr) (skip-verbatim-tags rdr line template))
4465      (catch Exception ex
4466        (validation-error (str &quot;Error parsing the tag: &quot; (.getMessage ex)) nil line template))))</pre></td></tr><tr><td class="docs">
4467  </td><td class="codes"><pre class="brush: clojure">(defn validate-tags [template]
4468    (with-open [rdr (reader template)]
4469      (loop [tags [], ch (read-char rdr), line 1]
4470        (if ch
4471          (if (open-tag? ch rdr)
4472            (if-let [tag-info (read-tag rdr line template)]
4473              (recur (valide-tag template line tags tag-info) (read-char rdr) line)
4474              (recur tags (read-char rdr) line))
4475            (recur tags (read-char rdr) (if (= \newline ch) (inc line) line)))
4476          tags))))</pre></td></tr><tr><td class="docs">
4477  </td><td class="codes"><pre class="brush: clojure">(defn validate [template]
4478    (when @validate?
4479      (check-template-exists template)
4480      (if-let [orphan-tags (not-empty (validate-tags template))]
4481        (validation-error
4482          (-&gt;&gt; orphan-tags
4483               (map (fn [{:keys [tag-name line] :as tag}] (str (format-tag tag) &quot; on line &quot; line)))
4484               (interpose &quot;, &quot;)
4485               doall
4486               (clojure.string/join &quot;The template contains orphan tags: &quot;))
4487          &quot;The template contains orphan tags.&quot;
4488          nil
4489          orphan-tags
4490          template))))</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_selmer.filter-parser">selmer.filter-parser</li><li class="floating-toc-li" id="floating-toc_selmer.filters">selmer.filters</li><li class="floating-toc-li" id="floating-toc_selmer.middleware">selmer.middleware</li><li class="floating-toc-li" id="floating-toc_selmer.node">selmer.node</li><li class="floating-toc-li" id="floating-toc_selmer.parser">selmer.parser</li><li class="floating-toc-li" id="floating-toc_selmer.tags">selmer.tags</li><li class="floating-toc-li" id="floating-toc_selmer.template-parser">selmer.template-parser</li><li class="floating-toc-li" id="floating-toc_selmer.util">selmer.util</li><li class="floating-toc-li" id="floating-toc_selmer.validator">selmer.validator</li></ul></div></div><script type="text/javascript">SyntaxHighlighter.defaults['gutter'] = false;
4491  SyntaxHighlighter.all();
4492  
4493  // hackity hack
4494  $(window).load(function() {
4495      var ft = $("#floating-toc");
4496      var ul = ft.find('ul');
4497      var lis = ft.find('li');
4498      var liHeight = $(lis.first()).height();
4499  
4500      ul.css('margin', '0px');
4501      ft.css('height', liHeight + 'px');
4502  
4503      showNs = function(ns) {
4504          var index = 0;
4505  
4506          for(i in nsPositions.nss) {
4507              if(ns == nsPositions.nss[i]) index = i;
4508          }
4509  
4510          if(index != lastNsIndex) {
4511              lastNsIndex = index;
4512              ul.animate({marginTop: (-1 * liHeight * index) + 'px'},
4513                 300);
4514          }
4515  
4516      }
4517  
4518      var calcNsPositions = function() {
4519          var hheight = $('.docs-header').first().height();
4520          var nss = [];
4521          var anchors = [];
4522          var positions = [];
4523          $.each(lis, function(i, el) {
4524              var ns = $(el).attr('id').split('_')[1];
4525              nss.push(ns);
4526              var a = $("a[name='"+ns+"']");
4527              anchors.push(a);
4528              positions.push(a.offset().top - hheight);
4529              // console.log(a.offset().top)
4530          });
4531  
4532          return {nss: nss, positions: positions};
4533      }
4534  
4535      var nsPositions = calcNsPositions();
4536      // console.log(nsPositions)
4537      var lastNsIndex = -1;
4538      var $window = $(window);
4539  
4540      var currentSection = function(nsp) {
4541          var ps = nsp.positions;
4542          var scroll = $window.scrollTop();
4543          var nsIndex = -1;
4544  
4545          for(var i = 0, length = ps.length; i < length; i++) {
4546              if(ps[i] >= scroll) {
4547                  nsIndex = i-1;
4548                  break;
4549              }
4550          }
4551  
4552          if(nsIndex == -1) {
4553               if(scroll >= ps[0]) {
4554                   nsIndex = ps.length - 1;
4555               } else {
4556                   nsIndex = 0;
4557               }
4558          }
4559  
4560          return nsp.nss[nsIndex];
4561      }
4562  
4563      $(window).scroll(function(e) {
4564          showNs(currentSection(nsPositions));
4565      });
4566  });
4567  </script></body></html>