├── README.md
├── tests
├── tests.html
└── assets
│ ├── modernizr.js
│ ├── cufon.js
│ ├── sifr.js
│ ├── google_closure
│ └── base.js
│ └── glow
│ └── core.js
└── sniffer.js
/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).
--------------------------------------------------------------------------------
/tests/tests.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
22 |
23 |
24 |
25 |
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 |
--------------------------------------------------------------------------------
/tests/assets/modernizr.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Modernizr JavaScript library 1.5
3 | * http://www.modernizr.com/
4 | *
5 | * Copyright (c) 2009-2010 Faruk Ates - http://farukat.es/
6 | * Dual-licensed under the BSD and MIT licenses.
7 | * http://www.modernizr.com/license/
8 | *
9 | * Featuring major contributions by
10 | * Paul Irish - http://paulirish.com
11 | */
12 | window.Modernizr=function(i,e,I){function C(a,b){for(var c in a)if(m[a[c]]!==I&&(!b||b(a[c],D)))return true}function r(a,b){var c=a.charAt(0).toUpperCase()+a.substr(1);return!!C([a,"Webkit"+c,"Moz"+c,"O"+c,"ms"+c,"Khtml"+c],b)}function P(){j[E]=function(a){for(var b=0,c=a.length;b7)};d.historymanagement=function(){return!!(i.history&&history.pushState)};d.draganddrop=function(){return u("drag")&&u("dragstart")&&u("dragenter")&&u("dragover")&&u("dragleave")&&u("dragend")&&u("drop")};d.websockets=function(){return"WebSocket"in i};d.rgba=function(){m.cssText="background-color:rgba(150,255,150,.5)";return(""+m.backgroundColor).indexOf("rgba")!==-1};d.hsla=function(){m.cssText="background-color:hsla(120,40%,100%,.5)";return(""+
17 | m.backgroundColor).indexOf("rgba")!==-1};d.multiplebgs=function(){m.cssText="background:url(//:),url(//:),red url(//:)";return/(url\s*\(.*?){3}/.test(m.background)};d.backgroundsize=function(){return r("backgroundSize")};d.borderimage=function(){return r("borderImage")};d.borderradius=function(){return r("borderRadius","",function(a){return(""+a).indexOf("orderRadius")!==-1})};d.boxshadow=function(){return r("boxShadow")};d.opacity=function(){var a=y.join("opacity:.5;")+"";m.cssText=a;return(""+m.opacity).indexOf("0.5")!==
18 | -1};d.cssanimations=function(){return r("animationName")};d.csscolumns=function(){return r("columnCount")};d.cssgradients=function(){var a=("background-image:"+y.join("gradient(linear,left top,right bottom,from(#9f9),to(white));background-image:")+y.join("linear-gradient(left top,#9f9, white);background-image:")).slice(0,-17);m.cssText=a;return(""+m.backgroundImage).indexOf("gradient")!==-1};d.cssreflections=function(){return r("boxReflect")};d.csstransforms=function(){return!!C(["transformProperty",
19 | "WebkitTransform","MozTransform","OTransform","msTransform"])};d.csstransforms3d=function(){var a=!!C(["perspectiveProperty","WebkitPerspective","MozPerspective","OPerspective","msPerspective"]);if(a){var b=document.createElement("style"),c=e.createElement("div");b.textContent="@media ("+y.join("transform-3d),(")+"modernizr){#modernizr{height:3px}}";e.getElementsByTagName("head")[0].appendChild(b);c.id="modernizr";s.appendChild(c);a=c.offsetHeight===3;b.parentNode.removeChild(b);c.parentNode.removeChild(c)}return a};
20 | d.csstransitions=function(){return r("transitionProperty")};d.fontface=function(){var a;if(/*@cc_on@if(@_jscript_version>=5)!@end@*/0)a=true;else{var b=e.createElement("style"),c=e.createElement("span"),h,t=false,g=e.body,o,w;b.textContent="@font-face{font-family:testfont;src:url('data:font/ttf;base64,AAEAAAAMAIAAAwBAT1MvMliohmwAAADMAAAAVmNtYXCp5qrBAAABJAAAANhjdnQgACICiAAAAfwAAAAEZ2FzcP//AAMAAAIAAAAACGdseWYv5OZoAAACCAAAANxoZWFk69bnvwAAAuQAAAA2aGhlYQUJAt8AAAMcAAAAJGhtdHgGDgC4AAADQAAAABRsb2NhAIQAwgAAA1QAAAAMbWF4cABVANgAAANgAAAAIG5hbWUgXduAAAADgAAABPVwb3N03NkzmgAACHgAAAA4AAECBAEsAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAACAAMDAAAAAAAAgAACbwAAAAoAAAAAAAAAAFBmRWQAAAAgqS8DM/8zAFwDMwDNAAAABQAAAAAAAAAAAAMAAAADAAAAHAABAAAAAABGAAMAAQAAAK4ABAAqAAAABgAEAAEAAgAuqQD//wAAAC6pAP///9ZXAwAAAAAAAAACAAAABgBoAAAAAAAvAAEAAAAAAAAAAAAAAAAAAAABAAIAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEACoAAAAGAAQAAQACAC6pAP//AAAALqkA////1lcDAAAAAAAAAAIAAAAiAogAAAAB//8AAgACACIAAAEyAqoAAwAHAC6xAQAvPLIHBADtMrEGBdw8sgMCAO0yALEDAC88sgUEAO0ysgcGAfw8sgECAO0yMxEhESczESMiARDuzMwCqv1WIgJmAAACAFUAAAIRAc0ADwAfAAATFRQWOwEyNj0BNCYrASIGARQGKwEiJj0BNDY7ATIWFX8aIvAiGhoi8CIaAZIoN/43KCg3/jcoAWD0JB4eJPQkHh7++EY2NkbVRjY2RgAAAAABAEH/+QCdAEEACQAANjQ2MzIWFAYjIkEeEA8fHw8QDxwWFhwWAAAAAQAAAAIAAIuYbWpfDzz1AAsEAAAAAADFn9IuAAAAAMWf0i797/8zA4gDMwAAAAgAAgAAAAAAAAABAAADM/8zAFwDx/3v/98DiAABAAAAAAAAAAAAAAAAAAAABQF2ACIAAAAAAVUAAAJmAFUA3QBBAAAAKgAqACoAWgBuAAEAAAAFAFAABwBUAAQAAgAAAAEAAQAAAEAALgADAAMAAAAQAMYAAQAAAAAAAACLAAAAAQAAAAAAAQAhAIsAAQAAAAAAAgAFAKwAAQAAAAAAAwBDALEAAQAAAAAABAAnAPQAAQAAAAAABQAKARsAAQAAAAAABgAmASUAAQAAAAAADgAaAUsAAwABBAkAAAEWAWUAAwABBAkAAQBCAnsAAwABBAkAAgAKAr0AAwABBAkAAwCGAscAAwABBAkABABOA00AAwABBAkABQAUA5sAAwABBAkABgBMA68AAwABBAkADgA0A/tDb3B5cmlnaHQgMjAwOSBieSBEYW5pZWwgSm9obnNvbi4gIFJlbGVhc2VkIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgT3BlbiBGb250IExpY2Vuc2UuIEtheWFoIExpIGdseXBocyBhcmUgcmVsZWFzZWQgdW5kZXIgdGhlIEdQTCB2ZXJzaW9uIDMuYmFlYzJhOTJiZmZlNTAzMiAtIHN1YnNldCBvZiBKdXJhTGlnaHRiYWVjMmE5MmJmZmU1MDMyIC0gc3Vic2V0IG9mIEZvbnRGb3JnZSAyLjAgOiBKdXJhIExpZ2h0IDogMjMtMS0yMDA5YmFlYzJhOTJiZmZlNTAzMiAtIHN1YnNldCBvZiBKdXJhIExpZ2h0VmVyc2lvbiAyIGJhZWMyYTkyYmZmZTUwMzIgLSBzdWJzZXQgb2YgSnVyYUxpZ2h0aHR0cDovL3NjcmlwdHMuc2lsLm9yZy9PRkwAQwBvAHAAeQByAGkAZwBoAHQAIAAyADAAMAA5ACAAYgB5ACAARABhAG4AaQBlAGwAIABKAG8AaABuAHMAbwBuAC4AIAAgAFIAZQBsAGUAYQBzAGUAZAAgAHUAbgBkAGUAcgAgAHQAaABlACAAdABlAHIAbQBzACAAbwBmACAAdABoAGUAIABPAHAAZQBuACAARgBvAG4AdAAgAEwAaQBjAGUAbgBzAGUALgAgAEsAYQB5AGEAaAAgAEwAaQAgAGcAbAB5AHAAaABzACAAYQByAGUAIAByAGUAbABlAGEAcwBlAGQAIAB1AG4AZABlAHIAIAB0AGgAZQAgAEcAUABMACAAdgBlAHIAcwBpAG8AbgAgADMALgBiAGEAZQBjADIAYQA5ADIAYgBmAGYAZQA1ADAAMwAyACAALQAgAHMAdQBiAHMAZQB0ACAAbwBmACAASgB1AHIAYQBMAGkAZwBoAHQAYgBhAGUAYwAyAGEAOQAyAGIAZgBmAGUANQAwADMAMgAgAC0AIABzAHUAYgBzAGUAdAAgAG8AZgAgAEYAbwBuAHQARgBvAHIAZwBlACAAMgAuADAAIAA6ACAASgB1AHIAYQAgAEwAaQBnAGgAdAAgADoAIAAyADMALQAxAC0AMgAwADAAOQBiAGEAZQBjADIAYQA5ADIAYgBmAGYAZQA1ADAAMwAyACAALQAgAHMAdQBiAHMAZQB0ACAAbwBmACAASgB1AHIAYQAgAEwAaQBnAGgAdABWAGUAcgBzAGkAbwBuACAAMgAgAGIAYQBlAGMAMgBhADkAMgBiAGYAZgBlADUAMAAzADIAIAAtACAAcwB1AGIAcwBlAHQAIABvAGYAIABKAHUAcgBhAEwAaQBnAGgAdABoAHQAdABwADoALwAvAHMAYwByAGkAcAB0AHMALgBzAGkAbAAuAG8AcgBnAC8ATwBGAEwAAAAAAgAAAAAAAP+BADMAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAQACAQIAEQt6ZXJva2F5YWhsaQ==')}";
21 | e.getElementsByTagName("head")[0].appendChild(b);c.setAttribute("style","font:99px _,arial,helvetica;position:absolute;visibility:hidden");if(!g){g=s.appendChild(e.createElement("fontface"));t=true}c.innerHTML="........";c.id="fonttest";g.appendChild(c);h=c.offsetWidth*c.offsetHeight;c.style.font="99px testfont,_,arial,helvetica";a=h!==c.offsetWidth*c.offsetHeight;var v=function(){if(g.parentNode){a=j.fontface=h!==c.offsetWidth*c.offsetHeight;s.className=s.className.replace(/(no-)?fontface\b/,"")+
22 | (a?" ":" no-")+"fontface"}};setTimeout(v,75);setTimeout(v,150);addEventListener("load",function(){v();(w=true)&&o&&o(a);setTimeout(function(){t||(g=c);g.parentNode.removeChild(g);b.parentNode.removeChild(b)},50)},false)}j._fontfaceready=function(p){w||a?p(a):(o=p)};return a||h!==c.offsetWidth};d.video=function(){var a=e.createElement("video"),b=!!a.canPlayType;if(b){b=new Boolean(b);b.ogg=a.canPlayType('video/ogg; codecs="theora"');b.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"');b.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"')}return b};
23 | d.audio=function(){var a=e.createElement("audio"),b=!!a.canPlayType;if(b){b=new Boolean(b);b.ogg=a.canPlayType('audio/ogg; codecs="vorbis"');b.mp3=a.canPlayType("audio/mpeg;");b.wav=a.canPlayType('audio/wav; codecs="1"');b.m4a=a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")}return b};d.localStorage=function(){return"localStorage"in i&&i.localStorage!==null};d.sessionStorage=function(){try{return"sessionStorage"in i&&i.sessionStorage!==null}catch(a){return false}};d.webworkers=function(){return!!i.Worker};
24 | d.applicationCache=function(){var a=i.applicationCache;return!!(a&&typeof a.status!="undefined"&&typeof a.update=="function"&&typeof a.swapCache=="function")};d.svg=function(){return!!e.createElementNS&&!!e.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect};d.smil=function(){return!!e.createElementNS&&/SVG/.test(M.call(e.createElementNS("http://www.w3.org/2000/svg","animate")))};d.svgclippaths=function(){return!!e.createElementNS&&/SVG/.test(M.call(e.createElementNS("http://www.w3.org/2000/svg",
25 | "clipPath")))};for(var z in d)if(O(d,z))N.push(((j[z.toLowerCase()]=d[z]())?"":"no-")+z.toLowerCase());j[E]||P();j.addTest=function(a,b){a=a.toLowerCase();if(!j[a]){b=!!b();s.className+=" "+(b?"":"no-")+a;j[a]=b;return j}};m.cssText="";D=n=null;(function(){var a=e.createElement("div");a.innerHTML=" ";return a.childNodes.length!==1})()&&function(a,b){function c(f,k){if(o[f])o[f].styleSheet.cssText+=k;else{var l=t[G],q=b[A]("style");q.media=f;l.insertBefore(q,l[G]);o[f]=q;c(f,k)}}function h(f,
26 | k){for(var l=new RegExp("\\b("+w+")\\b(?!.*[;}])","gi"),q=function(B){return".iepp_"+B},x=-1;++x\\s*$","i");g.innerHTML=f.outerHTML.replace(/\r|\n/g," ").replace(l,f.currentStyle.display=="block"?"":"
");l=g.childNodes[0];l.className+=" iepp_"+q;l=p[p.length]=[f,l];f.parentNode.replaceChild(l[1],l[0])}h(b.styleSheets,"all")});a.attachEvent("onafterprint",
28 | function(){for(var f=-1,k;++f]+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
5 |
6 | Older versions:
7 | * IFR by Shaun Inman
8 | * sIFR 1.0 by Mike Davidson, Shaun Inman and Tomas Jogin
9 | * sIFR 2.0 by Mike Davidson, Shaun Inman, Tomas Jogin and Mark Wubben
10 |
11 | See also and .
12 |
13 | This software is licensed and provided under the CC-GNU LGPL.
14 | See
15 | *****************************************************************************/
16 |
17 | var sIFR=new function(){var O=this;var E={ACTIVE:"sIFR-active",REPLACED:"sIFR-replaced",IGNORE:"sIFR-ignore",ALTERNATE:"sIFR-alternate",CLASS:"sIFR-class",LAYOUT:"sIFR-layout",FLASH:"sIFR-flash",FIX_FOCUS:"sIFR-fixfocus",DUMMY:"sIFR-dummy"};E.IGNORE_CLASSES=[E.REPLACED,E.IGNORE,E.ALTERNATE];this.MIN_FONT_SIZE=6;this.MAX_FONT_SIZE=126;this.FLASH_PADDING_BOTTOM=5;this.VERSION="436";this.isActive=false;this.isEnabled=true;this.fixHover=true;this.autoInitialize=true;this.setPrefetchCookie=true;this.cookiePath="/";this.domains=[];this.forceWidth=true;this.fitExactly=false;this.forceTextTransform=true;this.useDomLoaded=true;this.useStyleCheck=false;this.hasFlashClassSet=false;this.repaintOnResize=true;this.replacements=[];var L=0;var R=false;function Y(){}function D(c){function d(e){return e.toLocaleUpperCase()}this.normalize=function(e){return e.replace(/\n|\r|\xA0/g,D.SINGLE_WHITESPACE).replace(/\s+/g,D.SINGLE_WHITESPACE)};this.textTransform=function(e,f){switch(e){case"uppercase":return f.toLocaleUpperCase();case"lowercase":return f.toLocaleLowerCase();case"capitalize":return f.replace(/^\w|\s\w/g,d)}return f};this.toHexString=function(e){if(e.charAt(0)!="#"||e.length!=4&&e.length!=7){return e}e=e.substring(1);return"0x"+(e.length==3?e.replace(/(.)(.)(.)/,"$1$1$2$2$3$3"):e)};this.toJson=function(g,f){var e="";switch(typeof(g)){case"string":e='"'+f(g)+'"';break;case"number":case"boolean":e=g.toString();break;case"object":e=[];for(var h in g){if(g[h]==Object.prototype[h]){continue}e.push('"'+h+'":'+this.toJson(g[h]))}e="{"+e.join(",")+"}";break}return e};this.convertCssArg=function(e){if(!e){return{}}if(typeof(e)=="object"){if(e.constructor==Array){e=e.join("")}else{return e}}var l={};var m=e.split("}");for(var h=0;h-1){g=g.substr(f+1);var e=h.lastIndexOf(g);if(e>-1&&(e+g.length)==h.length){return true}}return false};this.uriEncode=function(e){return encodeURI(decodeURIComponent(e))};this.delay=function(f,h,g){var e=Array.prototype.slice.call(arguments,3);setTimeout(function(){h.apply(g,e)},f)}}D.UNIT_REMOVAL_PROPERTIES={leading:true,"margin-left":true,"margin-right":true,"text-indent":true};D.SINGLE_WHITESPACE=" ";function U(e){var d=this;function c(g,j,h){var k=d.getStyleAsInt(g,j,e.ua.ie);if(k==0){k=g[h];for(var f=3;f=5.5@*/;this.ieWin=this.ie&&this.windows/*@cc_on&&@_jscript_version>=5.1@*/;this.windows=this.windows&&(!this.ie||this.ieWin);this.ieMac=this.ie&&this.macintosh/*@cc_on&&@_jscript_version<5.1@*/;this.macintosh=this.macintosh&&(!this.ie||this.ieMac);this.safari=/safari/.test(g);this.webkit=!this.konqueror&&/applewebkit/.test(g);this.khtml=this.webkit||this.konqueror;this.gecko=!this.khtml&&q=="gecko";this.ieVersion=this.ie&&/.*msie\s(\d\.\d)/.exec(g)?this.parseVersion(RegExp.$1):"0";this.operaVersion=this.opera&&/.*opera(\s|\/)(\d+\.\d+)/.exec(g)?this.parseVersion(RegExp.$2):"0";this.webkitVersion=this.webkit&&/.*applewebkit\/(\d+).*/.exec(g)?this.parseVersion(RegExp.$1):"0";this.geckoVersion=this.gecko&&/.*rv:\s*([^\)]+)\)\s+gecko/.exec(g)?this.parseVersion(RegExp.$1):"0";this.konquerorVersion=this.konqueror&&/.*konqueror\/([\d\.]+).*/.exec(g)?this.parseVersion(RegExp.$1):"0";this.flashVersion=0;if(this.ieWin){var l;var o=false;try{l=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7")}catch(m){try{l=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");this.flashVersion=this.parseVersion("6");l.AllowScriptAccess="always"}catch(m){o=this.flashVersion==this.parseVersion("6")}if(!o){try{l=new ActiveXObject("ShockwaveFlash.ShockwaveFlash")}catch(m){}}}if(!o&&l){this.flashVersion=this.parseVersion((l.GetVariable("$version")||"").replace(/^\D+(\d+)\D+(\d+)\D+(\d+).*/g,"$1.$2.$3"))}}else{if(navigator.plugins&&navigator.plugins["Shockwave Flash"]){var n=navigator.plugins["Shockwave Flash"].description.replace(/^.*\s+(\S+\s+\S+$)/,"$1");var p=n.replace(/^\D*(\d+\.\d+).*$/,"$1");if(/r/.test(n)){p+=n.replace(/^.*r(\d*).*$/,".$1")}else{if(/d/.test(n)){p+=".0"}}this.flashVersion=this.parseVersion(p);var j=false;for(var k=0,c=this.flashVersion>=H.MIN_FLASH_VERSION;c&&k-1){c=false;this.quicktime=true}}}if(this.quicktime||!j){this.flashVersion=this.parseVersion("0")}}}this.flash=this.flashVersion>=H.MIN_FLASH_VERSION;this.transparencySupport=this.macintosh||this.windows||this.linux&&(this.flashVersion>=this.parseVersion("10")&&(this.gecko&&this.geckoVersion>=this.parseVersion("1.9")||this.opera));this.computedStyleSupport=this.ie||!!document.defaultView.getComputedStyle;this.fixFocus=this.gecko&&this.windows;this.nativeDomLoaded=this.gecko||this.webkit&&this.webkitVersion>=this.parseVersion("525")||this.konqueror&&this.konquerorMajor>this.parseVersion("03")||this.opera;this.mustCheckStyle=this.khtml||this.opera;this.forcePageLoad=this.webkit&&this.webkitVersion=this.parseVersion("9.61"))&&(!this.webkit||this.webkitVersion>=this.parseVersion("412"))&&(!this.gecko||this.geckoVersion>=this.parseVersion("1.8.0.12"))&&(!this.konqueror)}H.parseVersion=function(c){return c.replace(/(^|\D)(\d+)(?=\D|$)/g,function(f,e,g){f=e;for(var d=4-g.length;d>=0;d--){f+="0"}return f+g})};H.MIN_FLASH_VERSION=H.parseVersion("8");function F(c){this.fix=c.ua.ieWin&&window.location.hash!="";var d;this.cache=function(){d=document.title};function e(){document.title=d}this.restore=function(){if(this.fix){setTimeout(e,0)}}}function S(l){var e=null;function c(){try{if(l.ua.ie||document.readyState!="loaded"&&document.readyState!="complete"){document.documentElement.doScroll("left")}}catch(n){return setTimeout(c,10)}i()}function i(){if(l.useStyleCheck){h()}else{if(!l.ua.mustCheckStyle){d(null,true)}}}function h(){e=l.dom.create("div",E.DUMMY);l.dom.getBody().appendChild(e);m()}function m(){if(l.dom.getComputedStyle(e,"marginLeft")=="42px"){g()}else{setTimeout(m,10)}}function g(){if(e&&e.parentNode){e.parentNode.removeChild(e)}e=null;d(null,true)}function d(n,o){l.initialize(o);if(n&&n.type=="load"){if(document.removeEventListener){document.removeEventListener("DOMContentLoaded",d,false)}if(window.removeEventListener){window.removeEventListener("load",d,false)}}}function j(){l.prepareClearReferences();if(document.readyState=="interactive"){document.attachEvent("onstop",f);setTimeout(function(){document.detachEvent("onstop",f)},0)}}function f(){document.detachEvent("onstop",f);k()}function k(){l.clearReferences()}this.attach=function(){if(window.addEventListener){window.addEventListener("load",d,false)}else{window.attachEvent("onload",d)}if(!l.useDomLoaded||l.ua.forcePageLoad||l.ua.ie&&window.top!=window){return}if(l.ua.nativeDomLoaded){document.addEventListener("DOMContentLoaded",i,false)}else{if(l.ua.ie||l.ua.khtml){c()}}};this.attachUnload=function(){if(!l.ua.ie){return}window.attachEvent("onbeforeunload",j);window.attachEvent("onunload",k)}}var Q="sifrFetch";function N(c){var e=false;this.fetchMovies=function(f){if(c.setPrefetchCookie&&new RegExp(";?"+Q+"=true;?").test(document.cookie)){return}try{e=true;d(f)}catch(g){}if(c.setPrefetchCookie){document.cookie=Q+"=true;path="+c.cookiePath}};this.clear=function(){if(!e){return}try{var f=document.getElementsByTagName("script");for(var g=f.length-1;g>=0;g--){var h=f[g];if(h.type=="sifr/prefetch"){h.parentNode.removeChild(h)}}}catch(j){}};function d(f){for(var g=0;g<\/script>')}}}function b(e){var g=e.ua.ie;var f=g&&e.ua.flashVersion=0;h--){c[j[h].getAttribute("id")]=j[h]}}for(var k in c){if(Object.prototype[k]!=c[k]){this.cleanup(k,true)}}}}function K(d,g,f,c,e){this.sIFR=d;this.id=g;this.vars=f;this.movie=null;this.__forceWidth=c;this.__events=e;this.__resizing=0}K.prototype={getFlashElement:function(){return document.getElementById(this.id)},getAlternate:function(){return document.getElementById(this.id+"_alternate")},getAncestor:function(){var c=this.getFlashElement().parentNode;return !this.sIFR.dom.hasClass(E.FIX_FOCUS,c)?c:c.parentNode},available:function(){var c=this.getFlashElement();return c&&c.parentNode},call:function(c){var d=this.getFlashElement();if(!d[c]){return false}return Function.prototype.apply.call(d[c],d,Array.prototype.slice.call(arguments,1))},attempt:function(){if(!this.available()){return false}try{this.call.apply(this,arguments)}catch(c){if(this.sIFR.debug){throw c}return false}return true},updateVars:function(c,e){for(var d=0;d ';var m="";for(var l=0;l'}this.html=this.html.replace(/(<\/object>)/,m+"$1");j.style.minHeight=o+"px";j.innerHTML=this.html;this.broken.register(j.firstChild)}d.prototype={reset:function(f,g){g=g.cloneNode(true);var e=f.parentNode;e.innerHTML=this.html;this.broken.register(e.firstChild);e.appendChild(g)},remove:function(e,f){this.broken.cleanup(f)},setSize:function(e,f){this.html=this.html.replace(e=="height"?/(height)="\d+"/:/(width)="\d+"/,'$1="'+f+'"')},injectVars:function(e,f){if(e!=this.html){return}this.html=this.html.replace(/(flashvars(=|\"\svalue=)\")[^\"]+/,"$1"+f)}}};this.errors=new Y(O);var A=this.util=new D(O);var W=this.dom=new U(O);var T=this.ua=new H(O);var G={fragmentIdentifier:new F(O),pageLoad:new S(O),prefetch:new N(O),brokenFlashIE:new b(O)};this.__resetBrokenMovies=G.brokenFlashIE.reset;var J={kwargs:[],replaceAll:function(d){for(var c=0;c1&&AP){AK+=Math.round((AH-1)*AP)}var AB=AD?c:"100%";var AI="sIFR_replacement_"+L++;var AQ=["id="+AI,"content="+A.escape(p.text),"width="+c,"renderheight="+AK,"link="+A.escape(p.primaryLink.href||""),"target="+A.escape(p.primaryLink.target||""),"size="+n,"css="+A.escape(AC),"cursor="+k,"tunewidth="+(x.tuneWidth||0),"tuneheight="+r,"offsetleft="+(x.offsetLeft||""),"offsettop="+(x.offsetTop||""),"fitexactly="+q,"preventwrap="+AS,"forcesingleline="+AN,"antialiastype="+(x.antiAliasType||""),"thickness="+(x.thickness||""),"sharpness="+(x.sharpness||""),"kerning="+o,"gridfittype="+AJ,"flashfilters="+v,"opacity="+AW,"blendmode="+(x.blendMode||""),"selectable="+(x.selectable==null||AG!=""&&!sIFR.ua.macintosh&&sIFR.ua.gecko&&sIFR.ua.geckoVersion>=sIFR.ua.parseVersion("1.9")?"true":x.selectable===true),"fixhover="+(this.fixHover===true),"events="+z,"delayrun="+G.brokenFlashIE.fixFlash,"version="+this.VERSION];var y=A.encodeVars(AQ);var g=new K(O,AI,AQ,AD,{onReplacement:x.onReplacement,onRollOver:x.onRollOver,onRollOut:x.onRollOut,onRelease:x.onRelease});g.movie=X.create(sIFR,G.brokenFlashIE,AF,T.fixFocus&&x.fixFocus,AI,w,AB,AK,y,AG,e);this.replacements.push(g);this.replacements[AI]=g;if(x.selector){if(!this.replacements[x.selector]){this.replacements[x.selector]=[g]}else{this.replacements[x.selector].push(g)}}d.setAttribute("id",AI+"_alternate");AF.appendChild(d);W.addClass(E.REPLACED,AF)}G.fragmentIdentifier.restore()};this.getReplacementByFlashElement=function(d){for(var c=0;c-1){n=n.match("(\\s|^)"+E.CLASS+"-([^\\s$]*)(\\s|$)")[2]}else{n=n.match(/^([^\s]+)/)[1]}}if(n!=""){h.push('class="'+n+'"')}if(r=="a"){var d=s(f.getAttribute("href")||"");var l=f.getAttribute("target")||"";h.push('href="'+d+'"','target="'+l+'"');if(!k){k={href:d,target:l}}}m.push("<"+r+(h.length>0?" ":"")+h.join(" ")+">");p=true;if(f.hasChildNodes()){q.push(j);j=0;e=f.childNodes;continue}else{if(!/^(br|img)$/i.test(f.nodeName)){m.push("",f.nodeName.toLowerCase(),">")}}}if(q.length>0&&!f.nextSibling){do{j=q.pop();e=f.parentNode.parentNode.childNodes;f=e[j];if(f){m.push("",f.nodeName.toLowerCase(),">")}}while(j==e.length-1&&q.length>0)}j++}return{text:m.join("").replace(/^\s+|\s+$|\s*( )\s*/g,"$1"),primaryLink:k||{}}}};
18 | var parseSelector=(function(){var B=/\s*,\s*/;var A=/\s*([\s>+~(),]|^|$)\s*/g;var L=/([\s>+~,]|[^(]\+|^)([#.:@])/g;var F=/(^|\))[^\s>+~]/g;var M=/(\)|^)/;var K=/[\s#.:>+~()@]|[^\s#.:>+~()@]+/g;function H(R,P){P=P||document.documentElement;var S=R.split(B),X=[];for(var U=0;U":function(O,R){var N=[];for(var Q=0,S;QCLOSURE_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('