├── README.md ├── sniffer.js └── tests ├── assets ├── cufon.js ├── glow │ └── core.js ├── google_closure │ └── base.js ├── modernizr.js └── sifr.js └── tests.html /README.md: -------------------------------------------------------------------------------- 1 | Sniffer 2 | ======= 3 | 4 | A JS library for sniffing out information about pages, such as which JS libraries are used, what CMS the site runs on, what analytics packages it uses, and more. It is intended to be used in bookmarklets or injected JS widgets that need to gather information about the host page and it's component parts. 5 | 6 | Where it can, Sniffer will return a string with more information (such as a version number) for each test; otherwise it will return boolean `true` or `false`. 7 | 8 | Please see the main site at [http://allmarkedup.github.com/sniffer/](http://allmarkedup.github.com/sniffer/) for more information and usage instructions. 9 | 10 | Originally created for use in [Snoopy](http://github.com/allmarkedup/snoopy). -------------------------------------------------------------------------------- /sniffer.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Sniffer - sniffs web pages to extract information such as JS libraries, CMS, analytics packages, etc. 3 | * Author: Mark Perkins, mark@allmarkedup.com 4 | */ 5 | 6 | var Sniffer = (function( win, doc, undefined ){ 7 | 8 | var sniff = {}, 9 | detect = {}, 10 | pageinfo = {}, 11 | test_runner = {}, 12 | results = {}, 13 | indexed_results = {}, 14 | scripts = doc.getElementsByTagName("script"), 15 | metas = doc.getElementsByTagName("meta"), 16 | html = doc.documentElement.outerHTML || doc.documentElement.innerHTML, 17 | doctype = doc.doctype, 18 | has_run = false; 19 | 20 | // discard meta tags that aren't useful 21 | metas = (function(){ 22 | for ( var meta, temp = [], i = -1; meta = metas[++i]; ) 23 | { 24 | if ( meta.name && meta.content ) temp.push(meta); 25 | } 26 | return temp; 27 | })(); 28 | 29 | // discard script tags that aren't useful 30 | scripts = (function(){ 31 | for ( var script, temp = [], i = -1; script = scripts[++i]; ) 32 | { 33 | if ( script.src ) temp.push(scripts); 34 | } 35 | return temp; 36 | })(); 37 | 38 | /* page component detection tests */ 39 | 40 | detect.pageinfo = { 41 | 42 | description : 'Page information', 43 | 44 | return_type : 'detail', 45 | 46 | tests : { 47 | 48 | 'Doctype' : [ 49 | { 50 | type : 'doctype', // source: http://www.w3.org/QA/2002/04/valid-dtd-list.html 51 | test : { 52 | 'HTML5' : { name : 'html', publicId : '' }, 53 | 'HTML 4.01 Strict' : { name : 'html', publicId : '-//W3C//DTD HTML 4.01//EN' }, 54 | 'HTML 4.01 Transitional' : { name : 'html', publicId : '-//W3C//DTD HTML 4.01 Transitional//EN' }, 55 | 'XHTML 1.0 Strict' : { name : 'html', publicId : '-//W3C//DTD XHTML 1.0 Strict//EN' }, 56 | 'XHTML 1.0 Transitional' : { name : 'html', publicId : '-//W3C//DTD XHTML 1.0 Transitional//EN' }, 57 | 'XHTML 1.0 Frameset' : { name : 'html', publicId : '-//W3C//DTD XHTML 1.0 Frameset//EN' }, 58 | 'XHTML 1.1' : { name : 'html', publicId : '-//W3C//DTD XHTML 1.1//EN' }, 59 | 'HTML 2.0' : { name : 'html', publicId : '-//IETF//DTD HTML 2.0//EN' }, 60 | 'HTML 3.0' : { name : 'html', publicId : '-//W3C//DTD HTML 3.2 Final//EN' }, 61 | 'XHTML 1.0 Basic' : { name : 'html', publicId : '-//W3C//DTD XHTML Basic 1.0//EN' } 62 | } 63 | } 64 | ], 65 | 'Charset' : [ 66 | { 67 | type : 'custom', 68 | test : function(){ return doc.characterSet || 'None detected'; } 69 | } 70 | ] 71 | } 72 | 73 | }; 74 | 75 | detect.js_libs = { 76 | 77 | description : 'JavaScript Libraries', 78 | 79 | return_type : 'version', 80 | 81 | // All individual tests should either return a version number, true or false. 82 | 83 | tests : { 84 | 85 | 'jQuery' : [ 86 | { 87 | type : 'custom', 88 | test : function(){ return win.jQuery ? win.jQuery.fn.jquery : false; } 89 | } 90 | ], 91 | 'jQuery UI' : [ 92 | { 93 | type : 'custom', 94 | test : function(){ return win.jQuery && win.jQuery.ui ? win.jQuery.ui.version : false; } 95 | } 96 | ], 97 | 'Prototype' : [ 98 | { 99 | type : 'custom', 100 | test : function(){ return win.Prototype ? win.Prototype.Version : false; } 101 | } 102 | ], 103 | 'Scriptaculous' : [ 104 | { 105 | type : 'custom', 106 | test : function(){ return win.Scriptaculous ? win.Scriptaculous.Version : false; } 107 | } 108 | ], 109 | 'MooTools' : [ 110 | { 111 | type : 'custom', 112 | test : function(){ return win.MooTools ? win.MooTools.version : false; } 113 | } 114 | ], 115 | 'Glow' : [ 116 | { 117 | type : 'custom', 118 | test : function(){ return win.glow ? win.glow.VERSION : false; } 119 | } 120 | ], 121 | 'Dojo' : [ 122 | { 123 | type : 'custom', 124 | test : function(){ return win.dojo ? win.dojo.version.toString() : false; } 125 | } 126 | ], 127 | 'ExtJS' : [ 128 | { 129 | type : 'custom', 130 | test : function(){ return win.Ext ? win.Ext.version : false; } 131 | } 132 | ], 133 | 'YUI' : [ 134 | { 135 | type : 'custom', 136 | test : function(){ return win.YAHOO ? win.YAHOO.VERSION : false; } 137 | } 138 | ], 139 | 'Google Closure' : [ 140 | { 141 | type : 'custom', 142 | test : function(){ return !! win.goog; } // need to figure out how to get YUI version 143 | } 144 | ], 145 | 'Modernizr' : [ 146 | { 147 | type : 'custom', 148 | test : function(){ return win.Modernizr ? win.Modernizr._version : false; } // need to figure out how to get YUI version 149 | } 150 | ], 151 | 'Raphael' : [ 152 | { 153 | type : 'custom', 154 | test : function(){ return win.Raphael ? win.Raphael.version : false; } 155 | } 156 | ] 157 | } 158 | }; 159 | 160 | detect.cms = { 161 | 162 | description : 'Content Management System', 163 | 164 | return_type : 'version', 165 | 166 | tests : { 167 | 168 | 'Wordpress' : [ 169 | { 170 | type : 'meta', 171 | test : { name : 'generator', match : /WordPress\s?([\w\d\.\-_]*)/i } 172 | }, 173 | { 174 | type : 'text', 175 | test : /]+wp-content/i 176 | } 177 | ], 178 | 'Typepad' : [ 179 | { 180 | type : 'meta', 181 | test : { name : 'generator', match : /typepad\.com/i } 182 | } 183 | ], 184 | 'Joomla' : [ 185 | { 186 | type : 'meta', 187 | test : { name : 'generator', match : /joomla\!?\s?([\d.]*)/i } 188 | } 189 | ], 190 | 'Blogger' : [ 191 | { 192 | type : 'meta', 193 | test : { name : 'generator', match : /blogger/i } 194 | } 195 | ], 196 | 'MovableType' : [ 197 | { 198 | type : 'meta', 199 | test : { name : 'generator', match : /Movable Type Pro ([\d.]*)/i } 200 | } 201 | ], 202 | 'Drupal' : [ 203 | { 204 | type : 'custom', 205 | test : function() { return win.Drupal ? true : false; } // no version in js obj 206 | } 207 | ], 208 | 'Cisco Eos' : [ 209 | { 210 | type : 'custom', 211 | test : function() { return win.eos ? true : false; } // no version in js obj 212 | }, 213 | { 214 | type : 'text', 215 | test : /]+ciscoeos.com/i 216 | } 217 | ] 218 | } 219 | 220 | }; 221 | 222 | detect.analytics = { 223 | 224 | description : 'Analytics', 225 | 226 | return_type : 'version', 227 | 228 | tests : { 229 | 230 | 'Google Analytics' : [ 231 | { 232 | type : 'custom', 233 | test : function(){ return !! (win._gat || win._gaq); } 234 | } 235 | ], 236 | 'Reinvigorate' : [ 237 | { 238 | type : 'custom', 239 | test : function(){ return !! win.reinvigorate; } 240 | } 241 | ], 242 | 'Piwik' : [ 243 | { 244 | type : 'custom', 245 | test : function(){ return !! win.Piwik; } 246 | } 247 | ], 248 | 'Clicky' : [ 249 | { 250 | type : 'custom', 251 | test : function(){ return !! win.clicky; } 252 | } 253 | ], 254 | 'Open Web Analytics' : [ 255 | { 256 | type : 'custom', 257 | test : function() { return !! win.OWA; } 258 | } 259 | ] 260 | } 261 | 262 | }; 263 | 264 | detect.fonts = { 265 | 266 | description : 'Fonts', 267 | 268 | return_type : 'version', 269 | 270 | tests : { 271 | 272 | 'Cufon' : [ 273 | { 274 | type : 'custom', 275 | test : function(){ return !! win.Cufon } 276 | } 277 | ], 278 | 'Typekit' : [ 279 | { 280 | type : 'custom', 281 | test : function(){ return !! win.Typekit } 282 | } 283 | ], 284 | 'Fontdeck' : [ 285 | { 286 | type : 'text', 287 | test : /]+f.fontdeck.com/i 288 | } 289 | ], 290 | 'Google Webfonts' : [ 291 | { 292 | type : 'custom', 293 | test : function(){ return !! win.WebFont } 294 | } 295 | ], 296 | 'sIFR' : [ 297 | { 298 | type : 'custom', 299 | test : function(){ return win.sIFR ? win.sIFR.VERSION : false } 300 | } 301 | ] 302 | } 303 | 304 | }; 305 | 306 | 307 | /* test runners */ 308 | 309 | // custom tests just run a function that returns a version number, true or false. 310 | test_runner.custom = function( test ) 311 | { 312 | return test(); 313 | } 314 | 315 | // one off regexp-based tests 316 | test_runner.text = function( test ) 317 | { 318 | return match( html, test ); 319 | } 320 | 321 | if ( doctype ) 322 | { 323 | test_runner.doctype = function( test ) 324 | { 325 | for ( subtest in test ) 326 | { 327 | if ( test.hasOwnProperty(subtest) ) 328 | { 329 | var t = test[subtest]; 330 | 331 | if ( doctype.name.toLowerCase() == t.name && doctype.publicId == t.publicId ) 332 | { 333 | return subtest; 334 | } 335 | } 336 | } 337 | return false; 338 | } 339 | } 340 | else 341 | { 342 | test_runner.doctype = function(){ 343 | return 'None detected'; 344 | } 345 | } 346 | 347 | // check the script src... probably pretty unreliable 348 | if ( scripts.length ) 349 | { 350 | test_runner.script = function( test ) 351 | { 352 | for ( var script, i = -1; script = scripts[++i]; ) 353 | { 354 | return match( script.src, test ); 355 | } 356 | return false; 357 | } 358 | } 359 | else 360 | { 361 | // no scripts, tests will always return false. 362 | test_runner.script = function(){ return false; } 363 | } 364 | 365 | // check the meta elements in the head 366 | if ( metas.length ) 367 | { 368 | test_runner.meta = function( test ) 369 | { 370 | for ( var meta, i = -1; meta = metas[++i]; ) 371 | { 372 | if ( meta.name == test.name ) 373 | { 374 | var res = match( meta.content, test.match ); 375 | if ( res ) return res; 376 | } 377 | } 378 | return false; 379 | } 380 | } 381 | else 382 | { 383 | // there are no meta elements on the page so this will always return false 384 | test_runner.meta = function(){ return false; } 385 | } 386 | 387 | // test arg should be a regexp, in which the only *specific* match is the version number 388 | function match( str, test ) 389 | { 390 | var match = str.match(test); 391 | if ( match ) return match[1] && match[1] != '' ? match[1] : true; // return version number if poss or else true. 392 | return false; 393 | } 394 | 395 | /* main function responsible for running the tests */ 396 | 397 | var run = function( tests_array ) 398 | { 399 | for ( var check, i = -1; check = tests_array[++i]; ) 400 | { 401 | var result = test_runner[check.type]( check.test ); 402 | if ( result !== false ) return result; 403 | } 404 | return false; 405 | } 406 | 407 | var empty = function( obj ) 408 | { 409 | for ( var name in obj ) return false; 410 | return true; 411 | } 412 | 413 | // utility function for iterating over the tests 414 | var forEachTest = function( callback ) 415 | { 416 | for ( group in detect ) 417 | { 418 | if ( detect.hasOwnProperty(group) ) 419 | { 420 | for ( test in detect[group].tests ) 421 | { 422 | if ( detect[group].tests.hasOwnProperty(test) ) 423 | { 424 | if ( callback( group, test ) === false ) return; 425 | } 426 | } 427 | } 428 | } 429 | } 430 | 431 | var addToResults = function( group, test, res ) 432 | { 433 | // add results to group results object 434 | 435 | results[group] = results[group] || {}; 436 | results[group].results = results[group].results || {}; 437 | 438 | results[group].description = detect[group].description; 439 | results[group].return_type = detect[group].return_type; 440 | 441 | results[group]['results'][test] = res; 442 | 443 | // add the result to the name-index results object 444 | 445 | indexed_results[test.toLowerCase()] = res; 446 | } 447 | 448 | /* publicly available methods */ 449 | 450 | // return results of all checks run so far 451 | sniff.results = function(){ 452 | return results; 453 | }; 454 | 455 | // perform an individual check 456 | sniff.check = function( to_test ) 457 | { 458 | to_test = to_test.toLowerCase(); 459 | if ( indexed_results[to_test] != undefined ) return indexed_results[to_test]; 460 | else { 461 | 462 | forEachTest(function( group, test ){ 463 | 464 | if ( test.toLowerCase() === to_test ) 465 | { 466 | addToResults( group, test, run( detect[group].tests[test] ) ); 467 | return false; // break out of forEachTest loop 468 | } 469 | 470 | }); 471 | } 472 | return indexed_results[to_test]; 473 | }; 474 | 475 | // run or re-run all checks 476 | sniff.run = function() 477 | { 478 | forEachTest(function( group, test ){ 479 | 480 | addToResults( group, test, run( detect[group].tests[test] ) ); 481 | 482 | }); 483 | 484 | return sniff.results(); 485 | }; 486 | 487 | return sniff; 488 | 489 | })( window, document ); -------------------------------------------------------------------------------- /tests/assets/cufon.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009 Simo Kinnunen. 3 | * Licensed under the MIT license. 4 | * 5 | * @version 1.09 6 | */ 7 | var Cufon=(function(){var m=function(){return m.replace.apply(null,arguments)};var x=m.DOM={ready:(function(){var C=false,E={loaded:1,complete:1};var B=[],D=function(){if(C){return}C=true;for(var F;F=B.shift();F()){}};if(document.addEventListener){document.addEventListener("DOMContentLoaded",D,false);window.addEventListener("pageshow",D,false)}if(!window.opera&&document.readyState){(function(){E[document.readyState]?D():setTimeout(arguments.callee,10)})()}if(document.readyState&&document.createStyleSheet){(function(){try{document.body.doScroll("left");D()}catch(F){setTimeout(arguments.callee,1)}})()}q(window,"load",D);return function(F){if(!arguments.length){D()}else{C?F():B.push(F)}}})(),root:function(){return document.documentElement||document.body}};var n=m.CSS={Size:function(C,B){this.value=parseFloat(C);this.unit=String(C).match(/[a-z%]*$/)[0]||"px";this.convert=function(D){return D/B*this.value};this.convertFrom=function(D){return D/this.value*B};this.toString=function(){return this.value+this.unit}},addClass:function(C,B){var D=C.className;C.className=D+(D&&" ")+B;return C},color:j(function(C){var B={};B.color=C.replace(/^rgba\((.*?),\s*([\d.]+)\)/,function(E,D,F){B.opacity=parseFloat(F);return"rgb("+D+")"});return B}),fontStretch:j(function(B){if(typeof B=="number"){return B}if(/%$/.test(B)){return parseFloat(B)/100}return{"ultra-condensed":0.5,"extra-condensed":0.625,condensed:0.75,"semi-condensed":0.875,"semi-expanded":1.125,expanded:1.25,"extra-expanded":1.5,"ultra-expanded":2}[B]||1}),getStyle:function(C){var B=document.defaultView;if(B&&B.getComputedStyle){return new a(B.getComputedStyle(C,null))}if(C.currentStyle){return new a(C.currentStyle)}return new a(C.style)},gradient:j(function(F){var G={id:F,type:F.match(/^-([a-z]+)-gradient\(/)[1],stops:[]},C=F.substr(F.indexOf("(")).match(/([\d.]+=)?(#[a-f0-9]+|[a-z]+\(.*?\)|[a-z]+)/ig);for(var E=0,B=C.length,D;E0){E=" "+E}}else{if(B400}if(I==500){I=400}for(var J in G){if(!k(G,J)){continue}J=parseInt(J,10);if(!F||JD){D=J}K.push(J)}if(ID){I=D}K.sort(function(M,L){return(E?(M>=I&&L>=I)?ML:(M<=I&&L<=I)?M>L:MO){O=K}if(I>N){N=I}if(Kcufoncanvas{text-indent:0;}@media screen{cvml\\:shape,cvml\\:rect,cvml\\:fill,cvml\\:shadow{behavior:url(#default#VML);display:block;antialias:true;position:absolute;}cufoncanvas{position:absolute;text-align:left;}cufon{display:inline-block;position:relative;vertical-align:'+(h?"middle":"text-bottom")+";}cufon cufontext{position:absolute;left:-10000in;font-size:1px;}a cufon{cursor:pointer}}@media print{cufon cufoncanvas{display:none;}}").replace(/;/g,"!important;"));function c(i,j){return a(i,/(?:em|ex|%)$|^[a-z-]+$/i.test(j)?"1em":j)}function a(l,m){if(m==="0"){return 0}if(/px$/i.test(m)){return parseFloat(m)}var k=l.style.left,j=l.runtimeStyle.left;l.runtimeStyle.left=l.currentStyle.left;l.style.left=m.replace("%","em");var i=l.style.pixelLeft;l.style.left=k;l.runtimeStyle.left=j;return i}function f(l,k,j,n){var i="computed"+n,m=k[i];if(isNaN(m)){m=k.get(n);k[i]=m=(m=="normal")?0:~~j.convertFrom(a(l,m))}return m}var g={};function d(p){var q=p.id;if(!g[q]){var n=p.stops,o=document.createElement("cvml:fill"),i=[];o.type="gradient";o.angle=180;o.focus="0";o.method="sigma";o.color=n[0][1];for(var m=1,l=n.length-1;m=6)};}(),module:function(u){var t=2,w=u.depends[0]||[],d=w.length,e=u.name,v=window.glow;if(u.library[1]!=n.VERSION){throw new Error("Cannot register "+e+": Version mismatch");}if(w[2]){for(;t");}if(u.delimiter==undefined){d=/\{[^{}]+\}/g;}else{v=u.delimiter.substr(0,1).replace(b,"\\$1");e=u.delimiter.substr(1,1).replace(b,"\\$1")||v;d=new RegExp(v+"[^"+v+e+"]+"+e,"g");}return t.replace(d,function(D){var A=D.slice(1,-1),C=A.split("."),B,z=0,y=C.length;if(A in w){B=w[A];}else{B=w;for(;z 5.5)@*/ 19 | (window.gloader||glow).module({name:"glow.i18n",library:["glow","1.7.3"],depends:[["glow","1.7.3"]],builder:function(r){var A;var t={l:/^[a-z]$/,lv:/^[a-z]{2,3}$/,s:/^[A-Z][a-z]{3}$/,r:/^[A-Z]{2}|[0-9]{3}$/,v:/^[a-z0-9]{4,}$/};var s=1,k=2,l=4,j=8,p=s+k+l+j,f=s+l+j,x=s+k+j,c=s+j,y=s+k+l,e=s+l,d=s+k;var m={l:s,s:k,r:l,v:j},I=["l","s","r","v"],F={l:0,s:1,r:2,v:3};var C={};var b={};var o=w(document.documentElement.lang||"en")||w("en");function D(K){for(var J in t){if(t[J].test(K)){return J;}}return"";}function w(V){if(!V.split){V="";}var N=V.split("-"),Q=N.length,R=[],K={l:"",s:"",r:"",v:""},J=0,O=J,U=0,P,S;for(var M=0,T=I.length;M]?)\s*/,classNameOrId:(n.webkit<417)?new RegExp("^([\\.#])((?:(?![\\.#\\[:\\s\\\\]).|\\\\.)+)"):/^([\.#])((?:[^\.#\[:\\\s]+|\\.)+)/},X=/([$^\\\/()|?+*\[\]{}.-])/g,B={},R={checked:"checked","class":"className",disabled:"disabled","for":"htmlFor",maxlength:"maxLength"},c={checked:true,disabled:true},ah={maxlength:function(r){return r.toString()=="2147483647"?undefined:r;}},ad=1,x="_unique"+u.UID,ai="_uniqueData"+u.UID,ag=1,L=[],I={black:0,silver:12632256,gray:8421504,white:16777215,maroon:8388608,red:16711680,purple:8388736,fuchsia:16711935,green:32768,lime:65280,olive:8421376,yellow:16776960,navy:128,blue:255,teal:32896,aqua:65535,orange:16753920},D=/height|top/,t=/^rgb\(([\d\.]+)(%?),\s*([\d\.]+)(%?),\s*([\d\.]+)(%?)/i,A=/^(?:(width|height)|(border-(top|bottom|left|right)-width))$/,C=/width|height|top$|bottom$|left$|right$|spacing$|indent$|font-size/,T,d,K,H,aa=window,l=document,V,G,w,P=l.createElement("div"),y=[1,"","
"],ab=[0,"",""],O=n.webkit<526?[0,"","",true]:[1,"b
","
"],a=[3,"","
"],E={caption:y,thead:y,th:a,colgroup:y,tbody:y,tr:[2,"","
"],td:a,tfoot:y,option:[1,""],legend:[1,"
","
"],link:O,script:O,style:O};if(n.ie){window.attachEvent("onunload",function(){P=null;});}u.ready(function(){V=l.body;G=l.documentElement;});(function(){var r=l.createElement("div");r.a=1;w=!!r.cloneNode(true).a;})();function af(r){for(var aj=r.firstChild;aj;aj=aj.nextSibling){if(aj.nodeType==1){return aj;}}return null;}function v(r){return new RegExp(["(^|\\s)",r.replace(X,"\\$1"),"($|\\s)"].join(""),"g");}function N(ap){var ao=[],al=(/^\s*<([^\s>]+)/.exec(ap)||[,"div"])[1],aj=E[al]||ab,am,ak,an=0;P.innerHTML=(aj[1]+ap+aj[2]);ak=P;am=aj[0];while(am--){ak=ak.lastChild;}while(ak.firstChild){ao[an++]=ak.removeChild(ak.firstChild);}ak=null;return ao;}function p(al){var ak=[],aj=0;for(;al[aj];aj++){ak[aj]=al[aj];}return ak;}function e(am,aj){for(var al=this,r=0,ak=al.length;r500&&n.webkit<526&&al=="margin-right"&&an.getPropertyValue("position")!="absolute"){al="margin-left";}ak=an.getPropertyValue(al);}}else{if(am){if(al=="opacity"){aq=/alpha\(opacity=([^\)]+)\)/.exec(am.filter);return aq?String(parseInt(aq[1],10)/100):"1";}ak=String(am[W(al)]);if(/^-?[\d\.]+(?!px)[%a-z]+$/i.test(ak)&&al!="font-size"){ak=J(ar,ak,D.test(al))+"px";}}}}}if(al.indexOf("color")!=-1){ak=S(ak).toString();}else{if(ak.indexOf("url")==0){ak=ak.replace(/\"/g,"");}}return ak;}function J(ao,aq,am){var ak=am?"top":"left",an=am?"Top":"Left",ar=ao.style,al=ar[ak],ap=ao.runtimeStyle[ak],aj;ao.runtimeStyle[ak]=ao.currentStyle[ak];ar[ak]=aq;aj=ar["pixel"+an];ar[ak]=al;ao.runtimeStyle[ak]=ap;return aj;}function S(ak){if(/^(transparent|rgba\(0, ?0, ?0, ?0\))$/.test(ak)){return"transparent";}var ao,aj,ap,aq,al,an=Math.round,ar=parseInt,am=parseFloat;if(ao=t.exec(ak)){aj=ao[2]?an(((am(ao[1])/100)*255)):ar(ao[1]);ap=ao[4]?an(((am(ao[3])/100)*255)):ar(ao[3]);aq=ao[6]?an(((am(ao[5])/100)*255)):ar(ao[5]);}else{if(typeof ak=="number"){al=ak;}else{if(ak.charAt(0)=="#"){if(ak.length=="4"){ak="#"+ak.charAt(1)+ak.charAt(1)+ak.charAt(2)+ak.charAt(2)+ak.charAt(3)+ak.charAt(3);}al=ar(ak.slice(1),16);}else{al=I[ak];}}aj=(al)>>16;ap=(al&65280)>>8;aq=(al&255);}ak=new String("rgb("+aj+", "+ap+", "+aq+")");ak.r=aj;ak.g=ap;ak.b=aq;return ak;}function m(an){var am="",ak=an.childNodes,al=0,aj=ak.length;for(;al=521){for(;r1?am:undefined;}if(typeof ak=="object"){for(al in ak){if(k.hasOwnProperty(ak,al)){am.attr(al,ak[al]);}}return am;}if(n.ie&&R[ak]){if(r>1){e.call(am,aj[1],function(ao){this[R[ak]]=ao;});return am;}an=am[0][R[ak]];if(c[ak]){return an?ak:undefined;}else{if(ah[ak]){return ah[ak](an);}}return an;}if(r>1){e.call(am,aj[1],function(ao){this.setAttribute(ak,ao);});return am;}return M(am[0])?am[0].getAttribute(ak):am[0].getAttribute(ak,2);},removeAttr:function(aj){var r=n.ie&&R[aj],am=this,ak=0,al=am.length;for(;ak-1?ap.options[ap.selectedIndex].value:"";}else{if(am=="select-multiple"){for(var aq=ap.options.length;ao0){for(;aj500){r+=parseInt(Z(an,"border-left-width"))||0;ao+=parseInt(Z(an,"border-top-width"))||0;}if(an.nodeName.toLowerCase()!="body"){ak=an;}}an=aj;while((an=an.parentNode)&&(an!=V)&&(an!=G)){r-=an.scrollLeft;ao-=an.scrollTop;if(n.gecko&&Z(an,"overflow")!="visible"){r+=parseInt(Z(an,"border-left-width"));ao+=parseInt(Z(an,"border-top-width"));}}if(am){r+=al.x;ao+=al.y;}if((n.webkit<500&&(am||Z(ak,"position")=="absolute"))||(n.gecko&&Z(ak,"position")!="absolute")){r-=V.offsetLeft;ao-=V.offsetTop;}return{left:r,top:ao};}},position:function(){var aj=Y.get(F(this[0])),ao=!!aj[0],an=parseInt(this.css("margin-left"))||0,am=parseInt(this.css("margin-top"))||0,al=(ao&&parseInt(aj.css("border-left-width")))||0,r=(ao&&parseInt(aj.css("border-top-width")))||0,ap=this.offset(),ak=ao?aj.offset():{top:0,left:0};return{left:ap.left-ak.left-an-al,top:ap.top-ak.top-am-r};},append:function(an){var am=this,aj=0,ak=1,al=am.length,r;if(al==0){return am;}r=typeof an=="string"?p(N(an)):an.nodeType?[an]:p(an);for(;r[aj];aj++){am[0].appendChild(r[aj]);}for(;ak=0;al--){ao[0].parentNode.insertBefore(ak[al],ao[0].nextSibling);}for(;am=0;al--){ao[am].parentNode.insertBefore(r[al],ao[am].nextSibling);}}return ao;},before:function(ap){var ao=this,an=ao.length,al=0,am=1,ak,aj,r;if(an==0){return ao;}ak=typeof ap=="string"?Y.create(ap):ap instanceof Y.NodeList?ap:Y.get(ap);aj=ak.length;for(;al"){ar[aC++]=[al,[null]];if(av){ar[aC++]=[ap,[av.replace(/\\/g,""),null]];}if(aA&&aA!="*"){ar[aC++]=[aq,[aA,null]];}}}aB=true;while(aB){if(az.charAt(0)=="#"||az.charAt(0)=="."){if(ax=s.classNameOrId.exec(az)){if(az.charAt(0)=="#"){ar[aC++]=[ap,[ax[2].replace(/\\/g,""),null]];}else{ar[aC++]=[ao,[ax[2].replace(/\\/g,""),null]];}az=az.slice(ax[0].length);}else{throw new Error("Invalid Selector "+aw);}}else{aB=false;}}au=false;}if(az!==""){throw new Error("Invalid Selector "+aw);}return B[az]=ar;}function an(ar,av){var au=av;for(var at=0,aw=ar.length;at');u.dom=Y;}});(window.gloader||glow).module({name:"glow.events",library:["glow","1.7.3"],depends:[["glow","1.7.3","glow.dom"]],builder:function(o){var k=o.dom.get;var C={};var x=1;var m=1;var n={};var b={};var p={};var l="__eventId"+o.UID;var g=l+"PreventDefault";var u=l+"StopPropagation";var E={};var f=1;var B={};var z={};var G=1;var d=2;var s=4;var h={TAB:"\t",SPACE:" ",ENTER:"\n",BACKTICK:"`"};var K={"96":223};var t={CAPSLOCK:20,NUMLOCK:144,SCROLLLOCK:145,BREAK:19,BACKTICK:223,BACKSPACE:8,PRINTSCREEN:44,MENU:93,SPACE:32,SHIFT:16,CTRL:17,ALT:18,ESC:27,TAB:9,META:91,RIGHTMETA:92,ENTER:13,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,INS:45,HOME:36,PAGEUP:33,DEL:46,END:35,PAGEDOWN:34,LEFT:37,UP:38,RIGHT:39,DOWN:40};var I={};for(var H in t){I[""+t[H]]=H;}var y="0123456789=;'\\/#,.-";function D(O){var N=z[O];if(!N){return false;}var M=B[N];if(!M){return false;}for(var L=0,r=M.length;L418)){if((N=="focus"||N=="blur")&&(o.env.opera)){O.parentNode.addEventListener(N,function(){},true);}O.addEventListener(N.toLowerCase()=="mousewheel"&&o.env.gecko?"DOMMouseScroll":N,Q,L);}else{var M="on"+N;var P=O[M];if(P){O[M]=function(){var R=P.apply(this,arguments),S=Q.apply(this,arguments);return(R!==false)&&(S!==false);};}else{O[M]=Q;}}O=null;}function a(M,N){var O=k(M),r=N?"mouseout":"mouseover",L=N?"mouseleave":"mouseenter";C.addListener(M,r,function(Q){var P=k(Q.relatedTarget);if(!P.eq(O)&&!P.isWithin(O)){return !C.fire(O[0],L,Q).defaultPrevented();}});}C._copyListeners=function(R,Q){var M=R.length,P,r,L,O,N;while(M--){if(R[M][l]){P=n[R[M][l]];for(r in P){L=0;O=P[r].length;for(;L").text(html).html();}};}});(window.gloader||glow).module({name:"glow.net",library:["glow","1.7.3"],depends:[["glow","1.7.3","glow.data","glow.events"]],builder:function(h){var t={XML_ERR:"Cannot get response as XML, check the mime type of the data",POST_DEFAULT_CONTENT_TYPE:"application/x-www-form-urlencoded;"},u=/\+xml$/,p=[],e="c",o="_"+h.UID+"loadScriptCbs",g=h.dom.get,c=h.events,f=function(){},k=1;function s(){if(window.ActiveXObject){return(s=function(){return new ActiveXObject("Microsoft.XMLHTTP");})();}else{return(s=function(){return new XMLHttpRequest();})();}}function d(w){var r=h.lang.apply({onLoad:f,onError:f,onAbort:f,headers:{},async:true,useCache:false,data:null,defer:false,forceXml:false},w||{});if(!("X-Requested-With" in r.headers)){r.headers["X-Requested-With"]="XMLHttpRequest";}return r;}function v(r){return[r,(/\?/.test(r)?"&":"?"),"a",new Date().getTime(),parseInt(Math.random()*100000)].join("");}function j(C,r,z){var y=s(),A=z.data&&(typeof z.data=="string"?z.data:h.data.encodeUrl(z.data)),w,x=new q(y,z);if(!z.useCache){r=v(r);}y.open(C,r,z.async);for(w in z.headers){y.setRequestHeader(w,z.headers[w]);}function B(){x.send=f;if(z.async){if(z.timeout){x._timeout=setTimeout(function(){a(x);var E=new b(y,true,x);c.fire(x,"error",E);},z.timeout*1000);}y.onreadystatechange=function(){if(y.readyState==4){x._timeout&&clearTimeout(x._timeout);x.completed=true;var E=new b(y,false,x);if(E.wasSuccessful){c.fire(x,"load",E);}else{c.fire(x,"error",E);}y.onreadystatechange=new Function();}};y.send(A);return x;}else{y.send(A);x.completed=true;var D=new b(y,false,x);if(D.wasSuccessful){c.fire(x,"load",D);}else{c.fire(x,"error",D);}return D;}}x.send=B;return z.defer?x:B();}var m={};m.get=function(r,w){w=d(w);return j("GET",r,w);};m.post=function(r,w,x){x=d(x);x.data=w;if(!x.headers["Content-Type"]){x.headers["Content-Type"]=t.POST_DEFAULT_CONTENT_TYPE;}return j("POST",r,x);};m.send=function(y,r,w,x){w=w||"";x=d(x);x.data=w;return j(y,r,x);};m.put=function(r,w,x){x=d(x);x.data=w;if(!x.headers["Content-Type"]){x.headers["Content-Type"]=t.POST_DEFAULT_CONTENT_TYPE;}return j("PUT",r,x);};m.del=function(r,w){w=d(w);return j("DELETE",r,w);};m.loadScript=function(w,z){var x=p.length,r,A=e+x,z=d(z),y=new q(x,z),w=z.useCache?w:v(w),B=window[o]||(window[o]={});if(z.onLoad!=f){B[A]=function(){y._timeout&&clearTimeout(y._timeout);y.completed=true;z.onLoad.apply(this,arguments);y.destroy();r=B[A]=undefined;delete B[A];};w=h.lang.interpolate(w,{callback:o+"."+A});}r=p[x]=document.createElement("script");if(z.charset){r.charset=z.charset;}c.addListener(y,"abort",z.onAbort);h.ready(function(){if(z.timeout){y._timeout=setTimeout(function(){a(y);z.onError();},z.timeout*1000);}if(h.env.opera){setTimeout(function(){if(r){r.src=w;}},0);}else{r.src=w;}document.body.appendChild(r);});return y;};function a(w){var r=w.nativeRequest,x=w._callbackIndex;w._timeout&&clearTimeout(w._timeout);if(r){r.onreadystatechange=new Function();r.abort();}else{if(x){window[o][e+x]=f;h.dom.get(p[x]).destroy();}}}function q(y,w){this._timeout=null;this._forceXml=w.forceXml;if(w.forceXml&&y.overrideMimeType){y.overrideMimeType("application/xml");}this.complete=false;if(typeof y=="number"){this._callbackIndex=y;}else{this.nativeRequest=y;}var x=["Load","Error","Abort"],r=0;for(;r<3;r++){c.addListener(this,x[r].toLowerCase(),w["on"+x[r]]);}}q.prototype={send:function(){},abort:function(){if(!this.completed&&!c.fire(this,"abort").defaultPrevented()){a(this);}return this;},destroy:function(){var r=this;if(this._callbackIndex!==undefined){setTimeout(function(){g(p[r._callbackIndex]).destroy();p[r._callbackIndex]=undefined;delete p[r._callbackIndex];},0);}return this;}};function b(x,r,w){c.Event.call(this);this._request=w;this.nativeResponse=x;this.status=r?408:x.status==1223?204:x.status;this.timedOut=!!r;this.wasSuccessful=(this.status>=200&&this.status<300)||this.status==304||(this.status==0&&x.responseText);}function l(){var r=this.header("Content-Type");return u.test(r)||r==="";}h.lang.extend(b,c.Event,{text:function(){return this.nativeResponse.responseText;},xml:function(){var w=this.nativeResponse;if((h.env.ie&&l.call(this))||(this._request._forceXml&&!this._request.nativeRequest.overrideMimeType&&window.ActiveXObject)){var r=new ActiveXObject("Microsoft.XMLDOM");r.loadXML(w.responseText);return r;}else{if(!w.responseXML){throw new Error(t.XML_ERR);}return w.responseXML;}},json:function(r){return h.data.decodeJson(this.text(),{safeMode:r});},header:function(r){return this.nativeResponse.getResponseHeader(r);},statusText:function(){return this.timedOut?"Request Timeout":this.nativeResponse.statusText;}});var n=function(r,x,y,w){this.url=r;this.data=x;this.isGet=y;this.opts=w;};n.prototype={_send:function(){this._addIframe();this._addForm();this._addTimeout();this.onLoad=this._handleResponse;this._submitForm();},_addIframe:function(){this.iframe=h.dom.create('');var r=this.iframe[0],w=this,x=function(){if(w.onLoad){w.onLoad();}};if(r.attachEvent){r.attachEvent("onload",x);}else{r.onload=x;}g("body").append(this.iframe);},_addForm:function(){var x=this._window().document;if(h.env.ie){x.open();x.write("");x.close();}var w=this.form=x.createElement("form");w.setAttribute("action",this.url);w.setAttribute("method",this.isGet?"GET":"POST");var r=x.getElementsByTagName("body")[0];r.appendChild(w);this._addFormData();},_addFormData:function(){for(var x in this.data){if(!this.data.hasOwnProperty(x)){continue;}if(this.data[x] instanceof Array){var r=this.data[x].length;for(var w=0;w');function addEventsFromOpts(instance,opts,eventProps){for(var i=0,len=eventProps.length;ianim.duration){anim.position=anim.duration;}}else{anim.position++;}anim.value=anim.tween(anim.position/anim.duration);events.fire(anim,"frame");}}};})();function convertCssUnit(element,fromValue,toUnit,axis){var elmStyle=testElement[0].style,axisProp=(axis=="x")?"width":"height",startPixelValue,toUnitPixelValue;elmStyle.margin=elmStyle.padding=elmStyle.border="0";startPixelValue=testElement.css(axisProp,fromValue).insertAfter(element)[axisProp]();toUnitPixelValue=testElement.css(axisProp,10+toUnit)[axisProp]()/10;testElement.remove();return startPixelValue/toUnitPixelValue;}function keepWithinRange(num,start,end){if(start!==undefined&&numend){return end;}return num;}function buildAnimFunction(element,spec){var cssProp,r=["a=(function(){"],rLen=1,fromUnit,unitDefault=[0,"px"],to,from,unit,a;for(cssProp in spec){r[rLen++]='element.css("'+cssProp+'", ';if(typeof spec[cssProp]!="object"){to=spec[cssProp];}else{to=spec[cssProp].to;}if((from=spec[cssProp].from)===undefined){if(cssProp=="font-size"||cssProp=="background-position"){throw new Error("From value must be set for "+cssProp);}from=element.css(cssProp);}if(hasUnits.test(cssProp)){unit=(getUnit.exec(to)||unitDefault)[1];fromUnit=(getUnit.exec(from)||unitDefault)[1];from=parseFloat(from)||0;to=parseFloat(to)||0;if(from&&unit!=fromUnit){if(cssProp=="font-size"){throw new Error("Units must be the same for font-size");}from=convertCssUnit(element,from+fromUnit,unit,usesYAxis.test(cssProp)?"y":"x");}if(noNegatives.test(cssProp)){r[rLen++]="keepWithinRange(("+(to-from)+" * this.value) + "+from+', 0) + "'+unit+'"';}else{r[rLen++]="("+(to-from)+" * this.value) + "+from+' + "'+unit+'"';}}else{if(!(isNaN(from)||isNaN(to))){from=Number(from);to=Number(to);r[rLen++]="("+(to-from)+" * this.value) + "+from;}else{if(cssProp.indexOf("color")!=-1){to=dom.parseCssColor(to);if(!glow.lang.hasOwnProperty(from,"r")){from=dom.parseCssColor(from);}r[rLen++]='"rgb(" + keepWithinRange(Math.round('+(to.r-from.r)+" * this.value + "+from.r+'), 0, 255) + "," + keepWithinRange(Math.round('+(to.g-from.g)+" * this.value + "+from.g+'), 0, 255) + "," + keepWithinRange(Math.round('+(to.b-from.b)+" * this.value + "+from.b+'), 0, 255) + ")"';}else{if(cssProp=="background-position"){var vals={},fromTo=["from","to"],unit=(getUnit.exec(from)||unitDefault)[1];vals.fromOrig=from.toString().split(/\s/);vals.toOrig=to.toString().split(/\s/);if(vals.fromOrig[1]===undefined){vals.fromOrig[1]="50%";}if(vals.toOrig[1]===undefined){vals.toOrig[1]="50%";}for(var i=0;i<2;i++){vals[fromTo[i]+"X"]=parseFloat(vals[fromTo[i]+"Orig"][0]);vals[fromTo[i]+"Y"]=parseFloat(vals[fromTo[i]+"Orig"][1]);vals[fromTo[i]+"XUnit"]=(getUnit.exec(vals[fromTo[i]+"Orig"][0])||unitDefault)[1];vals[fromTo[i]+"YUnit"]=(getUnit.exec(vals[fromTo[i]+"Orig"][1])||unitDefault)[1];}if((vals.fromXUnit!==vals.toXUnit)||(vals.fromYUnit!==vals.toYUnit)){throw new Error("Mismatched axis units cannot be used for "+cssProp);}r[rLen++]="("+(vals.toX-vals.fromX)+" * this.value + "+vals.fromX+') + "'+vals.fromXUnit+' " + ('+(vals.toY-vals.fromY)+" * this.value + "+vals.fromY+') + "'+vals.fromYUnit+'"';}}}}r[rLen++]=");";}r[rLen++]="})";return eval(r.join(""));}var r={};r.css=function(element,duration,spec,opts){element=get(element);var anim=new r.Animation(duration,opts);if(element[0]){events.addListener(anim,"frame",buildAnimFunction(element,spec));}return anim;};slideElement=function slideElement(element,duration,action,opts){duration=duration||0.5;element=$(element);opts=glow.lang.apply({tween:glow.tweens.easeBoth(),onStart:function(){},onComplete:function(){}},opts);var i=0,thatlength=element.length,completeHeight,fromHeight,channels=[],timeline;for(;i0)){element[i].style.overflow="hidden";if(glow.env.ie<8){element[i].style.zoom=1;}completeHeight=0;fromHeight=element.slice(i,i+1).height();}else{if(action=="down"||(action=="toggle"&&element.slice(i,i+1).height()==0)){fromHeight=element.slice(i,i+1).height();element[i].style.height="";completeHeight=element.slice(i,i+1).height();if(completeHeight===0){element[i].style.height="auto";completeHeight=element.slice(i,i+1).height();}element[i].style.height=fromHeight+"px";}}channels[i]=[glow.anim.css(element[i],duration,{height:{from:fromHeight,to:completeHeight}},{tween:opts.tween})];}timeline=new glow.anim.Timeline(channels,{destroyOnComplete:true});events.addListener(timeline,"complete",function(){element.each(function(){if(this.style.height.slice(0,1)!="0"){this.style.height="";if(glow.dom.get(this).height()===0){this.style.height="auto";}}});});events.addListener(timeline,"start",opts.onStart);events.addListener(timeline,"complete",opts.onComplete);return timeline.start();};r.slideDown=function(element,duration,opts){return slideElement(element,duration,"down",opts);};r.slideUp=function(element,duration,opts){return slideElement(element,duration,"up",opts);};r.slideToggle=function(element,duration,opts){return slideElement(element,duration,"toggle",opts);};r.fadeOut=function(element,duration,opts){return r.fadeTo(element,0,duration,opts);};r.fadeIn=function(element,duration,opts){return r.fadeTo(element,1,duration,opts);};r.fadeTo=function(element,opacity,duration,opts){duration=duration||0.5;element=$(element);opts=glow.lang.apply({tween:glow.tweens.easeBoth(),onStart:function(){},onComplete:function(){}},opts);var i=0,thatlength=element.length,channels=[],timeline;for(;ianim.duration){anim.position=anim.duration;}anim.value=anim.tween(anim.position/anim.duration);events.fire(anim,"frame");if(anim.position==anim.duration){this._advanceChannel(i);}}},start:function(){var e=events.fire(this,"start");if(e.defaultPrevented()){return this;}var i,iLen,j,jLen,anim;this._playing=true;for(i=0,iLen=this._channels.length;ithis.duration){if(this.loop){pos=pos%this.duration;}else{pos=this.duration;}}this._controlAnim.goTo(pos);for(i=0;ipos){this._channelPos[i]=j;anim.goTo(pos-runningDuration);break;}anim.goTo(anim.duration);runningDuration+=anim.duration;}}for(k=channelLen;k>j;k--){anim.goTo(0);}}}else{for(i=0;i=this._fields[this._fieldCur]._tests.length){if(!d.call(this)){return;}}var j=this._fields[this._fieldCur]._tests[this._testCur];var h;if(j.opts.field){h=this.formNode.val()[j.opts.field]||"";j.isConditional=true;}else{h=this.formNode.val()[this._fields[this._fieldCur].name]||"";}if(!h.join){h=[h];}var k=function(l){return function(){e.apply(l,arguments);};}(this);j.opts.on=j.opts.on||"submit";if(this._result.eventName&&(" "+j.opts.on+" ").indexOf(" "+this._result.eventName+" ")!=-1){if(this._fieldName&&this._fieldName!=j.name){c.call(this);return;}if(typeof g.forms.tests[j.type]!="function"){throw"Unimplemented test: no test exists of type '"+j.type+"'.";}j.opts._localeModule=this._localeModule;g.forms.tests[j.type](h,j.opts,k,this.formNode.val());}else{c.call(this);}};var d=function(){this._fieldCur++;this._testCur=0;if(this._fieldCur>=this._fields.length){this._fieldCur=0;g.events.fire(this,"validate",this._result);if(this.eventName=="submit"&&this._result&&!this._result.defaultPrevented()){try{this.formNode[0].submit();}catch(h){throw new Error("Glow can't submit the form because the submit function can't be called. Perhaps that form's submit was replaced by an input element named 'submit'?");}}return false;}return true;};var e=function(h,j){if(typeof h=="boolean"){h=(h)?g.forms.PASS:g.forms.FAIL;}if(this._fields[this._fieldCur]._tests[this._testCur].isConditional&&h===g.forms.FAIL){h=g.forms.SKIP;}this._result.fields.push({name:this._fields[this._fieldCur].name,result:h,message:j});if(h!==g.forms.PASS){if(h===g.forms.FAIL){this._result.errorCount++;}this._testCur=this._fields[this._fieldCur]._tests.length;}c.call(this);};g.forms.Form.prototype.addTests=function(r){var q={name:r,_tests:[]};var j=function(s){return function(){s.validate.apply(s,["change",r]);};}(this);var n=function(s){return function(){s.validate.apply(s,["click",r]);};}(this);var o=function(s){return function(){s.validate.apply(s,["idle",r]);};}(this);for(var l=1;l1)?arguments[l][1]:{};q._tests.push({name:r,type:k,opts:p});if(!j.added&&(" "+p.on+" ").indexOf(" change ")!=-1){var m=this.formNode.get("*").each(function(s){if(this.name==r){g.events.addListener(this,"change",j);j.added=true;}});}if(!n.added&&(" "+p.on+" ").indexOf(" click ")!=-1){var m=this.formNode.get("*").each(function(s){if(this.name==r){g.events.addListener(this,"click",n);n.added=true;}});}if(!o.added&&(" "+p.on+" ").indexOf(" idle ")!=-1){var h=(typeof p.delay!="undefined")?parseInt(p.delay):1000;var m=this.formNode.get("*").each(function(s){if(this.name==r){g.events.addListener(this,"keyup",function(u){return function(){window.clearTimeout(this.idleTimeoutID);if(this.value){this.idleTimeoutID=window.setTimeout(o,u);}};}(h));g.events.addListener(this,"blur",function(){window.clearTimeout(this.idleTimeoutID);});o.added=true;}});}}this._fields.push(q);return this;};g.forms.ValidateResult=function(h){g.events.Event.apply(this);this.eventName=h;this.errorCount=0;this.value=undefined;this.fields=[];};g.lang.extend(g.forms.ValidateResult,g.events.Event);g.forms.PASS=1;g.forms.FAIL=0;g.forms.SKIP=-1;g.forms.tests={required:function(j,m,n){var l=m.message||m._localeModule.TEST_MESSAGE_REQUIRED;for(var k=0,h=j.length;kNumber(m.arg)){n(g.forms.FAIL,l);return;}}n(g.forms.PASS,l);},range:function(k,o,p){var n=o.arg.split("..");if(typeof n[0]=="undefined"||typeof n[1]=="undefined"){throw"Range test requires a parameter like 0..10.";}var m=o.message||f(o._localeModule.TEST_MESSAGE_RANGE,{min:n[0],max:n[1]});n[0]*=1;n[1]*=1;if(n[0]>n[1]){var j=n[0];n[0]=n[1];n[1]=j;}for(var l=0,h=k.length;ln[1]){p(g.forms.FAIL,m);return;}}p(g.forms.PASS,m);},minCount:function(h,m,n){var l=m.message||f(m._localeModule.TEST_MESSAGE_MIN_COUNT,{arg:m.arg});var k=0;for(var j=0;jm.arg){n(g.forms.FAIL,l);return;}n(g.forms.PASS,l);},count:function(h,m,n){var l=m.message||f(m._localeModule.TEST_MESSAGE_COUNT,{arg:m.arg});var k=0;for(var j=0;jm.arg){n(g.forms.FAIL,l);return;}}n(g.forms.PASS,l);},isEmail:function(j,m,n){var l=m.message||m._localeModule.TEST_MESSAGE_IS_EMAIL;for(var k=0,h=j.length;k').appendTo(document.body);}h[0].value++;}function k(o){var n=o.fields,r,q,s,p,m;for(p=0,m=n.length;p')));}s.text(n[p].message);r.addClass("glow-invalid");}}}}function j(p){var s=p.fields,v,n,o,r,m,q,t;p.form.formNode.get("div.glow-errorSummary").remove();n=g.dom.create('
    ');o=n.get("ul");for(q=0,t=s.length;q").text(m+": "+s[q].message));}}p.form.formNode.prepend(n.css("opacity","0"));g.anim.css(n,"0.5",{opacity:{from:0,to:1}},{tween:g.tweens.easeOut()}).start();try{n[0].focus();}catch(u){}l();}return function(m){if(m.eventName=="submit"){if(!m.errorCount){m.form.formNode.get("div.glow-errorSummary").remove();return;}j(m);}setTimeout(function(){k(m);},0);return false;};}());}});(window.gloader||glow).module({name:"glow.embed",library:["glow","1.7.3"],depends:[["glow","1.7.3","glow.dom","glow.data","glow.i18n"]],builder:function(n){var o=n.i18n;o.addLocaleModule("GLOW_EMBED","en",{FLASH_MESSAGE:"This content requires Flash Player version {min} (installed version: {installed})",NO_PLAYER_MESSAGE:"No Flash Flayer installed, or version is pre 6.0.0"});function b(s){var r="";for(var t in s){if(t.toLowerCase()=="flashvars"&&typeof s[t]=="object"){r+=' FlashVars="'+n.data.encodeUrl(s[t])+'"';}else{r+=" "+t+'="'+s[t]+'"';}}return r;}function q(s){var u="",t,v;for(t in s){if(t.toLowerCase()=="flashvars"&&typeof s[t]=="object"){v=n.data.encodeUrl(s[t]);}else{v=s[t];}u+='\n';}return u;}function h(s,r){s=s||{};for(var t in r){if(typeof s[t]=="undefined"){s[t]=r[t];}else{if(typeof r[t]=="object"){s[t]=h(s[t],r[t]);}}}return s;}function c(){var r=(navigator.platform||navigator.userAgent);return r.match(/win/i)?"win":r.match(/mac/i)?"mac":"other";}function l(r){var t=/^WIN (\d+),(\d+),(\d+),\d+$/;var s=r.GetVariable("$version");if($match=t.exec(s)){return{major:parseInt($match[1]),minor:parseInt($match[2]),release:parseInt($match[3]),actual:s};}else{}}function k(){var s,u,v={major:0,minor:0,release:0},r=v;if(n.env.ie){try{u=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");r=l(u);}catch(w){try{u=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");try{u.AllowScriptAccess="always";r=l(u);}catch(w){r={major:6,minor:0,release:29};}}catch(w){}}}else{var t=/^Shockwave Flash\s*(\d+)\.(\d+)\s*\w(\d+)$/;if((u=navigator.plugins["Shockwave Flash"])&&(s=t.exec(u.description))){r={major:parseInt(s[1]),minor:parseInt(s[2]),release:parseInt(s[3]),actual:u.description};}}r.toString=function(){return this.major?[this.major,this.minor,this.release].join("."):o.getLocaleModule("GLOW_EMBED").NO_PLAYER_MESSAGE;};return r;}var m=k();function f(t){if(typeof t!="object"){var s=String(t).match(/^(\d+)(?:\.(\d+)(?:\.(\d+))?)?$/);if(!s){throw new Error('glow.embed._meetsVersionRequirements: invalid format for version string, require "n.n.n" or "n.n" or simply "n" where n is a numeric value');}t={major:parseInt(s[1],10),minor:parseInt(s[2]||0,10),release:parseInt(s[3]||0,10)};}var r=m,u=t;return(r.major>u.major||(r.major==u.major&&r.minor>u.minor)||(r.major==u.major&&r.minor==u.minor&&r.release>=u.release));}var e=n.env.ie?j:g;function g(t,r,s){return'";}function j(t,r,s){return''+q(s)+"";}var a={},p=0;function d(){return n.UID+"FlashEmbed"+(p++);}a.Flash=function(x,r,w,v){v=h(v,{width:"100%",height:"100%",params:{allowscriptaccess:"always",allowfullscreen:"true",quality:"high"},attributes:{},message:n.lang.interpolate(o.getLocaleModule("GLOW_EMBED").FLASH_MESSAGE,{min:w,installed:m}),id:(v&&v.attributes&&v.attributes.id)||d()});r=n.dom.get(r);if(!r.length){throw new Error("glow.embed.Flash unable to locate container");}this.container=r;this.movie=null;this._displayErrorMessage=typeof v.message=="function"?v.message:function(){return v.message;};this.isSupported;if(this.isSupported=f(w)){var s=v.attributes,u=["id","width","height"],t=u.length;while(t--){if(v[u[t]]){s[u[t]]=v[u[t]];}}if(v.className){s["class"]=v.className;}this._embed_tag=e(x,s,v.params);}};a.Flash.version=function(){return m;};a.Flash.prototype.embed=function(){var s=this.container[0];if(this.isSupported){s.innerHTML=this._embed_tag;this.movie=s.firstChild;}else{var r=this._displayErrorMessage();if(r){s.innerHTML=r;}}return this;};n.embed=a;}});(window.gloader||glow).module({name:"glow.dragdrop",library:["glow","1.7.3"],depends:[["glow","1.7.3","glow.tweens","glow.events","glow.dom","glow.anim"]],builder:function(j){var c=j.events,k=c.addListener,v=c.fire,g=c.removeListener,q=j.dom,h=q.get,m=q.create;var n={},w=1000,a=(document.compatMode=="CSS1Compat"&&j.env.ie>=5)?true:false,x=(document.compatMode!="CSS1Compat"&&j.env.ie>=5)?true:false,d=j.env.ie>=5,s=["top","right","bottom","left"];function b(r,z){var A=r.prototype[z];var y="cached_"+z;r.prototype[z]=function(){if(y in this){return this[y];}return this[y]=A.apply(this,arguments);};}function u(A,z){var r=s.length,y;while(r--){y="margin-"+s[r];A.css(y,z.css(y));}}function f(r,y){var A=r.prototype[y];var z="cached_"+y;r.prototype[y]=function(B){if(!this[z]){this[z]={};}if(B in this[z]){return this[z][B];}return this[z][B]=A.apply(this,arguments);};}function t(A,z){for(var y=0,r=z.length;y=y[0]&&A<=y[1]&&B<=y[2]&&A>=y[3];},containsPoint:function(y){var r=this.el.offset();return y.x>=r.left&&y.y>=r.top&&y.x<=r.left+this.borderWidth()&&y.y<=r.top+this.borderHeight();},positionedAncestorBox:function(){var r=this.el.parent(),y;while(r[0]){y=r.css("position")||"static";if(y=="relative"||y=="absolute"||y=="fixed"){return new o(r);}r=r.parent();}return null;}});function e(y){var r=y[0].tagName.toLowerCase()=="li"?"li":"div";var z=m("<"+r+">");if(r=="li"){z.css("list-style-type","none");}return z;}n.Draggable=function(A,B){this.element=h(A);this._opts=B=j.lang.apply({dragPrevention:["input","textarea","button","select","option","a"],placeholder:"spacer",placeholderClass:"glow-dragdrop-placeholder",step:{x:1,y:1}},B||{});if(typeof B.step=="number"){B.step={x:B.step,y:B.step};}else{B.step.x=B.step.x||1;B.step.y=B.step.y||1;}this._preventDrag=[];for(var y=0,r=B.dragPrevention.length;yA[1]?A[1]:D;}if(y!="x"){B=BA[2]?A[2]:B;}}r[0].style.left=D+"px";r[0].style.top=B+"px";if(this.dropTargets){this._mousePos={x:C.pageX,y:C.pageY};}if(d&&C.nativeEvent.button==0){this._releaseElement(C);return false;}return false;},_testForDropTargets:function(H){if(!this._lock){this._lock=0;}if(H){this._lock--;}else{if(this.lock){return;}}if(this._dragging!=1){return;}var z=this.activeTarget,y,R=this.dropTargets,S,C,F=this._box,K=this._mousePos;F.resetPosition();var D=0;for(var L=0,J=R.length;LD){D=M;y=S;}}}}this.activeTarget=y;if(y!==z){if(y){var I=new c.Event();I.draggable=this;v(y,"enter",I);var r=new c.Event();r.dropTarget=y;v(this,"enter",r);}if(z){var E=new c.Event();E.draggable=this;v(z,"leave",E);var G=new c.Event();G.dropTarget=z;v(this,"leave",G);}}if(y&&y._opts.dropIndicator!="none"){var P,N=y._childBoxes,A=y._children;F.resetPosition();var Q=y._box.innerTopPos();var T=K.y-F.offsetParentPageTop();var O=0;for(var L=0,J=N.length;L1){throw"more than one element passed into DropTarget constructor";}this._id=++l;this._opts=y=j.lang.apply({dropIndicator:"none",dropIndicatorClass:"glow-dragdrop-dropindicator",tolerance:"intersect"},y||{});if(y.onActive){k(this,"active",y.onActive);}if(y.onInactive){k(this,"inactive",y.onInactive);}if(y.onEnter){k(this,"enter",y.onEnter);}if(y.onLeave){k(this,"leave",y.onLeave);}if(y.onDrop){k(this,"drop",y.onDrop);}k(this,"active",this._onActive);k(this,"inactive",this._onInactive);return this;};n.DropTarget.prototype={setLogicalBottom:function(r){this._logicalBottom=r;},_onActive:function(A){var y=A.draggable;this._box=new o(this.element);if(this._logicalBottom){this._box.setLogicalBottom(this._logicalBottom);}if(this._opts.dropIndicator=="none"){return;}this._onEnterListener=k(this,"enter",this._onEnter);this._onLeaveListener=k(this,"leave",this._onLeave);this._dropIndicator=e(y.element);if(this._opts.dropIndicatorClass){this._dropIndicator.addClass(this._opts.dropIndicatorClass);}y._box.sizePlaceholder(this._dropIndicator,"relative",0,0);var z=this._children=h(this.element.children()).filter(function(){var B=h(this);return(!A.draggable._placeholder||!B.eq(A.draggable._placeholder))&&(!this._dropIndicator||!B.eq(this._dropIndicator));});var r=this._childBoxes=[];z.each(function(B){r[B]=new o(h(z[B]));});},_onInactive:function(r){g(this._onEnterListener);g(this._onLeaveListener);delete this._box;if(this._opts.dropIndicator=="none"){return;}if(!r.droppedOnThis&&this._dropIndicator){this._dropIndicator.remove();delete this._dropIndicator;}delete this._childBoxes;delete this._children;},_onEnter:function(){this._dropIndicatorAt=-1;},_onLeave:function(){this._dropIndicator.remove();},moveToPosition:function(y){var C=this._dropIndicator,z=new o(C);var B=parseInt(C.css("margin-left"))||0,A=parseInt(C.css("margin-top"))||0,r=z.el.position();y._startOffset={x:r.left,y:r.top};y._dropIndicator=C;delete this._dropIndicator;}};j.dragdrop=n;}}); 20 | /*@end @*/ 21 | -------------------------------------------------------------------------------- /tests/assets/google_closure/base.js: -------------------------------------------------------------------------------- 1 | // Copyright 2006 The Closure Library Authors. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS-IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /** 16 | * @fileoverview Bootstrap for the Google JS Library (Closure). 17 | * 18 | * In uncompiled mode base.js will write out Closure's deps file, unless the 19 | * global CLOSURE_NO_DEPS is set to true. This allows projects to 20 | * include their own deps file(s) from different locations. 21 | * 22 | * 23 | * 24 | */ 25 | 26 | /** 27 | * @define {boolean} Overridden to true by the compiler when --closure_pass 28 | * or --mark_as_compiled is specified. 29 | */ 30 | var COMPILED = false; 31 | 32 | 33 | /** 34 | * Base namespace for the Closure library. Checks to see goog is 35 | * already defined in the current scope before assigning to prevent 36 | * clobbering if base.js is loaded more than once. 37 | * 38 | * @const 39 | */ 40 | var goog = goog || {}; 41 | 42 | 43 | /** 44 | * Reference to the global context. In most cases this will be 'window'. 45 | */ 46 | goog.global = this; 47 | 48 | 49 | /** 50 | * @define {boolean} DEBUG is provided as a convenience so that debugging code 51 | * that should not be included in a production js_binary can be easily stripped 52 | * by specifying --define goog.DEBUG=false to the JSCompiler. For example, most 53 | * toString() methods should be declared inside an "if (goog.DEBUG)" conditional 54 | * because they are generally used for debugging purposes and it is difficult 55 | * for the JSCompiler to statically determine whether they are used. 56 | */ 57 | goog.DEBUG = true; 58 | 59 | 60 | /** 61 | * @define {string} LOCALE defines the locale being used for compilation. It is 62 | * used to select locale specific data to be compiled in js binary. BUILD rule 63 | * can specify this value by "--define goog.LOCALE=" as JSCompiler 64 | * option. 65 | * 66 | * Take into account that the locale code format is important. You should use 67 | * the canonical Unicode format with hyphen as a delimiter. Language must be 68 | * lowercase, Language Script - Capitalized, Region - UPPERCASE. 69 | * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN. 70 | * 71 | * See more info about locale codes here: 72 | * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers 73 | * 74 | * For language codes you should use values defined by ISO 693-1. See it here 75 | * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from 76 | * this rule: the Hebrew language. For legacy reasons the old code (iw) should 77 | * be used instead of the new code (he), see http://wiki/Main/IIISynonyms. 78 | */ 79 | goog.LOCALE = 'en'; // default to en 80 | 81 | 82 | /** 83 | * Indicates whether or not we can call 'eval' directly to eval code in the 84 | * global scope. Set to a Boolean by the first call to goog.globalEval (which 85 | * empirically tests whether eval works for globals). @see goog.globalEval 86 | * @type {?boolean} 87 | * @private 88 | */ 89 | goog.evalWorksForGlobals_ = null; 90 | 91 | 92 | /** 93 | * Creates object stubs for a namespace. When present in a file, goog.provide 94 | * also indicates that the file defines the indicated object. Calls to 95 | * goog.provide are resolved by the compiler if --closure_pass is set. 96 | * @param {string} name name of the object that this file defines. 97 | */ 98 | goog.provide = function(name) { 99 | if (!COMPILED) { 100 | // Ensure that the same namespace isn't provided twice. This is intended 101 | // to teach new developers that 'goog.provide' is effectively a variable 102 | // declaration. And when JSCompiler transforms goog.provide into a real 103 | // variable declaration, the compiled JS should work the same as the raw 104 | // JS--even when the raw JS uses goog.provide incorrectly. 105 | if (goog.getObjectByName(name) && !goog.implicitNamespaces_[name]) { 106 | throw Error('Namespace "' + name + '" already declared.'); 107 | } 108 | 109 | var namespace = name; 110 | while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) { 111 | goog.implicitNamespaces_[namespace] = true; 112 | } 113 | } 114 | 115 | goog.exportPath_(name); 116 | }; 117 | 118 | 119 | if (!COMPILED) { 120 | /** 121 | * Namespaces implicitly defined by goog.provide. For example, 122 | * goog.provide('goog.events.Event') implicitly declares 123 | * that 'goog' and 'goog.events' must be namespaces. 124 | * 125 | * @type {Object} 126 | * @private 127 | */ 128 | goog.implicitNamespaces_ = {}; 129 | } 130 | 131 | 132 | /** 133 | * Builds an object structure for the provided namespace path, 134 | * ensuring that names that already exist are not overwritten. For 135 | * example: 136 | * "a.b.c" -> a = {};a.b={};a.b.c={}; 137 | * Used by goog.provide and goog.exportSymbol. 138 | * @param {string} name name of the object that this file defines. 139 | * @param {*=} opt_object the object to expose at the end of the path. 140 | * @param {Object=} opt_objectToExportTo The object to add the path to; default 141 | * is |goog.global|. 142 | * @private 143 | */ 144 | goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) { 145 | var parts = name.split('.'); 146 | var cur = opt_objectToExportTo || goog.global; 147 | 148 | // Internet Explorer exhibits strange behavior when throwing errors from 149 | // methods externed in this manner. See the testExportSymbolExceptions in 150 | // base_test.html for an example. 151 | if (!(parts[0] in cur) && cur.execScript) { 152 | cur.execScript('var ' + parts[0]); 153 | } 154 | 155 | // Certain browsers cannot parse code in the form for((a in b); c;); 156 | // This pattern is produced by the JSCompiler when it collapses the 157 | // statement above into the conditional loop below. To prevent this from 158 | // happening, use a for-loop and reserve the init logic as below. 159 | 160 | // Parentheses added to eliminate strict JS warning in Firefox. 161 | for (var part; parts.length && (part = parts.shift());) { 162 | if (!parts.length && goog.isDef(opt_object)) { 163 | // last part and we have an object; use it 164 | cur[part] = opt_object; 165 | } else if (cur[part]) { 166 | cur = cur[part]; 167 | } else { 168 | cur = cur[part] = {}; 169 | } 170 | } 171 | }; 172 | 173 | 174 | /** 175 | * Returns an object based on its fully qualified external name. If you are 176 | * using a compilation pass that renames property names beware that using this 177 | * function will not find renamed properties. 178 | * 179 | * @param {string} name The fully qualified name. 180 | * @param {Object=} opt_obj The object within which to look; default is 181 | * |goog.global|. 182 | * @return {Object} The object or, if not found, null. 183 | */ 184 | goog.getObjectByName = function(name, opt_obj) { 185 | var parts = name.split('.'); 186 | var cur = opt_obj || goog.global; 187 | for (var part; part = parts.shift(); ) { 188 | if (cur[part]) { 189 | cur = cur[part]; 190 | } else { 191 | return null; 192 | } 193 | } 194 | return cur; 195 | }; 196 | 197 | 198 | /** 199 | * Globalizes a whole namespace, such as goog or goog.lang. 200 | * 201 | * @param {Object} obj The namespace to globalize. 202 | * @param {Object=} opt_global The object to add the properties to. 203 | * @deprecated Properties may be explicitly exported to the global scope, but 204 | * this should no longer be done in bulk. 205 | */ 206 | goog.globalize = function(obj, opt_global) { 207 | var global = opt_global || goog.global; 208 | for (var x in obj) { 209 | global[x] = obj[x]; 210 | } 211 | }; 212 | 213 | 214 | /** 215 | * Adds a dependency from a file to the files it requires. 216 | * @param {string} relPath The path to the js file. 217 | * @param {Array} provides An array of strings with the names of the objects 218 | * this file provides. 219 | * @param {Array} requires An array of strings with the names of the objects 220 | * this file requires. 221 | */ 222 | goog.addDependency = function(relPath, provides, requires) { 223 | if (!COMPILED) { 224 | var provide, require; 225 | var path = relPath.replace(/\\/g, '/'); 226 | var deps = goog.dependencies_; 227 | for (var i = 0; provide = provides[i]; i++) { 228 | deps.nameToPath[provide] = path; 229 | if (!(path in deps.pathToNames)) { 230 | deps.pathToNames[path] = {}; 231 | } 232 | deps.pathToNames[path][provide] = true; 233 | } 234 | for (var j = 0; require = requires[j]; j++) { 235 | if (!(path in deps.requires)) { 236 | deps.requires[path] = {}; 237 | } 238 | deps.requires[path][require] = true; 239 | } 240 | } 241 | }; 242 | 243 | 244 | 245 | /** 246 | * Implements a system for the dynamic resolution of dependencies 247 | * that works in parallel with the BUILD system. Note that all calls 248 | * to goog.require will be stripped by the JSCompiler when the 249 | * --closure_pass option is used. 250 | * @param {string} rule Rule to include, in the form goog.package.part. 251 | */ 252 | goog.require = function(rule) { 253 | 254 | // if the object already exists we do not need do do anything 255 | // TODO(user): If we start to support require based on file name this has 256 | // to change 257 | // TODO(user): If we allow goog.foo.* this has to change 258 | // TODO(user): If we implement dynamic load after page load we should probably 259 | // not remove this code for the compiled output 260 | if (!COMPILED) { 261 | if (goog.getObjectByName(rule)) { 262 | return; 263 | } 264 | var path = goog.getPathFromDeps_(rule); 265 | if (path) { 266 | goog.included_[path] = true; 267 | goog.writeScripts_(); 268 | } else { 269 | var errorMessage = 'goog.require could not find: ' + rule; 270 | if (goog.global.console) { 271 | goog.global.console['error'](errorMessage); 272 | } 273 | 274 | 275 | throw Error(errorMessage); 276 | 277 | } 278 | } 279 | }; 280 | 281 | 282 | /** 283 | * Path for included scripts 284 | * @type {string} 285 | */ 286 | goog.basePath = ''; 287 | 288 | 289 | /** 290 | * A hook for overriding the base path. 291 | * @type {string|undefined} 292 | */ 293 | goog.global.CLOSURE_BASE_PATH; 294 | 295 | 296 | /** 297 | * Whether to write out Closure's deps file. By default, 298 | * the deps are written. 299 | * @type {boolean|undefined} 300 | */ 301 | goog.global.CLOSURE_NO_DEPS; 302 | 303 | 304 | /** 305 | * Null function used for default values of callbacks, etc. 306 | * @return {void} Nothing. 307 | */ 308 | goog.nullFunction = function() {}; 309 | 310 | 311 | /** 312 | * The identity function. Returns its first argument. 313 | * 314 | * @param {...*} var_args The arguments of the function. 315 | * @return {*} The first argument. 316 | * @deprecated Use goog.functions.identity instead. 317 | */ 318 | goog.identityFunction = function(var_args) { 319 | return arguments[0]; 320 | }; 321 | 322 | 323 | /** 324 | * When defining a class Foo with an abstract method bar(), you can do: 325 | * 326 | * Foo.prototype.bar = goog.abstractMethod 327 | * 328 | * Now if a subclass of Foo fails to override bar(), an error 329 | * will be thrown when bar() is invoked. 330 | * 331 | * Note: This does not take the name of the function to override as 332 | * an argument because that would make it more difficult to obfuscate 333 | * our JavaScript code. 334 | * 335 | * @type {!Function} 336 | * @throws {Error} when invoked to indicate the method should be 337 | * overridden. 338 | */ 339 | goog.abstractMethod = function() { 340 | throw Error('unimplemented abstract method'); 341 | }; 342 | 343 | 344 | /** 345 | * Adds a {@code getInstance} static method that always return the same instance 346 | * object. 347 | * @param {!Function} ctor The constructor for the class to add the static 348 | * method to. 349 | */ 350 | goog.addSingletonGetter = function(ctor) { 351 | ctor.getInstance = function() { 352 | return ctor.instance_ || (ctor.instance_ = new ctor()); 353 | }; 354 | }; 355 | 356 | 357 | if (!COMPILED) { 358 | /** 359 | * Object used to keep track of urls that have already been added. This 360 | * record allows the prevention of circular dependencies. 361 | * @type {Object} 362 | * @private 363 | */ 364 | goog.included_ = {}; 365 | 366 | 367 | /** 368 | * This object is used to keep track of dependencies and other data that is 369 | * used for loading scripts 370 | * @private 371 | * @type {Object} 372 | */ 373 | goog.dependencies_ = { 374 | pathToNames: {}, // 1 to many 375 | nameToPath: {}, // 1 to 1 376 | requires: {}, // 1 to many 377 | // used when resolving dependencies to prevent us from 378 | // visiting the file twice 379 | visited: {}, 380 | written: {} // used to keep track of script files we have written 381 | }; 382 | 383 | 384 | /** 385 | * Tries to detect whether is in the context of an HTML document. 386 | * @return {boolean} True if it looks like HTML document. 387 | * @private 388 | */ 389 | goog.inHtmlDocument_ = function() { 390 | var doc = goog.global.document; 391 | return typeof doc != 'undefined' && 392 | 'write' in doc; // XULDocument misses write. 393 | }; 394 | 395 | 396 | /** 397 | * Tries to detect the base path of the base.js script that bootstraps Closure 398 | * @private 399 | */ 400 | goog.findBasePath_ = function() { 401 | if (!goog.inHtmlDocument_()) { 402 | return; 403 | } 404 | var doc = goog.global.document; 405 | if (goog.global.CLOSURE_BASE_PATH) { 406 | goog.basePath = goog.global.CLOSURE_BASE_PATH; 407 | return; 408 | } 409 | var scripts = doc.getElementsByTagName('script'); 410 | // Search backwards since the current script is in almost all cases the one 411 | // that has base.js. 412 | for (var i = scripts.length - 1; i >= 0; --i) { 413 | var src = scripts[i].src; 414 | var l = src.length; 415 | if (src.substr(l - 7) == 'base.js') { 416 | goog.basePath = src.substr(0, l - 7); 417 | return; 418 | } 419 | } 420 | }; 421 | 422 | 423 | /** 424 | * Writes a script tag if, and only if, that script hasn't already been added 425 | * to the document. (Must be called at execution time) 426 | * @param {string} src Script source. 427 | * @private 428 | */ 429 | goog.writeScriptTag_ = function(src) { 430 | if (goog.inHtmlDocument_() && 431 | !goog.dependencies_.written[src]) { 432 | goog.dependencies_.written[src] = true; 433 | var doc = goog.global.document; 434 | doc.write(' 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | Sniffer Tests 63 | 64 | 65 | 66 |

    Sniffer Tests

    67 | 68 |

    Below is a list of all the tests that Sniffer currently runs. All tests should either return true or a string result (numbers generally represent version numbers) below.

    69 | 70 |
    71 | 72 | 73 | 74 | 88 | 89 | 90 | 95 | 96 | 106 | 107 | 123 | 124 | 125 | 139 | 140 | 144 | 145 | 146 | 147 | 148 | 174 | 175 | 176 | --------------------------------------------------------------------------------