1// start of index.js 2 3 4 5var GIGO = {}; // We will use this as a name space. 6GIGO.lang = "en"; 7GIGO.langUC = "EN"; 8GIGO.locale = "en_US"; 9 10/*! 11 * Copyright 2010 Jason Fesler. All rights reserved. 12 * Author: Jason Fesler <[email protected]> 13 * Code deployed at: http:/test-ipv6.com 14 * Source: http://code.google.com/p/falling-sky/ 15 * 16 * The following were also used: 17 * 18 * http://geekswithblogs.net/svanvliet/archive/2006/03/23/simple-javascript-object-dump-function.aspx - Scott Van Vliet 19 * http://jquery.com/ - John Resig 20 * http://sizzlejs.com/ - The Dojo Foundation 21 * http://code.google.com/p/jquery-jsonp/ - Julian Aubourg 22 * http://t.wits.sg (progress bar) - Gary Teo 23 * http://mootools.net - The MooTools production team 24 * 25 * Full credit is in the source, see 26 * http://code.google.com/p/falling-sky/source/browse/trunk/source/js/ext/NOTICE?r=HEAD 27 * 28 * Most of what you see below will be heavily compressed, including obfuscation 29 * to reduce the served content size. Use the source tree instead to browse 30 * the source. 31 * 32 * Alternately, view http://beta.test-ipv6.com/index.js, 33 * and scroll down. 34 */ 35 36/*! JSON v3.3.2 | http://bestiejs.github.io/json3 | Copyright 2012-2014, Kit Cambridge | http://kit.mit-license.org */ 37(function(){function N(p,r){function q(a){if(q[a]!==w)return q[a];var c;if("bug-string-char-index"==a)c="a"!="a"[0];else if("json"==a)c=q("json-stringify")&&q("json-parse");else{var e;if("json-stringify"==a){c=r.stringify;var b="function"==typeof c&&s;if(b){(e=function(){return 1}).toJSON=e;try{b="0"===c(0)&&"0"===c(new t)&&'""'==c(new A)&&c(u)===w&&c(w)===w&&c()===w&&"1"===c(e)&&"[1]"==c([e])&&"[null]"==c([w])&&"null"==c(null)&&"[null,null,null]"==c([w,u,null])&&'{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}'== 38c({a:[e,!0,!1,null,"\x00\b\n\f\r\t"]})&&"1"===c(null,e)&&"[\n 1,\n 2\n]"==c([1,2],null,1)&&'"-271821-04-20T00:00:00.000Z"'==c(new C(-864E13))&&'"+275760-09-13T00:00:00.000Z"'==c(new C(864E13))&&'"-000001-01-01T00:00:00.000Z"'==c(new C(-621987552E5))&&'"1969-12-31T23:59:59.999Z"'==c(new C(-1))}catch(f){b=!1}}c=b}if("json-parse"==a){c=r.parse;if("function"==typeof c)try{if(0===c("0")&&!c(!1)){e=c('{"a":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}');var n=5==e.a.length&&1===e.a[0];if(n){try{n=!c('"\t"')}catch(d){}if(n)try{n= 391!==c("01")}catch(g){}if(n)try{n=1!==c("1.")}catch(m){}}}}catch(X){n=!1}c=n}}return q[a]=!!c}p||(p=k.Object());r||(r=k.Object());var t=p.Number||k.Number,A=p.String||k.String,H=p.Object||k.Object,C=p.Date||k.Date,G=p.SyntaxError||k.SyntaxError,K=p.TypeError||k.TypeError,L=p.Math||k.Math,I=p.JSON||k.JSON;"object"==typeof I&&I&&(r.stringify=I.stringify,r.parse=I.parse);var H=H.prototype,u=H.toString,v,B,w,s=new C(-0xc782b5b800cec);try{s=-109252==s.getUTCFullYear()&&0===s.getUTCMonth()&&1===s.getUTCDate()&& 4010==s.getUTCHours()&&37==s.getUTCMinutes()&&6==s.getUTCSeconds()&&708==s.getUTCMilliseconds()}catch(Q){}if(!q("json")){var D=q("bug-string-char-index");if(!s)var x=L.floor,M=[0,31,59,90,120,151,181,212,243,273,304,334],E=function(a,c){return M[c]+365*(a-1970)+x((a-1969+(c=+(1<c)))/4)-x((a-1901+c)/100)+x((a-1601+c)/400)};(v=H.hasOwnProperty)||(v=function(a){var c={},e;(c.__proto__=null,c.__proto__={toString:1},c).toString!=u?v=function(a){var c=this.__proto__;a=a in(this.__proto__=null,this);this.__proto__= 41c;return a}:(e=c.constructor,v=function(a){var c=(this.constructor||e).prototype;return a in this&&!(a in c&&this[a]===c[a])});c=null;return v.call(this,a)});B=function(a,c){var e=0,b,f,n;(b=function(){this.valueOf=0}).prototype.valueOf=0;f=new b;for(n in f)v.call(f,n)&&e++;b=f=null;e?B=2==e?function(a,c){var e={},b="[object Function]"==u.call(a),f;for(f in a)b&&"prototype"==f||v.call(e,f)||!(e[f]=1)||!v.call(a,f)||c(f)}:function(a,c){var e="[object Function]"==u.call(a),b,f;for(b in a)e&&"prototype"== 42b||!v.call(a,b)||(f="constructor"===b)||c(b);(f||v.call(a,b="constructor"))&&c(b)}:(f="valueOf toString toLocaleString propertyIsEnumerable isPrototypeOf hasOwnProperty constructor".split(" "),B=function(a,c){var e="[object Function]"==u.call(a),b,h=!e&&"function"!=typeof a.constructor&&F[typeof a.hasOwnProperty]&&a.hasOwnProperty||v;for(b in a)e&&"prototype"==b||!h.call(a,b)||c(b);for(e=f.length;b=f[--e];h.call(a,b)&&c(b));});return B(a,c)};
42if(!q("json-stringify")){var U={92:"\\\\",34:'\\"',8:"\\b", 4312:"\\f",10:"\\n",13:"\\r",9:"\\t"},y=function(a,c){return("000000"+(c||0)).slice(-a)},R=function(a){for(var c='"',b=0,h=a.length,f=!D||10<h,n=f&&(D?a.split(""):a);b<h;b++){var d=a.charCodeAt(b);switch(d){case 8:case 9:case 10:case 12:case 13:case 34:case 92:c+=U[d];break;default:if(32>d){c+="\\u00"+y(2,d.toString(16));break}c+=f?n[b]:a.charAt(b)}}return c+'"'},O=function(a,c,b,h,f,n,d){var g,m,k,l,p,r,s,t,q;try{g=c[a]}catch(z){}if("object"==typeof g&&g)if(m=u.call(g),"[object Date]"!=m||v.call(g, 44"toJSON"))"function"==typeof g.toJSON&&("[object Number]"!=m&&"[object String]"!=m&&"[object Array]"!=m||v.call(g,"toJSON"))&&(g=g.toJSON(a));else if(g>-1/0&&g<1/0){if(E){l=x(g/864E5);for(m=x(l/365.2425)+1970-1;E(m+1,0)<=l;m++);for(k=x((l-E(m,0))/30.42);E(m,k+1)<=l;k++);l=1+l-E(m,k);p=(g%864E5+864E5)%864E5;r=x(p/36E5)%24;s=x(p/6E4)%60;t=x(p/1E3)%60;p%=1E3}else m=g.getUTCFullYear(),k=g.getUTCMonth(),l=g.getUTCDate(),r=g.getUTCHours(),s=g.getUTCMinutes(),t=g.getUTCSeconds(),p=g.getUTCMilliseconds(); 45g=(0>=m||1E4<=m?(0>m?"-":"+")+y(6,0>m?-m:m):y(4,m))+"-"+y(2,k+1)+"-"+y(2,l)+"T"+y(2,r)+":"+y(2,s)+":"+y(2,t)+"."+y(3,p)+"Z"}else g=null;b&&(g=b.call(c,a,g));if(null===g)return"null";m=u.call(g);if("[object Boolean]"==m)return""+g;if("[object Number]"==m)return g>-1/0&&g<1/0?""+g:"null";if("[object String]"==m)return R(""+g);if("object"==typeof g){for(a=d.length;a--;)if(d[a]===g)throw K();d.push(g);q=[];c=n;n+=f;if("[object Array]"==m){k=0;for(a=g.length;k<a;k++)m=O(k,g,b,h,f,n,d),q.push(m===w?"null": 46m);a=q.length?f?"[\n"+n+q.join(",\n"+n)+"\n"+c+"]":"["+q.join(",")+"]":"[]"}else B(h||g,function(a){var c=O(a,g,b,h,f,n,d);c!==w&&q.push(R(a)+":"+(f?" ":"")+c)}),a=q.length?f?"{\n"+n+q.join(",\n"+n)+"\n"+c+"}":"{"+q.join(",")+"}":"{}";d.pop();return a}};r.stringify=function(a,c,b){var h,f,n,d;if(F[typeof c]&&c)if("[object Function]"==(d=u.call(c)))f=c;else if("[object Array]"==d){n={};for(var g=0,k=c.length,l;g<k;l=c[g++],(d=u.call(l),"[object String]"==d||"[object Number]"==d)&&(n[l]=1));}if(b)if("[object Number]"== 47(d=u.call(b))){if(0<(b-=b%1))for(h="",10<b&&(b=10);h.length<b;h+=" ");}else"[object String]"==d&&(h=10>=b.length?b:b.slice(0,10));return O("",(l={},l[""]=a,l),f,n,h,"",[])}}if(!q("json-parse")){var V=A.fromCharCode,W={92:"\\",34:'"',47:"/",98:"\b",116:"\t",110:"\n",102:"\f",114:"\r"},b,J,l=function(){b=J=null;throw G();},z=function(){for(var a=J,c=a.length,e,h,f,k,d;b<c;)switch(d=a.charCodeAt(b),d){case 9:case 10:case 13:case 32:b++;break;case 123:case 125:case 91:case 93:case 58:case 44:return e= 48D?a.charAt(b):a[b],b++,e;case 34:e="@";for(b++;b<c;)if(d=a.charCodeAt(b),32>d)l();else if(92==d)switch(d=a.charCodeAt(++b),d){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:e+=W[d];b++;break;case 117:h=++b;for(f=b+4;b<f;b++)d=a.charCodeAt(b),48<=d&&57>=d||97<=d&&102>=d||65<=d&&70>=d||l();e+=V("0x"+a.slice(h,b));break;default:l()}else{if(34==d)break;d=a.charCodeAt(b);for(h=b;32<=d&&92!=d&&34!=d;)d=a.charCodeAt(++b);e+=a.slice(h,b)}if(34==a.charCodeAt(b))return b++,e;l();default:h= 49b;45==d&&(k=!0,d=a.charCodeAt(++b));if(48<=d&&57>=d){for(48==d&&(d=a.charCodeAt(b+1),48<=d&&57>=d)&&l();b<c&&(d=a.charCodeAt(b),48<=d&&57>=d);b++);if(46==a.charCodeAt(b)){for(f=++b;f<c&&(d=a.charCodeAt(f),48<=d&&57>=d);f++);f==b&&l();b=f}d=a.charCodeAt(b);if(101==d||69==d){d=a.charCodeAt(++b);43!=d&&45!=d||b++;for(f=b;f<c&&(d=a.charCodeAt(f),48<=d&&57>=d);f++);f==b&&l();b=f}return+a.slice(h,b)}k&&l();if("true"==a.slice(b,b+4))return b+=4,!0;if("false"==a.slice(b,b+5))return b+=5,!1;if("null"==a.slice(b, 50b+4))return b+=4,null;l()}return"$"},P=function(a){var c,b;"$"==a&&l();if("string"==typeof a){if("@"==(D?a.charAt(0):a[0]))return a.slice(1);if("["==a){for(c=[];;b||(b=!0)){a=z();if("]"==a)break;b&&(","==a?(a=z(),"]"==a&&l()):l());","==a&&l();c.push(P(a))}return c}if("{"==a){for(c={};;b||(b=!0)){a=z();if("}"==a)break;b&&(","==a?(a=z(),"}"==a&&l()):l());","!=a&&"string"==typeof a&&"@"==(D?a.charAt(0):a[0])&&":"==z()||l();c[a.slice(1)]=P(z())}return c}l()}return a},T=function(a,b,e){e=S(a,b,e);e=== 51w?delete a[b]:a[b]=e},S=function(a,b,e){var h=a[b],f;if("object"==typeof h&&h)if("[object Array]"==u.call(h))for(f=h.length;f--;)T(h,f,e);else B(h,function(a){T(h,a,e)});return e.call(a,b,h)};r.parse=function(a,c){var e,h;b=0;J=""+a;e=P(z());"$"!=z()&&l();b=J=null;return c&&"[object Function]"==u.call(c)?S((h={},h[""]=e,h),"",c):e}}}r.runInContext=N;return r}var K=typeof define==="function"&&define.amd,F={"function":!0,object:!0},G=F[typeof exports]&&exports&&!exports.nodeType&&exports,k=F[typeof window]&& 52window||this,t=G&&F[typeof module]&&module&&!module.nodeType&&"object"==typeof global&&global;
52!t||t.global!==t&&t.window!==t&&t.self!==t||(k=t);if(G&&!K)N(k,G);else{var L=k.JSON,Q=k.JSON3,M=!1,A=N(k,k.JSON3={noConflict:function(){M||(M=!0,k.JSON=L,k.JSON3=Q,L=Q=null);return A}});k.JSON={parse:A.parse,stringify:A.stringify}}K&&define(function(){return A})}).call(this); 53 54/*! jQuery v1.12.2 | (c) jQuery Foundation | jquery.org/license */ 55!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="1.12.2
vendor: 17,072 bytes, line 55
55",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(!l.ownFirst)for(b in a)return k.call(a,b);for(b in a);return void 0===b||k.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(h)return h.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=e.call(arguments,2),d=function(){return a.apply(b||this,c.concat(e.call(arguments)))},d.guid=a.guid=a.guid||n.guid++,d):void 0},now:function(){return+new Date},support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)}
vendor: 10,751 bytes, line 55
55,input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=la(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=ma(b);function pa(){}pa.prototype=d.filters=d.pseudos,d.setFilters=new pa,g=fa.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=R.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=S.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(Q," ")}),h=h.slice(c.length));for(g in d.filter)!(e=W[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fa.error(a):z(a,i).slice(0)};function qa(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}if(f=d.getElementById(e[2]),f&&f.parentNode){if(f.id!==e[2])return A.find(a);this.length=1,this[0]=f}return this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||(e=n.uniqueSort(e)),D.test(a)&&(e=e.reverse())),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){n.each(b,function(b,c){n.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==n.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return n.each(arguments,function(a,b){var c;while((c=n.inArray(b,f,c))>-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=!0,c||j.disable(),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.pu
vendor: 4,130 bytes, lines 55-56
55sh(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.addEventListener?(d.removeEventListener("DOMContentLoaded",K),a.removeEventListener("load",K)):(d.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(d.addEventListener||"load"===a.event.type||"complete"===d.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll)a.setTimeout(n.ready);else if(d.addEventListener)d.addEventListener("DOMContentLoaded",K),a.addEventListener("load",K);else{d.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&d.documentElement}catch(e){}c&&c.doScroll&&!function f(){if(!n.isReady){try{c.doScroll("left")}catch(b){return a.setTimeout(f,50)}J(),n.ready()}}()}return I.promise(b)},n.ready.promise();var L;for(L in n(l))break;l.ownFirst="0"===L,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c,e;c=d.getElementsByTagName("body")[0],c&&c.style&&(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",l.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(e))}),function(){var a=d.createElement("div");l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}a=null}();var M=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b},N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0; 56}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(M(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}
vendor: 4,101 bytes, line 56
56:{toJSON:n.noop}),"object"!=typeof b&&"function"!=typeof b||(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f}}function S(a,b,c){if(M(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=void 0)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=n._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}}),function(){var a;l.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,e;return c=d.getElementsByTagName("body")[0],c&&c.style?(b=d.createElement("div"),e=d.createElement("div"),e.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(e).appendChild(b),"undefined"!=typeof b.style.zoom&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(d.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(e),a):void 0}}();var T=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,U=new RegExp("^(?:([+-])=|)("+T+")([a-z%]*)$","i"),V=["Top","Right","Bottom","Left"],W=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)};function X(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return n.css(a,b,"")},i=h(),j=c&&c[3]||(n.cssNumber[b]?"":"px"),k=(n.cssNumber[b]||"px"!==j&&+i)&&U.exec(n.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,n.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var Y=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;
vendor: 6,432 bytes, line 56
56for(h in c)Y(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},Z=/^(?:checkbox|radio)$/i,$=/<([\w:-]+)/,_=/^$|\/(?:java|ecma)script/i,aa=/^\s+/,ba="abbr|article|aside|audio|bdi|canvas|data|datalist|details|dialog|figcaption|figure|footer|header|hgroup|main|mark|meter|nav|output|picture|progress|section|summary|template|time|video";function ca(a){var b=ba.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}!function(){var a=d.createElement("div"),b=d.createDocumentFragment(),c=d.createElement("input");a.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",l.leadingWhitespace=3===a.firstChild.nodeType,l.tbody=!a.getElementsByTagName("tbody").length,l.htmlSerialize=!!a.getElementsByTagName("link").length,l.html5Clone="<:nav></:nav>"!==d.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,b.appendChild(c),l.appendChecked=c.checked,a.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!a.cloneNode(!0).lastChild.defaultValue,b.appendChild(a),c=d.createElement("input"),c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),a.appendChild(c),l.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!!a.addEventListener,a[n.expando]=1,l.attributes=!a.getAttribute(n.expando)}();var da={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:l.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]};da.optgroup=da.option,da.tbody=da.tfoot=da.colgroup=da.caption=da.thead,da.th=da.td;function ea(a,b){var c,d,e=0,f="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,ea(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function fa(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}var ga=/<|&#?\w+;/,ha=/<tbody/i;function ia(a){Z.test(a.type)&&(a.defaultChecked=a.checked)}function ja(a,b,c,d,e){for(var f,g,h,i,j,k,m,o=a.length,p=ca(b),q=[],r=0;o>r;r++)if(g=a[r],g||0===g)if("object"===n.type(g))n.merge(q,g.nodeType?[g]:g);else if(ga.test(g)){i=i||p.appendChild(b.createElement("div")),j=($.exec(g)||["",""])[1].toLowerCase(),m=da[j]||da._default,i.innerHTML=m[1]+n.htmlPrefilter(g)+m[2],f=m[0];while(f--)i=i.lastChild;if(!l.leadingWhitespace&&aa.test(g)&&q.push(b.createTextNode(aa.exec(g)[0])),!l.tbody){g="table"!==j||ha.test(g)?"<table>"!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>
vendor: 9,867 bytes, line 56
56-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[n.expando])return a;var b,c,e,f=a.type,g=a,h=this.fixHooks[f];h||(this.fixHooks[f]=h=ma.test(f)?this.mouseHooks:la.test(f)?this.keyHooks:{}),e=h.props?this.props.concat(h.props):this.props,a=new n.Event(g),b=e.length;while(b--)c=e[b],a[c]=g[c];return a.target||(a.target=g.srcElement||d),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,h.filter?h.filter(a,g):a},props:"altKey bubbles cancelable ctrlKey currentTarget detail eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,e,f,g=b.button,h=b.fromElement;return null==a.pageX&&null!=b.clientX&&(e=a.target.ownerDocument||d,f=e.documentElement,c=e.body,a.pageX=b.clientX+(f&&f.scrollLeft||c&&c.scrollLeft||0)-(f&&f.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(f&&f.scrollTop||c&&c.scrollTop||0)-(f&&f.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&h&&(a.relatedTarget=h===a.target?b.toElement:h),a.which||void 0===g||(a.which=1&g?1:2&g?3:4&g?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==ra()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===ra()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return n.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c){var d=n.extend(new n.Event,c,{type:a,isSimulated:!0});n.event.trigger(d,null,b),d.isDefaultPrevented()&&c.preventDefault()}},n.removeEvent=d.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)}:function(a,b,c){var d="on"+b;a.detachEvent&&("undefined"==typeof a[d]&&(a[d]=null),a.detachEvent(d,c))},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?pa:qa):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={constructor:n.Event,isDefaultPrevented:qa,isPropagationStopped:qa,isImmediatePropagationStopped:qa,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=pa,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=pa,a&&!this.isSimulated&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=pa,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||n.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),l.submit||(n.event.special.submit={setup:function(){return n.nodeName(this,"form")?!1:void n.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=n.nodeName(b,"input")||n.nodeName(b,"button")?n.prop(b,"form"):void 0;c&&!n._data(c,"submit")&&(n.event.add(c,"submit._submit",function(a){a._submitBubble=!0}),n._data(c,"submit",!0))})},postDispatch:function(a){a._submitBubble&&(delete a._submitBubble,this.parentNode&&!a.isTrigger&&n.event.simulate("submit",this.parentNode,a))},teardown:function(){return n.nodeName(this,"form")?!1:void n.event.remove(this,"._submit")}}),l.change||(n.event.special.change={setup:function(){return ka.test(this.nodeName)?("checkbox"!==this.type&&"radio"!==this.type||(n.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._justChanged=!0)}),n.event.add(this,"click._change",function(a){this._justChanged&&!a.isTrigger&&(this._justChanged=!1),n.event.simulate("change",this,a)})),!1):void n.event.add(this,"beforeactivate._change",function(a){var b=a.target;ka.test(b.nodeName)&&!n._data(b,"change")&&(n.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||n.event.simulate("change",this.parentNode,a)}),n._data(b,"change",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return n.event.remove(this,"._change"),!ka.test(this.nodeName)}}),l.focusin||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a))};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=n._data(d,b);e||d.addEventListener(a,c,!0),n._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=n._data(d,b)-1;e?n._data(d,b,e):(d.removeEventListener(a,c,!0),n._removeData(d,b))}}}),n.fn.extend({on:function(a,b,c,d){return sa(this,a,b,c,d)},one:function(a,b,c,d){return sa(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=qa),this.each(function(){n.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}});var ta=/ jQuery\d+="(?:null|\d+)"/g,ua=new RegExp("<(?:"+ba+")[\\s/>]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/<script|<style|<link/i,xa=/checked\s*(?:[^=]|=\s*.checked.)/i,ya=/^true\/(.*)/,za=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,Aa=ca(d),Ba=Aa.appendChild(d.createElement("div"));function Ca(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function Da(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function Ea(a){var b=ya.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Fa(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Ga(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(Da(b).text=a.text,Ea(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&Z.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}}function Ha(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);
vendor: 14,454 bytes, lines 56-57
56if(r||o>1&&"string"==typeof q&&!l.checkClone&&xa.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),Ha(f,b,c,d)});if(o&&(k=ja(b,a[0].ownerDocument,!1,a,d),e=k.firstChild,1===k.childNodes.length&&(k=e),e||d)){for(i=n.map(ea(k,"script"),Da),h=i.length;o>m;m++)g=k,m!==p&&(g=n.clone(g,!0,!0),h&&n.merge(i,ea(g,"script"))),c.call(a[m],g,m);if(h)for(j=i[i.length-1].ownerDocument,n.map(i,Ea),m=0;h>m;m++)g=i[m],_.test(g.type||"")&&!n._data(g,"globalEval")&&n.contains(j,g)&&(g.src?n._evalUrl&&n._evalUrl(g.src):n.globalEval((g.text||g.textContent||g.innerHTML||"").replace(za,"")));k=e=null}return a}function Ia(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(ea(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&fa(ea(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(va,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!ua.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(Ba.innerHTML=a.outerHTML,Ba.removeChild(f=Ba.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=ea(f),h=ea(a),g=0;null!=(e=h[g]);++g)d[g]&&Ga(e,d[g]);if(b)if(c)for(h=h||ea(a),d=d||ea(f),g=0;null!=(e=h[g]);g++)Fa(e,d[g]);else Fa(a,f);return d=ea(f,"script"),d.length>0&&fa(d,!i&&ea(a,"script")),d=h=e=null,f},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.attributes,m=n.event.special;null!=(d=a[h]);h++)if((b||M(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k||"undefined"==typeof d.removeAttribute?d[i]=void 0:d.removeAttribute(i),c.push(f))}}}),n.fn.extend({domManip:Ha,detach:function(a){return Ia(this,a,!0)},remove:function(a){return Ia(this,a)},text:function(a){return Y(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||d).createTextNode(a))},null,a,arguments.length)},append:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.appendChild(a)}})},prepend:function(){return Ha(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Ca(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ha(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(ea(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return Y(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(ta,""):void 0;if("string"==typeof a&&!wa.test(a)&&(l.htmlSerialize||!ua.test(a))&&(l.leadingWhitespace||!aa.test(a))&&!da[($.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ea(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return Ha(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(ea(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],f=n(a),h=f.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(f[d])[b](c),g.apply(e,c.get());return this.pushStack(e)}});var Ja,Ka={HTML:"block",BODY:"block"};function La(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function Ma(a){var b=d,c=Ka[a];return c||(c=La(a,b),"none"!==c&&c||(Ja=(Ja||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Ja[0].contentWindow||Ja[0].contentDocument).document,b.write(),b.close(),c=La(a,b),Ja.detach()),Ka[a]=c),c}var Na=/^margin/,Oa=new RegExp("^("+T+")(?!px)[a-z%]+$","i"),Pa=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e},Qa=d.documentElement;!function(){var b,c,e,f,g,h,i=d.createElement("div"),j=d.createElement("div");if(j.style){j.style.cssText="float:left;opacity:.5",l.opacity="0.5"===j.style.opacity,l.cssFloat=!!j.style.cssFloat,j.style.backgroundClip="content-box",j.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===j.style.backgroundClip,i=d.createElement("div"),i.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",j.innerHTML="",i.appendChild(j),l.boxSizing=""===j.style.boxSizing||""===j.style.MozBoxSizing||""===j.style.WebkitBoxSizing,n.extend(l,{reliableHiddenOffsets:function(){return null==b&&k(),f},boxSizingReliable:function(){return null==b&&k(),e},pixelMarginRight:function(){return null==b&&k(),c},pixelPosition:function(){return null==b&&k(),b},reliableMarginRight:function(){return null==b&&k(),g},reliableMarginLeft:function(){return null==b&&k(),h}});function k(){var k,l,m=d.documentElement;m.appendChild(i),j.style.cssText="-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",b=e=h=!1,c=g=!0,a.getComputedStyle&&(l=a.getComputedStyle(j),b="1%"!==(l||{}).top,h="2px"===(l||{}).marginLeft,e="4px"===(l||{width:"4px"}).width,j.style.marginRight="50%",c="4px"===(l||{marginRight:"4px"}).marginRight,k=j.appendChild(d.createElement("div")),k.style.cssText=j.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",k.style.marginRight=k.style.width="0",j.style.width="1px",g=!parseFloat((a.getComputedStyle(k)||{}).marginRight),j.removeChild(k)),j.style.display="none",f=0===j.getClientRects().length,f&&(j.style.display="",j.innerHTML="<table><tr><td></td><td>t</td></tr></table>",k=j.getElementsByTagName("td"),k[0].style.cssText="margin:0;border:0;padding:0;display:none",f=0===k[0].offsetHeight,f&&(k[0].style.display="",k[1].style.display="none",f=0===k[0].offsetHeight)),m.removeChild(i)}}}();var Ra,Sa,Ta=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ra=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),g=c?c.getPropertyValue(b)||c[b]:void 0,""!==g&&void 0!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),c&&!l.pixelMarginRight()&&Oa.test(g)&&Na.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f),void 0===g?g:g+""}):Qa.currentStyle&&(Ra=function(a){return a.currentStyle},Sa=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ra(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Oa.test(g)&&!Ta.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Ua(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Va=/alpha\([^)]*\)/i,Wa=/opacity\s*=\s*([^)]*)/i,Xa=/^(none|table(?!-c[ea]).+)/,Ya=new RegExp("^("+T+")(.*)$","i"),Za={position:"absolute",visibility:"hidden",display:"block"},$a={letterSpacing:"0",fontWeight:"400"},_a=["Webkit","O","Moz","ms"],ab=d.createElement("div").style;function bb(a){if(a in ab)return a;var b=a.charAt(0).toUpperCase()+a.slice(1),c=_a.length;while(c--)if(a=_a[c]+b,a in ab)return a}function cb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=n._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&W(d)&&(f[g]=n._data(d,"olddisplay",Ma(d.nodeName)))):(e=W(d),(c&&"none"!==c||!e)&&n._data(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function db(a,b,c){var d=Ya.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function eb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+V[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+V[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+V[f]+"Width",!0,e))):(g+=n.css(a,"padding"+V[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+V[f]+"Width",!0,e)));return g}function fb(b,c,e){var f=!0,g="width"===c?b.offsetWidth:b.offsetHeight,h=Ra(b),i=l.boxSizing&&"border-box"===n.css(b,"boxSizing",!1,h);if(d.msFullscreenElement&&a.top!==a&&b.getClientRects().length&&(g=Math.round(100*b.getBoundingClientRect()[c])),0>=g||null==g){if(g=Sa(b,c,h),(0>g||null==g)&&(g=b.style[c]),Oa.test(g))return g;f=i&&(l.boxSizingReliable()||g===b.style[c]),g=parseFloat(g)||0}return g+eb(b,c,e||(i?"border":"content"),f,h)+"px"}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Sa(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":l.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;if(b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=U.exec(c))&&e[1]&&(c=X(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(n.cssNumber[h]?"":"px")),l.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=bb(h)||h),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Sa(a,b,d)),"normal"===f&&b in $a&&(f=$a[b]),""===c||c?(e=parseFloat(f),c===!0||isFinite(e)?e||0:f):f}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?Xa.test(n.css(a,"display"))&&0===a.offsetWidth?Pa(a,Za,function(){return fb(a,b,d)}):fb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ra(a);return db(a,c,d?eb(a,b,d,l.boxSizing&&"border-box"===n.css(a,"boxSizing",!1,e),e):0)}}}),l.opacity||(n.cssHooks.opacity={get:function(a,b){return Wa.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=n.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===n.trim(f.replace(Va,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Va.test(f)?f.replace(Va,e):f+" "+e)}}),n.cssHooks.marginRight=Ua(l.reliableMarginRight,function(a,b){return b?Pa(a,{display:"inline-block"},Sa,[a,"marginRight"]):void 0}),n.cssHooks.marginLeft=Ua(l.reliableMarginLeft,function(a,b){ 57return b?(parseFloat(Sa(a,"marginLeft"))||(n.contains(a.ownerDocument,a)?a.getBoundingClientRect().left-Pa(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}):0))+"px":void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+V[d]+b]=f[d]||f[d-2]||f[0];return e}},Na.test(a)||(n.cssHooks[a+b].set=db)}),n.fn.extend({css:function(a,b){return Y(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ra(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return cb(this,!0)},hide:function(){return cb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){W(this)?n(this).show():n(this).hide()})}});function gb(a,b,c,d,e){return new gb.prototype.init(a,b,c,d,e)}n.Tween=gb,gb.prototype={constructor:gb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||n.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=gb.propHooks[this.prop];return a&&a.get?a.get(this):gb.propHooks._default.get(this)},run:function(a){var b,c=gb.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):gb.propHooks._default.set(this),this}},gb.prototype.init.prototype=gb.prototype,gb.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[n.cssProps[a.prop]]&&!n.cssHooks[a.prop]?a.elem[a.prop]=a.now:n.style(a.elem,a.prop,a.now+a.unit)}}},gb.propHooks.scrollTop=gb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},n.fx=gb.prototype.init,n.fx.step={};var hb,ib,jb=/^(?:toggle|show|hide)$/,kb=/queueHooks$/;function lb(){return a.setTimeout(function(){hb=void 0}),hb=n.now()}function mb(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=V[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function nb(a,b,c){for(var d,e=(qb.tweeners[b]||[]).concat(qb.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ob(a,b,c){var d,e,f,g,h,i,j,k,m=this,o={},p=a.style,q=a.nodeType&&W(a),r=n._data(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,m.always(function(){m.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=n.css(a,"display"),k="none"===j?
vendor: 21,191 bytes, line 57
57n._data(a,"olddisplay")||Ma(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(l.inlineBlockNeedsLayout&&"inline"!==Ma(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",l.shrinkWrapBlocks()||m.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],jb.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(o))"inline"===("none"===j?Ma(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=n._data(a,"fxshow",{}),f&&(r.hidden=!q),q?n(a).show():m.done(function(){n(a).hide()}),m.done(function(){var b;n._removeData(a,"fxshow");for(b in o)n.style(a,b,o[b])});for(d in o)g=nb(q?r[d]:0,d,m),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function pb(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function qb(a,b,c){var d,e,f=0,g=qb.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=hb||lb(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{},easing:n.easing._default},c),originalProperties:b,originalOptions:c,startTime:hb||lb(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for(pb(k,j.opts.specialEasing);g>f;f++)if(d=qb.prefilters[f].call(j,a,k,j.opts))return n.isFunction(d.stop)&&(n._queueHooks(j.elem,j.opts.queue).stop=n.proxy(d.stop,d)),d;return n.map(k,nb,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(qb,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return X(c.elem,a,U.exec(b),c),c}]},tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.match(G);for(var c,d=0,e=a.length;e>d;d++)c=a[d],qb.tweeners[c]=qb.tweeners[c]||[],qb.tweeners[c].unshift(b)},prefilters:[ob],prefilter:function(a,b){b?qb.prefilters.unshift(a):qb.prefilters.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,null!=d.queue&&d.queue!==!0||(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(W).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=qb(this,n.extend({},a),f);(e||n._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=n._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&kb.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=n._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(mb(b,!0),a,d,e)}}),n.each({slideDown:mb("show"),slideUp:mb("hide"),slideToggle:mb("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=n.timers,c=0;for(hb=n.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||n.fx.stop(),hb=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){ib||(ib=a.setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){a.clearInterval(ib),ib=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(b,c){return b=n.fx?n.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a,b=d.createElement("input"),c=d.createElement("div"),e=d.createElement("select"),f=e.appendChild(d.createElement("option"));c=d.createElement("div"),c.setAttribute("className","t"),c.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",a=c.getElementsByTagName("a")[0],b.setAttribute("type","checkbox"),c.appendChild(b),a=c.getElementsByTagName("a")[0],a.style.cssText="top:1px",l.getSetAttribute="t"!==c.className,l.style=/top/.test(a.getAttribute("style")),l.hrefNormalized="/a"===a.getAttribute("href"),l.checkOn=!!b.value,l.optSelected=f.selected,l.enctype=!!d.createElement("form").enctype,e.disabled=!0,l.optDisabled=!f.disabled,b=d.createElement("input"),b.setAttribute("value",""),l.input=""===b.getAttribute("value"),b.value="t",b.setAttribute("type","radio"),l.radioValue="t"===b.value}();var rb=/\r/g,sb=/[\x20\t\r\n\f]+/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(rb,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a)).replace(sb," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],(c.selected||i===e)&&(l.optDisabled?!c.disabled:null===c.getAttribute("disabled"))&&(!c.parentNode.disabled||!n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)if(d=e[g],n.inArray(n.valHooks.option.get(d),f)>-1)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>-1:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var tb,ub,vb=n.expr.attrHandle,wb=/^(?:checked|selected)$/i,xb=l.getSetAttribute,yb=l.input;n.fn.extend({attr:function(a,b){return Y(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),e=n.attrHooks[b]||(n.expr.match.bool.test(b)?ub:tb)),void 0!==c?null===c?void n.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=n.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(G);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)?yb&&xb||!wb.test(c)?a[d]=!1:a[n.camelCase("default-"+c)]=a[d]=!1:n.attr(a,c,""),a.removeAttribute(xb?c:d)}}),ub={set:function(a,b,c){return b===!1?n.removeAttr(a,c):yb&&xb||!wb.test(c)?a.setAttribute(!xb&&n.propFix[c]||c,c):a[n.camelCase("default-"+c)]=a[c]=!0,c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=vb[b]||n.find.attr;yb&&xb||!wb.test(b)?vb[b]=function(a,b,d){var e,f;return d||(f=vb[b],vb[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,vb[b]=f),e}:vb[b]=function(a,b,c){return c?void 0:a[n.camelCase("default-"+b)]?b.toLowerCase():null}}),yb&&xb||(n.attrHooks.value={set:function(a,b,c){return n.nodeName(a,"input")?void(a.defaultValue=b):tb&&tb.set(a,b,c)}}),xb||(tb={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},vb.id=vb.name=vb.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},n.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:tb.set},n.attrHooks.contenteditable={set:function(a,b,c){tb.set(a,""===b?!1:b,c)}},n.each(["width","height"],function(a,b){n.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),l.style||(n.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var zb=/^(?:input|select|textarea|button|object)$/i,Ab=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return Y(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return a=n.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),n.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&n.isXMLDoc(a)||(b=n.propFix[b]||b,e=n.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,"tabindex");return b?parseInt(b,10):zb.test(a.nodeName)||Ab.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),l.hrefNormalized||n.each(["href","src"],function(a,b){n.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this}),l.enctype||(n.propFix.enctype="encoding");var Bb=/[\t\r\n\f]/g;function Cb(a){return n.attr(a,"class")||""}n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,Cb(this)))});if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(" "+e+" ").replace(Bb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=n.trim(d),e!==h&&n.attr(c,"class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,Cb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=Cb(c),d=1===c.nodeType&&(" "+e+" ").replace(Bb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=n.trim(d),e!==h&&n.attr(c,"class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):n.isFunction(a)?this.each(function(c){n(this).toggleClass(a.call(this,c,Cb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=n(this),f=a.match(G)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=Cb(this),b&&n._data(this,"__className__",b),n.attr(this,"class",b||a===!1?"":n._data(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+Cb(c)+" ").replace(Bb," ").indexOf(b)>-1)return!0;return!1}}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Db=a.location,Eb=n.now(),Fb=/\?/,Gb=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;n.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=n.trim(b+"");return e&&!n.trim(e.replace(Gb,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():n.error("Invalid JSON: "+b)},n.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new a.DOMParser,c=d.parseFromString(b,"text/xml")):(c=new a.ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var Hb=/#.*$/,Ib=/([?&])_=[^&]*/,Jb=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Kb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Lb=/^(?:GET|HEAD)$/,Mb=/^\/\//,Nb=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Ob={},Pb={},Qb="*/".concat("*"),Rb=Db.href,Sb=Nb.exec(Rb.toLowerCase())||[];function Tb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(G)||[];if(n.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Ub(a,b,c,d){var e={},f=a===Pb;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Vb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&n.extend(!0,a,c),a}function Wb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Xb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Rb,type:"GET",isLocal:Kb.test(Sb[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Qb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Vb(Vb(a,n.ajaxSettings),b):Vb(n.ajaxSettings,a)},ajaxPrefilter:Tb(Ob),ajaxTransport:Tb(Pb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var d,e,f,g,h,i,j,k,l=n.ajaxSetup({},c),m=l.context||l,o=l.context&&(m.nodeType||m.jquery)?n(m):n.event,p=n.Deferred(),q=n.Callbacks("once memory"),r=l.statusCode||{},s={},t={},u=0,v="canceled",w={readyState:0,getResponseHeader:function(a){var b;if(2===u){if(!k){k={};while(b=Jb.exec(g))k[b[1].toLowerCase()]=b[2]}b=k[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===u?g:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return u||(a=t[c]=t[c]||a,s[a]=b),this},overrideMimeType:function(a){return u||(l.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>u)for(b in a)r[b]=[r[b],a[b]];else w.always(a[w.status]);return this},abort:function(a){var b=a||v;return j&&j.abort(b),y(0,b),this}};if(p.promise(w).complete=q.add,w.success=w.done,w.error=w.fail,l.url=((b||l.url||Rb)+"").replace(Hb,"").replace(Mb,Sb[1]+"//"),l.type=c.method||c.type||l.method||l.type,l.dataTypes=n.trim(l.dataType||"*").toLowerCase().match(G)||[""],null==l.crossDomain&&(d=Nb.exec(l.url.toLowerCase()),l.crossDomain=!(!d||d[1]===Sb[1]&&d[2]===Sb[2]&&(d[3]||("http:"===d[1]?"80":"443"))===(Sb[3]||("http:"===Sb[1]?"80":"443")))),l.data&&l.processData&&"string"!=typeof l.data&&(l.data=n.param(l.data,l.traditional)),Ub(Ob,l,c,w),2===u)return w;i=n.event&&l.global,i&&0===n.active++&&n.event.trigger("ajaxStart"),l.type=l.type.toUpperCase(),l.hasContent=!Lb.test(l.type),f=l.url,l.hasContent||(l.data&&(f=l.url+=(Fb.test(f)?"&":"?")+l.data,delete l.data),l.cache===!1&&(l.url=Ib.test(f)?f.replace(Ib,"$1_="+Eb++):f+(Fb.test(f)?"&":"?")+"_="+Eb++)),l.ifModified&&(n.lastModified[f]&&w.setRequestHeader("If-Modified-Since",n.lastModified[f]),n.etag[f]&&w.setRequestHeader("If-None-Match",n.etag[f])),(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&w.setRequestHeader("Content-Type",l.contentType),w.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+("*"!==l.dataTypes[0]?", "+Qb+"; q=0.01":""):l.accepts["*"]);for(e in l.headers)w.setRequestHeader(e,l.headers[e]);if(l.beforeSend&&(l.beforeSend.call(m,w,l)===!1||2===u))return w.abort();v="abort";for(e in{success:1,error:1,complete:1})w[e](l[e]);if(j=Ub(Pb,l,c,w)){if(w.readyState=1,i&&o.trigger("ajaxSend",[w,l]),2===u)return w;l.async&&l.timeout>0&&(h=a.setTimeout(function(){w.abort("timeout")},l.timeout));try{u=1,j.send(s,y)}catch(x){if(!(2>u))throw x;y(-1,x)}}else y(-1,"No Transport");function y(b,c,d,e){var k,s,t,v,x,y=c;2!==u&&(u=2,h&&a.clearTimeout(h),j=void 0,g=e||"",w.readyState=b>0?4:0,k=b>=200&&300>b||304===b,d&&(v=Wb(l,w,d)),v=Xb(l,v,w,k),k?(l.ifModified&&(x=w.getResponseHeader("Last-Modified"),x&&(n.lastModified[f]=x),x=w.getResponseHeader("etag"),x&&(n.etag[f]=x)),204===b||"HEAD"===l.type?y="nocontent":304===b?y="notmodified":(y=v.state,s=v.data,t=v.error,k=!t)):(t=y,!b&&y||(y="error",0>b&&(b=0))),w.status=b,w.statusText=(c||y)+"",k?p.resolveWith(m,[s,y,w]):p.rejectWith(m,[w,y,t]),w.statusCode(r),r=void 0,i&&o.trigger(k?"ajaxSuccess":"ajaxError",[w,l,k?s:t]),q.fireWith(m,[w,y]),i&&(o.trigger("ajaxComplete",[w,l]),--n.active||n.event.trigger("ajaxStop")))}return w},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax(n.extend({url:a,type:b,dataType:e,data:c,success:d},n.isPlainObject(a)&&a))}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){if(n.isFunction(a))return this.each(function(b){n(this).wrapAll(a.call(this,b))});if(this[0]){var b=n(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return n.isFunction(a)?this.each(function(b){n(this).wrapInner(a.call(this,b))}):this.each(function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}});function Yb(a){return a.style&&a.style.display||n.css(a,"display")}function Zb(a){
vendor: 9,897 bytes, lines 57-105
57while(a&&1===a.nodeType){if("none"===Yb(a)||"hidden"===a.type)return!0;a=a.parentNode}return!1}n.expr.filters.hidden=function(a){return l.reliableHiddenOffsets()?a.offsetWidth<=0&&a.offsetHeight<=0&&!a.getClientRects().length:Zb(a)},n.expr.filters.visible=function(a){return!n.expr.filters.hidden(a)};var $b=/%20/g,_b=/\[\]$/,ac=/\r?\n/g,bc=/^(?:submit|button|image|reset|file)$/i,cc=/^(?:input|select|textarea|keygen)/i;function dc(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||_b.test(a)?d(a,e):dc(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)dc(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)dc(c,a[c],b,e);return d.join("&").replace($b,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&cc.test(this.nodeName)&&!bc.test(a)&&(this.checked||!Z.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(ac,"\r\n")}}):{name:b.name,value:c.replace(ac,"\r\n")}}).get()}}),n.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return this.isLocal?ic():d.documentMode>8?hc():/^(get|post|head|put|delete|options)$/i.test(this.type)&&hc()||ic()}:hc;var ec=0,fc={},gc=n.ajaxSettings.xhr();a.attachEvent&&a.attachEvent("onunload",function(){for(var a in fc)fc[a](void 0,!0)}),l.cors=!!gc&&"withCredentials"in gc,gc=l.ajax=!!gc,gc&&n.ajaxTransport(function(b){if(!b.crossDomain||l.cors){var c;return{send:function(d,e){var f,g=b.xhr(),h=++ec;if(g.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(f in b.xhrFields)g[f]=b.xhrFields[f];b.mimeType&&g.overrideMimeType&&g.overrideMimeType(b.mimeType),b.crossDomain||d["X-Requested-With"]||(d["X-Requested-With"]="XMLHttpRequest");for(f in d)void 0!==d[f]&&g.setRequestHeader(f,d[f]+"");g.send(b.hasContent&&b.data||null),c=function(a,d){var f,i,j;if(c&&(d||4===g.readyState))if(delete fc[h],c=void 0,g.onreadystatechange=n.noop,d)4!==g.readyState&&g.abort();else{j={},f=g.status,"string"==typeof g.responseText&&(j.text=g.responseText);try{i=g.statusText}catch(k){i=""}f||!b.isLocal||b.crossDomain?1223===f&&(f=204):f=j.text?200:404}j&&e(f,i,j,g.getAllResponseHeaders())},b.async?4===g.readyState?a.setTimeout(c):g.onreadystatechange=fc[h]=c:c()},abort:function(){c&&c(void 0,!0)}}}});function hc(){try{return new a.XMLHttpRequest}catch(b){}}function ic(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}n.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=d.head||n("head")[0]||d.documentElement;return{send:function(e,f){b=d.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||f(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var jc=[],kc=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=jc.pop()||n.expando+"_"+Eb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(kc.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&kc.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(kc,"$1"+e):b.jsonp!==!1&&(b.url+=(Fb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?n(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,jc.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||d;var e=x.exec(a),f=!c&&[];return e?[b.createElement(e[1])]:(e=ja([a],b,f),f&&f.length&&n(f).remove(),n.merge([],e.childNodes))};var lc=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&lc)return lc.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=n.trim(a.slice(h,a.length)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(g,f||[a.responseText,b,a])})}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};function mc(a){return n.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&n.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,n.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,n.contains(b,e)?("undefined"!=typeof e.getBoundingClientRect&&(d=e.getBoundingClientRect()),c=mc(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===n.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(c=a.offset()),c.top+=n.css(a[0],"borderTopWidth",!0),c.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-n.css(d,"marginTop",!0),left:b.left-c.left-n.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&!n.nodeName(a,"html")&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Qa})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);n.fn[a]=function(d){return Y(this,function(a,d,e){var f=mc(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?n(f).scrollLeft():e,c?e:n(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Ua(l.pixelPosition,function(a,c){ 58return c?(c=Sa(a,b),Oa.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return Y(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}}),n.fn.size=function(){return this.length},n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var nc=a.jQuery,oc=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=oc),b&&a.jQuery===n&&(a.jQuery=nc),n},b||(a.jQuery=a.$=n),n}); 59 60/* 61--- 62MooTools: the javascript framework 63 64web build: 65 - http://mootools.net/core/21ecee8cf9f9a4471a45ae1bb3f26e12 66 67packager build: 68 - packager build Core/Browser Core/JSON 69 70... 71*/ 72 73/* 74--- 75 76name: Core 77 78description: The heart of MooTools. 79 80license: MIT-style license. 81 82copyright: Copyright (c) 2006-2012 [Valerio Proietti](http://mad4milk.net/). 83 84authors: The MooTools production team (http://mootools.net/developers/) 85 86inspiration: 87 - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php) 88 - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php) 89 90provides: [Core, MooTools, Type, typeOf, instanceOf, Native] 91 92... 93*/ 94 95(function(){ 96 97this.MooTools = { 98 version: '1.4.5', 99 build: 'ab8ea8824dc3b24b6666867a2c4ed58ebb762cf0' 100}; 101 102// typeOf, instanceOf 103 104var typeOf = this.typeOf = function(item){ 105 if (item == null) return 'null';
106 if (item.$family != null) return item.$family(); 107 108 if (item.nodeName){ 109 if (item.nodeType == 1) return 'element'; 110 if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace'; 111 } else if (typeof item.length == 'number'){ 112 if (item.callee) return 'arguments'; 113 if ('item' in item) return 'collection'; 114 } 115 116 return typeof item; 117}; 118 119var instanceOf = this.instanceOf = function(item, object){ 120 if (item == null) return false; 121 var constructor = item.$constructor || item.constructor; 122 while (constructor){ 123 if (constructor === object) return true; 124 constructor = constructor.parent; 125 } 126 /*<ltIE8>*/ 127 if (!item.hasOwnProperty) return false; 128 /*</ltIE8>*/ 129 return item instanceof object; 130}; 131 132// Function overloading 133 134var Function = this.Function; 135 136var enumerables = true; 137for (var i in {toString: 1}) enumerables = null; 138if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor']; 139 140Function.prototype.overloadSetter = function(usePlural){ 141 var self = this; 142 return function(a, b){ 143 if (a == null) return this; 144 if (usePlural || typeof a != 'string'){ 145 for (var k in a) self.call(this, k, a[k]); 146 if (enumerables) for (var i = enumerables.length; i--;){ 147 k = enumerables[i]; 148 if (a.hasOwnProperty(k)) self.call(this, k, a[k]); 149 } 150 } else { 151 self.call(this, a, b); 152 } 153 return this; 154 }; 155}; 156 157Function.prototype.overloadGetter = function(usePlural){ 158 var self = this; 159 return function(a){ 160 var args, result; 161 if (typeof a != 'string') args = a; 162 else if (arguments.length > 1) args = arguments; 163 else if (usePlural) args = [a]; 164 if (args){ 165 result = {}; 166 for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]); 167 } else { 168 result = self.call(this, a); 169 } 170 return result; 171 }; 172}; 173 174Function.prototype.extend = function(key, value){ 175 this[key] = value; 176}.overloadSetter(); 177 178Function.prototype.implement = function(key, value){ 179 this.prototype[key] = value; 180}.overloadSetter(); 181 182// From 183 184var slice = Array.prototype.slice; 185 186Function.from = function(item){ 187 return (typeOf(item) == 'function') ? item : function(){ 188 return item; 189 }; 190}; 191 192Array.from = function(item){ 193 if (item == null) return []; 194 return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item]; 195}; 196 197Number.from = function(item){ 198 var number = parseFloat(item); 199 return isFinite(number) ? number : null; 200}; 201 202String.from = function(item){ 203 return item + ''; 204}; 205 206// hide, protect 207 208Function.implement({ 209 210 hide: function(){ 211 this.$hidden = true; 212 return this; 213 }, 214 215 protect: function(){ 216 this.$protected = true; 217 return this; 218 } 219 220}); 221 222// Type 223 224var Type = this.Type = function(name, object){ 225 if (name){ 226 var lower = name.toLowerCase(); 227 var typeCheck = function(item){ 228 return (typeOf(item) == lower); 229 }; 230 231 Type['is' + name] = typeCheck; 232 if (object != null){ 233 object.prototype.$family = (function(){ 234 return lower; 235 }).hide(); 236 237 } 238 } 239 240 if (object == null) return null; 241 242 object.extend(this); 243 object.$constructor = Type; 244 object.prototype.$constructor = object; 245 246 return object; 247}; 248 249var toString = Object.prototype.toString; 250 251Type.isEnumerable = function(item){ 252 return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' ); 253}; 254 255var hooks = {}; 256 257var hooksOf = function(object){ 258 var type = typeOf(object.prototype); 259 return hooks[type] || (hooks[type] = []); 260}; 261 262var implement = function(name, method){ 263 if (method && method.$hidden) return; 264 265 var hooks = hooksOf(this); 266 267 for (var i = 0; i < hooks.length; i++){ 268 var hook = hooks[i]; 269 if (typeOf(hook) == 'type') implement.call(hook, name, method); 270 else hook.call(this, name, method); 271 } 272 273 var previous = this.prototype[name]; 274 if (previous == null || !previous.$protected) this.prototype[name] = method; 275 276 if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){ 277 return method.apply(item, slice.call(arguments, 1)); 278 }); 279}; 280 281var extend = function(name, method){ 282 if (method && method.$hidden) return; 283 var previous = this[name]; 284 if (previous == null || !previous.$protected) this[name] = method; 285}; 286 287Type.implement({ 288 289 implement: implement.overloadSetter(), 290 291 extend: extend.overloadSetter(), 292 293 alias: function(name, existing){ 294 implement.call(this, name, this.prototype[existing]); 295 }.overloadSetter(), 296 297 mirror: function(hook){ 298 hooksOf(this).push(hook); 299 return this; 300 } 301 302}); 303 304new Type('Type', Type); 305 306// Default Types 307 308var force = function(name, object, methods){ 309 var isType = (object != Object), 310 prototype = object.prototype; 311 312 if (isType) object = new Type(name, object); 313 314 for (var i = 0, l = methods.length; i < l; i++){ 315 var key = methods[i], 316 generic = object[key], 317 proto = prototype[key]; 318 319 if (generic) generic.protect(); 320 if (isType && proto) object.implement(key, proto.protect()); 321 } 322 323 if (isType){ 324 var methodsEnumerable = prototype.propertyIsEnumerable(methods[0]); 325 object.forEachMethod = function(fn){ 326 if (!methodsEnumerable) for (var i = 0, l = methods.length; i < l; i++){ 327 fn.call(prototype, prototype[methods[i]], methods[i]); 328 } 329 for (var key in prototype) fn.call(prototype, prototype[key], key) 330 }; 331 } 332 333 return force; 334}; 335 336force('String', String, [ 337 'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search', 338 'slice', 'split', 'substr', 'substring', 'trim', 'toLowerCase', 'toUpperCase' 339])('Array', Array, [ 340 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', 341 'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight' 342])('Number', Number, [
343 'toExponential', 'toFixed', 'toLocaleString', 'toPrecision' 344])('Function', Function, [ 345 'apply', 'call', 'bind' 346])('RegExp', RegExp, [ 347 'exec', 'test' 348])('Object', Object, [ 349 'create', 'defineProperty', 'defineProperties', 'keys', 350 'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', 351 'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen' 352])('Date', Date, ['now']); 353 354Object.extend = extend.overloadSetter(); 355 356Date.extend('now', function(){ 357 return +(new Date); 358}); 359 360new Type('Boolean', Boolean); 361 362// fixes NaN returning as Number 363 364Number.prototype.$family = function(){ 365 return isFinite(this) ? 'number' : 'null'; 366}.hide(); 367 368// Number.random 369 370Number.extend('random', function(min, max){ 371 return Math.floor(Math.random() * (max - min + 1) + min); 372}); 373 374// forEach, each 375 376var hasOwnProperty = Object.prototype.hasOwnProperty; 377Object.extend('forEach', function(object, fn, bind){ 378 for (var key in object){ 379 if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object); 380 } 381}); 382 383Object.each = Object.forEach; 384 385Array.implement({ 386 387 forEach: function(fn, bind){ 388 for (var i = 0, l = this.length; i < l; i++){ 389 if (i in this) fn.call(bind, this[i], i, this); 390 } 391 }, 392 393 each: function(fn, bind){ 394 Array.forEach(this, fn, bind); 395 return this; 396 } 397 398}); 399 400// Array & Object cloning, Object merging and appending 401 402var cloneOf = function(item){ 403 switch (typeOf(item)){ 404 case 'array': return item.clone(); 405 case 'object': return Object.clone(item); 406 default: return item; 407 } 408}; 409 410Array.implement('clone', function(){ 411 var i = this.length, clone = new Array(i); 412 while (i--) clone[i] = cloneOf(this[i]); 413 return clone; 414}); 415 416var mergeOne = function(source, key, current){ 417 switch (typeOf(current)){ 418 case 'object': 419 if (typeOf(source[key]) == 'object') Object.merge(source[key], current); 420 else source[key] = Object.clone(current); 421 break; 422 case 'array': source[key] = current.clone(); break; 423 default: source[key] = current; 424 } 425 return source; 426}; 427 428Object.extend({ 429 430 merge: function(source, k, v){ 431 if (typeOf(k) == 'string') return mergeOne(source, k, v); 432 for (var i = 1, l = arguments.length; i < l; i++){ 433 var object = arguments[i]; 434 for (var key in object) mergeOne(source, key, object[key]); 435 } 436 return source; 437 }, 438 439 clone: function(object){ 440 var clone = {}; 441 for (var key in object) clone[key] = cloneOf(object[key]); 442 return clone; 443 }, 444 445 append: function(original){ 446 for (var i = 1, l = arguments.length; i < l; i++){ 447 var extended = arguments[i] || {}; 448 for (var key in extended) original[key] = extended[key]; 449 } 450 return original; 451 } 452 453}); 454 455// Object-less types 456 457['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){ 458 new Type(name); 459}); 460 461// Unique ID 462 463var UID = Date.now(); 464 465String.extend('uniqueID', function(){ 466 return (UID++).toString(36); 467}); 468 469 470 471})(); 472 473 474/* 475--- 476 477name: Array 478 479description: Contains Array Prototypes like each, contains, and erase. 480 481license: MIT-style license. 482 483requires: Type 484 485provides: Array 486 487... 488*/ 489 490Array.implement({ 491 492 /*<!ES5>*/ 493 every: function(fn, bind){ 494 for (var i = 0, l = this.length >>> 0; i < l; i++){ 495 if ((i in this) && !fn.call(bind, this[i], i, this)) return false; 496 } 497 return true; 498 }, 499 500 filter: function(fn, bind){ 501 var results = []; 502 for (var value, i = 0, l = this.length >>> 0; i < l; i++) if (i in this){ 503 value = this[i]; 504 if (fn.call(bind, value, i, this)) results.push(value); 505 } 506 return results; 507 }, 508 509 indexOf: function(item, from){ 510 var length = this.length >>> 0; 511 for (var i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++){ 512 if (this[i] === item) return i; 513 } 514 return -1; 515 }, 516 517 map: function(fn, bind){ 518 var length = this.length >>> 0, results = Array(length); 519 for (var i = 0; i < length; i++){ 520 if (i in this) results[i] = fn.call(bind, this[i], i, this); 521 } 522 return results; 523 }, 524 525 some: function(fn, bind){ 526 for (var i = 0, l = this.length >>> 0; i < l; i++){ 527 if ((i in this) && fn.call(bind, this[i], i, this)) return true; 528 } 529 return false; 530 }, 531 /*</!ES5>*/ 532 533 clean: function(){ 534 return this.filter(function(item){ 535 return item != null; 536 }); 537 }, 538 539 invoke: function(methodName){ 540 var args = Array.slice(arguments, 1); 541 return this.map(function(item){
542 return item[methodName].apply(item, args); 543 }); 544 }, 545 546 associate: function(keys){ 547 var obj = {}, length = Math.min(this.length, keys.length); 548 for (var i = 0; i < length; i++) obj[keys[i]] = this[i]; 549 return obj; 550 }, 551 552 link: function(object){ 553 var result = {}; 554 for (var i = 0, l = this.length; i < l; i++){ 555 for (var key in object){ 556 if (object[key](this[i])){ 557 result[key] = this[i]; 558 delete object[key]; 559 break; 560 } 561 } 562 } 563 return result; 564 }, 565 566 contains: function(item, from){ 567 return this.indexOf(item, from) != -1; 568 }, 569 570 append: function(array){ 571 this.push.apply(this, array); 572 return this; 573 }, 574 575 getLast: function(){ 576 return (this.length) ? this[this.length - 1] : null; 577 }, 578 579 getRandom: function(){ 580 return (this.length) ? this[Number.random(0, this.length - 1)] : null; 581 }, 582 583 include: function(item){ 584 if (!this.contains(item)) this.push(item); 585 return this; 586 }, 587 588 combine: function(array){ 589 for (var i = 0, l = array.length; i < l; i++) this.include(array[i]); 590 return this; 591 }, 592 593 erase: function(item){ 594 for (var i = this.length; i--;){ 595 if (this[i] === item) this.splice(i, 1); 596 } 597 return this; 598 }, 599 600 empty: function(){ 601 this.length = 0; 602 return this; 603 }, 604 605 flatten: function(){ 606 var array = []; 607 for (var i = 0, l = this.length; i < l; i++){ 608 var type = typeOf(this[i]); 609 if (type == 'null') continue; 610 array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]); 611 } 612 return array; 613 }, 614 615 pick: function(){ 616 for (var i = 0, l = this.length; i < l; i++){ 617 if (this[i] != null) return this[i]; 618 } 619 return null; 620 }, 621 622 hexToRgb: function(array){ 623 if (this.length != 3) return null; 624 var rgb = this.map(function(value){ 625 if (value.length == 1) value += value; 626 return value.toInt(16); 627 }); 628 return (array) ? rgb : 'rgb(' + rgb + ')'; 629 }, 630 631 rgbToHex: function(array){ 632 if (this.length < 3) return null; 633 if (this.length == 4 && this[3] == 0 && !array) return 'transparent'; 634 var hex = []; 635 for (var i = 0; i < 3; i++){ 636 var bit = (this[i] - 0).toString(16); 637 hex.push((bit.length == 1) ? '0' + bit : bit); 638 } 639 return (array) ? hex : '#' + hex.join(''); 640 } 641 642}); 643 644 645 646 647/* 648--- 649 650name: Function 651 652description: Contains Function Prototypes like create, bind, pass, and delay. 653 654license: MIT-style license. 655 656requires: Type 657 658provides: Function 659 660... 661*/ 662 663Function.extend({ 664 665 attempt: function(){ 666 for (var i = 0, l = arguments.length; i < l; i++){ 667 try { 668 return arguments[i](); 669 } catch (e){} 670 } 671 return null; 672 } 673 674}); 675 676Function.implement({ 677 678 attempt: function(args, bind){ 679 try { 680 return this.apply(bind, Array.from(args)); 681 } catch (e){} 682 683 return null; 684 }, 685 686 /*<!ES5-bind>*/ 687 bind: function(that){ 688 var self = this, 689 args = arguments.length > 1 ? Array.slice(arguments, 1) : null, 690 F = function(){}; 691 692 var bound = function(){ 693 var context = that, length = arguments.length; 694 if (this instanceof bound){ 695 F.prototype = self.prototype; 696 context = new F; 697 } 698 var result = (!args && !length) 699 ? self.call(context) 700 : self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments); 701 return context == that ? result : context; 702 }; 703 return bound; 704 }, 705 /*</!ES5-bind>*/ 706 707 pass: function(args, bind){ 708 var self = this; 709 if (args != null) args = Array.from(args); 710 return function(){ 711 return self.apply(bind, args || arguments); 712 }; 713 }, 714 715 delay: function(delay, bind, args){ 716 return setTimeout(this.pass((args == null ? [] : args), bind), delay); 717 }, 718 719 periodical: function(periodical, bind, args){ 720 return setInterval(this.pass((args == null ? [] : args), bind), periodical); 721 } 722 723}); 724 725 726 727 728/* 729--- 730 731name: Number 732 733description: Contains Number Prototypes like limit, round, times, and ceil. 734 735license: MIT-style license. 736 737requires: Type 738 739provides: Number 740 741... 742*/ 743 744Number.implement({ 745 746 limit: function(min, max){ 747 return Math.min(max, Math.max(min, this)); 748 }, 749 750 round: function(precision){ 751 precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0); 752 return Math.round(this * precision) / precision; 753 }, 754 755 times: function(fn, bind){ 756 for (var i = 0; i < this; i++) fn.call(bind, i, this); 757 }, 758 759 toFloat: function(){ 760 return parseFloat(this); 761 }, 762 763 toInt: function(base){ 764 return parseInt(this, base || 10); 765 } 766 767}); 768 769Number.alias('each', 'times'); 770 771(function(math){ 772 var methods = {}; 773 math.each(function(name){ 774 if (!Number[name]) methods[name] = function(){ 775 return Math[name].apply(null, [this].concat(Array.from(arguments))); 776 }; 777 }); 778 Number.implement(methods); 779})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']); 780 781 782/* 783--- 784 785name: String 786
787description: Contains String Prototypes like camelCase, capitalize, test, and toInt. 788 789license: MIT-style license. 790 791requires: Type 792 793provides: String 794 795... 796*/ 797 798String.implement({ 799 800 test: function(regex, params){ 801 return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this); 802 }, 803 804 contains: function(string, separator){ 805 return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : String(this).indexOf(string) > -1; 806 }, 807 808 trim: function(){ 809 return String(this).replace(/^\s+|\s+$/g, ''); 810 }, 811 812 clean: function(){ 813 return String(this).replace(/\s+/g, ' ').trim(); 814 }, 815 816 camelCase: function(){ 817 return String(this).replace(/-\D/g, function(match){ 818 return match.charAt(1).toUpperCase(); 819 }); 820 }, 821 822 hyphenate: function(){ 823 return String(this).replace(/[A-Z]/g, function(match){ 824 return ('-' + match.charAt(0).toLowerCase()); 825 }); 826 }, 827 828 capitalize: function(){ 829 return String(this).replace(/\b[a-z]/g, function(match){ 830 return match.toUpperCase(); 831 }); 832 }, 833 834 escapeRegExp: function(){ 835 return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); 836 }, 837 838 toInt: function(base){ 839 return parseInt(this, base || 10); 840 }, 841 842 toFloat: function(){ 843 return parseFloat(this); 844 }, 845 846 hexToRgb: function(array){ 847 var hex = String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); 848 return (hex) ? hex.slice(1).hexToRgb(array) : null; 849 }, 850 851 rgbToHex: function(array){ 852 var rgb = String(this).match(/\d{1,3}/g); 853 return (rgb) ? rgb.rgbToHex(array) : null; 854 }, 855 856 substitute: function(object, regexp){ 857 return String(this).replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){ 858 if (match.charAt(0) == '\\') return match.slice(1); 859 return (object[name] != null) ? object[name] : ''; 860 }); 861 } 862 863}); 864 865 866/* 867--- 868 869name: Browser 870 871description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash. 872 873license: MIT-style license. 874 875requires: [Array, Function, Number, String] 876 877provides: [Browser, Window, Document] 878 879... 880*/ 881 882(function(){ 883 884var document = this.document; 885var window = document.window = this; 886 887var ua = navigator.userAgent.toLowerCase(), 888 platform = navigator.platform.toLowerCase(), 889 UA = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0], 890 mode = UA[1] == 'ie' && document.documentMode; 891 892var Browser = this.Browser = { 893 894 extend: Function.prototype.extend, 895 896 name: (UA[1] == 'version') ? UA[3] : UA[1], 897 898 version: mode || parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]), 899 900 Platform: { 901 name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0] 902 }, 903 904 Features: { 905 xpath: !!(document.evaluate), 906 air: !!(window.runtime), 907 query: !!(document.querySelector), 908 json: !!(window.JSON) 909 }, 910 911 Plugins: {} 912 913}; 914 915Browser[Browser.name] = true; 916Browser[Browser.name + parseInt(Browser.version, 10)] = true; 917Browser.Platform[Browser.Platform.name] = true; 918 919// Request 920 921Browser.Request = (function(){ 922 923 var XMLHTTP = function(){ 924 return new XMLHttpRequest(); 925 }; 926 927 var MSXML2 = function(){ 928 return new ActiveXObject('MSXML2.XMLHTTP'); 929 }; 930 931 var MSXML = function(){ 932 return new ActiveXObject('Microsoft.XMLHTTP'); 933 }; 934 935 return Function.attempt(function(){ 936 XMLHTTP(); 937 return XMLHTTP; 938 }, function(){ 939 MSXML2(); 940 return MSXML2; 941 }, function(){ 942 MSXML(); 943 return MSXML; 944 }); 945 946})(); 947 948Browser.Features.xhr = !!(Browser.Request); 949 950// Flash detection 951 952var version = (Function.attempt(function(){ 953 return navigator.plugins['Shockwave Flash'].description; 954}, function(){ 955 return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); 956}) || '0 r0').match(/\d+/g); 957 958Browser.Plugins.Flash = { 959 version: Number(version[0] || '0.' + version[1]) || 0, 960 build: Number(version[2]) || 0 961}; 962 963// String scripts 964 965Browser.exec = function(text){ 966 if (!text) return text; 967 if (window.execScript){ 968 window.execScript(text); 969 } else { 970 var script = document.createElement('script'); 971 script.setAttribute('type', 'text/javascript'); 972 script.text = text; 973 document.head.appendChild(script); 974 document.head.removeChild(script); 975 } 976 return text; 977}; 978 979String.implement('stripScripts', function(exec){ 980 var scripts = ''; 981 var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){ 982 scripts += code + '\n'; 983 return ''; 984 }); 985 if (exec === true) Browser.exec(scripts); 986 else if (typeOf(exec) == 'function') exec(scripts, text); 987 return text; 988}); 989 990// Window, Document 991 992Browser.extend({ 993 Document: this.Document, 994 Window: this.Window, 995 Element: this.Element, 996 Event: this.Event 997}); 998 999this.Window = this.$constructor = new Type('Window', function(){}); 1000 1001this.$family = Function.from('window').hide(); 1002 1003Window.mirror(function(name, method){ 1004 window[name] = method; 1005}); 1006 1007this.Document = document.$constructor = new Type('Document', function(){}); 1008
1009document.$family = Function.from('document').hide(); 1010 1011Document.mirror(function(name, method){ 1012 document[name] = method; 1013}); 1014 1015document.html = document.documentElement; 1016if (!document.head) document.head = document.getElementsByTagName('head')[0]; 1017 1018if (document.execCommand) try { 1019 document.execCommand("BackgroundImageCache", false, true); 1020} catch (e){} 1021 1022/*<ltIE9>*/ 1023if (this.attachEvent && !this.addEventListener){ 1024 var unloadEvent = function(){ 1025 this.detachEvent('onunload', unloadEvent); 1026 document.head = document.html = document.window = null; 1027 }; 1028 this.attachEvent('onunload', unloadEvent); 1029} 1030 1031// IE fails on collections and <select>.options (refers to <select>) 1032var arrayFrom = Array.from; 1033try { 1034 arrayFrom(document.html.childNodes); 1035} catch(e){ 1036 Array.from = function(item){ 1037 if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){ 1038 var i = item.length, array = new Array(i); 1039 while (i--) array[i] = item[i]; 1040 return array; 1041 } 1042 return arrayFrom(item); 1043 }; 1044 1045 var prototype = Array.prototype, 1046 slice = prototype.slice; 1047 ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){ 1048 var method = prototype[name]; 1049 Array[name] = function(item){ 1050 return method.apply(Array.from(item), slice.call(arguments, 1)); 1051 }; 1052 }); 1053} 1054/*</ltIE9>*/ 1055 1056 1057 1058})(); 1059 1060 1061/* 1062--- 1063 1064name: JSON 1065 1066description: JSON encoder and decoder. 1067 1068license: MIT-style license. 1069 1070SeeAlso: <http://www.json.org/> 1071 1072requires: [Array, String, Number, Function] 1073 1074provides: JSON 1075 1076... 1077*/ 1078 1079if (typeof JSON == 'undefined') this.JSON = {}; 1080 1081 1082 1083(function(){ 1084 1085var special = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'}; 1086 1087var escape = function(chr){ 1088 return special[chr] || '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4); 1089}; 1090 1091JSON.validate = function(string){ 1092 string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). 1093 replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). 1094 replace(/(?:^|:|,)(?:\s*\[)+/g, ''); 1095 1096 return (/^[\],:{}\s]*$/).test(string); 1097}; 1098 1099JSON.encode = JSON.stringify ? function(obj){ 1100 return JSON.stringify(obj); 1101} : function(obj){ 1102 if (obj && obj.toJSON) obj = obj.toJSON(); 1103 1104 switch (typeOf(obj)){ 1105 case 'string': 1106 return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"'; 1107 case 'array': 1108 return '[' + obj.map(JSON.encode).clean() + ']'; 1109 case 'object': case 'hash': 1110 var string = []; 1111 Object.each(obj, function(value, key){ 1112 var json = JSON.encode(value); 1113 if (json) string.push(JSON.encode(key) + ':' + json); 1114 }); 1115 return '{' + string + '}'; 1116 case 'number': case 'boolean': return '' + obj; 1117 case 'null': return 'null'; 1118 } 1119 1120 return null; 1121}; 1122 1123JSON.decode = function(string, secure){ 1124 if (!string || typeOf(string) != 'string') return null; 1125 1126 if (secure || JSON.secure){ 1127 if (JSON.parse) return JSON.parse(string); 1128 if (!JSON.validate(string)) throw new Error('JSON could not decode the input; security is enabled and the value is not secure.'); 1129 } 1130 1131 return eval('(' + string + ')'); 1132}; 1133 1134})(); 1135 1136 1137/* 1138 * 1139 * TableSorter 2.0 - Client-side table sorting with ease! 1140 * Version 2.0.5b 1141 * @requires jQuery v1.2.3 1142 * 1143 * Copyright (c) 2007 Christian Bach 1144 * Examples and docs at: http://tablesorter.com 1145 * Dual licensed under the MIT and GPL licenses: 1146 * http://www.opensource.org/licenses/mit-license.php 1147 * http://www.gnu.org/licenses/gpl.html 1148 * 1149 */ 1150/** 1151 * 1152 * @description Create a sortable table with multi-column sorting capabilitys 1153 * 1154 * @example $('table').tablesorter(); 1155 * @desc Create a simple tablesorter interface. 1156 * 1157 * @example $('table').tablesorter({ sortList:[[0,0],[1,0]] }); 1158 * @desc Create a tablesorter interface and sort on the first and secound column column headers. 1159 * 1160 * @example $('table').tablesorter({ headers: { 0: { sorter: false}, 1: {sorter: false} } }); 1161 * 1162 * @desc Create a tablesorter interface and disableing the first and second column headers. 1163 * 1164 * 1165 * @example $('table').tablesorter({ headers: { 0: {sorter:"integer"}, 1: {sorter:"currency"} } }); 1166 * 1167 * @desc Create a tablesorter interface and set a column parser for the first 1168 * and second column. 1169 * 1170 * 1171 * @param Object 1172 * settings An object literal containing key/value pairs to provide 1173 * optional settings. 1174 * 1175 * 1176 * @option String cssHeader (optional) A string of the class name to be appended 1177 * to sortable tr elements in the thead of the table. Default value: 1178 * "header" 1179 * 1180 * @option String cssAsc (optional) A string of the class name to be appended to 1181 * sortable tr elements in the thead on a ascending sort. Default value: 1182 * "headerSortUp" 1183 * 1184 * @option String cssDesc (optional) A string of the class name to be appended 1185 * to sortable tr elements in the thead on a descending sort. Default 1186 * value: "headerSortDown" 1187 * 1188 * @option String sortInitialOrder (optional) A string of the inital sorting 1189 * order can be asc or desc. Default value: "asc" 1190 * 1191 * @option String sortMultisortKey (optional) A string of the multi-column s
1191ort 1192 * key. Default value: "shiftKey" 1193 * 1194 * @option String textExtraction (optional) A string of the text-extraction 1195 * method to use. For complex html structures inside td cell set this 1196 * option to "complex", on large tables the complex option can be slow. 1197 * Default value: "simple" 1198 * 1199 * @option Object headers (optional) An array containing the forces sorting 1200 * rules. This option let's you specify a default sorting rule. Default 1201 * value: null 1202 * 1203 * @option Array sortList (optional) An array containing the forces sorting 1204 * rules. This option let's you specify a default sorting rule. Default 1205 * value: null 1206 * 1207 * @option Array sortForce (optional) An array containing forced sorting rules. 1208 * This option let's you specify a default sorting rule, which is 1209 * prepended to user-selected rules. Default value: null 1210 * 1211 * @option Boolean sortLocaleCompare (optional) Boolean flag indicating whatever 1212 * to use String.localeCampare method or not. Default set to true. 1213 * 1214 * 1215 * @option Array sortAppend (optional) An array containing forced sorting rules. 1216 * This option let's you specify a default sorting rule, which is 1217 * appended to user-selected rules. Default value: null 1218 * 1219 * @option Boolean widthFixed (optional) Boolean flag indicating if tablesorter 1220 * should apply fixed widths to the table columns. This is usefull when 1221 * using the pager companion plugin. This options requires the dimension 1222 * jquery plugin. Default value: false 1223 * 1224 * @option Boolean cancelSelection (optional) Boolean flag indicating if 1225 * tablesorter should cancel selection of the table headers text. 1226 * Default value: true 1227 * 1228 * @option Boolean debug (optional) Boolean flag indicating if tablesorter 1229 * should display debuging information usefull for development. 1230 * 1231 * @type jQuery 1232 * 1233 * @name tablesorter 1234 * 1235 * @cat Plugins/Tablesorter 1236 * 1237 * @author Christian Bach/[email protected] 1238 */ 1239 1240(function ($) { 1241 $.extend({ 1242 tablesorter: new 1243 function () { 1244 1245 var parsers = [], 1246 widgets = []; 1247 1248 this.defaults = { 1249 cssHeader: "header", 1250 cssAsc: "headerSortUp", 1251 cssDesc: "headerSortDown", 1252 cssChildRow: "expand-child", 1253 sortInitialOrder: "asc", 1254 sortMultiSortKey: "shiftKey", 1255 sortForce: null, 1256 sortAppend: null, 1257 sortLocaleCompare: true, 1258 textExtraction: "simple", 1259 parsers: {}, widgets: [], 1260 widgetZebra: { 1261 css: ["even", "odd"] 1262 }, headers: {}, widthFixed: false, 1263 cancelSelection: true, 1264 sortList: [], 1265 headerList: [], 1266 dateFormat: "us", 1267 decimal: '/\.|\,/g', 1268 onRenderHeader: null, 1269 selectorHeaders: 'thead th', 1270 debug: false 1271 }; 1272 1273 /* debuging utils */ 1274 1275 function benchmark(s, d) { 1276 log(s + "," + (new Date().getTime() - d.getTime()) + "ms"); 1277 } 1278 1279 this.benchmark = benchmark; 1280 1281 function log(s) { 1282 if (typeof console != "undefined" && typeof console.debug != "undefined") { 1283 console.log(s); 1284 } else { 1285 alert(s); 1286 } 1287 } 1288 1289 /* parsers utils */ 1290 1291 function buildParserCache(table, $headers) { 1292 1293 if (table.config.debug) { 1294 var parsersDebug = ""; 1295 } 1296 1297 if (table.tBodies.length == 0) return; // In the case of empty tables 1298 var rows = table.tBodies[0].rows; 1299 1300 if (rows[0]) { 1301 1302 var list = [], 1303 cells = rows[0].cells, 1304 l = cells.length; 1305 1306 for (var i = 0; i < l; i++) { 1307 1308 var p = false; 1309 1310 if ($.metadata && ($($headers[i]).metadata() && $($headers[i]).metadata().sorter)) { 1311 1312 p = getParserById($($headers[i]).metadata().sorter); 1313 1314 } else if ((table.config.headers[i] && table.config.headers[i].sorter)) { 1315 1316 p = getParserById(table.config.headers[i].sorter); 1317 } 1318 if (!p) { 1319 1320 p = detectParserForColumn(table, rows, -1, i); 1321 } 1322 1323 if (table.config.debug) { 1324 parsersDebug += "column:" + i + " parser:" + p.id + "\n"; 1325 } 1326 1327 list.push(p); 1328 } 1329 } 1330 1331 if (table.config.debug) { 1332 log(parsersDebug); 1333 } 1334 1335 return list; 1336 }; 1337 1338 function detectParserForColumn(table, rows, rowIndex, cellIndex) { 1339 var l = parsers.length, 1340 node = false, 1341 nodeValue = false, 1342 keepLooking = true; 1343 while (nodeValue == '' && keepLooking) { 1344 rowIndex++; 1345 if (rows[rowIndex]) { 1346 node = getNodeFromRowAndCellIndex(rows, rowIndex, cellIndex); 1347 nodeValue = trimAndGetNodeText(table.config, node); 1348 if (table.config.debug) { 1349 log('Checking if value was empty on row:' + rowIndex); 1350 } 1351 } else { 1352 keepLooking = false; 1353 } 1354 } 1355 for (var i = 1; i < l; i++) { 1356 if (parsers[i].is(nodeValue, table, node)) { 1357 return parsers[i];
1358 } 1359 } 1360 // 0 is always the generic parser (text) 1361 return parsers[0]; 1362 } 1363 1364 function getNodeFromRowAndCellIndex(rows, rowIndex, cellIndex) { 1365 return rows[rowIndex].cells[cellIndex]; 1366 } 1367 1368 function trimAndGetNodeText(config, node) { 1369 return $.trim(getElementText(config, node)); 1370 } 1371 1372 function getParserById(name) { 1373 var l = parsers.length; 1374 for (var i = 0; i < l; i++) { 1375 if (parsers[i].id.toLowerCase() == name.toLowerCase()) { 1376 return parsers[i]; 1377 } 1378 } 1379 return false; 1380 } 1381 1382 /* utils */ 1383 1384 function buildCache(table) { 1385 1386 if (table.config.debug) { 1387 var cacheTime = new Date(); 1388 } 1389 1390 var totalRows = (table.tBodies[0] && table.tBodies[0].rows.length) || 0, 1391 totalCells = (table.tBodies[0].rows[0] && table.tBodies[0].rows[0].cells.length) || 0, 1392 parsers = table.config.parsers, 1393 cache = { 1394 row: [], 1395 normalized: [] 1396 }; 1397 1398 for (var i = 0; i < totalRows; ++i) { 1399 1400 /** Add the table data to main data array */ 1401 var c = $(table.tBodies[0].rows[i]), 1402 cols = []; 1403 1404 // if this is a child row, add it to the last row's children and 1405 // continue to the next row 1406 if (c.hasClass(table.config.cssChildRow)) { 1407 cache.row[cache.row.length - 1] = cache.row[cache.row.length - 1].add(c); 1408 // go to the next for loop 1409 continue; 1410 } 1411 1412 cache.row.push(c); 1413 1414 for (var j = 0; j < totalCells; ++j) { 1415 cols.push(parsers[j].format(getElementText(table.config, c[0].cells[j]), table, c[0].cells[j])); 1416 } 1417 1418 cols.push(cache.normalized.length); // add position for rowCache 1419 cache.normalized.push(cols); 1420 cols = null; 1421 }; 1422 1423 if (table.config.debug) { 1424 benchmark("Building cache for " + totalRows + " rows:", cacheTime); 1425 } 1426 1427 return cache; 1428 }; 1429 1430 function getElementText(config, node) { 1431 1432 var text = ""; 1433 1434 if (!node) return ""; 1435
1436 if (!config.supportsTextContent) config.supportsTextContent = node.textContent || false; 1437 1438 if (config.textExtraction == "simple") { 1439 if (config.supportsTextContent) { 1440 text = node.textContent; 1441 } else { 1442 if (node.childNodes[0] && node.childNodes[0].hasChildNodes()) { 1443 text = node.childNodes[0].innerHTML; 1444 } else { 1445 text = node.innerHTML; 1446 } 1447 } 1448 } else { 1449 if (typeof(config.textExtraction) == "function") { 1450 text = config.textExtraction(node); 1451 } else { 1452 text = $(node).text(); 1453 } 1454 } 1455 return text; 1456 } 1457 1458 function appendToTable(table, cache) { 1459 1460 if (table.config.debug) { 1461 var appendTime = new Date() 1462 } 1463 1464 var c = cache, 1465 r = c.row, 1466 n = c.normalized, 1467 totalRows = n.length, 1468 checkCell = (n[0].length - 1), 1469 tableBody = $(table.tBodies[0]), 1470 rows = []; 1471 1472 1473 for (var i = 0; i < totalRows; i++) { 1474 var pos = n[i][checkCell]; 1475 1476 rows.push(r[pos]); 1477 1478 if (!table.config.appender) { 1479 1480 //var o = ; 1481 var l = r[pos].length; 1482 for (var j = 0; j < l; j++) { 1483 tableBody[0].appendChild(r[pos][j]); 1484 } 1485 1486 // 1487 } 1488 } 1489 1490 1491 1492 if (table.config.appender) { 1493 1494 table.config.appender(table, rows); 1495 } 1496 1497 rows = null; 1498 1499 if (table.config.debug) { 1500 benchmark("Rebuilt table:", appendTime); 1501 } 1502 1503 // apply table widgets 1504 applyWidget(table); 1505 1506 // trigger sortend 1507 setTimeout(function () { 1508 $(table).trigger("sortEnd"); 1509 }, 0); 1510 1511 }; 1512 1513 function buildHeaders(table) { 1514 1515 if (table.config.debug) { 1516 var time = new Date(); 1517 } 1518 1519 var meta = ($.metadata) ? true : false; 1520 1521 var header_index = computeTableHeaderCellIndexes(table); 1522 1523 $tableHeaders = $(table.config.selectorHeaders, table).each(function (index) { 1524 1525 this.column = header_index[this.parentNode.rowIndex + "-" + this.cellIndex]; 1526 // this.column = index; 1527 this.order = formatSortingOrder(table.config.sortInitialOrder); 1528 1529 1530 this.count = this.order; 1531 1532 if (checkHeaderMetadata(this) || checkHeaderOptions(table, index)) this.sortDisabled = true; 1533 if (checkHeaderOptionsSortingLocked(table, index)) this.order = this.lockedOrder = checkHeaderOptionsSortingLocked(table, index); 1534 1535 if (!this.sortDisabled) { 1536 var $th = $(this).addClass(table.config.cssHeader); 1537 if (table.config.onRenderHeader) table.config.onRenderHeader.apply($th); 1538 } 1539 1540 // add cell to headerList 1541 table.config.headerList[index] = this; 1542 }); 1543 1544 if (table.config.debug) { 1545 benchmark("Built headers:", time); 1546 log($tableHeaders); 1547 } 1548 1549 return $tableHeaders; 1550 1551 }; 1552 1553 // from: 1554 // http://www.javascripttoolbox.com/lib/table/examples.php 1555 // http://www.javascripttoolbox.com/temp/table_cellindex.html 1556 1557 1558 function computeTableHeaderCellIndexes(t) { 1559 var matrix = []; 1560 var lookup = {}; 1561 var thead = t.getElementsByTagName('THEAD')[0]; 1562 var trs = thead.getElementsByTagName('TR'); 1563 1564 for (var i = 0; i < trs.length; i++) { 1565 var cells = trs[i].cells; 1566 for (var j = 0; j < cells.length; j++) { 1567 var c = cells[j];
1568 1569 var rowIndex = c.parentNode.rowIndex; 1570 var cellId = rowIndex + "-" + c.cellIndex; 1571 var rowSpan = c.rowSpan || 1; 1572 var colSpan = c.colSpan || 1 1573 var firstAvailCol; 1574 if (typeof(matrix[rowIndex]) == "undefined") { 1575 matrix[rowIndex] = []; 1576 } 1577 // Find first available column in the first row 1578 for (var k = 0; k < matrix[rowIndex].length + 1; k++) { 1579 if (typeof(matrix[rowIndex][k]) == "undefined") { 1580 firstAvailCol = k; 1581 break; 1582 } 1583 } 1584 lookup[cellId] = firstAvailCol; 1585 for (var k = rowIndex; k < rowIndex + rowSpan; k++) { 1586 if (typeof(matrix[k]) == "undefined") { 1587 matrix[k] = []; 1588 } 1589 var matrixrow = matrix[k]; 1590 for (var l = firstAvailCol; l < firstAvailCol + colSpan; l++) { 1591 matrixrow[l] = "x"; 1592 } 1593 } 1594 } 1595 } 1596 return lookup; 1597 } 1598 1599 function checkCellColSpan(table, rows, row) { 1600 var arr = [], 1601 r = table.tHead.rows, 1602 c = r[row].cells; 1603 1604 for (var i = 0; i < c.length; i++) { 1605 var cell = c[i]; 1606 1607 if (cell.colSpan > 1) { 1608 arr = arr.concat(checkCellColSpan(table, headerArr, row++)); 1609 } else { 1610 if (table.tHead.length == 1 || (cell.rowSpan > 1 || !r[row + 1])) { 1611 arr.push(cell); 1612 } 1613 // headerArr[row] = (i+row); 1614 } 1615 } 1616 return arr; 1617 }; 1618 1619 function checkHeaderMetadata(cell) { 1620 if (($.metadata) && ($(cell).metadata().sorter === false)) { 1621 return true; 1622 }; 1623 return false; 1624 } 1625 1626 function checkHeaderOptions(table, i) { 1627 if ((table.config.headers[i]) && (table.config.headers[i].sorter === false)) { 1628 return true; 1629 }; 1630 return false; 1631 } 1632 1633 function checkHeaderOptionsSortingLocked(table, i) { 1634 if ((table.config.headers[i]) && (table.config.headers[i].lockedOrder)) return table.config.headers[i].lockedOrder; 1635 return false; 1636 } 1637 1638 function applyWidget(table) { 1639 var c = table.config.widgets; 1640 var l = c.length; 1641 for (var i = 0; i < l; i++) { 1642 1643 getWidgetById(c[i]).format(table); 1644 } 1645 1646 } 1647 1648 function getWidgetById(name) { 1649 var l = widgets.length; 1650 for (var i = 0; i < l; i++) { 1651 if (widgets[i].id.toLowerCase() == name.toLowerCase()) { 1652 return widgets[i]; 1653 } 1654 } 1655 }; 1656 1657 function formatSortingOrder(v) { 1658 if (typeof(v) != "Number") { 1659 return (v.toLowerCase() == "desc") ? 1 : 0; 1660 } else { 1661 return (v == 1) ? 1 : 0; 1662 } 1663 } 1664 1665 function isValueInArray(v, a) { 1666 var l = a.length; 1667 for (var i = 0; i < l; i++) { 1668 if (a[i][0] == v) { 1669 return true; 1670 } 1671 } 1672 return false; 1673 } 1674 1675 function setHeadersCss(table, $headers, list, css) { 1676 // remove all header information 1677 $headers.removeClass(css[0]).removeClass(css[1]); 1678 1679 var h = []; 1680 $headers.each(function (offset) { 1681 if (!this.sortDisabled) { 1682 h[this.column] = $(this); 1683 } 1684 }); 1685 1686 var l = list.length; 1687 for (var i = 0; i < l; i++) { 1688 h[list[i][0]].addClass(css[list[i][1]]); 1689 } 1690 } 1691 1692 function fixColumnWidth(table, $headers) { 1693 var c = table.config; 1694 if (c.widthFixed) { 1695 var colgroup = $('<colgroup>'); 1696 $("tr:first td", table.tBodies[0]).each(function () { 1697 colgroup.append($('<col>').css('width', $(this).width())); 1698 }); 1699 $(table).prepend(colgroup); 1700 }; 1701 } 1702 1703 function updateHeaderSortCount(table, sortList) { 1704 var c = table.config, 1705 l = sortList.length; 1706 for (var i = 0; i < l; i++) { 1707 var s = sortList[i], 1708 o = c.headerList[s[0]]; 1709 o.count = s[1]; 1710 o.count++; 1711 } 1712 } 1713 1714 /* sorting methods */ 1715 1716 function multisort(table, sortList, cache) { 1717 1718 if (table.config.debug) { 1719 var sortTime = new Date(); 1720 } 1721 1722 var dynamicExp = "var sortWrapper = function(a,b) {", 1723 l = sortList.length; 1724 1725 // TODO: inline functions. 1726 for (var i = 0; i < l; i++) { 1727 1728 var c = sortList[i][0]; 1729 var order = sortList[i][1]; 1730 // var s = (getCachedSortType(table.config.parsers,c) == "text") ? 1731 // ((order == 0) ? "sortText" : "sortTextDesc") : ((order == 0) ? 1732 // "sortNumeric" : "sortNumericDesc"); 1733 // var s = (table.config.parsers[c].type == "text") ? ((order == 0) 1734 // ? makeSortText(c) : makeSortTextDesc(c)) : ((order == 0) ? 1735 // makeSortNumeric(c) : makeSortNumericDesc(c)); 1736 var s = (table.config.parsers[c].type == "text") ? ((order == 0) ? makeSortFunction("text", "asc", c) : makeSortFunction("text", "desc", c)) : ((order == 0) ? makeSortFunction("numeric", "asc", c) : makeSortFunction("numeric", "desc", c)); 1737 var e = "e" + i; 1738 1739 dynamicExp += "var " + e + " = " + s; // + "(a[" + c + "],b[" + c 1740 // + "]); "; 1741 dynamicExp += "if(" + e + ") { return " + e + "; } "; 1742 dynamicExp += "else { "; 1743 1744 } 1745 1746 // if value is the same keep orignal order 1747 var orgOrderCol = cache.normalized[0].length - 1; 1748 dynamicExp += "return a[" + orgOrderCol + "]-b[" + orgOrderCol + "];"; 1749 1750 for (var i = 0; i < l; i++) { 1751 dynamicExp += "}; "; 1752 } 1753 1754 dynamicExp += "return 0; "; 1755 dynamicExp += "}; "; 1756 1757 if (table.config.debug) { 1758 benchmark("Evaling expression:" + dynamicExp, new Date()); 1759 } 1760 1761 eval(dynamicExp); 1762 1763 cache.normalized.sort(sortWrapper); 1764 1765 if (table.config.debug) { 1766 benchmark("Sorting on " + sortList.toString() + " and dir " + order + " time:", sortTime); 1767 } 1768 1769 return cache; 1770 }; 1771 1772 function makeSortFunction(type, direction, index) { 1773 var a = "a[" + index + "]", 1774 b = "b[" + index + "]"; 1775 if (type == 'text' && direction == 'asc') { 1776 return "(" + a + " == " + b + " ? 0 : (" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : (" + a + " < " + b + ") ? -1 : 1 )));"; 1777 } else if (type == 'text' && direction == 'desc') { 1778 return "(" + a + " == " + b + " ? 0 : (" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : (" + b + " < " + a + ") ? -1 : 1 )));"; 1779 } else if (type == 'numeric' && direction == 'asc') { 1780 return "(" + a + " === null && " + b + " === null) ? 0 :("
1780+ a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : " + a + " - " + b + "));"; 1781 } else if (type == 'numeric' && direction == 'desc') { 1782 return "(" + a + " === null && " + b + " === null) ? 0 :(" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : " + b + " - " + a + "));"; 1783 } 1784 }; 1785 1786 function makeSortText(i) { 1787 return "((a[" + i + "] < b[" + i + "]) ? -1 : ((a[" + i + "] > b[" + i + "]) ? 1 : 0));"; 1788 }; 1789 1790 function makeSortTextDesc(i) { 1791 return "((b[" + i + "] < a[" + i + "]) ? -1 : ((b[" + i + "] > a[" + i + "]) ? 1 : 0));"; 1792 }; 1793 1794 function makeSortNumeric(i) { 1795 return "a[" + i + "]-b[" + i + "];"; 1796 }; 1797 1798 function makeSortNumericDesc(i) { 1799 return "b[" + i + "]-a[" + i + "];"; 1800 }; 1801 1802 function sortText(a, b) { 1803 if (table.config.sortLocaleCompare) return a.localeCompare(b); 1804 return ((a < b) ? -1 : ((a > b) ? 1 : 0)); 1805 }; 1806 1807 function sortTextDesc(a, b) { 1808 if (table.config.sortLocaleCompare) return b.localeCompare(a); 1809 return ((b < a) ? -1 : ((b > a) ? 1 : 0)); 1810 }; 1811 1812 function sortNumeric(a, b) { 1813 return a - b; 1814 }; 1815 1816 function sortNumericDesc(a, b) { 1817 return b - a; 1818 }; 1819 1820 function getCachedSortType(parsers, i) { 1821 return parsers[i].type; 1822 }; /* public methods */ 1823 this.construct = function (settings) { 1824 return this.each(function () { 1825 // if no thead or tbody quit. 1826 if (!this.tHead || !this.tBodies) return; 1827 // declare 1828 var $this, $document, $headers, cache, config, shiftDown = 0, 1829 sortOrder; 1830 // new blank config object 1831 this.config = {}; 1832 // merge and extend. 1833 config = $.extend(this.config, $.tablesorter.defaults, settings); 1834 // store common expression for speed 1835 $this = $(this); 1836 // save the settings where they read 1837 $.data(this, "tablesorter", config); 1838 // build headers 1839 $headers = buildHeaders(this); 1840 // try to auto detect column type, and store in tables config 1841 this.config.parsers = buildParserCache(this, $headers); 1842 // build the cache for the tbody cells 1843 cache = buildCache(this); 1844 // get the css class names, could be done else where. 1845 var sortCSS = [config.cssDesc, config.cssAsc]; 1846 // fixate columns if the users supplies the fixedWidth option 1847 fixColumnWidth(this); 1848 // apply event handling to headers 1849 // this is to big, perhaps break it out? 1850 $headers.click( 1851 1852 function (e) { 1853 var totalRows = ($this[0].tBodies[0] && $this[0].tBodies[0].rows.length) || 0; 1854 if (!this.sortDisabled && totalRows > 0) { 1855 // Only call sortStart if sorting is 1856 // enabled. 1857 $this.trigger("sortStart"); 1858 // store exp, for speed 1859 var $cell = $(this); 1860 // get current column index 1861 var i = this.column; 1862 // get current column sort order 1863 this.order = this.count++ % 2; 1864 // always sort on the locked order. 1865 if(this.lockedOrder) this.order = this.lockedOrder; 1866 1867 // user only whants to sort on one 1868 // column 1869 if (!e[config.sortMultiSortKey]) { 1870 // flush the sort list 1871 config.sortList = []; 1872 if (config.sortForce != null) { 1873 var a = config.sortForce; 1874 for (var j = 0; j < a.length; j++) { 1875 if (a[j][0] != i) { 1876 config.sortList.push(a[j]); 1877 } 1878 } 1879 } 1880 // add column to sort list 1881 config.sortList.push([i, this.order]); 1882 // multi column sorting 1883 } else { 1884 // the user has clicked on an all 1885 // ready sortet column. 1886 if (isValueInArray(i, config.sortList)) { 1887 // revers the sorting direction 1888 // for all tables. 1889 for (var j = 0; j < config.sortList.length; j++) { 1890 var s = config.sortList[j], 1891 o = config.headerList[s[0]]; 1892 if (s[0] == i) { 1893 o.count = s[1]; 1894 o.count++; 1895 s[1] = o.count % 2; 1896 } 1897 } 1898 } else { 1899 // add column to sort list array 1900 config.sortList.push([i, this.order]); 1901 } 1902 }; 1903 setTimeout(function () { 1904 // set css for headers 1905 setHeadersCss($this[0], $headers, config.sortList, sortCSS); 1906 appendToTable( 1907 $this[0], multisort( 1908 $this[0], config.sortList, cache) 1909 ); 1910 }, 1); 1911 // stop normal event by returning false 1912 return false; 1913 } 1914 // cancel selection 1915 }).mousedown(function () { 1916 if (config.cancelSelection) { 1917 this.onselectstart = function () { 1918 return false 1919 }; 1920 return false; 1921 } 1922 }); 1923 // apply easy methods that trigger binded events 1924 $this.bind("update", function () { 1925 var me = this; 1926 setTimeout(function () { 1927 // rebuild parsers. 1928 me.config.parsers = buildParserCache( 1929 me, $headers); 1930 // rebuild the cache map 1931 cache = buildCache(me); 1932 }, 1); 1933 }).bind("updateCell", function (e, cell) { 1934 var config = this.config; 1935 // get position from the dom. 1936 var pos = [(cell.parentNode.rowIndex - 1), cell.cellIndex]; 1937 // update cache 1938 cache.normalized[pos[0]][pos[1]] = config.parsers[pos[1]].format( 1939 getElementText(config, cell), cell); 1940 }).bind("sorton", function (e, list) { 1941 $(this).trigger("sortStart"); 1942 config.sortList = list; 1943 // update and store the sortlist 1944 var sortList = config.sortList; 1945 // update header count index 1946 updateHeaderSortCount(this, sortList); 1947 // set css for headers 1948 setHeadersCss(this, $headers, sortList, sortCSS); 1949 // sort the table and append it to the dom 1950 appendToTable(this, multisort(this, sortList, cache)); 1951 }).bind("appendCache", function () { 1952 appendToTable(this, cache); 1953 }).bind("applyWidgetId", function (e, id) { 1954 getWidgetById(id).format(this); 1955 }).bind("applyWidgets", function () { 1956 // apply widgets 1957 applyWidget(this); 1958 }); 1959 if ($.metadata && ($(this).metadata() && $(this).metadata().sortlist)) { 1960 config.sortList = $(this).metadata().sortlist; 1961 } 1962 // if user has supplied a sort list to constructor. 1963 if (config.sortList.length > 0) { 1964 $this.trigger("sorton", [config.sortList]); 1965 } 1966 // apply widgets 1967 applyWidget(this); 1968 }); 1969 }; 1970 this.addParser = function (parser) { 1971 var l = parsers.length, 1972 a = true; 1973 for (var i = 0; i < l; i++) { 1974 if (parsers[i].id.toLowerCase() == parser.id.toLowerCase()) { 1975 a = false; 1976 } 1977 } 1978 if (a) { 1979 parsers.push(parser); 1980 }; 1981 }; 1982 this.addWidget = function (widget) { 1983 widgets.push(widget); 1984 }; 1985 this.formatFloat = function (s) { 1986 var i = parseFloat(s); 1987 return (isNaN(i)) ? 0 : i; 1988 }; 1989 this.formatInt = function (s) { 1990 var i = parseInt(s); 1991 return (isNaN(i)) ? 0 : i; 1992 }; 1993 this.isDigit = function (s, config) { 1994 // replace all an wanted chars and match. 1995 return /^[-+]?\d*$/.test($.trim(s.replace(/[,.']/g, ''))); 1996 }; 1997 this.clearTableBody = function (table) { 1998 if ($.browser.msie) { 1999 function empty() { 2000 while (this.firstChild) 2001 this.removeChild(this.firstChild); 2002 } 2003 empty.apply(table.tBodies[0]); 2004 } else { 2005 table.tBodies[0].innerHTML = ""; 2006 } 2007 }; 2008 } 2009 });
2010 2011 // extend plugin scope 2012 $.fn.extend({ 2013 tablesorter: $.tablesorter.construct 2014 }); 2015 2016 // make shortcut 2017 var ts = $.tablesorter; 2018 2019 // add default parsers 2020 ts.addParser({ 2021 id: "text", 2022 is: function (s) { 2023 return true; 2024 }, format: function (s) { 2025 return $.trim(s.toLocaleLowerCase()); 2026 }, type: "text" 2027 }); 2028 2029 ts.addParser({ 2030 id: "digit", 2031 is: function (s, table) { 2032 var c = table.config; 2033 return $.tablesorter.isDigit(s, c); 2034 }, format: function (s) { 2035 return $.tablesorter.formatFloat(s); 2036 }, type: "numeric" 2037 }); 2038 2039 ts.addParser({ 2040 id: "currency", 2041 is: function (s) { 2042 return /^[£$€?.]/.test(s); 2043 }, format: function (s) { 2044 return $.tablesorter.formatFloat(s.replace(new RegExp(/[£$€]/g), "")); 2045 }, type: "numeric" 2046 }); 2047 2048 ts.addParser({ 2049 id: "ipAddress", 2050 is: function (s) { 2051 return /^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s); 2052 }, format: function (s) { 2053 var a = s.split("."), 2054 r = "", 2055 l = a.length; 2056 for (var i = 0; i < l; i++) { 2057 var item = a[i]; 2058 if (item.length == 2) { 2059 r += "0" + item; 2060 } else { 2061 r += item; 2062 } 2063 } 2064 return $.tablesorter.formatFloat(r); 2065 }, type: "numeric" 2066 }); 2067 2068 ts.addParser({ 2069 id: "url", 2070 is: function (s) { 2071 return /^(https?|ftp|file):\/\/$/.test(s); 2072 }, format: function (s) { 2073 return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//), '')); 2074 }, type: "text" 2075 }); 2076 2077 ts.addParser({ 2078 id: "isoDate", 2079 is: function (s) { 2080 return /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s); 2081 }, format: function (s) { 2082 return $.tablesorter.formatFloat((s != "") ? new Date(s.replace( 2083 new RegExp(/-/g), "/")).getTime() : "0"); 2084 }, type: "numeric" 2085 }); 2086 2087 ts.addParser({ 2088 id: "percent", 2089 is: function (s) { 2090 return /\%$/.test($.trim(s)); 2091 }, format: function (s) { 2092 return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g), "")); 2093 }, type: "numeric" 2094 }); 2095 2096 ts.addParser({ 2097 id: "usLongDate", 2098 is: function (s) { 2099 return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/)); 2100 }, format: function (s) { 2101 return $.tablesorter.formatFloat(new Date(s).getTime()); 2102 }, type: "numeric" 2103 }); 2104 2105 ts.addParser({ 2106 id: "shortDate", 2107 is: function (s) { 2108 return /\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s); 2109 }, format: function (s, table) { 2110 var c = table.config; 2111 s = s.replace(/\-/g, "/"); 2112 if (c.dateFormat == "us") { 2113 // reformat the string in ISO format 2114 s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$1/$2"); 2115 } else if (c.dateFormat == "uk") { 2116 // reformat the string in ISO format 2117 s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$2/$1"); 2118 } else if (c.dateFormat == "dd/mm/yy" || c.dateFormat == "dd-mm-yy") { 2119 s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/, "$1/$2/$3"); 2120 } 2121 return $.tablesorter.formatFloat(new Date(s).getTime()); 2122 }, type: "numeric" 2123 }); 2124 ts.addParser({ 2125 id: "time", 2126 is: function (s) { 2127 return /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s); 2128 }, format: function (s) { 2129 return $.tablesorter.formatFloat(new Date("2000/01/01 " + s).getTime()); 2130 }, type: "numeric" 2131 }); 2132 ts.addParser({ 2133 id: "metadata", 2134 is: function (s) { 2135 return false; 2136 }, format: function (s, table, cell) { 2137 var c = table.config, 2138 p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName; 2139 return $(cell).metadata()[p]; 2140 }, type: "numeric" 2141 });
2142 // add default widgets 2143 ts.addWidget({ 2144 id: "zebra", 2145 format: function (table) { 2146 if (table.config.debug) { 2147 var time = new Date(); 2148 } 2149 var $tr, row = -1, 2150 odd; 2151 // loop through the visible rows 2152 $("tr:visible", table.tBodies[0]).each(function (i) { 2153 $tr = $(this); 2154 // style children rows the same way the parent 2155 // row was styled 2156 if (!$tr.hasClass(table.config.cssChildRow)) row++; 2157 odd = (row % 2 == 0); 2158 $tr.removeClass( 2159 table.config.widgetZebra.css[odd ? 0 : 1]).addClass( 2160 table.config.widgetZebra.css[odd ? 1 : 0]) 2161 }); 2162 if (table.config.debug) { 2163 $.tablesorter.benchmark("Applying Zebra widget", time); 2164 } 2165 } 2166 }); 2167})(jQuery); 2168/* 2169 * jQuery JSONP Core Plugin 2.0.2 (2010-05-21) 2170 * 2171 * http://code.google.com/p/jquery-jsonp/ 2172 * 2173 * Copyright (c) 2010 Julian Aubourg 2174 * 2175 * This document is licensed as free software under the terms of the 2176 * MIT License: http://www.opensource.org/licenses/mit-license.php 2177 */ 2178 2179 /* 2180 Sections marked OLD OPERA indicate original 2.0.2 code. 2181 Lines immediately after are suggested by Daniel Bratell <[email protected]>. 2182 Old lines reflect Opera workarounds for the old Opera browser; 2183 the new Opera parser chokes up on those workarounds. 2184 */ 2185 2186 2187 2188( function( $ , setTimeout ) { 2189 2190 // ###################### UTILITIES ## 2191 2192 // Noop 2193 function noop() { 2194 } 2195 2196 // Generic callback for firefox & opera 2197 function genericCallback( data ) { 2198 lastValue = [ data ]; 2199 } 2200 2201 // Add script to document 2202 function appendScript( node ) { 2203 head.insertBefore( node , head.firstChild ); 2204 } 2205 2206 // Call if defined 2207 function callIfDefined( method , object , parameters ) { 2208 method && method.apply( object , parameters ); 2209 } 2210 2211 // Give joining character given url 2212 function qMarkOrAmp( url ) { 2213 return /\?/ .test( url ) ? "&" : "?"; 2214 } 2215 2216 var // String constants (for better minification) 2217 STR_ASYNC = "async", 2218 STR_EMPTY = "", 2219 STR_ERROR = "error", 2220 STR_JQUERY_JSONP = "_jqjsp", 2221 STR_ON = "on", 2222 STR_ONERROR = STR_ON + STR_ERROR, 2223 STR_ONLOAD = STR_ON + "load", 2224 STR_ONREADYSTATECHANGE = STR_ON + "readystatechange", 2225 STR_REMOVE_CHILD = "removeChild", 2226 STR_SCRIPT_TAG = "<script/>", 2227 STR_SUCCESS = "success", 2228 STR_TIMEOUT = "timeout", 2229 2230 // Head element (for faster use) 2231 head = $( "head" )[ 0 ] || document.documentElement, 2232 // Page cache 2233 pageCache = {}, 2234 // Counter 2235 count = 0, 2236 // Last returned value 2237 lastValue, 2238 2239 // ###################### DEFAULT OPTIONS ## 2240 xOptionsDefaults = { 2241 //beforeSend: undefined, 2242 //cache: false, 2243 callback: STR_JQUERY_JSONP, 2244 //callbackParameter: undefined, 2245 //complete: undefined, 2246 //data: "" 2247 //dataFilter: undefined, 2248 //error: undefined, 2249 //pageCache: false, 2250 //success: undefined, 2251 //timeout: 0, 2252 //traditional: false, 2253 url: location.href 2254 }; 2255 2256 // ###################### MAIN FUNCTION ## 2257 function jsonp( xOptions ) { 2258 2259 // Build data with default 2260 xOptions = $.extend( {} , xOptionsDefaults , xOptions ); 2261 2262 // References to xOptions members (for better minification) 2263 var completeCallback = xOptions.complete, 2264 dataFilter = xOptions.dataFilter, 2265 callbackParameter = xOptions.callbackParameter, 2266 successCallbackName = xOptions.callback, 2267 cacheFlag = xOptions.cache, 2268 pageCacheFlag = xOptions.pageCache, 2269 url = xOptions.url, 2270 data = xOptions.data, 2271 timeout = xOptions.timeout, 2272 pageCached, 2273 2274 // References to beforeSend (for better minification) 2275 beforeSendCallback = xOptions.beforeSend, 2276 2277 // Abort/done flag 2278 done = 0, 2279 2280 // Life-cycle functions 2281 cleanUp = noop; 2282 2283 // Create the abort method 2284 xOptions.abort = function() { 2285 ! done++ && cleanUp(); 2286 }; 2287 2288 // Call beforeSend if provided (early abort if false returned) 2289 if ( beforeSendCallback 2290 && ( beforeSendCallback( xOptions , xOptions ) === false || done ) ) { 2291 return xOptions; 2292 } 2293 2294 // Control entries 2295 url = url || STR_EMPTY; 2296 data = data ? ( (typeof data) == "string" ? data : $.param( data , xOptions.traditional ) ) : STR_EMPTY; 2297 2298 // Build final url 2299 url += data ? ( qMarkOrAmp( url ) + data ) : STR_EMPTY; 2300 2301 // Add callback parameter if provided as option 2302 callbackParameter && ( url += qMarkOrAmp( url ) + escape(callbackParameter) + "=?" ); 2303 2304 // Add anticache parameter if needed
2305 ! cacheFlag && ! pageCacheFlag && ( url += qMarkOrAmp( url ) + "_" + ( new Date() ).getTime() + "=" ); 2306 2307 // Replace last ? by callback parameter 2308 url = url.replace( /=\?(&|$)/ , "=" + successCallbackName + "$1" ); 2309 2310 // Success notifier 2311 function notifySuccess( json ) { 2312 ! done++ && setTimeout( function() { 2313 cleanUp(); 2314 // Pagecache if needed 2315 pageCacheFlag && ( pageCache [ url ] = { s: [ json ] } ); 2316 // Apply the data filter if provided 2317 dataFilter && ( json = dataFilter.apply( xOptions , [ json ] ) ); 2318 // Call success then complete 2319 callIfDefined( xOptions.success , xOptions , [ json , STR_SUCCESS ] ); 2320 callIfDefined( completeCallback , xOptions , [ xOptions , STR_SUCCESS ] ); 2321 } , 0 ); 2322 } 2323 2324 // Error notifier 2325 function notifyError( type ) { 2326 ! done++ && setTimeout( function() { 2327 // Clean up 2328 cleanUp(); 2329 // If pure error (not timeout), cache if needed 2330 pageCacheFlag && type != STR_TIMEOUT && ( pageCache[ url ] = type ); 2331 // Call error then complete 2332 callIfDefined( xOptions.error , xOptions , [ xOptions , type ] ); 2333 callIfDefined( completeCallback , xOptions , [ xOptions , type ] ); 2334 } , 0 ); 2335 } 2336 2337 // Check page cache 2338 pageCacheFlag && ( pageCached = pageCache[ url ] ) 2339 ? ( pageCached.s ? notifySuccess( pageCached.s[ 0 ] ) : notifyError( pageCached ) ) 2340 : 2341 // Initiate request 2342 setTimeout( function( script , scriptAfter , timeoutTimer ) { 2343 2344 if ( ! done ) { 2345 2346 // If a timeout is needed, install it 2347 timeoutTimer = timeout > 0 && setTimeout( function() { 2348 notifyError( STR_TIMEOUT ); 2349 } , timeout ); 2350 2351 // Re-declare cleanUp function 2352 cleanUp = function() { 2353 timeoutTimer && clearTimeout( timeoutTimer ); 2354 script[ STR_ONREADYSTATECHANGE ] 2355 = script[ STR_ONLOAD ] 2356 = script[ STR_ONERROR ] 2357 = null; 2358 head[ STR_REMOVE_CHILD ]( script ); 2359 // OLD OPERA: scriptAfter && head[ STR_REMOVE_CHILD ]( scriptAfter ); 2360 scriptAfter && scriptAfter.parentNode && head[ STR_REMOVE_CHILD ]( scriptAfter ); 2361 2362 }; 2363 2364 // Install the generic callback 2365 // (BEWARE: global namespace pollution ahoy) 2366 window[ successCallbackName ] = genericCallback; 2367 2368 // Create the script tag 2369 script = $( STR_SCRIPT_TAG )[ 0 ]; 2370 2371 // Callback function 2372 function callback( result ) { 2373 result = lastValue; 2374 lastValue = undefined; 2375 result ? notifySuccess( result[ 0 ] ) : notifyError( STR_ERROR ); 2376 } 2377 2378 // IE: onreadystatechange handler 2379 script[ STR_ONREADYSTATECHANGE ] = function() { 2380 2381 /loaded|complete/.test( script.readyState ) && callback(); 2382 2383 }; 2384 2385 // All: standard handlers 2386 script[ STR_ONERROR ] = script[ STR_ONLOAD ] = callback; 2387 2388 //ORIGINAL: $.browser.opera ? 2389 // NOW NEEDS MOOTOOLS 2390 Browser.opera ? 2391 2392 // Opera: onerror is not called, use synchronized script execution 2393 ( ( scriptAfter = $( STR_SCRIPT_TAG )[ 0 ] ).text = "jQuery('#" + ( script.id = STR_JQUERY_JSONP + count++ ) + "')[0]." + STR_ONERROR + "()" ) 2394 2395 // Firefox: set script as async to avoid blocking scripts 2396 : script[ STR_ASYNC ] = STR_ASYNC; 2397 2398 ; 2399 2400 // Set source 2401 script.src = url; 2402 2403 // Append main script 2404 appendScript( script ); 2405 2406 // Opera: Append trailing script 2407 // OLD OPERA: scriptAfter && appendScript( scriptAfter ); 2408 setTimeout(function(){scriptAfter && appendScript( scriptAfter )},1000); 2409 } 2410 2411 } , 0 ); 2412 2413 return xOptions; 2414 } 2415 2416 // ###################### SETUP FUNCTION ## 2417 jsonp.setup = function( xOptions ) { 2418 $.extend( xOptionsDefaults , xOptions ); 2419 }; 2420 2421 // ###################### INSTALL in jQuery ## 2422 $.jsonp = jsonp; 2423 2424} )( jQuery , setTimeout ); 2425/* 2426 * jQuery MD5 Plugin 1.2.1 2427 * https://github.com/blueimp/jQuery-MD5 2428 * 2429 * Copyright 2010, Sebastian Tschan 2430 * https://blueimp.net 2431 * 2432 * Licensed under the MIT license: 2433 * http://creativecommons.org/licenses/MIT/ 2434 * 2435 * Based on 2436 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message 2437 * Digest Algorithm, as defined in RFC 1321. 2438 * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 2439 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet 2440 * Distributed under the BSD License 2441 * See http://pajhome.org.uk/crypt/md5 for more info. 2442 */ 2443 2444/*jslint bitwise: true */ 2445/*global unescape, jQuery */ 2446 2447(function ($) { 2448 'use strict'; 2449 2450 /* 2451 * Add integers, wrapping at 2^32. This uses 16-bit operations internally 2452 * to work around bugs in some JS interpreters. 2453 */ 2454 function safe_add(x, y) { 2455 var lsw = (x & 0xFFFF) + (y & 0xFFFF), 2456 msw = (x >> 16) + (y >> 16) + (lsw >> 16); 2457 return (msw << 16) | (lsw & 0xFFFF); 2458 } 2459 2460 /* 2461 * Bitwise rotate a 32-bit number to the left. 2462 */ 2463 function bit_rol(num, cnt) { 2464 return (num << cnt) | (num >>> (32 - cnt)); 2465 } 2466 2467 /* 2468 * These functions implement the four basic operations the algorithm uses. 2469 */ 2470 function md5_cmn(q, a, b, x, s, t) { 2471 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b); 2472 } 2473 function md5_ff(a, b, c, d, x, s, t) { 2474 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); 2475 } 2476 function md5_gg(a, b, c, d, x, s, t) { 2477 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); 2478 } 2479 function md5_hh(a, b, c, d, x, s, t) { 2480 return md5_cmn(b ^ c ^ d, a, b, x, s, t); 2481 } 2482 function md5_ii(a, b, c, d, x, s, t) { 2483 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); 2484 } 2485 2486 /* 2487 * Calculate the MD5 of an array of little-endian words, and a bit length. 2488 */ 2489 function binl_md5(x, len) { 2490 /* append padding */ 2491 x[len >> 5] |= 0x80 << ((len) % 32); 2492 x[(((len + 64) >>> 9) << 4) + 14] = len; 2493 2494 var i, olda, oldb, oldc, oldd, 2495 a = 1732584193, 2496 b = -271733879, 2497 c = -1732584194, 2498 d = 271733878; 2499 2500 for (i = 0; i < x.length; i += 16) { 2501 olda = a; 2502 oldb = b; 2503 oldc = c; 2504 oldd = d; 2505 2506 a = md5_ff(a, b, c, d, x[i], 7, -680876936); 2507 d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586); 2508 c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819); 2509 b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330); 2510 a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897); 2511 d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426); 2512 c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341); 2513 b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983); 2514 a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416); 2515 d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417); 2516 c = md5_ff(c, d, a, b, x[i + 10], 17, -42063); 2517 b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162); 2518 a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682); 2519 d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101); 2520 c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290); 2521 b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329); 2522 2523 a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510); 2524 d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632); 2525 c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713); 2526 b = md5_gg(b, c, d, a, x[i], 20, -373897302); 2527 a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691); 2528 d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083); 2529 c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335); 2530 b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848); 2531 a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438); 2532 d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690); 2533 c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961); 2534 b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501); 2535 a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467); 2536 d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784); 2537 c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473); 2538 b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734); 2539 2540 a = md5_hh(a, b, c, d, x[i + 5], 4, -378558); 2541 d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463); 2542 c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562); 2543 b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556); 2544 a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060); 2545 d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353); 2546 c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632); 2547 b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640); 2548 a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174); 2549 d = md5_hh(d, a, b, c, x[i], 11, -358537222); 2550 c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979); 2551 b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189); 2552 a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487); 2553 d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835); 2554 c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520); 2555 b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651); 2556 2557 a = md5_ii(a, b, c, d, x[i], 6, -198630844); 2558 d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415); 2559 c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905); 2560 b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055); 2561 a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571); 2562 d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606); 2563 c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523); 2564 b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799); 2565 a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359); 2566 d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744); 2567 c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380); 2568 b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649); 2569 a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070); 2570 d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379); 2571 c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259); 2572 b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551); 2573 2574 a = safe_add(a, olda); 2575 b = safe_add(b, oldb); 2576 c = safe_add(c, oldc); 2577 d = safe_add(d, oldd); 2578 } 2579 return [a, b, c, d]; 2580 } 2581 2582 /* 2583 * Convert an array of little-endian words to a string 2584 */ 2585 function binl2rstr(input) { 2586 var i, 2587 output = ''; 2588 for (i = 0; i < input.length * 32; i += 8) { 2589 output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF); 2590 } 2591 return output; 2592 } 2593 2594 /* 2595 * Convert a raw string to an array of little-endian words 2596 * Characters >255 have their high-byte silently ignored. 2597 */ 2598 function rstr2binl(input) { 2599 var i, 2600 output = []; 2601 output[(input.length >> 2) - 1] = undefined; 2602 for (i = 0; i < output.length; i += 1) { 2603 output[i] = 0; 2604 } 2605 for (i = 0; i < input.length * 8; i += 8) { 2606 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32); 2607 } 2608 return output; 2609 } 2610 2611 /* 2612 * Calculate the MD5 of a raw string 2613 */ 2614 function rstr_md5(s) { 2615 return binl2rstr(binl_md5(rstr2binl(s), s.length * 8)); 2616 } 2617 2618 /* 2619 * Calculate the HMAC-MD5, of a key and some data (raw strings) 2620 */ 2621 function rstr_hmac_md5(key, data) { 2622 var i, 2623 bkey = rstr2binl(key), 2624 ipad = [], 2625 opad = [], 2626 hash; 2627 ipad[15] = opad[15] = undefined; 2628 if (bkey.length > 16) { 2629 bkey = binl_md5(bkey, key.length * 8); 2630 } 2631 for (i = 0; i < 16; i += 1) { 2632 ipad[i] = bkey[i] ^ 0x36363636; 2633 opad[i] = bkey[i] ^ 0x5C5C5C5C; 2634 } 2635 hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); 2636 return binl2rstr(binl_md5(opad.concat(hash), 512 + 128)); 2637 } 2638 2639 /* 2640 * Convert a raw string to a hex string 2641 */ 2642 function rstr2hex(input) { 2643 var hex_tab = '0123456789abcdef', 2644 output = '', 2645 x, 2646 i; 2647 for (i = 0; i < input.length; i += 1) { 2648 x = input.charCodeAt(i); 2649 output += hex_tab.charAt((x >>> 4) & 0x0F) + 2650 hex_tab.charAt(x & 0x0F); 2651 } 2652 return output; 2653 } 2654 2655 /* 2656 * Encode a string as utf-8 2657 */ 2658 function str2rstr_utf8(input) { 2659 return unescape(encodeURIComponent(input)); 2660 } 2661 2662 /* 2663 * Take string arguments and return either raw or hex encoded strings 2664 */ 2665 function raw_md5(s) { 2666 return rstr_md5(str2rstr_utf8(s)); 2667 } 2668 function hex_md5(s) { 2669 return rstr2hex(raw_md5(s)); 2670 } 2671 function raw_hmac_md5(k, d) { 2672 return rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)); 2673 } 2674 function hex_hmac_md5(k, d) { 2675 return rstr2hex(raw_hmac_md5(k, d)); 2676 } 2677 2678 $.md5 = function (string, key, raw) { 2679 if (!key) { 2680 if (!raw) { 2681 return hex_md5(string); 2682 } else { 2683 return raw_md5(string); 2684 } 2685 } 2686 if (!raw) { 2687 return hex_hmac_md5(key, string); 2688 } else { 2689 return raw_hmac_md5(key, string); 2690 } 2691 }; 2692 2693}(typeof jQuery === 'function' ? jQuery : this)); 2694 2695// test-ipv6.com javascript 2696var dummyConsole = []; 2697var console = console || {}; 2698if (!console.log) { 2699 console.log = function (message) { 2700 dummyConsole.push(message); 2701 }; 2702} 2703 2704 2705/*global GIGO, MirrorConfig, $gt, jQuery, window, alert, Browser */ 2706 2707/* TODO consider having something on the debug screen for missing variables */ 2708 2709GIGO.mirrorconfig = function (key1, key2, fallback) { 2710 var ret; 2711 try {
2712 ret = MirrorConfig[key1][key2]; 2713 if (typeof ret === "undefined") { 2714 ret = fallback; 2715 } 2716 } catch (e) { 2717 ret = fallback; 2718 } 2719 return ret; 2720}; 2721 2722/* Look for <span lookup=site.name>x</span> and replace "x" wih the config.js values */ 2723 2724GIGO.fix_logo_as_html = function () { 2725 if (MirrorConfig.footer.html) { 2726 jQuery("#logo").load(MirrorConfig.footer.html); 2727 } 2728}; 2729 2730GIGO.fix_logo_generic = function () { 2731 // logo, operator, link 2732 if (MirrorConfig.footer.logo || MirrorConfig.footer.operator) { 2733 if (MirrorConfig.footer.logo) { 2734 jQuery("#logo_img").append(jQuery("<img>", { 2735 src: MirrorConfig.footer.logo 2736 })); 2737 } 2738 if (MirrorConfig.footer.operator) { 2739 if (MirrorConfig.footer.transparent) { 2740 jQuery("#logo_operator").append("This instance of test-ipv6.com is provided by " + " "); 2741 } else { 2742 jQuery("#logo_operator").append("This mirror is provided by" + " "); 2743 } 2744 if (MirrorConfig.footer.link) { 2745 jQuery("#logo_operator").append(jQuery("<a>", { 2746 text: MirrorConfig.footer.operator, 2747 href: MirrorConfig.footer.link, 2748 target: "_blank" 2749 })); 2750 } else { 2751 jQuery("#logo_operator").append(jQuery("<span>").text(MirrorConfig.footer.operator)); 2752 } 2753 } 2754 } 2755}; 2756 2757 2758// This is called very late, after the test completes 2759// but before "Other Sites" are checked. We will by default 2760// wait until "late", to avoid interfering with the 2761// actual tests, since those are purely timing based. 2762GIGO.fix_footer_late = function () { 2763 if (MirrorConfig.footer) { 2764 if (!(MirrorConfig.footer.early)) { 2765 GIGO.fix_logo_as_html(); 2766 GIGO.fix_logo_generic(); 2767 } 2768 } 2769}; 2770 2771// This is called very early into the site startup. 2772// This gives the option of displaying any footer information 2773// at the risk of interfering with results. 2774GIGO.fix_footer_early = function() { 2775 2776 2777 2778 2779 if (MirrorConfig.footer) { 2780 if (MirrorConfig.footer.early) { 2781 GIGO.fix_logo_as_html(); 2782 GIGO.fix_logo_generic(); 2783 } 2784 } 2785}; 2786 2787 2788GIGO.fixup_html_per_site_config = function () { 2789 var key1, key2, find, sel; 2790 // First, do search/replace stuff.
2791 for (key1 in MirrorConfig) { 2792 if (MirrorConfig.hasOwnProperty(key1)) { 2793 for (key2 in MirrorConfig[key1]) { 2794 if (MirrorConfig[key1].hasOwnProperty(key2)) { 2795 find = key1 + "." + key2; 2796 sel = "span[lookup='" + find + "']"; 2797 jQuery(sel).text(MirrorConfig[key1][key2]); 2798 2799 sel = "div[lookup='" + find + "']"; 2800 jQuery(sel).html(MirrorConfig[key1][key2]); 2801 2802 sel = "a[linkup='" + find + "']"; 2803 jQuery(sel).attr("href", MirrorConfig[key1][key2]); 2804 2805 sel = "img[src='" + find + "']"; 2806 jQuery(sel).attr("src", MirrorConfig[key1][key2]); 2807 2808 sel = "a[mailto='" + find + "']"; 2809 jQuery(sel).attr("href", "mailto:" + MirrorConfig[key1][key2]); 2810 2811 2812 } 2813 } 2814 } 2815 } 2816 2817}; 2818 2819 2820GIGO.fixup_html_per_locale = function () { 2821 2822 if (/bot|google|baidu|bing|msn|duckduckgo|teoma|slurp|yandex/i.test(navigator.userAgent)) { 2823 console.log("skipping link fixup (crawler)"); 2824 return; 2825 } 2826 2827 2828 $('a').each(function() { 2829 var value = $(this).attr('href'); 2830 // if value starts with "/" and ends in .html .. fix it. 2831 if (value === "/") { 2832 value="/index.html"; 2833 } 2834 2835 if (value.startsWith("/") && value.endsWith(".html")) { 2836 value=value+'.en_US'; 2837 $(this).attr('href',value); 2838 //console.log("fixup_html_per_locale fixed href %o",value); 2839 } 2840 2841 }); 2842}; 2843 2844 2845/* 2846** Report errors centrally, if not using IE6. 2847** Do this as a fake image fetch - avoids any risk 2848** of loading foreign code into the browser. 2849*/ 2850window.onerror = function(message, url, linenumber) { 2851 var eurl; 2852 if (/\bMSIE 6/.test(navigator.userAgent) && !window.opera) { 2853 if (linenumber && parseInt(linenumber) < 100) { 2854 return; 2855 } 2856 } 2857 if (url && linenumber) { 2858 eurl = GIGO.protocol + "ds.main.test-ipv6.com/errors.php?"; 2859 eurl = eurl + "message=" + encodeURIComponent(message); 2860 eurl = eurl + "&url=" + encodeURIComponent(url); 2861 eurl = eurl + "&linenumber=" + encodeURIComponent(linenumber); 2862 eurl = eurl + "&lang=" + encodeURIComponent("EN"); 2863 eurl = eurl + "&version=" + encodeURIComponent("1.1.1033"); 2864 new Image().src = eurl; 2865 } 2866 return false; 2867}; 2868 2869 2870/*global GIGO, MirrorConfig, jQuery, alert, $gt */ 2871/*jslint nomen: true */ 2872 2873 2874GIGO.messages = { 2875 "bad": "bad", 2876 "ok": "ok", 2877 "slow": "slow", 2878 "timeout": "timeout", 2879 "skipped": "skipped", 2880 2881 "6to4": "You appear to be using a public 6to4 gateway; your router may be providing this to you automatically. Such public gateways have no service level agreements; you may see performance problems using such. Better would be to get a native IPv6 address from your ISP.", 2882 "teredo": "Your IPv6 connection appears to be using Teredo, a type of IPv4/IPv6 translation using a public gateway. The quality for this <i>may</i> suffer, as you are using a public gateway to reach IPv6 based sites.", 2883 "teredo-minimum": "Your IPv6 connection appears to be using Teredo, a type of IPv4/IPv6 gateway; currently it connects only to direct IP\'s. Your browser will not be able to go to IPv6 sites by name. This means the current configuration is not useful for browsing IPv6 web sites.", 2884 "teredo-v4pref": "Your IPv6 connection appears to be using Teredo, a type of IPv4/IPv6 gateway. Your particular teredo configuration is only used as a protocol of last resort. When visiting a site with both IPv4 and IPv6, IPv4 will be preferred.", 2885 "IPv6 MTU": "Danger! IPv6 sorta works - however, large packets appear to fail, giving the appearance of a broken website. If a publisher publishes to IPv6, you will believe their web site to be broken. Ask your ISP about MTU issues; possibly with your tunnel. Check your firewall to make sure that ICMPv6 messages are allowed (in particular, Type 2 or Packet Too Big).", 2886 "confused:ASK": "Test results inconclusive; they were not consistent with expectations. Please rerun the test, and if the results are the same, please fill out the contact form.", 2887 "confused:NOASK": "Test results inconclusive; they were not consistent with expectations. Please rerun the test, and if the results are the same, seek local network help.",
2888 "dualstack:ipv4_preferred": "-", 2889 "dualstack:ipv6_preferred": "-", 2890 "dualstack:slow": "For unknown reasons, your browser appears to operate slower when given the option of connecting to both IPv4 and IPv6. Please rerun the test, and if the results are the same, please fill out the contact form.", 2891 "ipv4_only": "You appear to be able to browse the IPv4 Internet only. You will not be able to reach IPv6-only sites.", 2892 "ipv4_only:ds_good": "When a publisher offers both IPv4 and IPv6, your browser appears to be happy to take the IPv4 site without delay.", 2893 "ipv4_only:ds_slow": "When a publisher offers both IPv4 and IPv6, your browser appears to slow down signficantly compared to an IPv4-only site. You may even believe the destination web site to be broken. This may be due to your IPv6 configuration.", 2894 "ipv4_only:ds_timeout": "When a publisher offers both IPv4 and IPv6, your browser will time out trying to connect. You may believe the site is down. This may be due to your IPv6 configuration. Consider disabling IPv6, or seeking help.", 2895 "ipv4_slow": "Connections to IPv4 are slow, but functional. Perhaps you or your ISP put you behind an IP sharing device (NAT) that is currently slow.", 2896 "ipv6_only": "You appear to be able to browse the IPv6 Internet only. You have no access to IPv4. That\'s pretty bold!", 2897 "ipv6_slow": "Connections to IPv6 are slow, but functional. Perhaps you are using a public IPv6 tunnel that is either slow, or not located near you.", 2898 "ipv6_timeout": "Connections to IPv6-only sites are timing out. Any web site that is IPv6 only, will appear to be down to you.", 2899 "broken_ipv6": "Connections to IPv6-capable web sites hang. It appears that you may have IPv6 configured; and your computer believes that your IPv6 is working, with a route. It is however completely failing. Any web site that adds IPv6, will become unreachable to you. If you are unable to fix your IPv6 routing or connectivity, seek help. If all else fails, strongly consider disabling IPv6 on your host.", 2900 "webfilter:blocked": "We are unable to test your system; it appears that a firewall or browser filter is preventing the test from running. Critical tests are failing. Try disabling any browser plugins, extensions, or add-ons (such as ad blockers); and reloading this page. If that still fails, you can leave a comment requesting help.", 2901 "webfilter:dsboth": "We are unable to test your system; it appears that a firewall or browser filter is preventing the test from running. The dual-stack tests are failing. Try disabling any browser plugins, extensions, or add-ons (such as ad blockers); and reloading this page. If that still fails, you can leave a comment requesting help.", 2902 "webfilter:addons": "Your browser is blocking the test urls. We will try alternate methods, but they may fail to show your IP address; and may affect the quality of the advice given.", 2903 "webfilter:firefox": "The most likely cause is NoScript or AdBlock+. NoScript can be told to permit all scripts on this page (you may need to do this more than once). At minimum, permit the urls listed below.", 2904 "v6ns:ok": "Your DNS server (possibly run by your ISP) appears to have IPv6 Internet access.", 2905 "v6ns:bad": "Your DNS server (possibly run by your ISP) appears to have no access to the IPv6 Internet, or is not configured to use it. This may in the future restrict your ability to reach IPv6-only sites.", 2906 "ip_timeout:firefox": "You are likely using a FireFox plugin that is causing IP based tests to fail. Examples: RequestPolicy. Please disable those while using this site.", 2907 "confused:obbo": "A lookup for an IPv6-only name failed; yet the lookup and connect for dual-stack connected via IPv6. Something appears to be confused with the DNS lookups.", 2908 "apple:dnsbug_aaaa": "A lookup for an IPv6-only name failed; yet the lookup and connect for dual-stack connected via IPv6. The IPv6-only lookup should have worked. Apple has a bug that sporadically causes some IPv6 lookups to fail. We saw evidence of it on this test. You can reload the page and try the test again. For more details, see <a href=\'http://openradar.appspot.com/7333104\'>http://openradar.appspot.com/7333104</a>.", 2909 "apple:dnsbug_ds": "A lookup for an dual-stack IPv4 and IPv6 name failed (at minimum it should have connected via IPv4). Apple has a bug that sporadically causes some IPv6 lookups to fail. We saw evidence of it on this test. You can reload the page and try the test again. For more details, see <a href=\'http://openradar.appspot.com/7333104\'>http://openradar.appspot.com/7333104</a>.", 2910 "ipv4:no_address": "No IPv4 address detected", 2911 "ipv6:no_address": "No IPv6 address detected", 2912 "no_address": "Your IP address(es) could not be detected due to inteference from browser add-ons.", 2913 "opera": "The Opera web browser seems to be break on this site frequently. <b>If you have trouble, try another browser</b>.", 2914 "opera:turbo": "<b>Disable turbo mode on Opera, and try again.</b> Turbo mode is not compatible with the needs of this site.", 2915 "needs_ipv6": "To ensure the best Internet performance and connectivity, ask your ISP about native IPv6.", 2916 "dualstack:safe": "<b>Good news!</b> Your current configuration will continue to work as web sites enable IPv6.", 2917 "dualstack:unsafe": "<b>Our tests show that you will have a broken or misconfigured IPv6 setup, and this will cause problems as web sites enable IPv6.</b>", 2918 "dualstack:mtu": "<b>Our tests show that you may have MTU problems with IPv6; this can cause web sites to load slow (or not at all) when web sites enable IPv6.</b>", 2919 "tunnel_6rd_dumb": "It appears that you use a managed tunnel mechanism, 6RD, to transport IPv6 over IPv4.", 2920 "proxy_via": "We have detected that you are using a proxy. This means we are testing your proxy server, not your computer. Proxy details (as reported by your proxy \'Via\' header): %details", 2921 "proxy_via_dumb": "We have detected that you are using a proxy. This means we are testing your proxy server, not your computer.", 2922 "ipv6:nodns": "IPv6 connections work, but connections using DNS names do not use IPv6. For some reason, your browser or your OS is not doing IPv6 DNS \'AAAA\' lookups.", 2923 "broken": "We have suggestions to help you fix your system.", 2924 "sites": "Since you have IPv6, we are including a tab that shows how well you can reach other IPv6 sites. %sites",
2925 "avoids_ipv6": "Your browser has real working IPv6 address - but is avoiding using it. We\'re concerned about this.", 2926 "ood":"This mirror has been marked as out of compliance; you should instead visit <a href=\'//test-ipv6.com/\'>test-ipv6.com</a>." 2927}; 2928 2929GIGO.messages_popups = { 2930// These are not just strings, but arrays, 2931// #1: url 2932// #2: link text to show (translate this!) 2933// Between the first and second string, there must be a comma and a space. 2934 "dualstack:mtu": ["faq_pmtud.html", "faq: MTU"], 2935 "IPv6 MTU": ["faq_pmtud.html", "faq: MTU"], 2936// "ipv4:no_address": ["faq_ipv4_only.html", "faq: No IPv4"], 2937"ipv6:no_address": ["faq_no_ipv6.html", "faq: No IPv6"], 2938"needs_ipv6": ["faq_no_ipv6.html", "faq: No IPv6"], 2939 "6to4": ["faq_6to4.html", "faq: 6to4"], 2940 "teredo-minimum": ["faq_teredo_minimum.html", "faq: Teredo Minimum"], 2941 "v6ns:bad": ["faq_v6ns_bad.html", "faq: v6ns Bad"], 2942 "webfilter:blocked": ["faq_browser_plugins.html", "faq: Browser Plugins"], 2943 "webfilter:dsboth": ["faq_browser_plugins.html", "faq: Browser Plugins"], 2944 "webfilter:firefox": ["faq_firefox_plugins.html", "faq: Firefox Add-Ons"], 2945 "webfilter:addons": ["faq_browser_plugins.html", "faq: Browser Plugins"], 2946 "ip_timeout:firefox": ["faq_firefox_plugins.html", "faq: Firefox Add-Ons"], 2947 "opera": ["faq_opera.html", "faq: Opera"], 2948 "broken": ["broken.html", "faq: Broken!"], 2949 "ipv6:nodns": ["faq_broken_aaaa.html", "faq: Broken DNS Lookups"], 2950 "avoids_ipv6": ["faq_avoids_ipv6.html", "faq: Avoiding IPv6?"], 2951 "tunnel_6rd_dumb": ["faq_tunnel_6rd.html", "faq: 6RD tunnel"], 2952 "tls_warning" : ["faq_https.html","faq: Using HTTPS"], 2953 "tls_beta" : ["faq_https.html","faq: Using HTTPS"], 2954 "tls_available" : ["faq_https.html","faq: Using HTTPS"] 2955}; 2956 2957 2958 2959/*global GIGO, jQuery, alert, $gt:true*/ 2960 2961/* Used to fetch external strings, to make localization a bit easier. */ 2962 2963GIGO.gettext = function (a, b) { 2964 var c; 2965 try { 2966 c = GIGO.gettext_messages[a][b]; 2967 } catch (e) { 2968 return "[NO TEXT: " + a + " " + b + "]"; 2969 } 2970 if (c) { 2971 return c; 2972 } 2973 return "[NO TEXT: " + a + " " + b + "]"; 2974}; 2975 2976/* global $gt(a,b) polution - for gettext */ 2977$gt = GIGO.gettext; 2978 2979$gt = function () { 2980 console.log("whoops still using $gt"); 2981}; 2982 2983 2984// Original source: 2985// http://geekswithblogs.net/svanvliet/archive/2006/03/23/simple-javascript-object-dump-function.aspx 2986// Modified for: 2987// GIGO name space 2988// Wrapper function 2989/*global GIGO, jQuery, window, top */ 2990/*jslint nomen: true */ 2991/*jslint browser: true */ 2992 2993 2994 2995 2996GIGO.dumpObj = function (obj, name) { 2997 var s = GIGO._dumpObj(obj, name, " ", 0); 2998 s = jQuery('<div/>').text(s).html(); 2999 GIGO.writeConsole("<pre>" + s + "</pre>"); 3000}; 3001 3002 3003GIGO._dumpObj_MAX_DUMP_DEPTH = 3; 3004 3005GIGO._dumpObj = function (obj, name, indent, depth) { /*jslint forin: false */ 3006 3007 var s = JSON.stringify(obj,null," "); 3008 return s; 3009 3010 // The rest of this is obsolete 3011 // (needs to be proven) 3012 var child, output, item; 3013 if (depth > GIGO._dumpObj_MAX_DUMP_DEPTH) { 3014 return indent + name + ": <Maximum Depth Reached>\n"; 3015 } 3016 if (typeof obj === "object") { 3017 child = null; 3018 output = indent + name + "\n"; 3019 indent += "\t"; 3020 for (item in obj) { 3021 if (obj.hasOwnProperty(item)) { 3022 3023 3024 try { 3025 child = obj[item]; 3026 } catch (e) { 3027 child = "<Unable to Evaluate>"; 3028 } 3029 if (typeof child === "object") { 3030 output += GIGO._dumpObj(child, item, indent, depth + 1); 3031 } else { 3032 output += indent + item + ": " + child + "\n"; 3033 } 3034 } 3035 } 3036 return output; 3037 } 3038 return obj; 3039}; 3040 3041// From http://www.javascripter.net/faq/writingt.htm 3042// Use this instead of "alert"; you can scroll the window this produces. 3043// It also sucks a bit less CPU generating this output, since 3044// a real browser window was designed for large output. 3045GIGO.writeConsole = function (content) { 3046 top.consoleRef = window.open('', 'myconsole', 'width=550,height=450' + ',menubar=1' + ',toolbar=1' + ',status=1'
3046+ ',scrollbars=1' + ',resizable=1'); 3047 top.consoleRef.document.writeln('<html><head><title>Console</title></head>' + '<body bgcolor=white onLoad="self.focus()">' + content + '</body></html>'); 3048 top.consoleRef.document.close(); 3049}; 3050 3051/*global GIGO, Browser, unescape */ 3052/*jslint browser: true */ 3053 3054GIGO.getms = function () { 3055 // Helper function to get the current date/time as milliseconds. 3056 var d = new Date(); 3057 return d.getTime(); 3058}; 3059 3060 3061GIGO.slow = 5000; // milliseconds . If a test takes longer than this, it is considered "slow" (if good) or "timeout" (if error) 3062GIGO.max_time = 15 * 1000; // milliseconds . Max time to allow a test to try and run, before giving up on it. 3063GIGO.retry_until = 15 * 1000; // milliseconds. If we want multiple passes, this says to stop new passes after this time. 3064GIGO.retry_min = 1; // Minimum time_ms to reload images, trying to differentiate service quality. 3065GIGO.retry_max = 3; // Max time_ms to allow reloading, no matter how fast. 3066GIGO.repeat_only_if_slow = 1; // If 1: only repeat tests if at least one test was slow. If 0: always repeat until retry_min/retry_max. 3067GIGO.repeated = 0; // How many time_ms we've tried so far. 3068 3069GIGO.results = {}; // what we want to expose as "this" to callback functions 3070 3071 3072GIGO.results.ipv4 = { 3073 ip: "", 3074 subtype: "" 3075}; // Customer IP information, per our web service call 3076GIGO.results.ipv6 = { 3077 ip: "", 3078 subtype: "" 3079}; // Customer IP information, per our web service call 3080 3081GIGO.results.tests = {}; // Store test specific data here. 3082 3083GIGO.tabhistory = ["main"]; // History of what tab we go to and when; used for GIGO.goback() 3084 3085GIGO.tests_planned = 0; // As we add tests, this will be incremented. Used by progress bar. 3086GIGO.tests_finished = 0; // As we finish tests, this will be incremented. Used by progress bar. 3087GIGO.start_time = GIGO.getms(); // Starting time. Used by progress bar as well as by retry_until 3088GIGO.finished = 0; // When we're done with all tests, set to 1 to hide the progress bar 3089GIGO.slowcount = 0; // How many background jsonp we spawned so far. Used when we execute tasks in parallel to stagger load. 3090 3091// If we rig the test, don't report the results to the status surver. 3092// This is what happens when the page is called with 3093// ?test=oooooooo (all "ok", and technically impossible). 3094// ?test=oobooooo (more likely result) 3095// Main purpose is to test the display logic for given patterns of 3096// "ok", "slow", "bad", "timeout". 3097GIGO.test_rigged = 0; 3098 3099GIGO.tests = []; // The list of all tests we will run. 3100GIGO.queue = []; // If use_queue then this is the list of pending jobs to start. 3101GIGO.dequeued = []; // Tests we have dequeued 3102GIGO.use_queue = 0; // Set to 1 for force serial execution. Set to 0 to permit parallel execution. 3103if (Browser.firefox) { 3104 GIGO.use_queue = 1; // Always do serial execution for Firefox and friends, due to funky socks behavior. 3105} 3106if (Browser.opera) { 3107 GIGO.use_queue = 1; // Any blocking thread, blocks all. 3108 GIGO.max_time = 15 * 1000; // Hmm. 3109} 3110 3111GIGO.helpdesk = {}; // Test results will pass data to the helpdesk page 3112GIGO.helpdesk.other_sites = {}; 3113GIGO.helpdesk.other_sites.finished = 0; 3114GIGO.helpdesk.other_sites.count = 0; 3115GIGO.helpdesk.other_sites.good = []; 3116GIGO.helpdesk.other_sites.bad = []; 3117 3118 3119// http://mootools.net/docs/core/Core/Browser 3120GIGO.slowcount_delay = 20; // How long (ms) to delay between backgrounding jsonp if use_queue==0 3121if (Browser.ie) { 3122 GIGO.slowcount_delay = 200; // Slow down spawning of ajax queries 3123} 3124 3125// Symbian appears to be particularly bad. 3126// DNS lookups for some people appear to slow things down by nearly 5 seconds 3127if (navigator.userAgent.match(/SymbianOS|SymbOS/)) { 3128 GIGO.slowcount_delay = 500; // Slow down on Symbian phones 3129 GIGO.slow = 9000; 3130} 3131 3132// What protocol (http, https) should we make our URLs? 3133// Force it into https:// or http:// (even though our inputs might say http or http:) 3134GIGO.protocol = MirrorConfig.options.protocol ? MirrorConfig.options.protocol : document.location.protocol; 3135GIGO.protocol = (GIGO.protocol.match(/https/)) ? "https://" : "http://";
3136GIGO.publishname = GIGO.protocol + GIGO.mirrorconfig("site", "name"); 3137 3138 3139GIGO.parseGetVars = function () { 3140 var getVars, returnVars, i, newVar; 3141 3142 3143 getVars = location.search.substring(1).split("&"); // From the browser URL 3144 returnVars = []; 3145 i = 0; 3146 3147 for (i = 0; i < getVars.length; i = i + 1) { 3148 newVar = getVars[i].split("="); 3149 returnVars[unescape(newVar[0])] = unescape(newVar[1]); 3150 } 3151 return returnVars; 3152}; 3153 3154 3155GIGO.CGI = GIGO.parseGetVars(); // Parse CGI arguements 3156GIGO.contact_wanted = GIGO.CGI.contact; // Do we want to force the contact form? 3157 3158console.log("GIGO.CGI=%o",GIGO.CGI); 3159 3160// If we found overrides, we will set GIGO.override 3161// as we as prepared each override into GIGO.overrides 3162GIGO.override = 0; 3163GIGO.overrides = {}; 3164 3165 3166 3167if (!String.prototype.endsWith) { 3168 String.prototype.endsWith = function(searchString, position) { 3169 var subjectString = this.toString(); 3170 if (typeof position !== "number" || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) { 3171 position = subjectString.length; 3172 } 3173 position -= searchString.length; 3174 var lastIndex = subjectString.lastIndexOf(searchString, position); 3175 return lastIndex !== -1 && lastIndex === position; 3176 }; 3177} 3178 3179GIGO.CheckHTTPS = function(s) { 3180 console.log("document protocol %o",document.location.protocol); 3181 return document.location.protocol.startsWith("https"); 3182}; 3183 3184GIGO.CheckTransparentDomain = function(s) { 3185 return s == "test-ipv6.com" || s.endsWith(".test-ipv6.com"); 3186}; 3187 3188GIGO.CheckTransparent = function() { 3189 if (GIGO.CheckTransparentDomain(document.location.hostname)) { 3190 3191 let og = JSON.parse(JSON.stringify(MirrorConfig.options)); 3192 3193 3194 // Bias the reporting location if the user is visiting a specific flavor of the site. 3195 let main = "main.test-ipv6.com" 3196 if (document.location.hostname.startsWith("ipv6.")) { 3197 main = "ipv6.main.test-ipv6.com"; 3198 } 3199 if (document.location.hostname.startsWith("ipv4.")) { 3200 main = "ipv4.main.test-ipv6.com"; 3201 } 3202 if (document.location.hostname.startsWith("ds.")) { 3203 main = "ds.main.test-ipv6.com"; 3204 } 3205 console.log("document.location.hostname is %o",document.location.hostname); 3206 console.log("main is %o",main); 3207 3208 3209 // Always replace certain things when it's test-ipv6.com 3210 //delete MirrorConfig.footer.html; 3211 delete MirrorConfig.footer.logo; 3212 MirrorConfig.footer.transparent = 1; 3213 MirrorConfig.site = { 3214 name: "test-ipv6.com", 3215 contact: "Jason Fesler", 3216 mailto: "[email protected]", 3217 retire: true, 3218 }; 3219 MirrorConfig.options.show_stats = GIGO.protocol + main + "/stats.html"; 3220 MirrorConfig.options.comment_html = 1; 3221 MirrorConfig.options.userdata = main; 3222 MirrorConfig.options.comment=""; // no comments 3223 // Only replace these, if the underlying domain is something else. 3224 if (!GIGO.CheckTransparentDomain(MirrorConfig.load.domain)) { 3225 MirrorConfig.orig_options = og; 3226 MirrorConfig.options.survey = "/survey.php"; 3227 MirrorConfig.options.comment = "/comment.php"; 3228 MirrorConfig.options.userdata = main; 3229 MirrorConfig.options.v6mtu = "mtu1280." + MirrorConfig.load.domain; 3230 } 3231 } 3232 console.log("CheckTransparent: MirrorConfig is now %o",MirrorConfig); 3233}; 3234 3235GIGO.CheckTransparent(); 3236 3237/*global GIGO, MirrorConfig, jQuery, Browser, setTimeout, alert, document */ 3238/*jslint nomen: true */ 3239/*jslint regexp: true */ 3240 3241 3242GIGO.generate_share_link_entry = function (name, def) { 3243 var s, t, id, p; 3244 s = ""; 3245 try { 3246 id = "test_" + name; 3247 t = GIGO.results.tests[id]; 3248 if ((t.status === "ok") || (t.status === "slow")) { 3249 s = "&" + name + "=" + encodeURIComponent(t.status) + "," + encodeURIComponent(t.time_ms); 3250 p = t.ipinfo.type.replace(/^ipv/, ""); 3251 s = s + "," + encodeURIComponent(p); 3252 } 3253 if ((t.status === "bad") || (t.status === "timeout")) { 3254 s = "&" + name + "=" + encodeURIComponent(t.status) + "," + encodeURIComponent(t.time_ms); 3255 } 3256 } catch (e) { 3257 noop = 1; 3258 } 3259 return s; 3260}; 3261 3262 3263 3264GIGO.generate_share_link = function () { 3265 var url; 3266 url = location.href.replace(/[?#].*$/,'') + "?"; 3267 if (GIGO.results.ipv4.ip) { 3268 url = url + "ip4=" + encodeURIComponent(GIGO.results.ipv4.ip); 3269 } else { 3270 url = url + "ip4="; 3271 } 3272 if (GIGO.results.ipv6.ip) { 3273 url = url + "&ip6=" + encodeURIComponent(GIGO.results.ipv6.ip).replace(/%3a/ig, ":"); 3274 } else { 3275 url = url + "&ip6="; 3276 } 3277 url = url + GIGO.generate_share_link_entry("a", "4"); 3278 url = url + GIGO.generate_share_link_entry("aaaa", "6"); 3279 url = url + GIGO.generate_share_link_entry("ds", "6"); 3280 url = url + GIGO.generate_share_link_entry("v6mtu", "6"); 3281 url = url + GIGO.generate_share_link_entry("v6ns", "6"); 3282 url = url + GIGO.generate_share_link_entry("dsmtu", "6"); 3283 3284 3285 // Working/Failed sites 3286 if (GIGO.isdef(GIGO.failed_sites)) { 3287 url = url + "&failed_sites=" + GIGO.failed_sites.join(","); 3288 } 3289 3290 return url; 3291}; 3292 3293 3294GIGO.show_share_link = function () { 3295 var url, a, t, te; 3296 url = GIGO.generate_share_link(); 3297 a = jQuery("<a>"); 3298 3299 t = jQuery("<p>"); 3300 t.text(url); 3301 te = t.html(); 3302 te = te.replace(/&/g, "<wbr>&"); 3303 a.html(te); 3304 a.attr("href", url); 3305 a.attr("target", "_blank"); 3306 d = jQuery("<p id=replayurl>").append(a); 3307 jQuery("#replayurl").replaceWith(d); 3308}; 3309 3310GIGO.show_debug = function () { 3311 var s, url; 3312 3313 s = GIGO._dumpObj(GIGO.results.tests, "GIGO.results.tests.", " ", 0); 3314 s = jQuery('<div/>').text(s).html(); 3315 jQuery("#debug_dump").html("<pre>" + s + "</pre>"); 3316 3317 GIGO.show_share_link(); 3318}; 3319 3320 3321// Some of our substitutions are expensive to compute. 3322// Let's just do it once. 3323GIGO.substitutions = {}; 3324GIGO.substitutions.HTTPS = '<a href="' + "https://" + document.location.hostname + document.location.pathname + '">HTTPS</a>'; 3325 3326 3327// Return a table with left side colored and with a symbol; right side, informative text. 3328GIGO.results_table_wrapper = function (color, text) { 3329 var table; 3330 color = color.toLowerCase(); 3331 3332 // Things we will do as substitutions 3333 text = text.replace("%HTTPS",GIGO.substitutions.HTTPS); 3334 3335 table = ""; 3336 table = "<table class=\"results_wrapper\">"; 3337 table = table + "<tr>"; 3338 3339 table = table + "<td class=\"results_left\"><p style=\"margin: 0;\">"; 3340 3341 switch (color) { 3342 case "green": 3343 table = table + '<img style="height: 2em; width: auto;" src="/images/hires_ok.png"/>'; 3344 break; 3345 case "red": 3346 table = table + '<img style="height: 2em; width: auto;" src="/images/hires_bad.png"/>'; 3347 break; 3348 case "blue": 3349 table = table + '<img style="height: 2em; width: auto;" src="/images/hires_info.png"/>'; 3350 break; 3351 case "orange": 3352 table = table + '<img style="height: 2em; width: auto;" src="/images/hires_attention.png"/>'; 3353 break; 3354 default: 3355 table = table + " "; 3356 break; 3357 } 3358 3359 table = table + "</p></td>"; 3360 3361 table = table + "<td class=\"results_right\">
3361" + text + "</td>"; 3362 table = table + "</tr></table>"; 3363 3364 return table; 3365}; 3366 3367 3368GIGO.showdebug = function () { 3369 jQuery("#debuglink").show(); 3370 GIGO.tabnav("debug"); 3371}; 3372 3373GIGO.start_sites = function () { 3374 var t, moreinfo, link, table; 3375 jQuery("#siteslink").show(); 3376 GIGO.test_sites(2); 3377 t = "Since you have IPv6, we are including a tab that shows how well you can reach other IPv6 sites. %sites"; 3378 moreinfo = "[more info]"; 3379 3380 link = '<a href="#" class="help_popup" onclick="return GIGO.tabnav(\'sites\');">' + moreinfo + '</a>'; 3381 3382 t = t.replace(/%sites/, link); 3383 table = GIGO.results_table_wrapper("blue", t); 3384 jQuery("#results_eof").before(table); 3385}; 3386 3387 3388GIGO.update_ip = function (id) { 3389 // G = the GIGO object 3390 var s, ipinfo, escaped, name; 3391 3392 ipinfo = GIGO.results.tests[id].ipinfo; 3393 3394 3395 GIGO.show_debug(); 3396 3397 if (GIGO.results.ipv4.ip !== "") { 3398 s = "Your IPv4 address on the public Internet appears to be" + " " + GIGO.results.ipv4.ip; 3399 if (GIGO.results.ipv4.subtype) { 3400 s = s + " (" + GIGO.results.ipv4.subtype + ")"; 3401 } 3402 if (GIGO.results.ipv4.via) { 3403 s = s + "<br/>
3403" + "Proxied" + ", <code>" + jQuery('<div/>').text("Via: " + GIGO.results.ipv4.via).html() + "</code>"; 3404 } 3405 3406 if ((GIGO.results.ipv4.asn_name) && (GIGO.results.ipv6.asn_name) && (GIGO.results.ipv4.asn_name !== GIGO.results.ipv6.asn_name)) { 3407 escaped = jQuery('<div/>').text(GIGO.results.ipv4.asn_name).html(); 3408 s = s + "<br/>(" + escaped + ")"; 3409 jQuery("#your_isp").html(""); 3410 } 3411 3412 s = GIGO.results_table_wrapper("blue", s); 3413 jQuery("#your_ipv4").html(s); 3414 } 3415 if (GIGO.results.ipv6.ip !== "") { 3416 s = "Your IPv6 address on the public Internet appears to be" + " " + GIGO.results.ipv6.ip; 3417 if (GIGO.results.ipv6.subtype) { 3418 s = s + "<br/>" + "Your IPv6 service appears to be" + ": " + GIGO.results.ipv6.subtype; 3419 } 3420 if (GIGO.results.ipv6.via) { 3421 s = s + "<br/>" + "Proxied" + ", <code>" + jQuery('<div/>').text("Via: " + GIGO.results.ipv6.via).html() + "</code>"; 3422 } 3423 if ((GIGO.results.ipv4.asn_name) && (GIGO.results.ipv6.asn_name) && (GIGO.results.ipv4.asn_name !== GIGO.results.ipv6.asn_name)) { 3424 escaped = jQuery('<div/>').text(GIGO.results.ipv6.asn_name).html(); 3425 s = s + "<br/>(" + escaped + ")"; 3426 jQuery("#your_isp").html(""); 3427 } 3428 s = GIGO.results_table_wrapper("blue", s); 3429 jQuery("#your_ipv6").html(s); 3430 } 3431 3432 if ( 3433 ((GIGO.results.ipv4.asn_name) && (GIGO.results.ipv6.asn_name) && (GIGO.results.ipv4.asn_name === GIGO.results.ipv6.asn_name)) || (GIGO.results.ipv4.asn_name && (!GIGO.results.ipv6.asn_name)) || (GIGO.results.ipv6.asn_name && (!GIGO.results.ipv4.asn_name)) 3434 ) { 3435 name = GIGO.results.ipv4.asn_name || GIGO.results.ipv6.asn_name; 3436 escaped = jQuery('<div/>').text(name).html(); 3437 s = "Your Internet Service Provider (ISP) appears to be" + " " + escaped; 3438 s = GIGO.results_table_wrapper("blue", s); 3439 jQuery("#your_isp").html(s); 3440 } 3441 3442 3443 3444 3445}; 3446 3447 3448GIGO.update_status = function (id) { 3449 // G = the GIGO object 3450 // url = the URL we just received 3451 // id = the update we just received (ie, "test_a", "test_aaaa") 3452 // ipinfo.ip = text form of ip; ipinfo.type = "ipv4" or "ipv6"; ipinfo.subtype MAY say "Teredo" or "6to4" 3453 var status, status_translated, time_ms, ipinfo, content, url, proxied; 3454 status = GIGO.results.tests[id].status; // This should be ok/bad/slow/timeout 3455 status_translated = GIGO.messages[status]; 3456 time_ms = GIGO.results.tests[id].time_ms; // This should be number of milliseconds spent 3457 ipinfo = GIGO.results.tests[id].ipinfo; // This may be "undef" 3458 url = GIGO.results.tests[id].url; 3459 3460 if (!time_ms) { 3461 content = "Started"; 3462 3463 } else if (GIGO.isdef(ipinfo)) { 3464 // TODO: Localize number formats 3465 proxied = ""; 3466 if (ipinfo.via) { 3467 proxied = " " + "proxied" + " "; 3468 } 3469 3470 3471 3472 content = "<span class=status_" + status + ">" + status_translated + "</span> " + "(" + (time_ms / 1000.0).toFixed(3) + "s) " + "using" + " " + proxied + ipinfo.type; 3473 if (ipinfo.subtype) { 3474 content = content + " " + ipinfo.subtype; 3475 } 3476 if (ipinfo.asn) { 3477 content = content + " ASN " + ipinfo.asn; 3478 } 3479 } else { 3480 // TODO: Localize number formats 3481 content = "<span class=status_" + status + ">" + status_translated + "</span> " + "(" + (time_ms / 1000.0).toFixed(3) + "s)"; 3482 } 3483 3484 jQuery("#" + id).html(content); 3485 jQuery("#sum_" + id).html(content); 3486}; 3487 3488GIGO.update_url = function (id) { 3489 var url, showurl, res; 3490 url = GIGO.results.tests[id].url; 3491 showurl = url.replace(/fill=xxxx*/, "fill=xxx...xxx"); // Obscene to show a nearly 2k url 3492 showurl = showurl.replace(/&testdomain=[^&]+&testname=[^&]+/,""); // Also remove the test name and test domain 3493 showurl = showurl.replace(/(gif|png|jpg)\?$/i,"$1"); // hmm 3494 res = id.replace(/test_/, "results_"); // Deterine which span to show this in 3495 jQuery("#" + res).html("<a id=url href='" + url + "'>" + showurl + " </a>"); 3496}; 3497 3498GIGO.browser_tweaks = function (G) {
3499 // Finish setting up the contact form 3500 if (Browser.Platform.win) { 3501 jQuery("#help_windows").show(); 3502 } else if (Browser.Platform.linux) { 3503 jQuery("#help_linux").show(); 3504 } else { 3505 jQuery("#help_generic").show(); 3506 } 3507}; 3508 3509GIGO.update_progress = function (G) { 3510 // G = the GIGO object 3511 // Now a spinner or "throbber" instead; 3512 // indicates how many tests have finished. 3513 // Prelude to being more flexible on dynamically adding tests. 3514 // Implements a progress bar 3515 // Based on: 3516 // G.queue.length - number of tests we have left to start 3517 // G.dequeued.length - number of tests we started already 3518 // G.tests_finished - number of tests completed (good or bad) 3519 // G.retry_max - maximum number of retries 3520 // G.start_time - time test started 3521 // G.retry_until - the point we stop running new tests 3522 // pct1 : percent done based on number of tests ran 3523 var sofar, outof; 3524 3525 sofar = G.tests_finished; 3526 outof = G.queue.length + G.dequeued.length; 3527 3528 jQuery(".pb1_text").html(" " + sofar + "/" + outof + " " + "tests run"); 3529 if (sofar === outof) { 3530 jQuery("#progress_bar").hide(); 3531 jQuery("#progress_bar").html(""); 3532 } 3533 3534}; 3535 3536GIGO.send_survey_global = function (tokens) { 3537 // Only if we are in transparent mode.. 3538 if (MirrorConfig.orig_options) { 3539 if (MirrorConfig.options.survey !== MirrorConfig.orig_options.survey || 3540 MirrorConfig.options.userdata !== MirrorConfig.orig_options.userdata ) { 3541 MirrorConfig.options.survey = MirrorConfig.orig_options.survey; 3542 MirrorConfig.options.userdata = MirrorConfig.orig_options.userdata; 3543 GIGO.send_survey(tokens); 3544 } 3545 } 3546}; 3547 3548 3549GIGO.send_survey = function (tokens) { 3550 3551 // Temporary(?): disable survey for "test-ipv6.com"; main.test-ipv6.com is 3552 // now non-op. 3553 if (GIGO.CheckTransparentDomain(document.location.hostname)) { 3554 return; 3555 } 3556 3557 var url = MirrorConfig.options.survey; 3558 if (!url) { 3559 return; 3560 } 3561 3562 if (MirrorConfig.options.userdata) { 3563 // We're going to completely override "url" 3564 if (GIGO.results.ipv4.ip) { 3565 url = GIGO.protocol + "ipv4." + MirrorConfig.options.userdata + MirrorConfig.options.survey; 3566 } else { 3567 url = GIGO.protocol + "ipv6." + MirrorConfig.options.userdata + MirrorConfig.options.survey; 3568 } 3569 } 3570 3571 3572 if (GIGO.is_replay()) { 3573 return; 3574 } 3575 3576 if (GIGO.override) { 3577 jQuery("#survey").html("(Survey posting skipped; test was rigged)"); 3578 return; 3579 } 3580 3581 3582 tokens = tokens.join(","); 3583 url += "?x&" + GIGO.cgistats("a") + GIGO.cgistats("aaaa") + GIGO.cgistats("ds4") + GIGO.cgistats("ds6") + GIGO.cgistats("v6ns") + GIGO.cgistats("dsmtu") + GIGO.cgistats("v6mtu") + "&tokens=" + encodeURI(tokens) + "&rand=" + Math.floor(Math.random() * 2000000000); 3584 3585 if (MirrorConfig.options.survey_ip) { 3586 if (GIGO.results.ipv4.ip) { 3587 url += "&ip4="+GIGO.results.ipv4.ip; 3588 } else { 3589 url += "&ip4="; 3590 } 3591 if (GIGO.results.ipv6.ip) { 3592 url += "&ip6="+GIGO.results.ipv6.ip; 3593 } else { 3594 url += "&ip6="; 3595 } 3596 } else { 3597 if (GIGO.results.ipv4.ip) { 3598 url += "&ip4=a29"; 3599 } else { 3600 url += "&ip4="; 3601 } 3602 3603 if (GIGO.results.ipv6.ip) { 3604 url += "&ip6=a29"; 3605 } else { 3606 url += "&ip6="; 3607 } 3608 } 3609 url += "&load=" + encodeURI(MirrorConfig.load.domain); 3610 3611 3612 url += "&ip6subtype=" + encodeURI(GIGO.results.ipv6.subtype); 3613 url += "&callback=?"; 3614 3615 3616 jQuery("#survey").html("(Updating server side IPv6 readiness stats)"); 3617 3618 3619 jQuery.jsonp({ 3620 "url": url, 3621 "cache": true, 3622 "pageCache": false, 3623 "timeout": GIGO.max_time, 3624 3625 "success": function (stuff) { 3626 jQuery("#survey").html("(Updated server side IPv6 readiness stats)"); 3627 }, 3628 "error": function (d, msg) { 3629 jQuery("#survey").html("(Survey posting failed; the above information is accurate, but not recorded.)" + " " + url); 3630 } 3631 }); 3632 3633}; 3634 3635GIGO.gen_help_link = function (token) { 3636 var page, title, code;
3637 // GIGO.gettext_messages.messages_popups has the urls and translated titles 3638 code = ""; 3639 if (GIGO.messages_popups.hasOwnProperty(token)) { 3640 page = GIGO.messages_popups[token][0]; 3641 title = GIGO.messages_popups[token][1]; 3642 code = "<a href='"+page+"' onclick=\"GIGO.help_popup('" + page + "','" + title + "'); return false;\" class=\"help_popup\">" + "[more info]" + "</a>"; 3643 } 3644 return code; 3645}; 3646 3647GIGO.testing_ipv4 = function () { 3648 var s; 3649 s = String(location.hostname); 3650 return (s.match(/ipv4/i) || s.match(/testv4/i) || s.match(/test-v4/i)); 3651}; 3652 3653 3654GIGO.show_results = function () { 3655 var tokens_hash, i, table, token_expanded, help, s4, s6, sid4, sid6; 3656 3657 3658 3659 // GIGO.dumpObj(this); // requires popups enabled 3660 // Check for some specific issues; and possibly either show 3661 // extra content panels (already in the HTML) and/or 3662 // highlight our contact form. 3663 tokens_hash = GIGO.oc(GIGO.results.tokens); 3664 if (tokens_hash.hasOwnProperty("Unliklely")) { 3665 GIGO.contact_wanted = 1; 3666 jQuery("#help_plugins").show(); // Encourage more feedback. 3667 } 3668 if (tokens_hash.hasOwnProperty("confused:ASK")) { 3669 if (MirrorConfig.options.comment) { 3670 GIGO.contact_wanted = 1; 3671 jQuery("#help_plugins").show(); // Encourage more feedback. 3672 } 3673 } 3674 if (tokens_hash.hasOwnProperty("webfilter:dsboth")) { 3675 jQuery("#help_plugins").show(); // Less encouraging of soliciting comments on this one. 3676 } 3677 if (tokens_hash.hasOwnProperty("webfilter:blocked")) { 3678 jQuery("#help_plugins").show(); // Less encouraging of soliciting comments on this one. 3679 } 3680 3681 GIGO.check_versions(); // Check OS, Browser, etc 3682 // Show the results to the user 3683 for (i = 0; i < GIGO.results.tokens_expanded.length; i = i + 1) { 3684 token_expanded = GIGO.results.tokens_expanded[i]; 3685 if (token_expanded.text !== "-") { 3686 3687 help = GIGO.gen_help_link(token_expanded.token); 3688 if (help) { 3689 token_expanded.text = token_expanded.text + " " + help; 3690 } 3691 3692 // token_expanded.token 3693 // token_expanded.color 3694 // token_expanded.text 3695 3696 table = GIGO.results_table_wrapper(token_expanded.color, token_expanded.text); 3697 jQuery("#results_eof").before(table); 3698 } 3699 } 3700 console.log("GIGO.results.tokens=%o",GIGO.results.tokens); 3701 3702 3703 3704 // Show summary table. TODO: Make this even simpler for people. 3705 s4 = " " + GIGO.results.score_transition + "/10"; 3706 sid4 = "score" + GIGO.results.score_transition; 3707 s6 = " " + GIGO.results.score_strict + "/10"; 3708 sid6 = "score" + GIGO.results.score_strict; 3709 3710 if (GIGO.results.score_transition === -1) { 3711 s4 = "n/a"; 3712 sid4 = "score0"; 3713 } 3714 if (GIGO.results.score_strict === -1) { 3715 s6 = "n/a"; 3716 sid6 = "score0"; 3717 } 3718 3719 table = "<div id=\"debugtable\"><table width=100%><tr><th colspan=2>" + "Your readiness score" + "</th></tr>"; 3720 if (GIGO.testing_ipv4(GIGO.results.score_transition)) { 3721 table += "<tr><td><span id=" + sid4 + ">" + s4 + "</span></td><td>" + "for your IPv4 stability and readiness, when publishers offer both IPv4 and IPv6" + "</td></tr>"; 3722 } 3723 table += "<tr><td><span id=" + sid6 + ">" + s6 + "</span></td><td>" + "for your IPv6 stability and readiness, when publishers are forced to go IPv6 only" + "</td></tr>"; 3724 table += "</table></div>"; 3725 table += "<div class='next'><p>" + "Click to see" + " <a href=\"#\" class=\"tabbutton_tests\" onclick='return GIGO.tabnav(\"tests\")'>" + "Test Data" + "</a></p></div>"; 3726 jQuery("#results_eof").before(table); 3727 3728 3729 // Update specific fields in above table. 3730 jQuery("[name=score_transition]").val(GIGO.results.score_transition); 3731 jQuery("[name=score_strict]").val(GIGO.results.score_strict); 3732 3733 // 3734 // jQuery("#results_eof").before("<div class=\"small\">" + GIGO.results.tokens.join(",") + "</div>"); 3735 // 3736 3737 GIGO.show_faq_link(GIGO.results.tokens); 3738 3739 if ((GIGO.results.score_transition === "?") || (GIGO.results.score_transition > 10) || (GIGO.contact_wanted)) { 3740 // I really want to talk to them. 3741 if (MirrorConfig.options.comment) { 3742 // But not if they are from places with known problems. 3743 // China 3744 if (!GIGO.isUnreliable()) { 3745 GIGO.showform(); 3746 } 3747 } 3748 } 3749}; 3750 3751GIGO.show_faq_link = function (tokens) { 3752 var html, faqs, page, title, linktext, m; 3753 3754 if (/ipv4_only/.test(tokens)) { 3755 page = "faq_ipv4_only.html"; 3756 } 3757 if (/broken/.test(tokens)) { 3758 page = "broken.html"; 3759 } 3760 3761console.log("show_faq_link: page=%o",page); 3762 3763 if (page) { 3764 jQuery("#comments_unwanted").hide(); 3765 jQuery("#comments_faq").show(); 3766 3767 title = "Your FAQ"; 3768 linktext = "Frequently Asked Questions"; 3769 3770 // handle = GIGO.help_popup(page, title, 0); // Don't auto-switch to this 3771 html = '<a href="#" onclick="return GIGO.help_popup(\'' + page + '\', \'' + title + '\');">' + linktext + '</a>'; 3772 3773 3774 m = jQuery("#comments_faq_link"); 3775 m.html(html); 3776 3777 } 3778}; 3779 3780 3781 3782 3783GIGO.help_popup = function (file, tabname, popup) { 3784 3785 var o, handle, t, hostname, lfile; 3786 if (popup === undefined) { 3787 popup = 1; 3788 } 3789 o = GIGO.newtab(file, tabname, popup); 3790 handle = "#tab_" + o.handle; 3791 3792 if (popup) { 3793 GIGO.tabnav(o.handle); 3794 } 3795 3796 if (!o.loaded) { 3797 o.loaded = 1; 3798 3799 // Because we are doing bad things with base hrefs, we must 3800 // force the help popups to show the original, user-entered 3801 // hostname (instead of the 'current server'); This is to 3802 // avoid cross-domain problems. 3803 file = GIGO.protocol + String(document.location.hostname) + "/" + file; 3804 lfile = file + '.en_US'; 3805 3806 3807 jQuery(handle).html("loading..."); // Loading indicator. 3808 jQuery(handle).load(lfile + " #content", function (responseText, textStatus) { 3809 if (textStatus !== 'success') { 3810 jQuery(handle).html("failed to load" + " " + lfile); 3811 } 3812 t = "<p>"; 3813 t = t + "<a href='#' onclick='return GIGO.goback()' class='goback'>"; 3814 t = t + "[go back]" + "</a> "; 3815 t = t + "<a target='_blank' href='" + file + "' class='permalink'>"; 3816 t = t + "[permalink]" + "</a> "; 3817 t = t + "</p>"; 3818 3819 jQuery(handle).append(t); 3820 }); 3821 if (!popup) { 3822 jQuery(handle).hide(); 3823 } 3824 } 3825 return (o.handle); 3826}; 3827 3828/*global GIGO, jQuery, alert, $gt, Browser, navigator */ 3829 3830GIGO.fix_version = function (underscored) { 3831 var t; 3832 t = underscored.replace(/_/g, "."); 3833 return t; 3834}; 3835 3836GIGO.zeropad = function (version) { 3837 // Take a version number like 4.10 and return back 00004.00010 3838 // Pad any sequence of digits to 10 points 3839 // So, for every matching set of \d+ 3840 // create new string 3841 // replace \b(original string)\b with new string 3842 var smallnumber, mymatch, mymatched, myindex, newstring, replace_re; 3843 3844 smallnumber = /\b(\d{1,9})\b/; 3845 while (smallnumber.test(version)) { 3846 mymatch = smallnumber.exec(version); 3847 mymatched = mymatch[0]; 3848 myindex = mymatch.index; 3849 3850 newstring = mymatched; 3851 while (newstring.length < 10) { 3852 newstring = "0" + newstring; 3853 } 3854 replace_re = new RegExp("\\b" + mymatched + "\\b"); 3855 version = version.replace(replace_re, newstring); 3856 } 3857 return version; 3858}; 3859 3860GIGO.check_version = function (appname, current, suggested) { 3861 var t, table, current_compare, suggested_compare; 3862 // Convert 10_6_7 to 10.6.7 before doing comparisons. 3863 if (current) { 3864 current = current.toString(); 3865 current = current.replace(/_/g, "."); 3866 suggested = suggested.replace(/_/g, "."); 3867 3868 current_compare = GIGO.zeropad(current); 3869 suggested_compare = GIGO.zeropad(suggested); 3870 3871 if (current_compare < suggested_compare) { 3872 t = "%app: You are running version %found; we recommend %suggest or newer."; 3873 t = t.replace(/%app/, appname); 3874 t = t.replace(/%found/, current); 3875 t = t.replace(/%suggest/, suggested); 3876 table = GIGO.results_table_wrapper("orange", t); 3877 jQuery("#results_eof").before(table); 3878 } 3879 } 3880}; 3881 3882GIGO.check_mac_os_version = function () { 3883 // Firefox will only return "10.6" not "10.6.7". 3884 // Safari and Chrome appear to do the right thing.
3885 if (navigator.userAgent.search(/(FireX|SilkX)/) < 0) { 3886 if (navigator.userAgent.search(/Intel Mac OS X ([0123456789]+[._][0123456789]+[._][0123456789]+)/) >= 0) { 3887 if (RegExp.$1) { 3888 GIGO.check_version("Mac OS X", RegExp.$1, "10.6.7"); 3889 } 3890 } else if (navigator.userAgent.search(/Intel Mac OS X ([0123456789]+[._][0123456789]+)/) >= 0) { 3891 if (RegExp.$1) { 3892 GIGO.check_version("Mac OS X", RegExp.$1, "10.6.7"); 3893 } 3894 } 3895 } 3896}; 3897 3898 3899 3900GIGO.check_browser_firefox = function () { 3901 if (Browser.firefox) { 3902 // Firefox only reports "4.0" not "4.0.1" 3903 if (Browser.Platform.mac) { 3904 GIGO.check_version("Firefox", Browser.version, "14"); 3905 } 3906 } 3907}; 3908 3909GIGO.check_browser_safari = function () { 3910 if (Browser.safari) { 3911 GIGO.check_version("Safari", Browser.version, "5.0.5"); 3912 } 3913}; 3914 3915GIGO.check_browser_opera = function () { 3916 if (Browser.opera) { 3917 // Browser.version for opera reports "11.1" not "11.10"
3918 if (navigator.userAgent.search(/Version\/([0-9.]+)$/) >= 0) { 3919 if (RegExp.$1) { 3920 GIGO.check_version("Opera", RegExp.$1, "11.10"); 3921 } 3922 } 3923 } 3924}; 3925 3926 3927GIGO.check_versions = function () { 3928 GIGO.check_mac_os_version(); 3929 GIGO.check_browser_firefox(); 3930 GIGO.check_browser_opera(); 3931}; 3932 3933/*global GIGO, jQuery, alert */ 3934/*jslint browser: true */ 3935/*jslint regexp: true */ 3936 3937GIGO.goback = function () { 3938 var prev; 3939 3940 // Remove the latest window from history. 3941 if (GIGO.tabhistory.length > 0) { 3942 GIGO.tabhistory.pop(); 3943 } 3944 3945 // Try and go to the window before that. 3946 if (GIGO.tabhistory.length > 0) { 3947 prev = GIGO.tabhistory.pop(); 3948 GIGO.tabnav(prev); 3949 } 3950 return false; 3951}; 3952 3953GIGO.extra_tabs = {}; 3954GIGO.newtab = function (which, title) { 3955 // INPUT: name of document or handle 3956 // INPUT: title to give tab 3957 // OUTPUT: object. object.handle = the name we should use. 3958 // can be altered later by other functions. 3959 // If the handle already exists, no new tab is created. 3960 // New tab is NOT made the foreground tab - use GIGO.tabnav 3961 var w, html, m; 3962 3963 3964 if (GIGO.extra_tabs.hasOwnProperty(which)) { 3965 return GIGO.extra_tabs[which]; 3966 } 3967 3968 3969 w = which.replace(/[^a-z0-9]/g, "_"); 3970 GIGO.extra_tabs[which] = { 3971 "original": which, 3972 "handle": w, 3973 "title": title 3974 }; 3975 3976 html = '<li><a href="#" class="tabbutton_' + w + '" onclick="return GIGO.tabnav(\'' + w + '\');">' + title + '</a></li>'; 3977 m = jQuery("ul#tabnavlist"); 3978 m.append(html); 3979 3980 //html = '<div id="tab_' + w + ' style="display:none"></div>'; 3981 html = '<div id="tab_' + w + '" ></div>'; 3982 3983 m = jQuery("div#tabbox_inside"); 3984 m.append(html); 3985 3986 3987 return (GIGO.extra_tabs[which]); 3988 3989}; 3990 3991GIGO.tabnav = function (which) { 3992 // "which" is which tab to show. 3993 var prev, i, m; 3994 prev = ""; 3995 3996 // Find out what the previous window was 3997 if (GIGO.tabhistory.length > 0) { 3998 prev = GIGO.tabhistory.pop(); 3999 GIGO.tabhistory.push(prev); 4000 } 4001 // Update the history, only if the previous window was different 4002 if (prev !== which) { 4003 GIGO.tabhistory.push(which); 4004 } 4005 4006 // Hide everything. 4007 jQuery("#tab_main").hide(); 4008 jQuery("#tab_tests").hide(); 4009 jQuery("#tab_tech").hide(); 4010 jQuery("#tab_stats").hide(); 4011 jQuery("#tab_helpdesk").hide(); 4012 jQuery("#tab_mail").hide(); 4013 jQuery("#tab_debug").hide(); 4014 jQuery("#tab_faq").hide(); 4015 jQuery("#tab_popup").hide(); 4016 jQuery("#tab_sites").hide(); 4017 4018 4019 // Remove any highlight attributes on tabs. 4020 jQuery("a.tabbutton_main").removeAttr("id"); 4021 jQuery("a.tabbutton_tests").removeAttr("id"); 4022 jQuery("a.tabbutton_tech").removeAttr("id"); 4023 jQuery("a.tabbutton_stats").removeAttr("id"); 4024 jQuery("a.tabbutton_helpdesk").removeAttr("id"); 4025 jQuery("a.tabbutton_mail").removeAttr("id"); 4026 jQuery("a.tabbutton_debug").removeAttr("id"); 4027 jQuery("a.tabbutton_faq").removeAttr("id"); 4028 jQuery("a.tabbutton_popup").removeAttr("id"); 4029 jQuery("a.tabbutton_sites").removeAttr("id"); 4030 4031 4032 // Same thing for all the extra tabs. TODO: Merge the above into just GIGO.extra_tabs or GIGO.tabs 4033 for (i in GIGO.extra_tabs) { 4034 if (GIGO.extra_tabs.hasOwnProperty(i)) { 4035 4036 m = jQuery("#tab_" + GIGO.extra_tabs[i].handle); 4037 m.hide(); 4038 4039 m = jQuery("a.tabbutton_" + GIGO.extra_tabs[i].handle); 4040 m.removeAttr("id"); 4041 } 4042 } 4043 4044 4045 // Re-highlight and show the desirable tab. 4046 jQuery("#tab_" + which).show(); 4047 jQuery("a.tabbutton_" + which).attr("id", "tabcurrent"); 4048 4049 // Possibly, really make the contact tab button stand out. 4050 if (GIGO.contact_wanted) { 4051 jQuery("a.tabbutton_mail").attr("id", "contactme"); 4052 } 4053 4054 return false; 4055 4056}; 4057 4058GIGO.tabnav_tests = function (which) { 4059 // Change detail of "tests" page 4060 GIGO.tabnav("tests"); 4061 jQuery("#tab_tests_simple").hide(); 4062 jQuery("#tab_tests_tech").hide(); 4063 jQuery("#tab_tests_" + which).show(); 4064 return false; 4065}; 4066 4067/*global GIGO */ 4068/*jslint maxlen: 100 */ 4069/* Stop bothering me about long lines */ 4070/*jslint sub: true */ 4071/* Stop bothering me about "foo"] */ 4072 4073// Scores: 4074// #1: Readiness for content providers to go IPv6 4075// #2: Readiness for content providers to give up IPv4 4076 4077// GREEN = success, green block with check mark 4078// RED = big caution symbol, red block 4079// BLUE = info symbol, blue block 4080// ORANGE = ? symbol 4081 4082// TEXT is now in source/text/text.en-us and similiar; to be compiled in at build time. 4083GIGO.scores = { 4084 "No Direct IP": [10, 10, "ORANGE"], 4085 "No Direct IPv4": [9, 10, "BLUE"], 4086 "No Direct IPv6": [10, 10, "BLUE"], 4087 "tls_warning": [10, 10, "BLUE"], 4088 "tls_beta": [10, 10, "BLUE"], 4089 "tls_available": [10, 10, "BLUE"], 4090 "6to4": [7, 7, "BLUE"], 4091 "teredo": [7, 7, "BLUE"], 4092 "teredo-v4pref": [10, 7, "BLUE"], 4093 "teredo-minimum": [10, 0, "BLUE"], 4094 "IPv6 MTU": [1, 1, "RED"], 4095 "confused:ASK": [0, 0, "ORANGE"], 4096 "confused:NOASK": [0, 0, "ORANGE"],
4097 "dualstack:ipv4_preferred": [10, 10, "GREEN"], 4098 "dualstack:ipv6_preferred": [10, 10, "GREEN"], 4099 "dualstack:slow": [7, 7, "BLUE"], 4100 "ipv4_only": [10, 0, "BLUE"], 4101 "ipv4_only:ds_good": [10, 0, "BLUE"], 4102 "ipv4_only:ds_slow": [5, 0, "RED"], 4103 "ipv4_only:ds_timeout": [5, 0, "RED"], 4104 "ipv4_slow": [5, 10, "RED"], 4105 "ipv6_only": [0, 10, "BLUE"], 4106 "ipv6_slow": [10, 5, "RED"], 4107 "ipv6_timeout": [10, 0, "RED"], 4108 "ipv6:nodns": [10, 0, "RED"], 4109 "broken_ipv6": [0, 0, "RED"], 4110 "webfilter:blocked": [-1, -1, "ORANGE"], 4111 "webfilter:dsboth": [10, 10, "ORANGE"], 4112 "webfilter:addons": [10, 10, "ORANGE"], 4113 "webfilter:firefox": [10, 10, "ORANGE"], 4114 "v6ns:ok": [10, 10, "GREEN"], 4115 "v6ns:bad": [10, 9, "BLUE"], 4116 "ip_timeout:firefox": [10, 10, "RED"], 4117 "confused:obbo": [10, 9, "BLUE"], 4118 "apple:dnsbug_aaaa": [10, 7, "BLUE"], 4119 "apple:dnsbug_ds": [10, 7, "BLUE"], 4120 "ipv4:no_address": [10, 10, "BLUE"], 4121 "ipv6:no_address": [10, 10, "RED"], 4122 "no_address": [10, 10, "RED"], 4123 "opera": [10, 10, "ORANGE"], 4124 "opera:turbo": [0, 0, "RED"], 4125 "dualstack:safe": [10, 10, "GREEN"], 4126 "needs_ipv6": [10, 10, "BLUE"], 4127 "dualstack:unsafe": [10, 10, "RED"], 4128 "dualstack:mtu": [10, 10, "RED"], 4129 "tunnel_dumb": [10, 10, "ORANGE"], 4130 "he_tunnel_dumb": [10, 10, "BLUE"], 4131 "tunnel_6rd_dumb": [10, 10, "BLUE"], 4132 "proxy_via": [10, 10, "ORANGE"], 4133 "proxy_via_dumb": [10, 10, "ORANGE"], 4134 "broken": [0, 0, "BLUE"], 4135 "avoids_ipv6": [10, 10, "ORANGE"], 4136 "ood": [10, 10, "RED"] 4137}; 4138 4139/*global GIGO, MirrorConfig, jQuery, alert, $gt */ 4140/*jslint nomen: true */ 4141 4142GIGO.form_setup_value = function (r) { 4143 var s; 4144 s = r.status + "," + r.time_ms / 1000.0; 4145 4146 if (r.ipinfo) { 4147 if (r.ipinfo.via) { 4148 s = s + " " + r.ipinfo.via; 4149 } 4150 } 4151 return s; 4152}; 4153 4154 4155GIGO.form_setup = function (tokens) { 4156 tokens = tokens.join(","); 4157 jQuery("[name=a]").val(GIGO.form_setup_value(GIGO.results.tests.test_a)); 4158 jQuery("[name=aaaa]").val(GIGO.form_setup_value(GIGO.results.tests.test_aaaa)); 4159 jQuery("[name=ds4]").val(GIGO.form_setup_value(GIGO.results.tests.test_ds4)); 4160 jQuery("[name=ds6]").val(GIGO.form_setup_value(GIGO.results.tests.test_ds6)); 4161 jQuery("[name=v6mtu]").val(GIGO.form_setup_value(GIGO.results.tests.test_v6mtu)); 4162 jQuery("[name=v6ns]").val(GIGO.form_setup_value(GIGO.results.tests.test_v6ns)); 4163 jQuery("[name=dsmtu]").val(GIGO.form_setup_value(GIGO.results.tests.test_dsmtu)); 4164 jQuery("[name=ip4]").val(GIGO.results.ipv4.ip); 4165 jQuery("[name=ip6]").val(GIGO.results.ipv6.ip); 4166 jQuery("[name=ip6subtype]").val(GIGO.results.ipv6.subtype); 4167 jQuery("[name=tokens]").val(tokens); 4168 4169 jQuery("[name=subdomain]").val(GIGO.mirrorconfig("site", "name")); 4170 4171 jQuery(".progress_bar").remove(); 4172 4173 jQuery("[name=form_tab_main]").val(jQuery("#tab_main_inside")[0].outerHTML); 4174 jQuery("[name=form_config]").val(JSON.encode(MirrorConfig)); 4175 jQuery("[name=form_results]").val(JSON.encode(GIGO.results)); 4176 jQuery("[name=form_replay]").val(GIGO.generate_share_link()); 4177 4178}; 4179 4180 4181GIGO.showform = function () { 4182 var msgs, share_text, share_link; 4183 4184 if (GIGO.isUnreliable()){ 4185 return; 4186 } 4187 4188 // Highlight the tab 4189 jQuery("a.tabbutton_mail").attr("id", "contactme"); 4190 GIGO.contact_wanted = 1; 4191 jQuery("#comments_wanted").show(); 4192 jQuery("#comments_unwanted").hide(); 4193 4194 jQuery("#contact_form").show(); 4195 jQuery("[name=purpose]").val("bug"); 4196 4197 share_text = "share your results"; 4198 share_link = "<a href='#' onclick='return GIGO.tabnav(\"mail\");'>%1</a>"; 4199 share_link = share_link.replace(/%1/, share_text); 4200 4201 msgs = "I am most interested in discussing your setup with you, because it was been determined that <B>your IPv6 connectivity is broken</b>, or at least not fully understood. This is not normal; would you be willing to %share?"; 4202 msgs = msgs.replace(/%share/, share_link); 4203 4204 msgs = "<div><p><span id='highlighter'>" + msgs + "</span></p></div>"; 4205 4206 jQuery("#results_eof").before(msgs); 4207 4208 // Add fields to the contact form 4209}; 4210 4211 4212GIGO.debuggercomments = function (thisform) { 4213 4214 var s = "[Debug info follows]\n" + GIGO._dumpObj(GIGO.results, ".", " ", 0); 4215 4216 GIGO.showform(); 4217 GIGO.tabnav("mail"); 4218 // "notes" for top box. "comments" for bottom box. 4219 jQuery("[name=notes]").val(s); 4220 return false;
4221}; 4222 4223 4224GIGO.validate_form = function (thisform) { 4225 4226 check = function (x) { 4227 try { 4228 return x.value.match(/\S/) 4229 } catch (e) { 4230 return false 4231 } 4232 } 4233 4234 // Nothing filled out? 4235 if (!( check(thisform.notes) || check(thisform.comments) || check(thisform.contact)) ) { 4236 thisform.notes.focus(); 4237 return false; 4238 } 4239 4240 if (!( $('#consent').prop('checked'))) { 4241 alert("Please consent to sharing your data."); 4242 thisform.consent.focus(); 4243 return false; 4244 } 4245 4246 if ((thisform.contact.value === null) || (thisform.contact.value === "")) { 4247 if (!GIGO.validate_form.asked) { 4248 GIGO.validate_form.asked = 1; 4249 alert("Note: I can\'t contact you, if the contact info is blank. If you really want to submit this anonymously, hit Send Results again."); 4250 thisform.contact.focus(); 4251 return false; 4252 } 4253 4254 } 4255 4256 4257 return true; 4258}; 4259GIGO.validate_form.asked = 0; 4260 4261GIGO.onchange_purpose = function (thisform) { 4262 4263 var e = document.getElementById("purpose"); 4264 var strUser = e.options[e.selectedIndex].value; 4265 4266 jQuery("div[id^=response]").hide(); 4267 jQuery("#contact_form").hide(); 4268 switch (strUser) { 4269 case "isp": 4270 jQuery("#response_isp").show(); 4271 break; 4272 4273 case "hacked": 4274 jQuery("#response_hacked").show(); 4275 break; 4276 4277 case "gfw": 4278 jQuery("#response_gfw").show(); 4279 break; 4280 4281 case "isp": 4282 jQuery("#response_isp").show(); 4283 break; 4284 4285 default: 4286 jQuery("#contact_form").show(); 4287 break; 4288 }; 4289 4290 4291 console.log("this is %o", strUser); 4292}; 4293 4294/*global GIGO jQuery */ 4295/*jslint browser: true */ 4296 4297 4298// Based on these variablse : status_a status_aaaa status_ds4 status_ds6 4299// which have values of ok, slow, bad, timeout (o,s,b,t) 4300// what is the primary diagnosis of the person's connectivity? 4301// Implemented as a table instead of a giant if/else (which was not terribly maintainable) 4302// confused:NOASK should ask the user to fill out the form; it will replace ASK with the initials 4303// of the status that was used to consult this table. From there a human can better 4304// attempt to classify that user's experience. 4305 4306GIGO.sym_primary = { 4307 "bbbb": "webfilter:blocked", 4308 "bbbo": "webfilter:blocked", 4309 "bbbs": "webfilter:blocked", 4310 "bbbt": "webfilter:blocked", 4311 "bbob": "webfilter:blocked", 4312 "bboo": "webfilter:blocked", 4313 "bbos": "webfilter:blocked", 4314 "bbot": "webfilter:blocked", 4315 "bbsb": "webfilter:blocked", 4316 "bbso": "webfilter:blocked", 4317 "bbss": "webfilter:blocked", 4318 "bbst": "webfilter:blocked", 4319 "bbtb": "webfilter:blocked", 4320 "bbto": "webfilter:blocked", 4321 "bbts": "webfilter:blocked", 4322 "bbtt": "webfilter:blocked", 4323 "bobb": "confused:NOASK", 4324 "bobo": "ipv6_only", 4325 "bobs": "ipv6_only", 4326 "bobt": "confused:NOASK", 4327 "boob": "confused:NOASK", 4328 "booo": "ipv6_only,webfilter:addons", 4329 "boos": "webfilter:dsboth", 4330 "boot": "confused:NOASK", 4331 "bosb": "confused:NOASK", 4332 "boso": "webfilter:dsboth", 4333 "boss": "ipv6_only,webfilter:addons", 4334 "bost": "confused:NOASK", 4335 "botb": "confused:NOASK", 4336 "boto": "confused:NOASK", 4337 "bots": "confused:NOASK", 4338 "bott": "confused:NOASK", 4339 "bsbb": "confused:NOASK", 4340 "bsbo": "ipv6_only", 4341 "bsbs": "ipv6_only", 4342 "bsbt": "confused:NOASK", 4343 "bsob": "confused:NOASK", 4344 "bsoo": "ipv6_only,ipv6_slow,webfilter:addons", 4345 "bsos": "webfilter:dsboth", 4346 "bsot": "confused:NOASK", 4347 "bssb": "confused:NOASK", 4348 "bsso": "webfilter:dsboth", 4349 "bsss": "ipv6_only,ipv6_slow,webfilter:addons", 4350 "bsst": "confused:NOASK", 4351 "bstb": "confused:NOASK", 4352 "bsto": "confused:NOASK", 4353 "bsts": "confused:NOASK", 4354 "bstt": "confused:NOASK", 4355 "btbb": "webfilter:blocked", 4356 "btbo": "webfilter:blocked", 4357 "btbs": "webfilter:blocked", 4358 "btbt": "webfilter:blocked", 4359 "btob": "webfilter:blocked", 4360 "btoo": "webfilter:blocked", 4361 "btos": "webfilter:blocked", 4362 "btot": "webfilter:blocked", 4363 "btsb": "webfilter:blocked", 4364 "btso": "webfilter:blocked", 4365 "btss": "webfilter:blocked", 4366 "btst": "webfilter:blocked", 4367 "bttb": "webfilter:blocked", 4368 "btto": "webfilter:blocked", 4369 "btts": "webfilter:blocked", 4370 "bttt": "webfilter:blocked", 4371 "obbb": "broken", 4372 "obbo": "confused:obbo", 4373 "obbs": "confused:obbs", 4374 "obbt": "confused:NOASK", 4375 "obob": "ipv4_only", 4376 "oboo": "ipv4_only,webfilter:addons", 4377 "obos": "webfilter:dsboth", 4378 "obot": "confused:NOASK", 4379 "obsb": "ipv4_only:ds_slow", 4380 "obso": "webfilter:dsboth", 4381 "obss": "ipv4_only,webfilter:addons", 4382 "obst": "confused:NOASK",
4383 "obtb": "ipv4_only:ds_timeout", 4384 "obto": "confused:NOASK", 4385 "obts": "confused:NOASK", 4386 "obtt": "broken", 4387 "oobb": "confused:NOASK", 4388 "oobo": "dualstack:ipv6_preferred", 4389 "oobs": "confused:NOASK", 4390 "oobt": "confused:NOASK", 4391 "ooob": "dualstack:ipv4_preferred", 4392 "oooo": "dualstack:safe,webfilter:addons", 4393 "ooos": "webfilter:dsboth", 4394 "ooot": "dualstack:ipv4_preferred", 4395 "oosb": "dualstack:slow", 4396 "ooso": "webfilter:dsboth", 4397 "ooss": "dualstack:safe,webfilter:addons", 4398 "oost": "confused:NOASK", 4399 "ootb": "confused:NOASK", 4400 "ooto": "dualstack:ipv6_preferred", 4401 "oots": "confused:NOASK", 4402 "oott": "confused:NOASK", 4403 "osbb": "confused:NOASK", 4404 "osbo": "confused:NOASK", 4405 "osbs": "confused:NOASK", 4406 "osbt": "confused:NOASK", 4407 "osob": "dualstack:ipv4_preferred,ipv6_slow", 4408 "osoo": "dualstack:ipv4_prefered,webfilter:addons", 4409 "osos": "webfilter:dsboth", 4410 "osot": "confused:NOASK", 4411 "ossb": "dualstack:ipv4_preferred,ipv6_slow", 4412 "osso": "webfilter:dsboth", 4413 "osss": "dualstack:ipv4_prefered,webfilter:addons", 4414 "osst": "confused:NOASK", 4415 "ostb": "confused:NOASK", 4416 "osto": "confused:NOASK", 4417 "osts": "confused:NOASK", 4418 "ostt": "confused:NOASK", 4419 "otbb": "broken", 4420 "otbo": "confused:NOASK", 4421 "otbs": "confused:NOASK", 4422 "otbt": "broken", 4423 "otob": "ipv4_only:ds_good,ipv6_timeout", 4424 "otoo": "ipv4_only,webfilter:addons", 4425 "otos": "webfilter:dsboth", 4426 "otot": "confused:NOASK", 4427 "otsb": "ipv4_only:ds_slow,ipv6_timeout", 4428 "otso": "webfilter:dsboth", 4429 "otss": "ipv4_only,webfilter:addons", 4430 "otst": "confused:NOASK", 4431 "ottb": "broken", 4432 "otto": "confused:NOASK", 4433 "otts": "confused:NOASK", 4434 "ottt": "broken", // symptoms.js will overrule this 4435 "sbbb": "confused:NOASK", 4436 "sbbo": "confused:NOASK", 4437 "sbbs": "confused:NOASK", 4438 "sbbt": "confused:NOASK", 4439 "sbob": "ipv4_only,ipv4_slow", 4440 "sboo": "ipv4_only,webfilter:addons", 4441 "sbos": "webfilter:dsboth", 4442 "sbot": "confused:NOASK", 4443 "sbsb": "ipv4_only,ipv4_slow", 4444 "sbso": "webfilter:dsboth", 4445 "sbss": "ipv4_only,webfilter:addons", 4446 "sbst": "confused:NOASK", 4447 "sbtb": "confused:NOASK", 4448 "sbto": "confused:NOASK", 4449 "sbts": "confused:NOASK", 4450 "sbtt": "confused:NOASK", 4451 "sobb": "dualstack:ipv4_preferred,ipv4_slow",
4452 "sobo": "confused:NOASK", 4453 "sobs": "confused:NOASK", 4454 "sobt": "confused:NOASK", 4455 "soob": "dualstack:ipv4_preferred,ipv4_slow", 4456 "sooo": "dualstack_ipv6_preferred,ipv4_slow,webfilter:addons", 4457 "soos": "webfilter:dsboth", 4458 "soot": "confused:NOASK", 4459 "sosb": "dualstack:ipv4_preferred,ipv4_slow", 4460 "soso": "webfilter:dsboth", 4461 "soss": "dualstack_ipv6_preferred,ipv4_slow,webfilter:addons", 4462 "sost": "confused:NOASK", 4463 "sotb": "confused:NOASK", 4464 "soto": "confused:NOASK", 4465 "sots": "confused:NOASK", 4466 "sott": "confused:NOASK", 4467 "ssbb": "confused:NOASK", 4468 "ssbo": "confused:NOASK", 4469 "ssbs": "confused:NOASK", 4470 "ssbt": "confused:NOASK", 4471 "ssob": "confused:NOASK", 4472 "ssoo": "dualstack,ipv4_slow,ipv6_slow,webfilter:addons", 4473 "ssos": "webfilter:dsboth", 4474 "ssot": "confused:NOASK", 4475 "sssb": "dualstack:ipv4_preferred,ipv4_slow,ipv6_slow", 4476 "ssso": "webfilter:dsboth", 4477 "ssss": "dualstack,ipv4_slow,ipv6_slow,webfilter:addons", 4478 "ssst": "confused:NOASK", 4479 "sstb": "confused:NOASK", 4480 "ssto": "confused:NOASK", 4481 "ssts": "confused:NOASK", 4482 "sstt": "confused:NOASK", 4483 "stbb": "confused:NOASK", 4484 "stbo": "confused:NOASK", 4485 "stbs": "confused:NOASK", 4486 "stbt": "confused:NOASK", 4487 "stob": "ipv4_only:ds_good,ipv6_timeout", 4488 "stoo": "ipv4_only:ds_good,webfilter:addons", 4489 "stos": "webfilter:dsboth", 4490 "stot": "confused:NOASK", 4491 "stsb": "ipv4_only:ds_slow,ipv6_timeout", 4492 "stso": "webfilter:dsboth", 4493 "stss": "ipv4_only:ds_good,webfilter:addons", 4494 "stst": "confused:NOASK", 4495 "sttb": "confused:NOASK", 4496 "stto": "confused:NOASK", 4497 "stts": "confused:NOASK", 4498 "sttt": "confused:NOASK", 4499 "tbbb": "webfilter:blocked", 4500 "tbbo": "webfilter:blocked", 4501 "tbbs": "webfilter:blocked", 4502 "tbbt": "webfilter:blocked", 4503 "tbob": "webfilter:blocked", 4504 "tboo": "webfilter:blocked", 4505 "tbos": "webfilter:blocked", 4506 "tbot": "webfilter:blocked", 4507 "tbsb": "webfilter:blocked", 4508 "tbso": "webfilter:blocked", 4509 "tbss": "webfilter:blocked", 4510 "tbst": "webfilter:blocked", 4511 "tbtb": "webfilter:blocked", 4512 "tbto": "webfilter:blocked", 4513 "tbts": "webfilter:blocked", 4514 "tbtt": "webfilter:blocked", 4515 "tobb": "confused:NOASK", 4516 "tobo": "ipv6_only", 4517 "tobs": "confused:NOASK", 4518 "tobt": "confused:NOASK", 4519 "toob": "confused:NOASK", 4520 "tooo": "ipv6_only,webfilter:both", 4521 "toos": "webfilter:dsboth", 4522 "toot": "confused:NOASK", 4523 "tosb": "confused:NOASK", 4524 "toso": "webfilter:dsboth", 4525 "toss": "ipv6_only,webfilter:both", 4526 "tost": "confused:NOASK", 4527 "totb": "confused:NOASK", 4528 "toto": "confused:NOASK", 4529 "tots": "confused:NOASK", 4530 "tott": "confused:NOASK", 4531 "tsbb": "confused:NOASK", 4532 "tsbo": "confused:NOASK", 4533 "tsbs": "confused:NOASK", 4534 "tsbt": "confused:NOASK", 4535 "tsob": "confused:NOASK", 4536 "tsoo": "ipv6_only,webfilter:addons", 4537 "tsos": "webfilter:dsboth", 4538 "tsot": "confused:NOASK", 4539 "tssb": "confused:NOASK", 4540 "tsso": "webfilter:dsboth", 4541 "tsss": "ipv6_only,webfilter:addons", 4542 "tsst": "confused:NOASK", 4543 "tstb": "confused:NOASK", 4544 "tsto": "confused:NOASK", 4545 "tsts": "confused:NOASK", 4546 "tstt": "confused:NOASK", 4547 "ttbb": "webfilter:blocked", 4548 "ttbo": "webfilter:blocked", 4549 "ttbs": "webfilter:blocked", 4550 "ttbt": "webfilter:blocked", 4551 "ttob": "webfilter:blocked",
4552 "ttoo": "webfilter:blocked", 4553 "ttos": "webfilter:blocked", 4554 "ttot": "webfilter:blocked", 4555 "ttsb": "webfilter:blocked", 4556 "ttso": "webfilter:blocked", 4557 "ttss": "webfilter:blocked", 4558 "ttst": "webfilter:blocked", 4559 "tttb": "webfilter:blocked", 4560 "ttto": "webfilter:blocked", 4561 "ttts": "webfilter:blocked", 4562 "tttt": "webfilter:blocked" 4563}; 4564 4565/*global GIGO jQuery */ 4566/*jslint browser: true */ 4567 4568// IPv4 by DNSS (values: ok or bad) 4569// IPV6 by DNS, and IPV6 type (global, 6[6to4], t[teredo],a[asn] 4570 4571GIGO.sym_helpdesk = { 4572 // +------ IPv4 by DNS (good,bad) 4573 // |:+--- IPv6 by DNS (good,bad) 4574 // |:|+-- IPv6 by IP6 TYPE (global, bad, teredo, 6to4, asn) 4575 // |:|| 4576 'g:gg': "Dual Stack", 4577 'g:gt': "IPv4 plus Teredo", 4578 'g:g6': "6to4", 4579 'g:ga': "Dual Stack, Possible Tunnel", 4580 'g:bg': "Dual Stack - but no Quad-A's (AAAA's)", 4581 'g:bb': "IPv4 Only", 4582 'g:bt': "IPv4 Only (Teredo Detected)", 4583 'g:b6': null, 4584 'g:ba': null, 4585 'g:tb': "IPv4, plus Broken IPv6", 4586 'b:gg': "IPv6 Only", 4587 'b:gt': null, 4588 'b:g6': null, 4589 'b:ga': null, 4590 'b:bg': null, 4591 'b:bb': null, 4592 'b:bt': null, 4593 'b:b6': null, 4594 'b:ba': null, 4595 'b:tb': null, 4596 4597}; 4598 4599GIGO.sym_helpdesk_qcode = { 4600 null: null, 4601 "Dual Stack": "46", 4602 "6to4": "624", 4603 "IPv4 Only": "4", 4604 "IPv4 Only (Teredo Detected)": "4", 4605 "IPv4, plus Broken IPv6": "112", 4606 "IPv6 Only": 6 4607 4608 // NO LONGER DETECTED: With HTTPS, we can't detect these things. 4609 // We're now seeing browsers forcing HTTPS. We're also seeing 4610 // the use of different ASNs for IPv6 vs IPv4. 4611 // 4612 // "IPv4 plus Teredo": "4t", 4613 // "Dual Stack, Possible Tunnel": "46t", 4614 // "NAT64": "64", 4615 // "NAT64, Possible Tunnel": "64t", 4616 4617}; 4618 4619// Input: an array. Returns: a "hash" (as best as javascript allows). 4620/*global GIGO, jQuery, alert, Browser, $gt */ 4621/*jslint browser: true */ 4622 4623 4624GIGO.oc = function (a) { 4625 var o, i; 4626 o = {}; 4627 for (i = 0; i < a.length; i = i + 1) { 4628 o[a[i]] = ''; 4629 } 4630 return o; 4631}; 4632 4633GIGO.isdef = function (x) { 4634 return (typeof x !== "undefined"); 4635}; 4636 4637 4638GIGO.cgistats = function (name) { 4639 var s, status, time_ms, id; 4640 id = "test_" + name; 4641 status = GIGO.results.tests[id].status; 4642 time_ms = GIGO.results.tests[id].time_ms; 4643 s = "&" + name + "=" + status + "," + time_ms; 4644 return s; 4645}; 4646 4647 4648 4649GIGO.expand_abbreviation = function (c) { 4650 if (c === "o") { 4651 return "ok"; 4652 } 4653 if (c === "b") { 4654 return "bad"; 4655 } 4656 if (c === "t") { 4657 return "timeout"; 4658 } 4659 if (c === "s") { 4660 return "slow"; 4661 } 4662 return "[" + "unknown expansion" + " " + c + "]"; 4663}; 4664 4665 4666GIGO.check_precheck = function () { 4667 // Dummy function at this time. 4668 // We could decide, based on something we saw, schedule further testing. 4669 return; 4670}; 4671 4672GIGO.check_results = function () { 4673 4674 var delta, mini_primary, mini_secondary, tokens, score_transition, score_strict, msgs, i, token, messages_plaintext, token_expanded, tokens_expanded; 4675 4676 tokens_expanded = []; 4677 GIGO.check_precheck(); 4678 if (GIGO.queue.length > 0) { 4679 return; // New tasks were added. 4680 } 4681 4682 4683 GIGO.show_debug(); 4684 GIGO.repeated = GIGO.repeated + 1; 4685 delta = GIGO.getms() - GIGO.start_time; 4686 4687 4688 // We *could* repeat the tests. This will be sure to get connection times 4689 // versus DNS times. However, I expect more bandwidth/hits from 4690 // the IPv6 Day announcement; lets try and do this only when it is worth 4691 // bothering. 4692 // In this case, lets do it only if one or more of our tests ran "slow". 4693 if ((GIGO.repeated <= GIGO.retry_min) || ((GIGO.repeated <= GIGO.retry_max) && (GIGO.delta < GIGO.retry_until))) { 4694 if ((GIGO.repeat_only_if_slow === 0) || (GIGO.ministates(["a", "aaaa", "ds4", "ds6", "v6mtu", "v6ns"]).match(/s/))) { 4695 GIGO.restart_tests(); // Minimum number of retries needed 4696 return; 4697 } 4698 } 4699 4700 GIGO.finished = 1; 4701 GIGO.update_progress(GIGO); 4702 GIGO.fix_comment_form_and_tab(); // Fix up the comments tab 4703 4704 4705 tokens = GIGO.identify_symptoms(); 4706 mini_primary = GIGO.ministates(["a", "aaaa", "ds4", "ds6"]); 4707 mini_secondary = GIGO.ministates([ "v6mtu", "v6ns"]); 4708 4709 4710 4711 score_transition = 100; 4712 score_strict = 100; 4713 msgs = ""; // HTML form of messages to give user 4714 messages_plaintext = []; // Array of plaintext in case some one prefers this format 4715 for (i = 0; i < tokens.length; i = i + 1) { 4716 token = tokens[i]; 4717 4718 4719 if (GIGO.isdef(GIGO.scores[token])) { 4720 token_expanded = {}; 4721 token_expanded.token = token; 4722 token_expanded.score_ipv4 = GIGO.scores[token][0]; 4723 token_expanded.score_ipv6 = GIGO.scores[token][1]; 4724 token_expanded.color = GIGO.scores[token][2]; 4725 token_expanded.text = GIGO.messages[token]; 4726 tokens_expanded.push(token_expanded); 4727 4728 4729 4730 4731 if (token_expanded.score_ipv4 <= score_transition) { 4732 score_transition = token_expanded.score_ipv4; 4733 } 4734 4735 if (token_expanded.score_ipv6 <= score_strict) { 4736 score_strict = token_expanded.score_ipv6; 4737 } 4738 4739 msgs = msgs + "<div><p>" + token_expanded.text + "</p></div>"; 4740 messages_plaintext.push(token_expanded.text); 4741 4742 4743 4744 4745 } else { 4746 token_expanded = {}; 4747 token_expanded.token = token; 4748 token_expanded.color = "YELLOW"; 4749 token_expanded.score_ipv4 = 10; 4750 token_expanded.score_ipv6 = 10; 4751 token_expanded.text = "(" + "unknown result code" + ": " + token + ")"; 4752 tokens_expanded.push(token_expanded); 4753 msgs = msgs + "<div><p>" + token_expanded.text + "</p></div>"; 4754 messages_plaintext.push(token_expanded.text); 4755 } 4756 } 4757 4758 4759 if (GIGO.oc(tokens).hasOwnProperty("confused:ASK")) { 4760 tokens.push("confused:" + mini_primary + ":" + mini_secondary); 4761 } 4762 4763 if (score_transition === 100) { 4764 score_transition = "?"; 4765 } 4766 if (score_strict === 100) { 4767 score_strict = "?"; 4768 } 4769 4770 if (score_strict > 7) { 4771 GIGO.start_sites(); // Check other sites for connections too. Starts a new on-page tab. 4772 } 4773 if (score_strict < 9) { 4774 GIGO.update_service_warning(); // China <-> rest of world is unreliable 4775 } 4776 4777 // Copy the results into a place that other people might find them 4778 // particularly if they just use the javascript and not the entire 4779 // test-ipv6.com site code 4780 // GIGO.results = {}; 4781 4782 GIGO.results.tokens = tokens; 4783 GIGO.results.score_transition = score_transition; 4784 GIGO.results.score_strict = score_strict; 4785 GIGO.results.divs = msgs; 4786 GIGO.results.messages_plaintext = messages_plaintext; 4787 GIGO.results.debug_code = mini_primary + ":" + mini_secondary; 4788 GIGO.results.tokens_expanded = tokens_expanded; 4789 4790 GIGO.show_debug(); 4791 GIGO.finish_helpdesk(); 4792 4793 4794 // Callbacks 4795 GIGO.fix_footer_late(); 4796 4797 GIGO.send_survey(tokens); 4798 GIGO.send_survey_global(tokens); 4799 GIGO.show_results(); 4800 GIGO.form_setup(tokens); 4801 GIGO.show_debug(); 4802 4803}; 4804 4805GIGO.isUnreliable = function() { 4806 var danger=false; 4807 try { 4808 if (GIGO.unreliable[ GIGO.results.tests.test_asn4.ipinfo.country ]) { 4809 danger=true; 4810 } 4811 } catch (e) { 4812 // noop 4813 } 4814 try { 4815 if (GIGO.unreliable[ GIGO.results.tests.test_asn6.ipinfo.country ]) { 4816 danger=true; 4817 } 4818 } catch (e) { 4819 // noop 4820 } 4821 return danger; 4822}; 4823 4824GIGO.update_service_warning = function () { 4825 if (GIGO.isUnreliable()) { 4826 s = "Tests using this web site are unreliable from your location."; 4827 table = GIGO.results_table_wrapper("orange",s); 4828 jQuery("#results_eof").before(table); 4829 } 4830 }; 4831 4832 4833 4834/*global GIGO, console, Browser */ 4835/*jslint browser: true */ 4836/* jshint undef: true, unused: true */ 4837/* jshint latedef: true */ 4838 4839 4840 4841/*jslint regexp: true */ 4842 4843/* Map equivalents of ASNs that arent really tunnels or distinct ISPS. 4844 First level: asn4 4845 Second level: asn6 4846 Third level: "1" 4847 */ 4848 4849GIGO.asn_same = { 4850 "comcast": [7922, 7853, 7757, 7725, 7016, 7015, 6161, 53297, 393232, 36733, 36732, 36377, 36196, 33668, 33667, 33666, 33665, 33664, 33663, 33662, 33661, 33660, 33659, 33658, 33657, 33656, 33655, 33654, 33653, 33652, 33651, 33650, 33542, 33491, 33490, 33489, 33287, 23266, 23253, 22909, 22258, 21508, 20214, 16748, 14668, 13385, 13367, 11025], 4851 "surewest": [14051], 4852 "aarnet": [757, 56132], 4853 "tmobile-usa": [21928, 22140], 4854 "att": [7132, 7018, 6389], 4855 "emirates": [8966, 5384], 4856 "sonic": [46375, 7065], 4857 "china-telecom-corp": [4134, 137691] 4858}; 4859 4860GIGO.asn_native = { 4861 668: 1, /* DREN, native non-tunnel provider */ 4862 24352: 1, /* CERNET2 */ 4863 "AR": 1, /* Argentina */ 4864 "AW": 1, 4865 "BZ": 1, 4866 "BO": 1, 4867 "BR": 1, 4868 "CL": 1, 4869 "CO": 1, 4870 "CR": 1, 4871 "CU": 1, 4872 "EC": 1, 4873 "GT": 1, 4874 "GY": 1, 4875 "GF": 1, 4876 "HT": 1, 4877 "HN": 1, 4878 "FK": 1, 4879 "MX": 1, 4880 "NI": 1, 4881 "PA": 1, 4882 "PY": 1, 4883 "PE": 1, 4884 "DO": 1, 4885 "MF": 1, 4886 "GS": 1, 4887 "SR": 1, 4888 "TT": 1, 4889 "UY": 1, 4890 "VE": 1 4891}; 4892 4893GIGO.unreliable = { 4894 "CN": 1, /* China */ 4895}; 4896 4897// Exceptions to the unreliable warning. 4898if (window.location.hostname.toLowerCase().endsWith(".cn")) { 4899 GIGO.unreliable["CN"]=0; 4900}; 4901 4902 4903GIGO.ministates = function (which) { 4904 var s, i, key, v, tests; 4905 4906 tests = GIGO.results.tests; // Convenience 4907 s = ""; // Build up return value 4908 for (i = 0; i < which.length; i = i + 1) { 4909 key = which[i]; 4910 try { 4911 v = GIGO.results.tests["test_" + key].status.charAt(0); 4912 if (GIGO.results.tests["test_" + key].status === "skipped") { 4913 v="x"; 4914 } 4915 } catch (e) { 4916 v = "?"; 4917 } 4918 s = s + v; 4919 } 4920 return s; 4921}; 4922 4923GIGO.find_evidence_of_noscript = function (tests, res) { 4924 var i, key_json, key_img, test_json, test_img, key, keys, blocked; 4925 keys = ["a", "aaaa", "ds", "v6mtu", "v6ns", "dsmtu"]; 4926 for (i = 0; i < keys.length; i = i + 1) { 4927 key = keys[i]; 4928 key_json = "test_" + key; 4929 key_img = "test_" + key + "_img"; 4930 if (tests.hasOwnProperty(key_img)) { 4931 test_json = tests[key_json].status; 4932 test_img = tests[key_img].status; 4933 if (test_img.match(/^[os]/)) { 4934 if (test_json.match(/^[bt]/)) { 4935 blocked = tests[key_json].url; 4936 //alert("test " + key + "was blocked by a browser add-on. Please configure your browser plugins (such as NoScript or AdBlock) to permit " + blocked + " and try this
4936site again."); 4937 res.push("webfilter:addons"); 4938 if (Browser.firefox) { 4939 res.push("webfilter:firefox"); 4940 } 4941 if (Browser.opera) { 4942 res.push("opera"); 4943 } 4944 res.push("webfilter:test_" + key); 4945 blocked = blocked.replace(/fill=xxxx*/, "fill=xxx...xxx"); // Obscene to show a nearly 2k url 4946 // Fake the gettext portion. We need to insert text into that dynamically based on local conditions. 4947 GIGO.messages["webfilter:test_" + key] = "Your browser blocked" + " " + blocked; 4948 4949 GIGO.scores["webfilter:test_" + key] = [10, 10, "ORANGE"]; 4950 4951 } 4952 } 4953 } 4954 } 4955 4956 4957}; 4958 4959GIGO.fallback_to_image_tests = function (tests, res) { 4960 // If the json was bad, but we have an image that worked, fudge it all. 4961 var keys, i, key, key_json, key_img, test_json, test_img; 4962 keys = ["a", "aaaa", "ds", "v6mtu", "v6ns", "dsmtu"]; 4963 for (i = 0; i < keys.length; i = i + 1) { 4964 key = keys[i]; 4965 key_json = "test_" + key; 4966 key_img = "test_" + key + "_img"; 4967 if (tests.hasOwnProperty(key_img)) { 4968 4969 test_json = tests[key_json].status; 4970 test_img = tests[key_img].status; 4971 if (test_img.match(/^[os]/)) { 4972 if (test_json.match(/^[bt]/)) { 4973 // Copy the IMAGE result data. 4974 tests["failed_" + key] = tests[key_json]; 4975 tests[key_json] = tests[key_img]; 4976 GIGO.update_status("test_" + key); 4977 GIGO.update_url("test_" + key); 4978 GIGO.show_debug(); 4979 4980 if (key === "ds") { 4981 tests.failed_test_ds4 = tests.test_ds4; 4982 tests.failed_test_ds6 = tests.test_ds6; 4983 tests.test_ds4 = tests.test_ds_img; 4984 tests.test_ds6 = tests.test_ds_img; 4985 GIGO.update_status("test_ds4"); 4986 GIGO.update_status("test_ds6"); 4987 GIGO.update_url("test_ds4"); 4988 GIGO.update_url("test_ds6"); 4989 GIGO.show_debug(); 4990 } 4991 4992 4993 } 4994 } 4995 } 4996 } 4997 4998 4999}; 5000 5001GIGO.dedupe_res = function (res) { 5002 var ret, unique, i; 5003 ret = []; 5004 unique = {}; 5005 if (res.length) { 5006 for (i = 0; i < res.length; i = i + 1) { 5007 if (!(unique).hasOwnProperty(res[i])) { 5008 ret.push(res[i]); 5009 unique[res[i]] = 1; 5010 } 5011 } 5012 } 5013 return ret; 5014}; 5015 5016 5017GIGO.ipinfo_in_tests = function (tests, name) { 5018 var keys, key, i; 5019 keys = ["a", "aaaa", "ds", "v6mtu", "v6ns", "dsmtu"]; 5020 for (i = 0; i < keys.length; i = i + 1) { 5021 key = "test_" + keys[i]; 5022 if (tests.hasOwnProperty(key)) { 5023 if (tests[key].hasOwnProperty("ipinfo")) { 5024 if (tests[key].ipinfo.hasOwnProperty(name)) { 5025 return tests[key].ipinfo[name]; 5026 } 5027 } 5028 } 5029 } 5030 return null; 5031}; 5032 5033GIGO.check6RD = function (addr4, addr6) { 5034 var i, bytes, addr4Bits, addr6Bits, chunk, index; 5035 5036 // Now process the IPv4 address by generating a string of 32 '0' or '1' based on the host address 5037 bytes = addr4.split('.'); 5038 addr4Bits = ''; 5039 for (i = 0; i < 4; i = i + 1) { 5040 chunk = parseInt(bytes[i], 10).toString(2); 5041 while (chunk.length < 8) 5042 chunk = '0' + chunk; 5043 addr4Bits = addr4Bits + chunk; 5044 } 5045 5046 // Now process the IPv6 address by generating a string of 64 '0' or '1' based on the /64 prefix 5047 bytes = addr6.split(':'); 5048 // We will however skip the first IPv6::/32 5049 addr6Bits = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; 5050 5051 // And include instead only the second //32 5052 for (i = 2; i < 4; i = i + 1) { 5053 chunk = parseInt(bytes[i], 16).toString(2); 5054 while (chunk.length < 16) 5055 chunk = '0' + chunk; 5056 addr6Bits = addr6Bits + chunk; 5057 } 5058 5059 // Now check whether full or at least 16 bits of the IPv4 is embedded into the IPv6 prefix 5060 while (addr4Bits.length >= 16) {
5061 index = addr6Bits.indexOf(addr4Bits); // Is part of the IPv4 address embedded in the /64 of IPv6? 5062 if (index >= 0) 5063 return addr4Bits.length + " bits of the IPv4 address are embedded in the IPv6 address starting at " + index; 5064 // Else, remove one leading bit of addr4 5065 addr4Bits = addr4Bits.substr(1, addr4Bits.length - 1); 5066 } 5067 return 0; 5068}; 5069 5070GIGO.identify_symptoms = function () { 5071 var tunnel_6rd, teredo, sixfour, mini_primary, mini_secondary, res, failed_pmtud, x, x_array, tests, via, alist, blist, ia, ib, a4, a6, k, i, r, f4, f6; 5072 5073 res = []; 5074 tests = GIGO.results.tests; // Convenience 5075 GIGO.find_evidence_of_noscript(tests, res); 5076 GIGO.fallback_to_image_tests(tests, res); // Hmm, we might use image connection data instead. 5077 5078 // HTTP proxies? 5079 via = GIGO.ipinfo_in_tests(tests, "via"); 5080 5081 // Tunnels? 5082 teredo = (GIGO.results.ipv6.subtype === "Teredo"); 5083 sixfour = (GIGO.results.ipv6.subtype === "6to4"); 5084 if (GIGO.results.ipv4.ip && GIGO.results.ipv6.ip) 5085 tunnel_6rd = GIGO.check6RD(GIGO.results.ipv4.ip, GIGO.results.ipv6.ip); 5086 else 5087 tunnel_6rd = 0; 5088 5089 GIGO.helpdesk.teredo = teredo; // save for later 5090 GIGO.helpdesk.sixfour = sixfour; // save for later 5091 5092 mini_primary = GIGO.ministates(["a", "aaaa", "ds4", "ds6"]); 5093 mini_secondary = GIGO.ministates([ "v6mtu", "v6ns"]); 5094 5095 mini_ood = GIGO.ministates(["ood"]) 5096 console.log("mini_ood %o", mini_ood); 5097 console.log("mini_secondary %o",mini_secondary); 5098 5099 GIGO.helpdesk.mini_primary = mini_primary; 5100 GIGO.helpdesk.mini_secondary = mini_secondary; 5101 5102 5103 // Out of date mirror flagged 5104 if (mini_ood.match(/^[os]/)) { 5105 res.push("ood") 5106 } 5107 5108 // alert("mini_primary " + mini_primary + " secondary " + mini_secondary); 5109 5110 console.log("res=%o",res); 5111 console.log("mini_primary=%o",mini_primary); 5112 5113 // Convert the JSON table entry to a series of initial elements 5114 x = GIGO.sym_primary[mini_primary]; 5115 x_array = x.split(","); 5116 5117 for (i = 0; i < x_array.length; i = i + 1) { 5118 res.push(x_array[i]); 5119 } 5120 5121 console.log("res=%o",res); 5122 5123 5124 5125 // IPv6 Flag Day - does DUAL STACK choke? 5126 // Only do this, if IPv4 appears to work, or IPv6 appears to work. 5127 // (Otherwise, some Firefox plugin is screwing us again.) 5128 if (tests.test_dsmtu.status === "ok") { 5129 // Do we want to encourage IPv6? Or acknowledge IPv6? 5130 if (teredo || sixfour || (!GIGO.results.ipv6.ip)) { 5131 // Encourage the use of IPv6 5132 res.push("needs_ipv6"); 5133 } else { 5134 // They have IPv6? Ah, nice. 5135 //res.unshift("dualstack:safe"); 5136 } 5137 } else { 5138 res.unshift("dualstack:unsafe"); 5139 } 5140 5141 5142 5143 if (via) { 5144 res.unshift("proxy_via_dumb"); 5145 } 5146 5147 5148 5149 // Do we have IP addresses? 5150 if ((!GIGO.results.ipv4.ip) && (!GIGO.results.ipv6.ip)) { 5151 res.unshift("no_address"); 5152 } else if (!GIGO.results.ipv4.ip) { 5153 res.unshift("ipv4:no_address"); 5154 } else if (!GIGO.results.ipv6.ip) { 5155 res.unshift("ipv6:no_address"); 5156 } 5157 5158 5159 // IPv4 preferred despite dual stack (and not teredo or fixfour) 5160 if ((!teredo) && (!sixfour)) { 5161 if ((GIGO.results.ipv4.ip) && (GIGO.results.ipv6.ip)) { 5162 if (mini_primary.match(/^[os][os][os][bt]/)) { 5163 res.unshift("avoids_ipv6"); 5164 } 5165 } 5166 } 5167 5168 if ((mini_primary.match(/o/)) && (mini_secondary.match(/^t/))) { 5169 // If at least a single name-based lookup worked, but all IP based ones were timeouts 5170 // both IPv4 and IPv6, then we more strongly suspect a filtering plugin. 5171 // RequestPolicy follows this pattern. 5172 if (Browser && Browser.Engine && Browser.Engine.gecko) { 5173 res.push("ip_timeout:firefox"); 5174 } 5175 // Specifically, those were TIMEOUTS 5176 } 5177 5178 // Other transition technologies 5179 if (teredo) { 5180 if (tests.test_aaaa.status === "bad") { 5181 res.push("teredo-minimum"); 5182 } else if (mini_primary.match(/^..[os]b/)) { 5183 // a aaaa ds4 ds6 5184 // If IPv4 is preferred, don't penalize the scores so hard. 5185 res.unshift("teredo-v4pref"); 5186 } else { 5187 res.push("teredo"); 5188 } 5189 } 5190 if (sixfour) { 5191 res.push("6to4"); 5192 } 5193 5194 5195 // What about IPv6 only DNS server 5196 if ((tests.test_ds4.status === "ok") || (tests.test_ds4.status === "slow") || (tests.test_ds6.status === "ok") || (tests.test_ds6.status === "slow")) { 5197 if ((tests.test_v6ns.status === "ok") || (tests.test_v6ns.status === "slow")) { 5198 res.push("v6ns:ok"); 5199 } else { 5200 res.push("v6ns:bad"); 5201 } 5202 } 5203 5204 5205 // Did our larger request work ok? 5206 if (Browser.opera) {
5207 // Opera always fails the 1600 byte test. WTF? 5208 if ((tests.test_aaaa.status === "ok") && ((tests.test_v6mtu.status === "timeout") || (tests.test_v6mtu.status === "slow"))) { 5209 res.push("IPv6 MTU"); // Uh oh, MTU problems. 5210 failed_pmtud = 1; 5211 } 5212 } else { 5213 if ((tests.test_aaaa.status === "ok") && ((tests.test_v6mtu.status === "bad") || (tests.test_v6mtu.status === "timeout") || (tests.test_v6mtu.status === "slow") || (tests.test_dsmtu.status === "bad") || (tests.test_dsmtu.status === "timeout") || (tests.test_dsmtu.status === "slow"))) { 5214 res.push("IPv6 MTU"); // Uh oh, MTU problems. 5215 failed_pmtud = 1; 5216 } 5217 } 5218 GIGO.helpdesk.failed_pmtud = failed_pmtud; 5219 5220 5221 for (i = 0; i < res.length; i += 1) { 5222 5223 if (failed_pmtud) { 5224 if (res[i] === "dualstack:safe") { 5225 res[i] = "dualstack:mtu"; 5226 } 5227 if (res[i] === "dualstack:unsafe") { 5228 res[i] = "dualstack:mtu"; 5229 } 5230 } 5231 5232 // Apple DNS bug. "A" record was fine. 5233 // Dual stack , for some reason, is bad. 5234 if (Browser.Platform.mac || Browser.Platform.ios) { 5235 if (res[i] === 'confused:obbo') { 5236 res[i] = "apple:dnsbug_aaaa"; // Failed to connect to AAAA but dual stack says it shoulda 5237 } 5238 if (res[i].match(/^confused/)) { 5239 if (mini_primary.match(/^obb[sob]/)) { 5240 res[i] = "apple:dnsbug_aaaa"; // Failed to connect to AAAA but dual stack says it shoulda 5241 } 5242 } 5243 } 5244 if (res[i].match(/^confused/)) { 5245 if ((mini_primary.match(/^ottt/)) && (mini_secondary.match(/^tt/))) { 5246 res[i] = "broken_ipv6"; 5247 } 5248 } 5249 5250 console.log("res[i]=%o",res[i]); 5251 5252 if (res[i].match(/^confused/)) { 5253 if (GIGO.isUnreliable()) { 5254 res[i]="confused:NOASK"; 5255 console.log("res[i] updated to %o",res[i]); 5256 } 5257 } 5258 } 5259 5260 if (res.length === 0) { 5261 res.push("Unknown"); 5262 } 5263 res = GIGO.dedupe_res(res); 5264 5265 console.log("score mini_primary=%o",mini_primary); 5266 console.log("score mini_secondary=%o",mini_secondary); 5267 console.log("score res=%o",res); 5268 5269 return res; 5270 5271}; 5272 5273/*global GIGO:true, jQuery, window, alert, Browser */ 5274/*jslint browser: true */ 5275 5276try { 5277 GIGO.tryme = 1; 5278} catch (e) { 5279 GIGO = {}; 5280} 5281 5282GIGO.hide_os_osx = function () { 5283 jQuery(".os_osx").hide(250); 5284}; 5285GIGO.hide_os_ios = function () { 5286 jQuery(".os_ios").hide(250); 5287}; 5288GIGO.hide_os_other = function () { 5289 jQuery(".os_other").hide(250); 5290}; 5291GIGO.hide_os_windows = function () { 5292 jQuery(".os_windows").hide(250); 5293}; 5294GIGO.hide_os_linux = function () { 5295 jQuery(".os_linux").hide(250); 5296}; 5297 5298GIGO.hide_os_all = function () { 5299 GIGO.hide_os_other(); 5300 GIGO.hide_os_osx(); 5301 GIGO.hide_os_ios(); 5302 GIGO.hide_os_windows(); 5303 GIGO.hide_os_linux(); 5304}; 5305 5306GIGO.show_os_osx = function () { 5307 jQuery(".os_osx").show(250); 5308}; 5309GIGO.show_os_ios = function () { 5310 jQuery(".os_ios").show(250); 5311}; 5312GIGO.show_os_windows = function () { 5313 jQuery(".os_windows").show(250); 5314}; 5315GIGO.show_os_linux = function () { 5316 jQuery(".os_linux").show(250); 5317}; 5318GIGO.show_os_other = function () { 5319 jQuery(".os_other").show(250); 5320}; 5321 5322GIGO.show_os_all = function () { 5323 GIGO.show_os_other(); 5324 GIGO.show_os_osx(); 5325 GIGO.show_os_ios(); 5326 GIGO.show_os_windows(); 5327 GIGO.show_os_linux(); 5328}; 5329 5330GIGO.show_os_only_osx = function () { 5331 GIGO.hide_os_all(); 5332 GIGO.show_os_osx(); 5333}; 5334GIGO.show_os_only_ios = function () { 5335 GIGO.hide_os_all(); 5336 GIGO.show_os_ios(); 5337}; 5338GIGO.show_os_only_windows = function () { 5339 GIGO.hide_os_all(); 5340 GIGO.show_os_windows(); 5341}; 5342GIGO.show_os_only_linux = function () { 5343 GIGO.hide_os_all(); 5344 GIGO.show_os_linux(); 5345}; 5346 5347GIGO.show_os_start = function () { 5348 if (Browser.Platform.mac) { 5349 GIGO.show_os_only_osx(); 5350 } else if (Browser.Platform.windows) { 5351 GIGO.show_os_only_windows(); 5352 } else if (Browser.Platform.linux) { 5353 GIGO.show_os_only_linux(); 5354 } else if (Browser.Platform.ios) {
5355 GIGO.show_os_only_ios(); 5356 } else { 5357 // Be aware we will show ALL platforms we know about. 5358 } 5359}; 5360 5361GIGO.sites_parsed={ 5362 "2.ayepv6.com": { 5363 "site": "ayepv6.com", 5364 "mirror": false, 5365 "hide": false, 5366 "v4": "https://v4.test-ipv6.vu.ayepv6.com/images/knob_green.png", 5367 "v6": "https://v6.test-ipv6.vu.ayepv6.com/images/knob_green.png", 5368 "loc": "UK", 5369 "provider": "Stephen Strowes (hosted at Vultr)", 5370 "monitor": "Stephen Strowes \[email protected]\u003e", 5371 "contact": "", 5372 "reason": "", 5373 "transparent": false 5374 }, 5375 "8n1.org": { 5376 "site": "8n1.org", 5377 "mirror": false, 5378 "hide": false, 5379 "v4": "https://ip4.8n1.org/test.gif", 5380 "v6": "https://ip6.8n1.org/test.gif", 5381 "loc": "NL", 5382 "provider": "8n1.org - a simple pastebin", 5383 "monitor": "Sander Smeenk \[email protected]\u003e", 5384 "contact": "", 5385 "reason": "", 5386 "transparent": false 5387 }, 5388 "ayepv6.com": { 5389 "site": "ayepv6.com", 5390 "mirror": false, 5391 "hide": false, 5392 "v4": "https://v4.test-ipv6.do.ayepv6.com/images/knob_green.png", 5393 "v6": "https://v6.test-ipv6.do.ayepv6.com/images/knob_green.png", 5394 "loc": "UK", 5395 "provider": "Stephen Strowes (hosted at Digital Ocean)", 5396 "monitor": "Stephen Strowes \[email protected]\u003e", 5397 "contact": "", 5398 "reason": "", 5399 "transparent": false 5400 }, 5401 "bvconline.com.ar": { 5402 "site": "bvconline.com.ar", 5403 "mirror": false, 5404 "hide": false, 5405 "v4": "http://ipv4.test-ipv6.bvconline.com.ar/knob_green.png", 5406 "v6": "http://ipv6.test-ipv6.bvconline.com.ar/knob_green.png", 5407 "loc": "AR", 5408 "provider": "BVNET S.A", 5409 "monitor": "Ariel Cuesta \[email protected]\u003e", 5410 "contact": "", 5411 "reason": "", 5412 "transparent": false 5413 }, 5414 "eurobilltracker.com": { 5415 "site": "eurobilltracker.com", 5416 "mirror": false, 5417 "hide": false,
5418 "v4": "https://ipv4-test-ipv6.eurobilltracker.com/img/1x1.gif", 5419 "v6": "https://ipv6-test-ipv6.eurobilltracker.com/img/1x1.gif", 5420 "loc": "FI", 5421 "provider": "EuroBillTracker", 5422 "monitor": "Anssi Johansson \[email protected]\u003e", 5423 "contact": "", 5424 "reason": "", 5425 "transparent": false 5426 }, 5427 "he.net": { 5428 "site": "he.net", 5429 "mirror": false, 5430 "hide": false, 5431 "v4": "https://ipv4.tunnelbroker.net/images/helogo.gif", 5432 "v6": "https://ipv6.tunnelbroker.net/images/helogo.gif", 5433 "loc": "US (CA)", 5434 "provider": "HE.net", 5435 "monitor": "Hurricane Electric \[email protected]\u003e", 5436 "contact": "Mike Tindle \[email protected]\u003e", 5437 "reason": "", 5438 "transparent": false 5439 }, 5440 "jamieweb.net": { 5441 "site": "jamieweb.net", 5442 "mirror": false, 5443 "hide": false, 5444 "v4": "https://ipv4.jamieweb.net/ipv4-only.png", 5445 "v6": "https://ipv6.jamieweb.net/ipv6-only.png", 5446 "loc": "UK", 5447 "provider": "Jamie Scaife (JamieWeb)", 5448 "monitor": "Jamie Scaife \[email protected]\u003e", 5449 "contact": "", 5450 "reason": "", 5451 "transparent": false 5452 }, 5453 "mudgee.host": { 5454 "site": "mudgee.host", 5455 "mirror": false, 5456 "hide": false, 5457 "v4": "https://ipv4.mudgee.host/logo.png", 5458 "v6": "https://ipv6.mudgee.host/logo.png", 5459 "loc": "AU", 5460 "provider": "Mudgee Host", 5461 "monitor": "Fraser Stuart \[email protected]\u003e", 5462 "contact": "", 5463 "reason": "", 5464 "transparent": false 5465 }, 5466 "nic.br": { 5467 "site": "nic.br", 5468 "mirror": false, 5469 "hide": false, 5470 "v4": "https://v4.ipv6.br/img/logo-ipv6.png", 5471 "v6": "https://v6.ipv6.br/img/logo-ipv6.png", 5472 "loc": "BR", 5473 "provider": "NIC.br", 5474 "monitor": "Antonio M. Moreiras \[email protected]\u003e", 5475 "contact": "", 5476 "reason": "", 5477 "transparent": false 5478 }, 5479 "nsx.de": { 5480 "site": "nsx.de", 5481 "mirror": false, 5482 "hide": false, 5483 "v4": "https://ipv4.nsx.de/images/knob_valid_green.png", 5484 "v6": "https://ipv6.nsx.de/images/knob_valid_green.png", 5485 "loc": "DE", 5486 "provider": "Stephan Fiebrandt (personal)", 5487 "monitor": "Stephan Fiebrandt \[email protected]\u003e", 5488 "contact": "", 5489 "reason": "", 5490 "transparent": false 5491 }, 5492 "salesianimestre.it": { 5493 "site": "salesianimestre.it", 5494 "mirror": false, 5495 "hide": false, 5496 "v4": "https://ipv4.salesianimestre.it/check.png", 5497 "v6": "https://ipv6.salesianimestre.it/check.png", 5498 "loc": "IT", 5499 "provider": "Salesiani Don Bosco Mestre", 5500 "monitor": "Vittore Zen \[email protected]\u003e", 5501 "contact": "", 5502 "reason": "", 5503 "transparent": false 5504 }, 5505 "stdio.be": { 5506 "site": "stdio.be", 5507 "mirror": false, 5508 "hide": false, 5509 "v4": "http://ipv4.stdio.be/images/knob_valid_green.png", 5510 "v6": "http://ipv6.stdio.be/images/knob_valid_green.png", 5511 "loc": "DE", 5512 "provider": "Andrew Yourtchenko (personal)", 5513 "monitor": "Andrew Yourtchenko \[email protected]\u003e", 5514 "contact": "", 5515 "reason": "", 5516 "transparent": false 5517 }, 5518 "test-ipv6.cgates.lt": { 5519 "site": "test-ipv6.cgates.lt", 5520 "mirror": false, 5521 "hide": false, 5522 "v4": "http://ipv4.test-ipv6.cgates.lt/images-nc/knob_green.png", 5523 "v6": "http://ipv6.test-ipv6.cgates.lt/images-nc/knob_green.png", 5524 "loc": "LT", 5525 "provider": "Cgates", 5526 "monitor": "Marius Sokas \[email protected]\u003e", 5527 "contact": "", 5528 "reason": "", 5529 "transparent": false 5530 }, 5531 "www.cidercounty.org.uk": { 5532 "site": "www.cidercounty.org.uk", 5533 "mirror": false, 5534 "hide": false, 5535 "v4": "https://ipv4.cidercounty.org.uk/images/happy_face.gif", 5536 "v6": "https://ipv6.cidercounty.org.uk/images/happy_face.gif", 5537 "loc": "UK", 5538 "provider": "Allen Coates (hosted at A\u0026A)", 5539 "monitor": "Allen Coates \[email protected]\u003e", 5540 "contact": "", 5541 "reason": "", 5542 "transparent": false 5543 }, 5544 "www.excathedra.co": { 5545 "site": "www.excathedra.co", 5546 "mirror": false, 5547 "hide": false, 5548 "v4": "https://ipv4.excathedra.co/knob_valid_green.png", 5549 "v6": "https://ipv6.excathedra.co/knob_valid_green.png", 5550 "loc": "UK", 5551 "provider": "Ex Cathedra Photography", 5552 "monitor": "Steve Durbin \[email protected]\u003e", 5553 "contact": "", 5554 "reason": "", 5555 "transparent": false 5556 }, 5557 "www.joram.it": { 5558 "site": "www.joram.it", 5559 "mirror": false, 5560 "hide": false, 5561 "v4": "https://ipv4.joram.it/oggetti/immagini/ipv4.png", 5562 "v6": "https://ipv6.joram.it/oggetti/immagini/ipv6.jpg", 5563 "loc": "IT", 5564 "provider": "Joram.IT", 5565 "monitor": "Servizio Partners - Joram.IT \[email protected]\u003e", 5566 "contact": "", 5567 "reason": "", 5568 "transparent": false 5569 }, 5570 "www.netflash.com.cy": { 5571 "site": "www.netflash.com.cy", 5572 "mirror": false, 5573 "hide": false,
5574 "v4": "https://ipv4-test.netflash.com.cy/knob_green.png", 5575 "v6": "https://ipv6-test.netflash.com.cy/knob_green.png", 5576 "loc": "CY", 5577 "provider": "A.C. NetFlash Technologies Ltd", 5578 "monitor": "[email protected]", 5579 "contact": "", 5580 "reason": "", 5581 "transparent": false 5582 }, 5583 "www.nop.hu": { 5584 "site": "www.nop.hu", 5585 "mirror": false, 5586 "hide": false, 5587 "v4": "http://ipv4.nop.hu/hosted.png", 5588 "v6": "http://ipv6.nop.hu/hosted.png", 5589 "loc": "HU", 5590 "provider": "nop.hu", 5591 "monitor": "matecs \[email protected]\u003e", 5592 "contact": "", 5593 "reason": "", 5594 "transparent": false 5595 }, 5596 "www.steffann.nl": { 5597 "site": "www.steffann.nl", 5598 "mirror": false, 5599 "hide": false, 5600 "v4": "https://v4-only.steffann.nl/v4-only.png", 5601 "v6": "https://v6-only.steffann.nl/v6-only.png", 5602 "loc": "NL", 5603 "provider": "SJM Steffann Consultancy", 5604 "monitor": "Sander Steffann \[email protected]\u003e", 5605 "contact": "", 5606 "reason": "", 5607 "transparent": false 5608 } 5609}; 5610/*global GIGO, jQuery, $, window, alert, Browser */ 5611/*jslint browser: true */ 5612 5613 5614/* Need to vary this a bit. 5615 5616Each host should: 5617 5618 try IPv4. 5619 try IPv4 again, if needed. 5620 On success, 5621 5622 try IPv6. 5623 try IPv6 again, if needed. 5624 5625The icky part is the "if needed". 5626 5627*/ 5628 5629 5630 5631GIGO.url_to_hash = function (url) { 5632 var hash; 5633 url = url.replace(/\?nocache.*$/, ""); 5634 hash = jQuery.md5(url); 5635 hash = hash.replace(/[^a-zA-Z0-9]/g, ''); 5636 hash = hash.substring(0, 4); 5637 return hash; 5638}; 5639 5640GIGO.fail_url = function (url) { 5641 var hash = GIGO.url_to_hash(url); 5642 5643 5644 // Create object, if needed. 5645 if (!GIGO.isdef(GIGO.failed_sites)) { 5646 GIGO.failed_sites = []; 5647 } 5648 5649 // Add hash, but only if not already found 5650 if (GIGO.failed_sites.indexOf(hash) < 0) { 5651 GIGO.failed_sites.push(hash); 5652 } 5653 GIGO.show_share_link(); 5654}; 5655 5656GIGO.was_failed_url = function (url) { 5657 var hash = GIGO.url_to_hash(url); 5658 if (!GIGO.isdef(GIGO.failed_sites)) { 5659 if (GIGO.isdef(GIGO.CGI.failed_sites)) { 5660 GIGO.failed_sites = GIGO.CGI.failed_sites.split(","); 5661 } else { 5662 GIGO.failed_sites = []; 5663 } 5664 } 5665 return (GIGO.failed_sites.indexOf(hash) >= 0); 5666}; 5667 5668 5669GIGO.is_replay = function () { 5670 return (GIGO.CGI.ip4 || GIGO.CGI.ip6); 5671}; 5672 5673 5674 5675GIGO.sites_table_init_1 = function (mode) { 5676 // Create a table, replace #sitestablediv 5677 // THIS IS FOR MIRRORS 5678 var newhtml; 5679 newhtml = '<div id="sitestablediv">'; 5680 newhtml = newhtml + '<table summary="sites" id="sites" class="tablesorter">'; 5681 newhtml = newhtml + "<thead><tr><th>link</th><th>location</th><th>provider</th><th>ipv6?</th><th>info</th></tr></thead>"; 5682 newhtml = newhtml + "<tbody>"; 5683 newhtml = newhtml + "</tbody></table>"; 5684 newhtml = newhtml + "</div>"; 5685 5686 // Make a table, keep the reference? 5687 jQuery("#sitestablediv").replaceWith($('<div>').html(newhtml)); 5688}; 5689 5690GIGO.sites_table_init_2 = function (mode) { 5691 // Create a table, replace #sitestablediv 5692 // THIS IS FOR MIRRORS+SITES, NO LANGUAGE INFO ETC 5693 var newhtml; 5694 newhtml = '<div id="sitestablediv">'; 5695 newhtml = newhtml + '<table summary="sites" id="sites" class="tablesorter">'; 5696 newhtml = newhtml + "<thead><tr><th>link</th><th>location</th><th>provider</th><th>ipv6?</th><th>info</th><th>mirror</th></tr></thead>"; 5697 newhtml = newhtml + "<tbody>"; 5698 newhtml = newhtml + "</tbody></table>"; 5699 newhtml = newhtml + "</div>"; 5700 5701 // Make a table, keep the reference? 5702 jQuery("#sitestablediv").replaceWith($('<div>').html(newhtml)); 5703}; 5704 5705GIGO.sites_table_init = function (mode) { 5706 if (mode === 1) { 5707 GIGO.sites_table_init_1(mode); 5708 } else if (mode === 2) { 5709 GIGO.sites_table_init_2(mode); 5710 } else { 5711 alert("bad GIGO.sites_table_init()"); 5712 } 5713}; 5714 5715 5716GIGO.sites_table_populate_1 = function (mode) { 5717 var i; 5718 for (i = 0; i < GIGO.sites_queue.length; i = i + 1) { 5719 GIGO.sites_display_add_record(GIGO.sites_queue[i], mode); 5720 } 5721 5722 5723 $("#sites").tablesorter({ 5724 textExtraction: "complex", 5725 sortInitialOrder: "asc", 5726 headers: { 5727 0: { 5728 sorter: "text" 5729 }, 5730 1: { 5731 sorter: "text" 5732 }, 5733 2: { 5734 sorter: "text" 5735 }, 5736 3: { 5737 sorter: "text" 5738 }, 5739 4: { 5740 sorter: "text" 5741 }, 5742 5: { 5743 sorter: false 5744 }, 5745 6: { 5746 sorter: false 5747 } 5748 } 5749 }); 5750 5751}; 5752 5753GIGO.sites_table_populate_2 = function (mode) { 5754 var i; 5755 for (i = 0; i < GIGO.sites_queue.length; i = i + 1) { 5756 GIGO.sites_display_add_record(GIGO.sites_queue[i], mode); 5757 } 5758 5759 5760 $("#sites").tablesorter({ 5761 textExtraction: "complex", 5762 sortInitialOrder: "asc", 5763 headers: { 5764 0: { 5765 sorter: "text" 5766 }, 5767 1: { 5768 sorter: "text" 5769 }, 5770 2: { 5771 sorter: "text" 5772 }, 5773 3: { 5774 sorter: false 5775 }, 5776 4: { 5777 sorter: false 5778 } 5779 } 5780 }); 5781 5782}; 5783 5784GIGO.sites_table_populate = function (mode) { 5785 if (mode === 1) { 5786 GIGO.sites_table_populate_1(mode); 5787 } else if (mode === 2) { 5788 GIGO.sites_table_populate_2(mode); 5789 } else { 5790 alert("bad GIGO.sites_table_populate()"); 5791 } 5792}; 5793 5794 5795 5796GIGO.sites_init = function () { 5797 GIGO.sites_queue = []; 5798}; 5799 5800GIGO.sites_queue_entry = function (r) { 5801 5802 if (!r.v4) {
5803 r.v4 = "http://ipv4." + r.site + "/images-nc/hires_ok.png"; 5804 } 5805 if (!r.v6) { 5806 r.v6 = "http://ipv6." + r.site + "/images-nc/hires_ok.png"; 5807 } 5808 5809 // Do we have a suitable protocol? 5810 // Shrink the list, if that is what it takes. 5811 if (GIGO.protocol==="https://") { 5812 // Be a bit more strict. 5813 if (!r.v4.startsWith("https://") || !r.v6.startsWith("https://")) { 5814 console.log("GIGO.sites_queue_entry skipping %o due to https",r); 5815 return; // When viewing as https, we require all images being tested also be https 5816 } 5817 } 5818 5819 5820 // Mark up r.v4 for site analytics 5821 if (r.v4.search(/\?/)<0) { 5822 r.v4 = r.v4 + "?"; 5823 } 5824 if (r.v6.search(/\?/)<0) { 5825 r.v6 = r.v6 + "?"; 5826 } 5827 5828 // This might actually fail; the mirrors page does 5829 // not load GIGO.options.domain . 5830 try { 5831 r.v4 = r.v4 + "&testdomain=" + GIGO.options.domain; 5832 r.v6 = r.v6 + "&testdomain=" + GIGO.options.domain; 5833 } catch (e) { 5834 r.v4 = r.v4 + "&testdomain=" + document.location.hostname; 5835 r.v6 = r.v6 + "&testdomain=" + document.location.hostname; 5836 } 5837 5838 r.v4 = r.v4 + "&testname=sites"; 5839 r.v6 = r.v6 + "&testname=sites"; 5840 5841 GIGO.sites_queue.push(r); 5842}; 5843 5844GIGO.sites_queue_all = function (mode) { 5845 var r, siteName; 5846 5847 console.log("in GIGO.sites_queue_all, GIGO.sites_parsed=%o",GIGO.sites_parsed); 5848 // mirrors only if mode=1 5849 // all sites if mode=2 5850 for (siteName in GIGO.sites_parsed) { 5851 r = GIGO.sites_parsed[siteName]; 5852 if (mode === 1) { 5853 if (! r.mirror) continue; 5854 } 5855 GIGO.sites_queue_entry(r); 5856 } 5857 5858}; 5859 5860GIGO.sites_prepare_helpdesk = function (mode) { 5861 GIGO.helpdesk.other_sites = {}; 5862 GIGO.helpdesk.other_sites.finished = 0; 5863 GIGO.helpdesk.other_sites.count = 0; 5864 GIGO.helpdesk.other_sites.good = []; 5865 GIGO.helpdesk.other_sites.bad = []; 5866 if (mode > 1) { 5867 GIGO.helpdesk.other_sites.count = GIGO.sites_queue.length; 5868 } 5869 5870}; 5871 5872GIGO.other_sites_info = function () { 5873 var g, b, f, c, o, text; 5874 g = GIGO.helpdesk.other_sites.good.length; 5875 b = GIGO.helpdesk.other_sites.bad.length; 5876 f = GIGO.helpdesk.other_sites.finished; 5877 c = GIGO.helpdesk.other_sites.count; 5878 o = g + b; 5879 text = ""; 5880 5881 if (!c) { 5882 return ""; 5883 } 5884 5885 if (f != c) { 5886 text = "(Global IPv6 connectivity being tested; " + f + "/" + c + ")"; 5887 // text = text + "b=" + b + " g=" + g + " f=" + f + " c=" + c + " o=" + o + ""; 5888 return text; 5889 } 5890 5891
5892 text = "OtherSites: " + g + "/" + o + " good"; 5893 if (b) { 5894 text = text + ", " + b + "/" + o + " bad"; 5895 } 5896 5897 5898 return text; 5899}; 5900 5901GIGO.other_sites_failures = function () { 5902 var div, table, i; 5903 if (!GIGO.helpdesk.other_sites.bad.length) { 5904 return jQuery("<div>"); // morally, "nothing to show" 5905 } 5906 div = jQuery("<div>"); 5907 div.append(jQuery("<p><span style='color: red'>Site(s) with failed connectivity</p>")); 5908 table = jQuery("<table>"); 5909 table.append(jQuery("<tr><td>Site</td><td>Failed URL</td></tr>")); 5910 for (i = 0; i < GIGO.helpdesk.other_sites.bad.length; i = i + 1) { 5911 table.append(GIGO.sites_display_bad_r_to_tr(GIGO.helpdesk.other_sites.bad[i])); 5912 } 5913 div.append(table); 5914 return div; 5915}; 5916 5917GIGO.sites_display_bad_r_to_tr = function (r) { 5918 var tr, a, parts; 5919 // r.site; 5920 // r.loc 5921 // r.provider 5922 // r.v6 5923 tr = jQuery("<tr>"); 5924 5925 parts = r.v6.split("/"); 5926 5927 tr.append(jQuery("<td>").text(parts[0])); 5928 5929 a = jQuery("<a>"); 5930 a.text(r.v6); 5931 a.attr("href", r.v6); 5932 a.attr("target", "_blank"); 5933 5934 tr.append(jQuery("<td>").append(a)); 5935 return tr; 5936 5937}; 5938 5939GIGO.sites_display_td_provider_div_update = function (r) { 5940 var i, td_provider_div; 5941 td_provider_div = r.refs.td_provider_div; 5942 td_provider_div.text(r.provider); 5943 for (i in arguments) { 5944 if (i > 0) { 5945 td_provider_div.append("<br/>"); 5946 td_provider_div.append(arguments[i]); 5947 } 5948 } 5949}; 5950 5951GIGO.sites_display_add_record = function (r, mode) { 5952 // Create new table row 5953 // Append it to existing table 5954 // Make sure that the row elements are easy to find by id 5955 var tr, td_link, td_loc, td_provider, td_status, td_info, td_mirror, mirror_button, site, td_provider_div; 5956 5957 5958 site = $("<a>", { 5959 text: r.site, 5960 href: "http://" + r.site, 5961 target: r.site 5962 }); 5963 tr = $('<tr></tr>'); // Don't use .hide here. Instead, lets show the table. Only .hide() on failure? 5964 td_link = $("<td>").append(site); 5965 td_loc = $("<td>").text(r.loc); 5966 td_provider_div = $("<div>").text(r.provider); 5967 td_provider = $("<td>").append(td_provider_div); 5968 5969 td_status = $("<td>").append( 5970 $("<img>", { src: "/images/hires_spinner.gif"}) 5971 .css("height","2em") 5972 .css("width","auto") 5973 .css("opacity", "0.1") 5974 .css("filter", "alpha(opacity=10)") 5975 ); 5976 td_info = $("<td>").append($("<img>", { 5977 src: "/images/hires_info.png" 5978 }).css("height","2em").css("width","auto")); 5979 5980 5981 5982 td_info.click(function () { 5983 GIGO.sites_display_td_provider_div_update(r, $("<a>", { 5984 text: r.v4, 5985 href: r.v4, 5986 target: "_blank" 5987 }), $("<a>", { 5988 text: r.v6, 5989 href: r.v6, 5990 target: "_blank" 5991 })); 5992 }); 5993 5994 if ((mode === 2) && (r.mirror)) { 5995 5996 // This should be done with jquery to avoid any potential abuse in mirrors.js, but 5997 // I can't find the right incantation. 5998 mirror_button = $("<a target='" + r.site + "' href='http://" + r.site + "'><img border=0 style='height: 2em; width: auto;' src='/images/hires_link.png'/></a>"); 5999 td_mirror = $("<td>").append(mirror_button); 6000 } else { 6001 td_mirror = $("<td>").html(" "); 6002 } 6003 6004 6005 6006 6007 if (mode === 1) { 6008 tr.append(td_link, td_loc, td_provider, td_status, td_info); 6009 } else if (mode === 2) { 6010 tr.append(td_link, td_loc, td_provider, td_status, td_info, td_mirror); 6011 } else { 6012 return; // We should have had plenty of alerts already. 6013 } 6014 6015 $('#sites > tbody:last').append(tr); 6016 $('#sites').find('tbody:last').append(tr); 6017 6018 6019 6020 // Copy references to "r" object. 6021 r.refs = {}; 6022 r.refs.tr = tr; 6023 r.refs.td_link = td_link; 6024 r.refs.td_loc = td_loc; 6025 r.refs.td_provider = td_provider; 6026 r.refs.td_provider_div = td_provider_div; 6027 r.refs.td_status = td_status; 6028 r.refs.td_info = td_info; 6029 r.refs.td_mirror = td_mirror; 6030}; 6031 6032GIGO.sites_display_success = function (r) { 6033 var new_td; 6034 new_td = $("<td>").append($("<img>", { 6035 src: "/images/hires_ok.png" 6036 }).css("height","2em").css("width","auto")); 6037 r.refs.td_status.replaceWith(new_td); 6038 GIGO.helpdesk.other_sites.finished = GIGO.helpdesk.other_sites.finished + 1; 6039 GIGO.helpdesk.other_sites.good.push(r); 6040 GIGO.sites_update_helpdesk(); 6041}; 6042GIGO.sites_display_failure = function (r) { 6043 var new_td; 6044 new_td = $("<td>").append($("<img>", { 6045 src: "/images/hires_bad.png" 6046 }).css("height","2em").css("width","auto")); 6047 r.refs.td_status.replaceWith(new_td); 6048 GIGO.helpdesk.other_sites.finished = GIGO.helpdesk.other_sites.finished + 1; 6049 GIGO.helpdesk.other_sites.bad.push(r); 6050 GIGO.sites_update_helpdesk(); 6051}; 6052 6053GIGO.sites_display_giveup = function (r) { 6054 var new_td; 6055 new_td = $("<td>").append($("<img>", { 6056 src: "/images/hires_offline.png" 6057 }).css("height","2em").css("width","auto")); 6058 r.refs.td_status.replaceWith(new_td); 6059 GIGO.sites_display_td_provider_div_update(r, "IPv4 site down, skipping IPv6 test"); 6060 GIGO.helpdesk.other_sites.finished = GIGO.helpdesk.other_sites.finished + 1; 6061 GIGO.sites_update_helpdesk(); 6062}; 6063 6064GIGO.sites_update_helpdesk = function () { 6065 if (GIGO.helpdesk.other_sites.count) { 6066 GIGO.finish_helpdesk(); 6067 } 6068}; 6069 6070 6071GIGO.sites_start_ipv6_take2 = function (r) { 6072 var url, img, img_pending; 6073 6074 if (!r.v6) { 6075 return; 6076 } 6077 6078 url = r.v6 + "?nocache=" + Math.random(); 6079 6080 6081 if (GIGO.is_replay()) { 6082 img_pending = 0; 6083 if (GIGO.was_failed_url(url)) { 6084 GIGO.fail_url(url); 6085 GIGO.sites_display_failure(r); 6086 } else { 6087 GIGO.sites_display_success(r); 6088 } 6089 GIGO.sites_next_in_queue(); 6090 return; 6091 } 6092 6093 setTimeout(function () { 6094 6095 // We have all the details we need to know. 6096 // We have a freshly incremented "id". 6097 // What we need now is to start an image 6098 // with handlers on it. 6099 // Finalize the URL. 6100 // Include a random number to defeat the browser cache. 6101 6102 // Create the image object. 6103 // We will keep this "off screen". 6104 img = jQuery('<img style="display:none" />'); 6105 img_pending = 1; 6106 6107 6108 jQuery(img).bind({ 6109 load: function () { 6110 if (img_pending) { 6111 img_pending = 0; 6112 GIGO.sites_display_success(r); 6113 GIGO.sites_next_in_queue(); 6114 } 6115 }, 6116 error: function () { 6117 if (img_pending) { 6118 img_pending = 0; 6119 GIGO.fail_url(url); 6120 GIGO.sites_display_failure(r); 6121 GIGO.sites_next_in_queue(); 6122 } 6123 } 6124 }); 6125 // Fake timeout here since IE doesn't pass errors 6126 setTimeout(function () { 6127 // TODO show FAIL 6128 if (img_pending) { 6129 img_pending = 0; 6130 GIGO.fail_url(url); 6131 GIGO.sites_display_failure(r); 6132 GIGO.sites_next_in_queue(); 6133 } 6134 }, GIGO.max_time); 6135 jQuery(img).attr("src", url); // Start the image loading! 6136 }, 1000); 6137 6138 6139}; 6140 6141GIGO.sites_start_ipv6 = function (r) { 6142 var url, img, img_pending; 6143 // console.log("sites_start_ipv6 %o",r); 6144 6145 if (!r.v6) { 6146 return; 6147 } 6148 6149 if (GIGO.is_replay()) { 6150 GIGO.sites_start_ipv6_take2(r); 6151 return; 6152 } 6153 6154 6155 // We have all the details we need to know. 6156 // We have a freshly incremented "id". 6157 // What we need now is to start an image 6158 // with handlers on it. 6159 // Finalize the URL. 6160 // Include a random number to defeat the browser cache. 6161 url = r.v6 + "?nocache=" + Math.random(); 6162 6163 // Create the image object. 6164 // We will keep this "off screen". 6165 img = jQuery('<img style="display:none" />'); 6166 img_pending = 1; 6167 6168 6169 jQuery(img).bind({ 6170 load: function () { 6171 if (img_pending) { 6172 img_pending = 0; 6173 GIGO.sites_display_success(r); 6174 GIGO.sites_next_in_queue(); 6175 } 6176 }, 6177 error: function () { 6178 if (img_pending) { 6179 img_pending = 0; 6180 GIGO.sites_start_ipv6_take2(r); 6181 } 6182 } 6183 }); 6184 // Fake timeout here since IE doesn't pass errors 6185 setTimeout(function () { 6186 // TODO show FAIL 6187 if (img_pending) { 6188 img_pending = 0; 6189 GIGO.sites_start_ipv6_take2(r); 6190 } 6191 }, GIGO.max_time); 6192 jQuery(img).attr("src", url); // Start the image loading! 6193}; 6194 6195 6196GIGO.sites_start_ipv4_take2 = function (r) { 6197 var url, img, img_pending; 6198 console.log("sites_start_ipv4 %o",r); 6199 6200 if (!r.v4) { 6201 return; 6202 } 6203 6204 6205 url = r.v4 + "?nocache=" + Math.random(); 6206 6207 6208 if (GIGO.is_replay()) { 6209 img_pending = 0; 6210 if (GIGO.was_failed_url(url)) { 6211 GIGO.fail_url(url); 6212 GIGO.sites_display_giveup(r); 6213 } else { 6214 GIGO.sites_start_ipv6(r); 6215 } 6216 GIGO.sites_next_in_queue(); 6217 return; 6218 } 6219 6220 6221 6222 6223 // Intentionally delay by a second 6224 // This gives a chance for the DNS to eventually 6225 // resolve, in case that was the source of the error. 6226 setTimeout(function () { 6227 6228 r.refs.td_status.find('img').css("opacity", "1.0").css("filter", "alpha(opacity=100)"); 6229 6230 img = jQuery('<img style="display:none" />'); 6231 img_pending = 1; 6232 6233 jQuery(img).bind({ 6234 load: function () { 6235 img_pending = 0; 6236 GIGO.sites_start_ipv6(r); 6237 }, 6238 error: function () { 6239 if (img_pending) { 6240 img_pending = 0; 6241 GIGO.fail_url(url); 6242 GIGO.sites_display_giveup(r); 6243 GIGO.sites_next_in_queue(); 6244 } 6245 } 6246 }); 6247 setTimeout(function () { 6248 // TODO show FAIL 6249 if (img_pending) { 6250 img_pending = 0; 6251 GIGO.fail_url(url); 6252 GIGO.sites_display_giveup(r); 6253 GIGO.sites_next_in_queue(); 6254 } 6255 }, GIGO.max_time); 6256 // Fake timeout here since IE doesn't pass errors 6257 jQuery(img).attr("src", url); // Start the image loading! 6258 }, 1000); 6259}; 6260 6261 6262 6263GIGO.sites_start_ipv4 = function (r) { 6264 var url, img, img_pending; 6265 6266 6267 if (!r.v4) { 6268 return; 6269 } 6270 6271 // Visiting the IPv6 specific site 6272 if (window.location.hostname.toLocaleLowerCase().startsWith("ipv6.")) { 6273 GIGO.sites_start_ipv6(r); 6274 return; 6275 } 6276 6277 // OR the beta site 6278 if (window.location.hostname.toLocaleLowerCase().startsWith("beta.")) { 6279 GIGO.sites_start_ipv6(r); 6280 return; 6281 } 6282 6283 // IPv6 only? Brave fellow. 6284 if ((!GIGO.results.ipv4.ip) && (GIGO.results.ipv6.ip)) { 6285 GIGO.sites_start_ipv6(r); 6286 return; 6287 } 6288 6289 if (GIGO.is_replay()) { 6290 GIGO.sites_start_ipv4_take2(r); 6291 return; 6292 } 6293 6294 6295 r.refs.td_status.find('img').css("opacity", "1.0").css("filter", "alpha(opacity=100)"); 6296 6297 url = r.v4 + "?nocache=" + Math.random(); 6298 img = jQuery('<img style="display:none" />'); 6299 img_pending = 1; 6300 6301 6302 jQuery(img).bind({ 6303 load: function () { 6304 if (img_pending) { 6305 img_pending = 0; 6306 GIGO.sites_start_ipv6(r); 6307 } 6308 }, 6309 error: function () { 6310 if (img_pending) { 6311 img_pending = 0; 6312 6313 GIGO.sites_start_ipv4_take2(r); 6314 } 6315 } 6316 }); 6317 setTimeout(function () { 6318 // TODO show FAIL 6319 if (img_pending) { 6320 img_pending = 0; 6321 GIGO.sites_start_ipv4_take2(r); 6322 } 6323 }, GIGO.max_time); 6324 // Fake timeout here since IE doesn't pass errors 6325 jQuery(img).attr("src", url); // Start the image loading! 6326}; 6327 6328 6329GIGO.sites_next_in_queue = function () { 6330 var r; 6331 if (GIGO.sites_queue.length > 0) { 6332 r = GIGO.sites_queue.shift(); 6333 GIGO.sites_start_ipv4(r); 6334 } 6335}; 6336 6337GIGO.sites_start_tests = function () { 6338 // 9 parallel runs, spaced a bit a part. 6339 if (0 && GIGO.is_replay()) { 6340 while (GIGO.sites_queue.length > 0) { 6341 GIGO.sites_next_in_queue(); 6342 } 6343 } else { 6344 setTimeout(GIGO.sites_next_in_queue, 1); 6345 setTimeout(GIGO.sites_next_in_queue, 75); 6346 setTimeout(GIGO.sites_next_in_queue, 150); 6347 setTimeout(GIGO.sites_next_in_queue, 225); 6348 setTimeout(GIGO.sites_next_in_queue, 300); 6349 setTimeout(GIGO.sites_next_in_queue, 375); 6350 setTimeout(GIGO.sites_next_in_queue, 450); 6351 setTimeout(GIGO.sites_next_in_queue, 525); 6352 setTimeout(GIGO.sites_next_in_queue, 600); 6353 } 6354}; 6355 6356GIGO.test_sites = function (mode) { 6357 GIGO.sites_init(mode); 6358 GIGO.sites_queue_all(mode); 6359 GIGO.fisherYates(GIGO.sites_queue); 6360 GIGO.sites_prepare_helpdesk(mode); 6361 GIGO.sites_table_init(mode); 6362 GIGO.sites_table_populate(mode); 6363 GIGO.sites_start_tests(mode); 6364}; 6365 6366 6367GIGO.fisherYates = function (myArray) { 6368 var i, j, tempi, tempj; 6369 i = myArray.length; 6370 if (i === 0) { 6371 return; 6372 } 6373 while (i > 0) {
6374 i = i - 1; 6375 j = Math.floor(Math.random() * (i + 1)); 6376 tempi = myArray[i]; 6377 tempj = myArray[j]; 6378 myArray[i] = tempj; 6379 myArray[j] = tempi; 6380 } 6381}; 6382 6383/*global GIGO, Browser, unescape */ 6384/*jslint browser: true */ 6385 6386// Call this early, to enable the isp helpdesk tab 6387 6388//GIGO.list_of_ipv4 = ["a", "ds4"]; 6389//GIGO.list_of_ipv6 = ["aaaa", "ds6", "test_v6mtu"]; 6390 6391 6392GIGO.start_helpdesk = function () { 6393 var want_helpdesk = 0; 6394 if (GIGO.CGI.isp) { 6395 want_helpdesk = 1; 6396 } 6397 if (GIGO.CGI.helpdesk) { 6398 want_helpdesk = 1; 6399 } 6400 if (String(location.pathname).match(/\b(isp|helpdesk)\b/i)) { 6401 want_helpdesk = 1; 6402 } 6403 if (String(location.hostname).match(/\b(isp|helpdesk)\b/i)) { 6404 want_helpdesk = 1; 6405 } 6406 if (String(location.hash).match(/^(isp|helpdesk)\$/i)) { 6407 want_helpdesk = 1; 6408 } 6409 6410 if (want_helpdesk) { 6411 GIGO.tabnav("helpdesk"); 6412 } else { 6413 $("#tabbutton_helpdesk_link").addClass("navright"); 6414 } 6415 6416}; 6417 6418 6419 6420GIGO.helpdesk_ob_status = function (n) { 6421 var s = GIGO.results.tests[n].status; 6422 if (s === "ok") return "g"; 6423 if (s === "slow") return "g"; 6424 if (s === "bad") return "b"; 6425 if (s === "timeout") return "t"; 6426 if (s === "skipped") return "x"; 6427}; 6428GIGO.helpdesk_ob_type = function () { 6429 //# global,bad,teredo,6to4,asn(different) 6430 var t = "b"; 6431 if ((GIGO.results.ipv6) && (GIGO.results.ipv6.ip)) { 6432 t = "g"; // By default it must have a global address, right? 6433 if (GIGO.helpdesk.teredo) { 6434 t = "t"; // teredo 6435 } 6436 if (GIGO.helpdesk.sixfour) { 6437 t = "6"; // 6to4 6438 } 6439 } 6440 return t; 6441}; 6442 6443 6444GIGO.helpdesk_score = function () { 6445 var mini_helpdesk, score; 6446 6447 // GIGO.results.tests[x].status 6448 var status_a = GIGO.helpdesk_ob_status("test_a"); 6449 var status_aaaa = GIGO.helpdesk_ob_status("test_aaaa"); 6450 var status_ipv6_type = GIGO.helpdesk_ob_type(); 6451 6452 var status = status_a + ":" + status_aaaa + status_ipv6_type; 6453 var ob = {}; 6454 6455 //console.log("helpdesk status code %o",status); 6456 6457 ob.found = GIGO.sym_helpdesk[status]; 6458 ob.qcode = GIGO.sym_helpdesk_qcode[ob.found]; 6459 6460 if (ob.found) { 6461 if (GIGO.helpdesk.failed_pmtud) { 6462 ob.found = ob.found + ", Potential MTU issues"; 6463 ob.qcode = ob.qcode + ",mtu"; 6464 } 6465 if (GIGO.helpdesk.mini_primary.match(/s/)) { 6466 ob.found = ob.found + ", Slow"; 6467 ob.qcode = ob.qcode + ",slow"; 6468 } 6469 return ob; 6470 } 6471 return; 6472}; 6473 6474GIGO.helpdesk_good_bad_slow = function (a) { 6475 var slow = 0; 6476 var good = 0; 6477 var tout = 0; 6478 var i = 0; 6479 for (i = 0; i < a.length; i = i + 1) { 6480 if (GIGO.results.tests[a[i]].status === "ok") { 6481 good = 1; 6482 } 6483 if (GIGO.results.tests[a[i]].status === "slow") { 6484 slow = 1; 6485 } 6486 if (GIGO.results.tests[a[i]].status === "timeout") { 6487 tout = 1; 6488 } 6489 } 6490 if (tout) return "Timeout"; 6491 if (slow) return "Slow"; 6492 if (good) return "Good"; 6493 return "Bad"; 6494}; 6495 6496GIGO.helpdesk_ipv4_info = function () { 6497 var test_a, test_asn4, s; 6498 test_a = GIGO.results.tests.test_a; 6499 test_asn4 = GIGO.results.tests.test_asn4; 6500 6501 // status 6502 // ipinfo.ip 6503 // ipinfo.asn 6504 // ipinfo.asn_name 6505 // time_ms 6506 6507 if ((test_a.ipinfo) && (test_a.ipinfo.ip)) { 6508 s = "IPv4: "; 6509 s = s + GIGO.helpdesk_good_bad_slow(["test_a", "test_ds4"]); 6510 if (test_asn4 && test_asn4.ipinfo && test_asn4.ipinfo.asn) { 6511 s = s + ", AS" + test_asn4.ipinfo.asn + " - "; 6512 s = s + test_asn4.ipinfo.asn_name; 6513 } 6514 return s; 6515 } else { 6516 return "IPv4: no"; 6517 } 6518}; 6519 6520GIGO.helpdesk_ipv6_info = function () { 6521 var test_aaaa, test_asn6, s; 6522 test_aaaa = GIGO.results.tests.test_aaaa; 6523 test_asn6 = GIGO.results.tests.test_asn6; 6524 6525 6526 // status 6527 // ipinfo.ip 6528 // ipinfo.asn 6529 // ipinfo.asn_name 6530 // time_ms 6531 6532 6533 // We need to warn if any of the IPv6 tries timed out 6534 6535 if ((test_aaaa.ipinfo) && (test_aaaa.ipinfo.ip)) { 6536 s = "IPv6: "; 6537 s = s + GIGO.helpdesk_good_bad_slow(["test_aaaa", "test_ds6", "test_v6mtu"]); 6538 if (test_asn6 && test_asn6.ipinfo && test_asn6.ipinfo.asn) { 6539 s = s + ", AS" + test_asn6.ipinfo.asn + " - "; 6540 s = s + test_asn6.ipinfo.asn_name; 6541 } 6542 return s; 6543 } else { 6544 6545 if ((GIGO.results.tests.test_aaaa) && (GIGO.results.tests.test_aaaa.status) && (GIGO.results.tests.test_aaaa.status === "timeout")) { 6546 return "IPv6: broken"; 6547 } 6548 if ((GIGO.results.tests.test_ds) && (GIGO.results.tests.test_ds.status) && (GIGO.results.tests.test_ds.status === "timeout")) { 6549 return "IPv6: broken"; 6550 } 6551 if ((GIGO.results.tests.test_ipv6) && (GIGO.results.tests.test_ipv6.status) && (GIGO.results.tests.test_ipv6.status === "timeout")) { 6552 return "IPv6: broken"; 6553 } 6554 return "IPv6: no"; 6555 } 6556}; 6557 6558 6559// call this late to populate the helpdesk tab 6560GIGO.finish_helpdesk = function () { 6561 var code, div; 6562 if (!GIGO.results.debug_code) { 6563 return; // Too soon. 6564 } 6565 6566 // Show the replay url 6567 jQuery("#replayurldiv").show(); 6568 6569 code = GIGO.helpdesk_score(); 6570 6571 div = jQuery("<div>", { 6572 id: "helpdesk_content" 6573 }); 6574 6575 // div.append("<div class=beta>BETA -This tab is a work in progress.</div>"); 6576 6577 div.append(jQuery("<p>").append("Your Internet help desk may ask you for the information below.")); 6578 6579 if ((code) && (code.qcode)) { 6580 div.append(jQuery("<p>
6580").append(jQuery("<span class=helpdeskcode>").text("Help desk code: " + code.qcode))); 6581 } 6582 if ((code) && (code.found)) { 6583 div.append(jQuery("<p>").append(jQuery("<b>").text(code.found))); 6584 } 6585 6586 // GIGO.results.ipv4 and ipv6, have our ASN info. 6587 6588 // div.append(jQuery("<div>").text(s)); 6589 div.append(jQuery("<div>").text(GIGO.helpdesk_ipv4_info())); 6590 div.append(jQuery("<div>").text(GIGO.helpdesk_ipv6_info())); 6591 if (GIGO.helpdesk.other_sites && GIGO.helpdesk.other_sites.count) { 6592 div.append(jQuery("<div>").text(GIGO.other_sites_info())); 6593 } 6594 6595 div.append("<div><p></p></div>"); // Space. 6596 if ((GIGO.results.ipv4) && (GIGO.results.ipv4.ip)) { 6597 div.append(jQuery("<div>").text("IPv4 address: " + GIGO.results.ipv4.ip)); 6598 } 6599 if ((GIGO.results.ipv6) && (GIGO.results.ipv6.ip)) { 6600 div.append(jQuery("<div>").text("IPv6 address: " + GIGO.results.ipv6.ip)); 6601 } 6602 div.append("<div><p></p></div>"); // Space. 6603 6604 if (GIGO.helpdesk.other_sites) { 6605 div.append(GIGO.other_sites_failures()); 6606 } 6607 6608 6609 // IPv4: Good, AS1234, CableCo 6610 // IPv6: Good, Teredo, Not Preferred 6611 // OtherSites: 40/40 Good 6612 6613 // IPv4 address: 192.0.2.1 6614 // IPv6 address: 2001:0c000:201::1 6615 6616 6617 $("#helpdesk_content").replaceWith(div); 6618 6619 6620 6621 6622 // $("#helpdesk_content") 6623 6624 // GIGO.results.tokens 6625 // GIGO.results.score_transition 6626 // GIGO.results.score_strict 6627 // GIGO.results.debug_code 6628 // GIGO.results.tokens_expanded 6629 // GIGO.results.mini_primary 6630 // GIGO.results.mini_secondary 6631 6632 // This is meant to be ran several times; each time will replace 6633 // #helpdesk_content 6634 6635 // First time replaced, will be before the "other sites" tab starts. 6636 // If we have IPV6, then it should say "checking other sites.." 6637 // And perhaps update only when done? 6638 6639}; 6640 6641/* We will pulse specific CSS elements, 6642cycling through colors ranging from yellow to white */ 6643 6644GIGO.pulse_background_speed = 250; 6645GIGO.pulse_background_colors_function = function () { 6646 if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { 6647 // dark mode 6648 return [ 6649 "#3b3528", 6650 "#59503c", 6651 "#786c50", 6652 "#968150", 6653 "#968150", 6654 "#786c50", 6655 "#59503c", 6656 "#3b3528"]; 6657 } else { 6658 return [ 6659 "#fffeee", 6660 "#fffeee", 6661 "#fffddd", 6662 "#fffccc", 6663 "#fffaaa", 6664 "#ffe6aa", 6665 "#fffaaa", 6666 "#fffccc", 6667 "#fffddd", 6668 "#fffeee", 6669 "#fffeee"]; 6670 } 6671} 6672 6673 6674GIGO.pulse_background_colors = GIGO.pulse_background_colors_function(); 6675 6676// On change, refresh the colors. 6677window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { 6678 GIGO.pulse_background_colors = GIGO.pulse_background_colors_function(); 6679}); 6680 6681GIGO.pulse_on = function () { 6682 var n = GIGO.pulse_background_colors.shift(); 6683 GIGO.pulse_background_colors.push(n); 6684 jQuery(".help_popup").css("background-color",n); 6685 jQuery("#comments_faq_link").css("background-color",n); 6686 setTimeout( function() { 6687 GIGO.pulse_on(); 6688 }, GIGO.pulse_background_speed); 6689} 6690 6691/*global GIGO, MirrorConfig, jQuery, window, alert, Browser */ 6692/*jslint browser: true */ 6693/*jslint regexp: true */ 6694 6695 6696GIGO.prepare_fake = function () { 6697 var i, funcname, shortname; 6698 for (i = 0; i < GIGO.queue.length; i = i + 1) { 6699 funcname = GIGO.queue[i][2]; 6700 shortname = funcname.replace(/^test_/, ""); 6701 if (GIGO.CGI[shortname]) { 6702 GIGO.override = 1; 6703 GIGO.overrides[funcname] = GIGO.CGI[shortname]; 6704 GIGO.use_queue = 1; 6705 } 6706 } 6707 if ((GIGO.isdef(GIGO.CGI.ip4)) || (GIGO.isdef(GIGO.CGI.ip6))) { 6708 GIGO.override = 1; 6709 } 6710}; 6711 6712 6713GIGO.override_id = function (id, url) { 6714 var tests, this_test, parts, status, protocol, whichasn; 6715 tests = GIGO.results.tests; // Convenience 6716 if (!(tests.hasOwnProperty(id))) { 6717 tests[id] = {}; 6718 } 6719 6720 tests[id] = {}; 6721 this_test = tests[id]; 6722 this_test.url = url; 6723 this_test.start_time = GIGO.getms(); 6724 this_test.ipinfo = {}; 6725 6726 GIGO.update_url(id); 6727 6728 // TODO copy from ipinfo 6729 parts = GIGO.overrides[id].split(/,/); 6730 6731 // parts[0] = status 6732 // parts[1] = time 6733 // parts[2] = protocol 6734 6735 // TODO I know this is totally gonna cause problems when the url is missing data 6736 status = parts[0]; 6737 protocol = parts[2]; 6738 if (!protocol) { 6739 if ((id === "test_aaaa") || (id === "test_v6mtu") || (id === "test_v6ns") || (id === "test_dsmtu") || (id === "test_ds")) { 6740 protocol = "ipv6"; 6741 } else { 6742 protocol = "ipv4"; 6743 } 6744 } 6745 // Is it abbreviated? 6746 if (protocol==="6" || protocol==="4") { 6747 protocol="ipv"+protocol; 6748 } 6749 6750 whichasn = "test_asn" + protocol.replace(/^ipv/, ""); 6751 6752 if (status === "ok") { 6753 for (var key in tests[whichasn].ipinfo) { 6754 if (!key.match(/^asn/)) { 6755 this_test.ipinfo[key] = tests[whichasn].ipinfo[key]; 6756 } 6757 } 6758 this_test.status = status; 6759 this_test.time_ms = parseInt(parts[1]) || 1; 6760 } 6761 if (status === "slow") { 6762 for (var key in tests[whichasn].ipinfo) { 6763 if (!key.match(/^asn/)) { 6764 this_test.ipinfo[key] = tests[whichasn].ipinfo[key]; 6765 } 6766 } 6767 this_test.status = status; 6768 this_test.time_ms = parseInt(parts[1]) || (GIGO.slow + 1); 6769 } 6770 if (status === "bad") { 6771 this_test.ipinfo = {}; 6772 this_test.status = status; 6773 this_test.time_ms = parseInt(parts[1]) || 1; 6774 } 6775 if (status === "timeout") { 6776 this_test.ipinfo = {}; 6777 this_test.status = status; 6778 this_test.time_ms = parseInt(parts[1]) || (GIGO.max_time + 1); 6779 } 6780 if (status === "skipped") { 6781 this_test.ipinfo = {}; 6782 this_test.status = status; 6783 this_test.time_ms = parseInt(parts[1]) || (0); 6784 } 6785 6786 if (id === "test_ds") { 6787 // We need to populate test_ds4 and test_ds6 in much the same way that GIGO.test_type_json() does 6788 if (this_test.ipinfo.type === "ipv6") { 6789 tests.test_ds6 = { 6790 url: this_test.url, 6791 time_ms: this_test.time_ms, 6792 status: this_test.status 6793 }; 6794 tests.test_ds4 = { 6795 url: this_test.url, 6796 time_ms: this_test.time_ms, 6797 status: "bad" 6798 }; 6799 } else { 6800 tests.test_ds4 = { 6801 url: this_test.url, 6802 time_ms: this_test.time_ms, 6803 status: this_test.status 6804 }; 6805 tests.test_ds6 = { 6806 url: this_test.url, 6807 time_ms: this_test.time_ms, 6808 status: "bad" 6809 }; 6810 } 6811 } 6812 this_test.ipinfo.type=protocol; 6813 6814}; 6815 6816GIGO.override_id_ip = function (id) { 6817 var tests, this_test, parts, status, protocol, whichasn; 6818 tests = GIGO.results.tests; // Convenience 6819 this_test = tests[id]; 6820 if (!this_test) { 6821 return; 6822 } 6823 if (!this_test.ipinfo.type) { 6824 return; 6825 } 6826 whichasn = "test_asn" + this_test.ipinfo.type.replace(/^ipv/, ""); 6827 6828 this_test.ipinfo = {}; 6829 6830 6831 for (var key in tests[whichasn].ipinfo) { 6832 if (!key.match(/^asn/)) { 6833 this_test.ipinfo[key] = tests[whichasn].ipinfo[key]; 6834 } 6835 } 6836}; 6837 6838 6839GIGO.ood_url = function () { 6840 var url; 6841 try { 6842 hash = jQuery.md5(MirrorConfig.load.domain); 6843 hash = hash.replace(/[^a-zA-Z0-9]/g, ''); 6844 hash = hash.substring(0, 8); 6845 url = "//test-ipv6.com/images/ood_" + hash + ".png"; 6846 } catch (err) { 6847 }; 6848 return url; 6849}; 6850 6851/*global GIGO, MirrorConfig, jQuery, window, alert, Browser */ 6852/*jslint browser: true */ 6853/*jslint regexp: true */ 6854 6855 6856GIGO.update_ipaddress = function (ipinfo) { 6857 // ipinfo: callback({"ip":"69.62.233.151","type":"ipv4","subtype":"","public":1,"filler":""}); 6858 6859 // What if "ip" is "192.0.2.1, 192.0.2.1"? Reduce it. 6860 if ((ipinfo) && (ipinfo.ip)) { 6861 let sp = ipinfo.ip.split(", "); 6862 let use = sp[0]; 6863 for (let element of sp.values()) { 6864 if (element !== sp[0]) { 6865 use=ipinfo.ip; 6866 } 6867 } 6868 ipinfo.ip=use ; 6869 } 6870 6871 if (ipinfo.type === "ipv4") { 6872 if (!GIGO.results.ipv4.asn) { 6873 GIGO.results.ipv4 = ipinfo; 6874 } 6875 } 6876 if (ipinfo.type === "ipv6") { 6877 if (!GIGO.results.ipv6.asn) { 6878 GIGO.results.ipv6 = ipinfo; 6879 } 6880 } 6881}; 6882 6883GIGO.test_type_delayed = function (url, id) { 6884 6885 // We will use this to stagger the start time_ms. 6886 // Since javascript has no "sleep" the next best 6887 // thing appears to be to set a timeout, and on timeout, 6888 // do what we really wanted. 6889 // We increase the timeout value each time we run this, so 6890 // that each thread time_ms out at a later time, to prevent 6891 // all tests from running INSTANTLY. 6892 // This is principally to work around IE problems 6893 // with too many jsonP queries initiating at once. 6894 GIGO.slowcount = GIGO.slowcount + 1; 6895 setTimeout(function () { 6896 GIGO.test_type(url, id); 6897 }, GIGO.slowcount * GIGO.slowcount_delay); 6898}; 6899 6900GIGO.finish_test = function (id) { 6901 var total_tests = GIGO.queue.length + GIGO.dequeued.length; // Once for main text, once for fallback image test 6902 GIGO.tests_finished = GIGO.tests_finished + 1; 6903 GIGO.update_progress(GIGO); 6904 GIGO.update_status(id); 6905 if (GIGO.tests_finished >= total_tests) { 6906 GIGO.check_results(); 6907 } 6908 GIGO.next_in_queue(); // Start next test, if available 6909 GIGO.show_debug(); 6910}; 6911 6912 6913GIGO.test_type_skip = function (url, id) { 6914 // name = dns name to fetch 6915 // id = which <div> to update 6916 var tests, this_test; 6917 6918 6919 6920 // Let us also add in some hints for mirror operators 6921 if (url.search(/\?/) < 0) { 6922 url = url + "?"; 6923 } 6924 url = url + "&testdomain=" + GIGO.options.domain; 6925 url = url + "&testname=" + id; 6926 if (Browser.opera) { 6927 url = url + "&random=" + Math.random(); 6928 } 6929 6930 6931 tests = GIGO.results.tests; // Convenience 6932 if (!(tests.hasOwnProperty(id))) { 6933 tests[id] = {}; 6934 } 6935 this_test = tests[id]; 6936 6937 this_test.start_time = GIGO.getms(); // Will use to find how long we ran 6938 this_test.url = url; // For later display of test urls 6939 // Update status to "Started" if we don't have any time for this yet 6940 6941 6942 6943 this_test.time_ms=0; 6944 this_test.status = "skipped"; 6945 GIGO.finish_test(id); 6946 GIGO.update_url(id); 6947 GIGO.show_debug(); 6948 6949}; 6950 6951 6952GIGO.test_type_json = function (url, id) { 6953 // name = dns name to fetch 6954 // id = which <div> to update 6955 var tests, this_test; 6956 6957 6958 6959 // Let us also add in some hints for mirror operators 6960 if (url.search(/\?/) < 0) { 6961 url = url + "?"; 6962 } 6963 url = url + "&testdomain=" + GIGO.options.domain; 6964 url = url + "&testname=" + id; 6965 if (Browser.opera) { 6966 url = url + "&random=" + Math.random(); 6967 } 6968 6969 6970 tests = GIGO.results.tests; // Convenience 6971 if (!(tests.hasOwnProperty(id))) { 6972 tests[id] = {}; 6973 } 6974 this_test = tests[id]; 6975 6976 this_test.start_time = GIGO.getms(); // Will use to find how long we ran 6977 this_test.url = url; // For later display of test urls 6978 // Update status to "Started" if we don't have any time for this yet 6979 6980 6981 6982 6983 if (GIGO.overrides && GIGO.overrides[id]) { 6984 // oh, we're faking this one. TODO 6985 // we can take a lot of short cuts. 6986 GIGO.override_id(id, url); 6987 GIGO.finish_test(id); 6988 GIGO.update_url(id); 6989 GIGO.show_debug(); 6990 return; 6991 } 6992 6993 6994 GIGO.update_url(id); 6995 6996 // Initiate new query. Based on pass/fail, update status. 6997 jQuery.jsonp({ 6998 "url": url, 6999 "cache": true, 7000 "pageCache": false, 7001 "timeout": GIGO.max_time, 7002 7003 "success": function (ipinfo) { 7004 // Keep track of IP information we receive 7005 var delta; 7006 7007 delete ipinfo.full; // Don't need this polluting anything. 7008 delete ipinfo.padding; // Don't need this polluting anything. 7009 this_test.ipinfo = ipinfo; // Record the IP address reported from this test 7010 if (GIGO.override) { 7011 GIGO.override_id_ip(id); 7012 } 7013 GIGO.update_ipaddress(this_test.ipinfo); // Make note of our IPv4 or IPv6 address based on the test 7014 GIGO.update_ip(id); // callback for presentation 7015 delta = GIGO.getms() - this_test.start_time; 7016 if (GIGO.isdef(this_test.time_ms)) { 7017 if (delta < this_test.time_ms) { 7018 this_test.time_ms = delta; 7019 } 7020 } else { 7021 this_test.time_ms = delta; 7022 } 7023 this_test.status = (this_test.time_ms < GIGO.slow) ? "ok" : "slow"; 7024 7025 7026 // Look for dual stack 7027 if (id === "test_ds") { 7028 // ds4 and ds6 have the same time; but if one is good, the other must be bad, 7029 // since we can't possibly connect to both with a single DNS name 7030 if (ipinfo.type === "ipv6") { 7031 tests.test_ds6 = { 7032 url: this_test.url, 7033 time_ms: this_test.time_ms, 7034 status: this_test.status 7035 }; 7036 tests.test_ds4 = { 7037 url: this_test.url, 7038 time_ms: this_test.time_ms, 7039 status: "bad" 7040 }; 7041 } else { 7042 tests.test_ds4 = { 7043 url: this_test.url, 7044 time_ms: this_test.time_ms, 7045 status: this_test.status 7046 }; 7047 tests.test_ds6 = { 7048 url: this_test.url, 7049 time_ms: this_test.time_ms, 7050 status: "bad" 7051 }; 7052 } 7053 } 7054 7055 GIGO.finish_test(id); 7056 7057 7058 }, 7059 "error": function (d, msg) { 7060 var delta; 7061 7062 console.log("test_type_json url=%o id=%o d=%o msg=%o",url,id,d,msg); 7063 7064 delta = GIGO.getms() - this_test.start_time; 7065 if (GIGO.isdef(this_test.time_ms)) { 7066 if (delta < this_test.time_ms) { 7067 this_test.time_ms = delta; 7068 } 7069 } else { 7070 this_test.time_ms = delta; 7071 } 7072 this_test.status = (this_test.time_ms < GIGO.slow) ? "bad" : "timeout"; 7073 7074 // Look for dual stack 7075 if (id === "test_ds") { 7076 tests.test_ds6 = { 7077 url: this_test.url, 7078 time_ms: this_test.time_ms, 7079 status: this_test.status 7080 }; 7081 tests.test_ds4 = { 7082 url: this_test.url, 7083 time_ms: this_test.time_ms, 7084 status: this_test.status 7085 }; 7086 } 7087 7088 7089 // Fallback to image test, if the primary tests fail. Just in case some filter blocked the script fetches. 7090 GIGO.finish_test(id); 7091 GIGO.queue.push(["test_type_img", GIGO.options.url[id + "_img"], id + "_img"]); 7092 } 7093 }); 7094 7095 // Perform callback for presentation 7096 GIGO.update_url(id); 7097 GIGO.show_debug(); 7098 7099}; 7100 7101 7102GIGO.test_type_json_only = function (url, id) { 7103 // name = dns name to fetch 7104 // id = which <div> to update 7105 var tests, this_test; 7106 7107 7108 if (url.search(/\?/) < 0) { 7109 url = url + "?"; 7110 } 7111 url = url + "&testdomain=" + GIGO.options.domain; 7112 url = url + "&testname=" + id; 7113 if (Browser.opera) { 7114 url = url + "&random=" + Math.random(); 7115 } 7116 7117 7118 7119 7120 tests = GIGO.results.tests; // Convenience 7121 if (!(tests.hasOwnProperty(id))) { 7122 tests[id] = {}; 7123 } 7124 this_test = tests[id]; 7125 7126 this_test.start_time = GIGO.getms(); // Will use to find how long we ran 7127 this_test.url = url; // For later display of test urls 7128 // Update status to "Started" if we don't have any time for this yet 7129 GIGO.update_url(id); 7130 7131 7132 7133 if ((id === "test_asn4") && (GIGO.isdef(GIGO.CGI.ip4))) { 7134 if ((GIGO.CGI.ip4) && (GIGO.CGI.ip4.match(/^[0-9abcdef.:]+$/))) { 7135 url = url + "&testip=" + GIGO.CGI.ip4; 7136 // url = "/ip/?callback=?&asn=1&testip=" + GIGO.CGI.ip4; 7137 // url = url + "&testdomain=" + GIGO.options.domain; 7138 // url = ur
7138l + "&testname=" + id; 7139 this_test.url = url; // For later display of test urls 7140 GIGO.update_url(id); 7141 } else { 7142 this_test.ipinfo = {}; 7143 this_test.status = "bad"; 7144 this_test.time_ms = 1; 7145 GIGO.finish_test(id); 7146 GIGO.update_url(id); 7147 GIGO.show_debug(); 7148 return; 7149 } 7150 } 7151 if ((id === "test_asn6") && (GIGO.isdef(GIGO.CGI.ip6))) { 7152 if ((GIGO.CGI.ip6) && (GIGO.CGI.ip6.match(/^[0-9abcdef.:]+$/))) { 7153 url = url + "&testip=" + GIGO.CGI.ip6; 7154 // 7155 // url = "/ip/?callback=?&asn=1&testip=" + GIGO.CGI.ip6; 7156 // url = url + "&testdomain=" + GIGO.options.domain; 7157 // url = url + "&testname=" + id; 7158 this_test.url = url; // For later display of test urls 7159 GIGO.update_url(id); 7160 } else { 7161 this_test.ipinfo = {}; 7162 this_test.status = "bad"; 7163 this_test.time_ms = 1; 7164 GIGO.finish_test(id); 7165 GIGO.update_url(id); 7166 GIGO.show_debug(); 7167 return; 7168 } 7169 } 7170 7171 7172 7173 7174 7175 // Initiate new query. Based on pass/fail, update status. 7176 jQuery.jsonp({ 7177 "url": url, 7178 "cache": true, 7179 "pageCache": false, 7180 "timeout": GIGO.max_time, 7181 7182 "success": function (ipinfo) { 7183 // Keep track of IP information we receive 7184 var delta; 7185 7186 delete ipinfo.full; // Don't need this polluting anything. 7187 delete ipinfo.padding; // Don't need this polluting anything. 7188 this_test.ipinfo = ipinfo; // Record the IP address reported from this test 7189 GIGO.update_ipaddress(this_test.ipinfo); // Make note of our IPv4 or IPv6 address based on the test 7190 GIGO.update_ip(id); // callback for presentation 7191 delta = GIGO.getms() - this_test.start_time; 7192 if (GIGO.isdef(this_test.time_ms)) { 7193 if (delta < this_test.time_ms) { 7194 this_test.time_ms = delta; 7195 } 7196 } else { 7197 this_test.time_ms = delta; 7198 } 7199 this_test.status = (this_test.time_ms < GIGO.slow) ? "ok" : "slow"; 7200 7201 7202 7203 GIGO.finish_test(id); 7204 7205 7206 }, 7207 "error": function (d, msg) { 7208 var delta; 7209 7210 delta = GIGO.getms() - this_test.start_time; 7211 if (GIGO.isdef(this_test.time_ms)) { 7212 if (delta < this_test.time_ms) { 7213 this_test.time_ms = delta; 7214 } 7215 } else { 7216 this_test.time_ms = delta; 7217 } 7218 this_test.status = (this_test.time_ms < GIGO.slow) ? "bad" : "timeout"; 7219 7220 7221 GIGO.finish_test(id); 7222 } 7223 }); 7224 7225 // Perform callback for presentation 7226 GIGO.update_url(id); 7227 GIGO.show_debug(); 7228}; 7229 7230 7231GIGO.test_type_img = function (url, id) { 7232 // name = dns name to fetch 7233 // id = which <div> to update 7234 var tests, this_test, img, img_pending; 7235 7236 if (url.search(/\?/) < 0) { 7237 url = url + "?"; 7238 } 7239 url = url + "&testdomain=" + GIGO.options.domain; 7240 url = url + "&testname=" + id; 7241 if (Browser.opera) { 7242 url = url + "&random=" + Math.random(); 7243 } 7244 7245 tests = GIGO.results.tests; // Convenience 7246 if (!(tests.hasOwnProperty(id))) { 7247 tests[id] = {}; 7248 } 7249 this_test = tests[id]; 7250 7251 this_test.start_time = GIGO.getms(); // Will use to find how long we ran 7252 this_test.url = url; // For later display of test urls 7253 // Update status to "Started" if we don't have any time for this yet 7254 GIGO.update_url(id); 7255 7256 // Create image. 7257 // Attach handlers to the image. 7258 // Create a timer to artificially timeout imgs 7259 img_pending = 1; 7260 7261 img = jQuery('<img style="display:none" />'); 7262 7263 jQuery(img).bind({ 7264 load: function () { 7265 var delta; 7266 7267 if (img_pending) { 7268 img_pending = 0; 7269 delta = GIGO.getms() - this_test.start_time; 7270 if (GIGO.isdef(this_test.time_ms)) { 7271 if (delta < this_test.time_ms) { 7272 this_test.time_ms = delta; 7273 } 7274 } else { 7275 this_test.time_ms = delta; 7276 } 7277 this_test.image = 1; 7278 this_test.status = (this_test.time_ms < GIGO.slow) ? "ok" : "slow"; 7279 if (this_test.test_ms > GIGO.max_time) { 7280 this_test.status = "timeout"; 7281 } 7282 GIGO.finish_test(id); 7283 } 7284 }, 7285 error: function () { 7286 var delta; 7287 if (img_pending) { 7288 img_pending = 0; 7289 delta = GIGO.getms() - this_test.start_time; 7290 if (GIGO.isdef(this_test.time_ms)) { 7291 if (delta < this_test.time_ms) { 7292 this_test.time_ms = delta; 7293 } 7294 } else { 7295 this_test.time_ms = delta; 7296 } 7297 this_test.image = 1; 7298 this_test.status = (this_test.time_ms < GIGO.slow) ? "bad" : "timeout"; 7299 GIGO.finish_test(id); 7300 } 7301 } 7302 }); 7303 7304 // FAKE IMAGE TIMEOUT HANDLER 7305 setTimeout(function () { 7306 var delta; 7307 if (img_pending) { 7308 img_pending = 0; 7309 // replace failing image url with one that should work, so that browser can call this done. 7310 // we tried setting to "" but safari at minimum treats that as replacing src 7311 // with the value of document.location (!). 7312 jQuery(img).css("height","2em").css("width","auto"); 7313 jQuery(img).attr("src", "/images/hires_bad.png"); 7314 7315 delta = GIGO.getms() - this_test.start_time; 7316 if (GIGO.isdef(this_test.time_ms)) { 7317 if (delta < this_test.time_ms) { 7318 this_test.time_ms = delta; 7319 } 7320 } else { 7321 this_test.time_ms = delta; 7322 } 7323 this_test.image = 1; 7324 this_test.status = (this_test.time_ms < GIGO.slow) ? "bad" : "timeout"; 7325 GIGO.finish_test(id); 7326 } 7327 }, GIGO.max_time); 7328 7329 7330 //jQuery('body').append(img); 7331 jQuery(img).attr("src", url); 7332 7333 // Perform callback for presentation 7334 GIGO.update_url(id); 7335 GIGO.show_debug(); 7336}; 7337 7338 7339 7340GIGO.retest = function () { 7341 window.location.reload(); 7342}; 7343 7344 7345 7346GIGO.next_in_queue = function () { 7347 var fname, a; 7348 if (GIGO.queue.length > 0) { 7349 a = GIGO.queue.shift(); // Dequeue the next test. 7350 GIGO.dequeued.push(a.slice(0)); // Save a COPY. 7351 try { 7352 fname = a.shift(); // Remove first field, the function name (in the GIGO namespace). This changes array "a". 7353 } catch (e) { 7354 alert("ERROR: GIGO.next_in_queue: not an array; value=" + a); 7355 } 7356 7357 // fname = function name 7358 // a = args array to pass. 7359 GIGO[fname].apply(GIGO, a); 7360 7361 // If we are permitted parallel execution, 7362 // set a timer to start the next job. 7363 if (!GIGO.use_queue) { 7364 setTimeout(GIGO.next_in_queue, GIGO.slowcount_delay); 7365 } 7366 } 7367 GIGO.update_progress(GIGO); 7368}; 7369 7370GIGO.start_tests = function () { 7371 GIGO.browser_tweaks(GIGO); // In case we want to do tweak the document 7372 GIGO.next_in_queue(); // Get the ball rolling! 7373}; 7374GIGO.restart_tests = function () { 7375 var i, l; 7376 l = GIGO.dequeued.length; 7377 for (i = 0; i < l; i = i + 1) { 7378 GIGO.queue.push(GIGO.dequeued[i]); 7379 } 7380 GIGO.update_progress(GIGO); 7381 GIGO.start_tests(); 7382}; 7383 7384 7385 7386GIGO.setup_tests = function () { 7387 7388 var asn_lookup_broken = 0; 7389 if (asn_lookup_broken) { 7390 jQuery('#sum_test_asn4').parent().parent().hide(); 7391 jQuery('#sum_test_asn6').parent().parent().hide(); 7392 jQuery('#test_asn4').parent().parent().hide(); 7393 jQuery('#test_asn6').parent().parent().hide(); 7394 } else { 7395 GIGO.queue.push(["test_type_json_only", GIGO.options.url.test_asn4, "test_asn4"]); 7396 GIGO.queue.push(["test_type_json_only", GIGO.options.url.test_asn6, "test_asn6"]); 7397 } 7398 7399 7400 7401 7402 7403 7404 GIGO.queue.push(["test_type_json", GIGO.options.url.test_a, "test_a"]); 7405 GIGO.queue.push(["test_type_json", GIGO.options.url.test_aaaa, "test_aaaa"]); 7406 GIGO.queue.push(["test_type_json", GIGO.options.url.test_ds, "test_ds"]); 7407 7408 GIGO.queue.push(["test_type_json", GIGO.options.url.test_v6mtu, "test_v6mtu"]); 7409 GIGO.queue.push(["test_type_json", GIGO.options.url.test_v6ns, "test_v6ns"]); 7410 GIGO.queue.push(["test_type_json", GIGO.options.url.test_dsmtu, "test_dsmtu"]); 7411 GIGO.queue.push(["test_type_img", GIGO.options.url.test_ood_img, "test_ood"]); 7412 7413 7414 7415 7416 7417 GIGO.show_debug(); 7418 GIGO.prepare_fake(); 7419 7420}; 7421 7422GIGO.fill = function (size, str) { 7423 var s = ""; 7424 while (s.length < size) { 7425 s = s + str; 7426 } 7427 s = s.substring(0, size); 7428 return s; 7429}; 7430 7431 7432 7433 7434GIGO.set_default_options = function (options) { 7435 7436 options.url = (options.hasOwnProperty("url")) ? options.url : {}; 7437
7438 options.domain = GIGO.mirrorconfig("site", "name", null); 7439 options.subdomain = GIGO.mirrorconfig("load", "domain", options.domain); 7440 options.ipv4 = GIGO.mirrorconfig("load", "ipv4", null); 7441 options.ipv6 = GIGO.mirrorconfig("load", "ipv6", null); 7442 options.uri = GIGO.mirrorconfig("options", "ip", "/ip/") + "?callback=?"; 7443 options.img_uri = "/images-nc/bg.gif"; 7444 options.img_uri_big = "/images-nc/hires_ok.png?&fill=" + GIGO.fill(1600, "x"); 7445 options.img_bad_uri = "/images-nc/hires_bad.png"; 7446 7447 // Determine if we can use an alternate v6mtu defined by the site config (options -> v6mtu) 7448// options.v6mtu = GIGO.mirrorconfig("options","v6mtu","ipv6." + options.subdomain); 7449 7450 7451 7452 // options.uri = "/report-ip.php?callback=?"; // Alternative to mod_ip 7453 options.url.test_a = GIGO.protocol+"ipv4." + options.subdomain + options.uri; 7454 options.url.test_aaaa = GIGO.protocol+"ipv6." + options.subdomain + options.uri; 7455 options.url.test_ds = GIGO.protocol+"ds." + options.subdomain + options.uri; 7456 7457 7458 options.url.test_v6ns = GIGO.protocol+"ds.v6ns." + options.subdomain + options.uri; 7459 options.url.test_v6mtu = GIGO.protocol+"mtu1280." + options.subdomain + options.uri + "&size=1600&fill=" + GIGO.fill(1600, "x"); 7460 options.url.test_dsmtu = GIGO.protocol+"ds." + options.subdomain + options.uri + "&size=1600&fill=" + GIGO.fill(1600, "x"); 7461 options.url.test_ood=""; // Dummy 7462 7463 7464 // ASN lookups are corrently broken. 7465 options.url.test_asn4 = GIGO.protocol+"ipv4.lookup.test-ipv6.com" + options.uri + "&asn=1"; 7466 options.url.test_asn6 = GIGO.protocol+"ipv6.lookup.test-ipv6.com" + options.uri + "&asn=1"; 7467 7468 7469 options.url.test_a_img = GIGO.protocol+"ipv4." + options.subdomain + options.img_uri; 7470 options.url.test_aaaa_img = GIGO.protocol+"ipv6." + options.subdomain + options.img_uri; 7471 options.url.test_ds_img = GIGO.protocol+"ds." + options.subdomain + options.img_uri; 7472 options.url.test_v6ns_img = GIGO.protocol+"ds.v6ns." + options.subdomain + options.img_uri; 7473 options.url.test_v6mtu_img = GIGO.protocol+"mtu1280." + options.subdomain + options.img_uri_big; 7474 options.url.test_dsmtu_img = GIGO.protocol+"ds." + options.subdomain + options.img_uri_big; 7475 options.url.test_ood_img = GIGO.ood_url() 7476 7477 7478 7479 7480 7481}; 7482 7483GIGO.fix_comment_form_and_tab = function () { 7484 if (MirrorConfig.options.comment) { 7485 jQuery("#tabbutton_mail_link").show(); 7486 7487 var url = MirrorConfig.options.comment; 7488 if (MirrorConfig.options.userdata) { 7489 if (GIGO.results.ipv4.ip) { 7490 url = GIGO.protocol+"ipv4." + MirrorConfig.options.userdata + "/comment.php"; 7491 } else if (GIGO.results.ipv6.ip) { 7492 url = GIGO.protocol+"ipv6." + MirrorConfig.options.userdata + "/comment.php"; 7493 } else { 7494 url = GIGO.protocol+"ds." + MirrorConfig.options.userdata + "/comment.php"; 7495 } 7496 } 7497 7498 $('#commentform').get(0).setAttribute('action', url); 7499 7500 } else { 7501 jQuery("#tabbutton_mail_link").hide(); 7502 jQuery("a.tabbutton_mail").hide(); 7503 } 7504 7505}; 7506 7507 7508GIGO.test_ipv6_gui = function (options) { 7509 // Check options 7510 if (!GIGO.isdef(options)) { 7511 options = {}; 7512 } 7513 GIGO.options = options; 7514 GIGO.set_default_options(options); 7515 7516 7517 7518 // Start real workload 7519 jQuery(document).ready(function () { 7520 // Primitive hack to avoid the web bots from comment spamming 7521 jQuery("[name=nobots]").val("serious"); 7522 if (GIGO.is_replay()) { 7523 jQuery("#replay").show(); 7524 } 7525 7526 // Possibly, kill that tab instead. 7527 // GIGO.fix_comment_form_and_tab(); 7528 GIGO.fix_footer_early(); 7529 GIGO.start_helpdesk(); 7530 GIGO.setup_tests(); 7531 GIGO.start_tests(); 7532 GIGO.pulse_on(); 7533 }); 7534}; 7535 7536GIGO.redirect = function (page) { 7537 var newurl, oldpath, newpath; 7538 newurl = document.location.protocol; 7539 newurl = newurl + "://"; 7540 newurl = newurl + document.location.hostname; 7541 if (document.location.port !== 80) { 7542 newurl = newurl + ":" + document.location.port; 7543 } 7544 7545 oldpath = String(document.location.pathname); 7546 newpath = oldpath.replace(/[^\/]+$/, ""); 7547 newpath = newpath + page; 7548 newpath = newpath.replace(/\/+/g, "/"); 7549 7550 document.location = newpath; 7551 7552 7553}; 7554 7555 7556 7557// end of base.js
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.