Modern.IE static code scan goes Open Source!

This commit is contained in:
molant 2013-07-24 19:16:32 -07:00
Коммит e6c0fee129
153 изменённых файлов: 34815 добавлений и 0 удалений

3
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,3 @@
/node_modules/
/.idea/
/lib/cvlists.json

68
Gruntfile.js Normal file
Просмотреть файл

@ -0,0 +1,68 @@
/*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
module.exports = function (grunt) {
"use strict";
// Project configuration.
grunt.initConfig({
pkg:grunt.file.readJSON('package.json'),
nodeunit:{
all:['test/**/*.js'],
libs:['test/**/checklibs*.js'],
compat:['test/**/compatlist*.js'],
cssprefixes:['test/**/cssprefixes*.js'],
doctype:['test/**/doctype*.js'],
favicon:['test/**/ie10favicon*.js'],
pluginfree:['test/**/pluginfree*.js'],
rwd:['test/**/responsive*.js'],
touch:['test/**/touch*.js'],
auth:['test/**/auth*.js']
},
watch:{
files:'<%= lint.files %>',
tasks:'jshint'
},
jshint:{
files: [
'grunt.js',
'lib/**/*.js',
'test/**/*.js'
],
options:{
strict: false,
curly:true,
eqeqeq:true,
immed:true,
latedef:true,
newcap:true,
noarg:true,
sub:true,
undef:true,
boss:true,
eqnull:true,
node: true,
globals: {
setImmediate: true,
exports:true
}
},
}
});
grunt.loadNpmTasks('grunt-contrib-nodeunit');
grunt.loadNpmTasks("grunt-contrib-watch");
grunt.loadNpmTasks("grunt-contrib-jshint");
// Default task.
grunt.registerTask('default', ['jshint', 'nodeunit']);
};

12
LICENSE Normal file
Просмотреть файл

@ -0,0 +1,12 @@
Copyright (c) Microsoft Corporation; All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.

56
README.md Normal file
Просмотреть файл

@ -0,0 +1,56 @@
# Modern.ie
The Modern.ie scan analyzes the HTML, CSS, and JavaScript of a site or application to
determine whether it is using good development practices.
It warns about practices such as incomplete specification of CSS properties, invalid or incorrect
doctypes, and obsolete versions of popular JavaScript libraries.
It's easiest to use Modern.ie by going to the [Modern.ie site](http://Modern.ie)
and entering the URL to scan there. To customize the scan, or to use the scan
to process files behind a firewall, you can clone and build the files from this repo
and run the scan locally.
## How it works
The Modern.ie local scan runs on a system behind your firewall; that system must have
access to the internal web site or application that is to be scanned.
Once the files have been analyzed, the analysis results are sent back to the Modern.ie
site to generate a complete formatted report that includes advice on remediating any issues.
The report generation code and formatted pages from the Modern.IE site are not included in this repo.
Since the local scan generates JSON output, you can alternatively use it as a standalone scanner
or incorporate it into a project's build process by processing the JSON with a local script.
The main service for the scan is in the `lib/service.js` file; it acts as an HTTP server.
It loads the contents of the web page and calls the individual tests, located in `/lib/checks/`.
Once all the checks have completed, it responds with a JSON object representing the results.
## Installation and configuration
* [Install node.js](https://github.com/joyent/node/wiki/Installation). You can use a [pre-compiled Windows executable](https://github.com/joyent/node/wiki/Installation#installing-on-windows) if desired. Version 0.10 or higher is required.
* [Install git](http://git-scm.com/downloads). You can choose [GitHub for Windows](http://windows.github.com/) instead if you prefer.
* Clone this repository.
* Install dependencies. From the Modern.ie subdirectory, type: `npm install`
* If desired, set an environment variable `PORT` to define the port the service will listen on. By default the port number is 1337. The Windows command to set the port to 8181 would be: `set PORT=8181`
* Start the scan service: From the Modern.ie subdirectory, type: `node lib/service.js` and the service should respond with a status message containing the port number it is using.
* Run a browser and go to the service's URL; assuming you are using the default port and are on the same computer, the URL would be: `http://localhost:1337/`
* Follow the instructions on the page.
## Testing
The project contains a set of unit tests in the `/test/` directory. To run the unit tests, type `grunt nodeunit`.
## JSON output
Once the scan completes, it produces a set of scan results in JSON format:
```js
{
"testName" : {
"testName": "Short description of the test",
"passed" : true/false,
"data": { /* optional data describing the results found */ }
}
}
```
The `data` property will vary depending on the test, but will generally provide further detail about any issues found.

1
cvlists.json Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -0,0 +1,144 @@
/**
* Description: Checks if a website is using browser sniffing in its JavaScript.
* To determine this we look for known patterns (like navigator.userAgent).
* We only look for JavaScript files in the same domain that the website.
* If a website www.domain.com embeds scripts from www.domain.com, script.domain.com
* and ad.server.com, only those in www.domain.com will be analyzed.
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
"use strict";
var Deferred = require('promised-io').Deferred,
Promise = require('promised-io/promise'),
request = require('request'),
url = require('url'),
rules = [
"navigator.userAgent",
"navigator.appVersion",
"navigator.appName",
"navigator.product",
"navigator.vendor",
"$.browser",
"Browser."
],
exceptions = [
"ajax.googleapis.com",
"ajax.aspnetcdn.com",
"ajax.microsoft.com",
"jquery",
"mootools",
"prototype",
"protoaculous"
];
request = request.defaults({
jar: false,
headers: {
'Accept-Language': 'en-US,en;q=0.5',
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)'}
});
function checkScript(url) {
var deferred = new Deferred();
//TODO: we should be using the predownloaded JS
request(url, function (error, res, body) {
// See if this script has any of our known libraries
var scriptText = body || "",
browserDetectionPassed = true,
ruleIndex,
lineNumber;
if (error) {
deferred.resolve({
passed: false,
pattern: 'Error parsing',
lineNumber: -1,
url: url
});
} else {
for (var i = 0; i < rules.length; i++) {
ruleIndex = scriptText.indexOf(rules[i]);
if (ruleIndex !== -1) {
browserDetectionPassed = false;
lineNumber = scriptText.substr(0, ruleIndex).split('\n').length;
break;
}
}
if (!browserDetectionPassed) {
deferred.resolve({
passed: false,
pattern: rules[i],
lineNumber: lineNumber,
url: res.request.href
});
} else {
deferred.resolve({
passed: true,
url: res.request.href
});
}
}
});
return deferred;
}
var check = function (website) {
var needsToBeProcessed = true;
var scripts = website.$("script"),
scriptPromises = [], src;
for (var i = 0; i < scripts.length; i++) {
src = scripts.eq(i).attr("src");
needsToBeProcessed = true;
//check if it is local, cdn or library
if (src) {
if (src.indexOf('http') === -1 && src.indexOf('//') === -1) {
src = url.resolve(website.url, src);
for (var j = 0; j < exceptions.length; j++) {
if (src.indexOf(exceptions[j]) !== -1) {
needsToBeProcessed = false;
break;
}
}
if (needsToBeProcessed) {
scriptPromises.push(checkScript(src));
}
}
}
}
return Promise.all(scriptPromises).then(function (promises) {
var test = {
testName: "browserDetection",
passed: true,
data: []
};
for (var a = 0; a < promises.length; a++) {
var pm = promises[a];
if (!pm.passed) {
test.passed = false;
}
test.data.push(pm);
}
return test;
});
};
module.exports.check = check;

Просмотреть файл

@ -0,0 +1,64 @@
/**
* Description: This check looks for the X-UA-Compatible meta tag in the HTML,
* and also checks whether/why the site is on the Microsoft CV list.
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
"use strict";
var cvlist = require('./compatlist.js'),
Deferred = require('promised-io').Deferred;
var initiate = function (website) {
var deferred = new Deferred(),
test = {
testName: "cvlist",
passed: true,
data: {}
};
//TODO: The compat tag may not be recognized if it is "too far down" the page; detect this.
var compatTag = website.$('meta[http-equiv]').filter(function(){
return this[0].attribs['http-equiv'].toLowerCase() === 'x-ua-compatible';
});
if (compatTag.length > 0) {
if (compatTag[0].attribs.content) {
var mode = compatTag[0].attribs.content.toLowerCase();
if (mode.indexOf("edge") === -1) {
test.passed = false;
test.data = { source: 'tag', mode: mode};
deferred.resolve(test);
return deferred.promise;
}
}
}
cvlist.getList().then(function (list) {
var resultWebsite = list[website.url.hostname.replace('-', '_').replace('www.', '')];
if (resultWebsite && (resultWebsite.docMode || resultWebsite.uaString || Object.keys(resultWebsite).length === 0)) {
test.passed = false;
test.data = {source: 'cvlist', mode: resultWebsite.docMode};
}
deferred.resolve(test);
}, function () {
deferred.reject();
});
return deferred.promise;
};
module.exports.check = initiate;

Просмотреть файл

@ -0,0 +1,162 @@
/**
* Description: This check looks for any missing vendor prefix (-webkit-, -moz-, -o-, -ms-) for the following CSS rules:
* transform, animation, transition-property, transition-duration, transition-timing-function, transition-delay, transition,
* linear-gradient, radial-gradient, gradient
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
"use strict";
// NB: PropMap/ExprMap information from caniuse.com
var Deferred = require('promised-io').Deferred,
vendorPrefixMatcher = /^(-\w+-)?((\w+)[\w\-]*)/,
// Properties may have following `-terms` (e.g., transition-delay)
prefixedPropMap = {
"animation": "-webkit-",
"perspective": "-ms- -webkit-",
"transform": "-ms- -webkit-",
"transition": "-webkit-"
},
// Expression terms are the entire name with optional prefix
prefixedExprMap = {
"linear-gradient": "-webkit-",
"radial-gradient": "-webkit-"
};
function htmlEncode(encodedHtml) {
if (typeof encodedHtml === 'undefined') {
return;
}
return encodedHtml.replace(/\//g, "%2F")
.replace(/\?/g, "%3F")
.replace(/\=/g, "%3D")
.replace(/&/g, "%26")
.replace(/@/g, "%40")
.replace(/</g, "")
.replace(/>/g, "");
}
function checkPrefixes(list, matcher, prefixMap, selector, add) {
var prefixList = {},
problems = [];
for ( var i = 0; i < list.length; i++ ) {
var item = list[i],
match = matcher.exec(item) || [],
unprefixed = match[2],
prefixesLeft = prefixList[unprefixed],
prefixesNeeded = prefixMap[unprefixed] || match[3] && prefixMap[match[3]];
if ( prefixesNeeded ) {
// We want to track prefixing for this property
if ( prefixesLeft === undefined ) {
// First time we've seen this property in the rule
prefixesLeft = prefixList[unprefixed] = prefixesNeeded + " " + unprefixed;
}
// Remove this prefix (or unprefixed value) if it is a required one
prefixList[unprefixed] = prefixesLeft.replace(new RegExp(match[1] || "\\b" + unprefixed + "\\b"), "");
}
}
// See if any rules are missing prefixed equivalents or vice-versa
for ( var p in prefixList ) {
// Use the full prefixed property name for reporting
// e.g. in: " -ms- transform", out: "-ms-transform transform"
var needed = prefixList[p].replace(/-(\s|$)/g, "-" + p + " ").trim().replace(/\s+/g, " ");
if ( needed ) {
add(selector, needed);
}
}
return problems;
}
function checkRules(css) {
var rules = css.css.cssRules,
report = {
cssFile: css.cssUrl,
selectors: []
},
start = 0,
// Function to add a problem report for this rule
addProblem = function(selector, missing) {
report.selectors.push({
selector: htmlEncode(selector),
styles: missing.split(" "),
lineNumber: css.cssBody.substr(0, start).split('\n').length
});
};
// Process each rule in the sheet: `selectors { prop: expr; ... }`
for ( var r=0; r < rules.length; r++ ) {
// CSSStyleDeclaration
var decls = rules[r].style || [];
// Set the starting character point for this declaration in the sheet
start = decls.__starts || 1;
// Check for prefixes on all the properties
checkPrefixes(
decls,
vendorPrefixMatcher,
prefixedPropMap,
rules[r].selectorText,
addProblem
);
// Check for prefixes on expressions in non-prefixed properties; see loadcss.js for
// details on how we are saving duplicate declarations using ~prop.
for ( var p = 0; p < decls.length; p++ ) {
var prop = decls[p];
if ( !/^-/.test(prop) ) {
checkPrefixes(
decls["~"+prop] || [ decls[prop] || "" ],
vendorPrefixMatcher,
prefixedExprMap,
rules[r].selectorText,
addProblem
);
}
}
}
return report;
}
function check(website) {
var deferred = new Deferred();
// Let the main loop run before we do this work
setImmediate(function() {
var test = {
testName: "cssprefixes",
passed: true,
data: []
};
for ( var i = 0; i < website.css.length; i++ ) {
var result = checkRules(website.css[i]);
if ( result.selectors.length ) {
test.passed = false;
test.data.push(result);
}
}
deferred.resolve(test);
});
return deferred.promise;
}
module.exports.check = check;

116
lib/checks/check-doctype.js Normal file
Просмотреть файл

@ -0,0 +1,116 @@
/**
* Description: Checks the doctype of website to see if the site is in Quirks mode.
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
"use strict";
var Deferred = require('promised-io').Deferred;
// Comments or newlines before doctype are allowed, as well as an xml header for XHTML docs.
// IE6 will always quirk out on an XML header but let's assume everyone is past that.
// SEE http://msdn.microsoft.com/en-us/library/ie/ms535242(v=vs.85).aspx
var spaces = '[\\s\\r\\n]*',
comment = '(?:' + spaces + '<!--(?:.|[\\r\\n])*-->)*',
xmltag = '(?:<?xml(?:.|[\\r\\n])*?>)?',
doctype = '<!doctype html' + spaces + '([^>]*)>',
// _, doctype-innards
headRE = new RegExp('^' + comment + spaces + xmltag + spaces + doctype),
// _, public|system, "public identifier", "system identifier"?
pubsysRE = new RegExp('^(public|system)' + spaces + '"([^"]*)"' + spaces + '("[^"]*")?'),
// _, (x)html, version, variant (e.g., "transitional")
pubidRE = new RegExp('-//w3c//dtd (x?html)\\S*\\s*([\\d\\.]+)?\\s*(\\w+)?//en'),
// Literal pubids that pass standards
pubidMap = {
"iso/iec 15445:1999//dtd hypertext markup language//en": true,
"iso/iec 15445:1999//dtd html//en": true,
"-//ietf//dtd html i18n//en": true,
"-//unknown//en": true
};
var check = function (website) {
var deferred = new Deferred(),
// Don't waste time looking through the whole doc; the doctype should be early
head = website.content.slice(0, 2000).trim().toLowerCase(),
dt = headRE.exec(head),
result = {
testName: "doctype",
passed: false,
data: {
lineNumber: -1,
mode : [ "No doctype" ]
}
};
if (dt) {
// Since the regexp matched this should succeed as well
result.data.lineNumber = head.substr(0,head.indexOf("<!doctype")).split('\n').length;
if ( !dt[1] ) {
// <!doctype html> (plain old html5 doctype without any following junk)
result.passed = true;
result.data.mode = [ "html5" ];
} else {
// Assume failure for simplicity
result.data.mode = [ "Invalid or Quirks doctype" ];
// Should have PUBLIC or SYSTEM plus identifier(s)
var pubsys = pubsysRE.exec(dt[1]) || [],
puborsys = pubsys[1],
pubid = pubsys[2],
sysid = pubsys[3];
if ( puborsys === "system" ) {
// Any SYSTEM doctypes are considered to be standards mode
result.passed = true;
result.data.mode = [ "html (system)" ];
} else if ( pubid === "" && sysid === undefined ) {
// <!doctype public ""> is standards mode
result.passed = true;
result.data.mode = [ "html5 (long form)" ];
} else if ( pubidMap[pubid] ) {
// One of the "OMG standards mode" bizarro doctypes
result.passed = true;
result.data.mode = [ "html standards" ];
} else if ( pubsys.length && pubid ) {
// Drill into the pubid to see if it's standards mode
var pubdata = pubidRE.exec(pubid) || [],
htmltype = pubdata[1],
version = pubdata[2],
variant = pubdata[3],
standards = pubdata.length > 0;
if ( htmltype === "html" ) {
if ( +version < 4.0 ) {
// Anything less than HTML4 is not standards
standards = false;
} else if ( version === "4.0" || version === "4.01" ) {
// HTML4 is only standards for frameset/transitional if a system id is provided
if ( /frameset|transitional/.test(variant) && !sysid ) {
standards = false;
}
}
}
result.passed = standards;
result.data.mode = [(htmltype + " " + version + " " + variant).trim()];
}
}
}
deferred.resolve(result);
return deferred.promise;
};
module.exports.check = check;

Просмотреть файл

@ -0,0 +1,46 @@
/**
* Description: Look for the presence of a tile meta tag for IE10 and Win8.
* Note if a Retina icon for iOS devices has been specified so it can be reused.
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
"use strict";
var Deferred = require('promised-io').Deferred;
var check = function (website) {
var deferred = new Deferred();
var tile = website.$('meta[name="msapplication-TileImage"]'),
iOS = website.$('link[rel*="apple-touch-icon"]'),
test = {
testName:"ie10favicon",
passed:false,
data: {iOS : false}
};
if (tile.length > 0) {
test.passed = true;
}
if(iOS.length > 0){
test.data.iOS = true;
}
deferred.resolve(test);
return deferred.promise;
};
module.exports.check = check;

204
lib/checks/check-libs.js Normal file
Просмотреть файл

@ -0,0 +1,204 @@
/**
* Description: Check for most common libraries and frameworks to verify site is
* using a version without known compatibility issues with IE9/10.
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
"use strict";
var Deferred = require('promised-io').Deferred;
function checkVersion(library, version) {
var vinfo = {
name: library.name,
needsUpdate: true,
minVersion: library.minVersions[0].major + library.minVersions[0].minor,
version: version
};
if (library.patchOptional) {
// If lib can have an implied ".0", add it when needed
// match 1.17, 1.17b2, 1.17-beta2; not 1.17.0, 1.17.2, 1.17b2
var parts = version.match(/(\d+\.\d+)([^\d\.](.*))$/);
if (parts) {
version = parts[1] + ".0" + parts[2];
}
}
for (var i = 0; i < library.minVersions.length; i++) {
var gv = library.minVersions[i];
if (version.indexOf(gv.major) === 0) {
vinfo.minVersion = gv.major + gv.minor;
vinfo.needsUpdate = +version.slice(gv.major.length) < +gv.minor;
break;
}
}
return vinfo;
}
var libraries = [
{
name: "jQuery",
minVersions: [
{ major: "1.6.", minor: "4" },
{ major: "1.7.", minor: "2" },
{ major: "1.8.", minor: "2" },
{ major: "1.9.", minor: "1" },
{ major: "1.10.", minor: "2" },
{ major: "2.0.", minor: "3" }
],
patchOptional: true,
check: function (scriptText) {
var version = scriptText.match(/jquery:\s*"([^"]+)/);
return version && checkVersion(this, version[1]);
}
},
{
name: "jQuery UI",
minVersions: [
{ major: "1.8.", minor: "24" },
{ major: "1.9.", minor: "2" },
{ major: "1.10.", minor: "3" }
],
check: function (scriptText) {
var version = scriptText.match(/\.ui,[\s\r\n]*\{[\s\r\n]*version:\s*"([^"]+)/m);
return version && checkVersion(this, version[1]);
}
},
{
name: "Prototype",
minVersions: [
{ major: "1.7.", minor: "1" }
],
check: function (scriptText) {
var version = scriptText.match(/Prototype JavaScript framework, version (\d+\.\d+\.\d+)/m);
return version && checkVersion(this, version[1]);
}
},
{
name: "Dojo",
minVersions: [
{ major: "1.5.", minor: "2" },
{ major: "1.6.", minor: "1" },
{ major: "1.7.", minor: "3" },
{ major: "1.8.", minor: "0" }
],
check: function (scriptText) {
var version = scriptText.match(/\.version\s*=\s*\{\s*major:\s*(\d+)\D+(\d+)\D+(\d+)/m);
return version && checkVersion(this, version[1] + "." + version[2] + "." + version[3]);
}
},
{
name: "Mootools",
minVersions: [
{ major: "1.2.", minor: "6" },
{ major: "1.4.", minor: "5" }
],
check: function (scriptText) {
var version = scriptText.match(/this.MooTools\s*=\s*\{version:\s*'(\d+\.\d+\.d+)/m);
return version && checkVersion(this, version[1]);
}
},
{
name: "SWFObject",
minVersions: [
{ major: "2.", minor: "2" }
],
check: function (scriptText) {
var version = scriptText.match(/\*\s+SWFObject v(\d+\.\d+)/m);
return version && checkVersion(this, version[1]);
}
},
{
name: "jQuery Form Plugin",
minVersions: [
{ major: "3.", minor: "22" }
],
check: function (scriptText) {
var version = scriptText.match(/Form Plugin\s+\*\s+version: (\d+\.\d+)/m);
return version && checkVersion(this, version[1]);
}
},
{
name: "Modernizr",
minVersions: [
{ major: "2.5.", minor: "2" },
{ major: "2.6.", minor: "2" }
],
check: function (scriptText) {
// Static analysis. :( The version is set as a local variable, far from
// where Modernizr._version is set. Just see if we have a commment header.
// ALT: look for /VAR="1.2.3"/ then for /._version=VAR/ ... ugh.
var version = scriptText.match(/\*\s*Modernizr\s+(\d+\.\d+\.d+)/m);
return version && checkVersion(this, version[1]);
}
}
];
function checkScript(js, website) {
var status = {
passed: true,
data: null
};
// See if this script has any of our known libraries
for (var i = 0; i < libraries.length; i++) {
var lib = libraries[i],
result;
if ( js.jsUrl !== "embed" ) {
result = lib.check.call(lib, js.code || "");
if ( result && result.needsUpdate ) {
var pos = website.content.indexOf(js.href),
lineNumber = website.content.substr(0, pos).split('\n').length;
result.url = js.finalUrl;
result.lineNumber = lineNumber;
status.data = result;
status.passed = false;
break;
}
}
}
return status;
}
var check = function (website) {
var deferred = new Deferred();
// Let the main loop run before we do this work
setImmediate(function() {
var test = {
testName: "jslibs",
url: website.url.href,
passed: true,
data: []
},
result;
for (var i = 0; i < website.js.length; i++) {
result = checkScript(website.js[i], website);
if ( !result.passed ) {
test.passed = false;
test.data.push(result.data);
}
}
deferred.resolve(test);
});
return deferred.promise;
};
module.exports.check = check;

Просмотреть файл

@ -0,0 +1,115 @@
/**
* Description: Looks for:
* 1) Compatibility issues related to ActiveX plugins in the CV lists
* 2) Any plugin or ActiveX control different than Flash or SVG
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
"use strict";
var cvlist = require('./compatlist.js'),
Deferred = require('promised-io').Deferred,
$ = require('cheerio');
var initiate = function (website) {
var deferred = new Deferred(),
test = {
testName: "pluginfree",
passed: true,
data: []
};
function removeItems(original, itemsToRemove) {
var cleaned = [],
remove;
for (var i = 0; i < original.length; i++) {
remove = true;
for (var j = 0; j < itemsToRemove.length; j++) {
if (original[i] === itemsToRemove[j]) {
remove = false;
break;
}
}
if (remove) {
cleaned.push(original[i]);
}
}
return cleaned;
}
cvlist.getList().then(function (list) {
var resultWebsite = list[website.url.hostname.replace('-', '_').replace('www.', '')];
if (resultWebsite && (resultWebsite.noFlash || (resultWebsite.featureSwitch && resultWebsite.featureSwitch === "requiresActiveX:true"))) {
test.passed = false;
test.data = {activex: !resultWebsite.noFlash , cvlist: true};
} else {
var $objects = website.$('object'),
$embeds = website.$('embed'),
$objectParams = website.$('object param[value*=swf]'),
$objectSWFparams = website.$('object[data*=swf]'),
$objectSVGparams = website.$('object[data*=svg]'),
$embedsSWF = website.$('embed[src*=swf]'),
$embedsSVG = website.$('embed[src*=svg]');
var activeXcontrols = $objects.length - $objectParams.length - $objectSWFparams.length - $objectSVGparams.length + $embeds.length - $embedsSWF.length - $embedsSVG.length;
if (activeXcontrols > 0) {
var endPoint, lines,
objectsToRemove = $objectParams.toArray().concat($objectSWFparams.toArray(), $objectSVGparams.toArray()),
embedsToRemove = $embedsSWF.toArray().concat($embedsSVG.toArray()),
uniqueObjects = removeItems($objects, objectsToRemove),
uniqueEmbeds = removeItems($embeds, embedsToRemove),
objectHtml = $.html($(uniqueObjects[0])),
embedHtml = $.html($(uniqueEmbeds[0])),
objectRegex = new RegExp(objectHtml, "gi"),
embedRegex = new RegExp(embedHtml, "gi"),
matches;
if (objectHtml !== "") {
matches = objectRegex.exec(website.content);
if (matches && matches.length > 0) {
endPoint = website.content.indexOf(matches[0]);
}
} else {
if (embedHtml !== "") {
matches = embedRegex.exec(website.content);
if (matches && matches.length > 0) {
endPoint = website.content.indexOf(matches[0]);
}
}
}
lines = website.content.substr(0, endPoint)
.split('\n').length;
test.passed = false;
test.data = {activex: true, cvlist: false, lineNumber: lines};
}
}
deferred.resolve(test);
},
function
() {
deferred.reject();
}
)
;
return deferred.promise;
}
;
module.exports.check = initiate;

Просмотреть файл

@ -0,0 +1,190 @@
/**
* Description: Look for known patterns used for RWD. Files added dynamically are not analyzed.
* 1) Look for media queries related to the size of the screen (min-width and max-width).
* If the website doesn't have any then the test is not passed.
* 2) If the website has CSS media queries, look for the min/max break points in those.
* Compare the website's breakpoints to the sizes 320, 480, 640 and 768 +- 25%.
* If any resolution doesn't have any breakpoint within the margin, flag a possible issue
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
"use strict";
var Deferred = require('promised-io').Deferred,
checklist = [320, 480, 640, 768, 960],
percentage = 0.25,
checklistMinPercentage = [],
checklistMaxPercentage = [],
maxWidth = /max-width\s*:\s*(.*)\).*/i,
minWidth = /min-width\s*:\s*(.*)\).*/i;
for (var i = 0; i < checklist.length; i++) {
checklistMinPercentage.push(checklist[i] * (1 - percentage));
}
for (i = 0; i < checklist.length; i++) {
checklistMaxPercentage.push(checklist[i] * (1 + percentage));
}
function analyzeMediaQuery(media, test) {
var regexResult = minWidth.exec(media),
value = 0;
if (regexResult) {
if (regexResult[1].indexOf('px') !== -1) {
value = parseFloat(regexResult[1].replace('px', ''));
} else if (regexResult[1].indexOf('em') !== -1) {
value = parseFloat(regexResult[1].replace('em', '')) * 16;
}
test.data.minBreakPoints.push(value);
}
regexResult = maxWidth.exec(media);
if (regexResult) {
if (regexResult[1].indexOf('px') !== -1) {
value = parseFloat(regexResult[1].replace('px', ''));
} else if (regexResult[1].indexOf('em') !== -1) {
value = parseFloat(regexResult[1].replace('em', '')) * 16;
}
test.data.maxBreakPoints.push(value);
}
}
function checkCSS(css, test) {
var found = false;
for (var i = 0; i < css.length; i++) {
if (css[i].media) {
for (var j = 0; j < css[i].media.length; j++) {
if (css[i].media[j].indexOf('min-width') !== -1 || css[i].media[j].indexOf('max-width') !== -1) {
found = true;
analyzeMediaQuery(css[i].media[j], test);
}
}
}
}
return found;
}
function sort(a, b) {
return a - b;
}
function removeDuplicates(list) {
for (i = list.length; i > 0; i--) {
if (list[i - 1] === list[i]) {
list.splice(i, 1);
}
}
}
function consolidate(tempSpectrum) {
var spectrum = [];
spectrum.push(tempSpectrum[0]);
for (var i = 1, j = 0; i < tempSpectrum.length; i++) {
if (tempSpectrum[i] && tempSpectrum[i].start <= spectrum[j].end) {
spectrum[j].end = Math.max(tempSpectrum[i].end, spectrum[j].end);
} else {
spectrum.push(tempSpectrum[i]);
j++;
}
}
return spectrum;
}
function mergeSpectrums(spectrum1, spectrum2) {
var tempSpectrum = spectrum1.concat(spectrum2);
tempSpectrum.sort(function (a, b) {
return a.start - b.start;
});
return consolidate(tempSpectrum);
}
function createSpectrum(test) {
var minBreakPoints = test.data.minBreakPoints,
maxBreakPoints = test.data.maxBreakPoints,
spectrumMin = [],
spectrumMax = [];
for (var i = 0; i < minBreakPoints.length; i++) {
spectrumMin.push({
start: minBreakPoints[i],
end: minBreakPoints[i] * (1 + percentage)
});
}
for (i = 0; i < maxBreakPoints.length; i++) {
spectrumMax.push({
start: maxBreakPoints[i] * (1 - percentage),
end: maxBreakPoints[i]
});
}
return mergeSpectrums(spectrumMin, spectrumMax);
}
function analyzeBreakPoints(test) {
test.data.minBreakPoints.sort(sort);
test.data.maxBreakPoints.sort(sort);
removeDuplicates(test.data.minBreakPoints);
removeDuplicates(test.data.maxBreakPoints);
test.data.spectrum = createSpectrum(test);
}
function check(website) {
var deferred = new Deferred();
// Let the main loop run before we do this work
setImmediate(function() {
var test = {
testName: "responsive",
passed: false,
data: {
minBreakPoints: [],
maxBreakPoints: [],
spectrum: []
}
},
passed;
for (var i = 0; i < website.css.length; i++) {
//CSS files can be included indicating directly the media. We check first for that:
//Ex: <link rel="stylesheet" media="only screen and (min-width: 480px)" href="480.css?v1.0">
var media = website.css[i].media;
if (media && (media.indexOf('min-width') !== -1 || media.indexOf('max-width') !== -1)) {
test.passed = true;
analyzeMediaQuery(media, test);
} else {
passed = checkCSS(website.css[i].css.cssRules, test);
if (passed && !test.passed) {
test.passed = true;
}
}
}
if (test.data.minBreakPoints.length > 0 || test.data.maxBreakPoints.length > 0) {
analyzeBreakPoints(test);
}
deferred.resolve(test);
});
return deferred.promise;
}
module.exports.check = check;

137
lib/checks/check-touch.js Normal file
Просмотреть файл

@ -0,0 +1,137 @@
/**
* Description: Look for known patterns of use for the Pointers API in CSS and JS files.
* (Keep in mind that files added dynamically are not analyzed.)
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
"use strict";
var Deferred = require('promised-io').Deferred,
cssRules = ['-ms-touch-action',
'-ms-scroll-snap-points-x',
'-ms-scroll-snap-points-y',
'-ms-scroll-snap-type',
'-ms-scroll-snap-x',
'-ms-scroll-snap-y',
'-ms-scroll-chaining',
'-ms-content-zooming',
'-ms-content-zoom-limit',
'-ms-content-zoom-limit-max',
'-ms-content-zoom-limit-min',
'-ms-content-zoom-chaining',
'-ms-content-zoom-snap-points',
'-ms-content-zoom-snap-type',
'-ms-content-zoom-snap'],
jsRules = [/MSgesture/g,
/MSPointer/g,
/msContentZoomFactor/g,
/navigator.msPointerEnabled/g,
/navigator.msMaxTouchPoints/g];
function checkCSS(css) {
var selectors = css.css.cssRules,
styleToCheck,
styleChecking,
selectorStyles,
currentStyle,
containsRule,
touchImplemented = false;
for (var selectorIndex = 0; selectorIndex < selectors.length; selectorIndex++) {
//if the selector is a media it will not have the property style
//it will have another array of cssRules but they selectors should be
//also in the common cssRules
if (touchImplemented) {
break;
}
if (selectors[selectorIndex].style) {
selectorStyles = selectors[selectorIndex].style;
for (var selectorStylesIndex = 0; selectorStylesIndex < selectorStyles.length; selectorStylesIndex++) {
if (touchImplemented) {
break;
}
currentStyle = selectorStyles[selectorStylesIndex];
for (var cssRuleIndex = 0; cssRuleIndex < cssRules.length; cssRuleIndex++) {
styleToCheck = cssRules[cssRuleIndex];
styleChecking = selectorStyles[currentStyle];
containsRule = currentStyle.indexOf(styleToCheck);
if (containsRule !== -1) {
touchImplemented = true;
break;
}
}
}
}
}
return touchImplemented;
}
function checkJS(js) {
var touchImplemented = false;
for (var i = 0; i < jsRules.length; i++) {
touchImplemented = jsRules[i].test(js.code);
if (touchImplemented) {
break;
}
}
return touchImplemented;
}
function check(website) {
var deferred = new Deferred(),
result = [];
var test = {
testName: "touch",
passed: false
};
for (var i = 0; i < website.css.length; i++) {
result.push(checkCSS(website.css[i]));
}
for (i = 0; i < result.length; i++) {
if (result[i]) {
test.passed = true;
break;
}
}
if (!test.passed) {
for (i = 0; i < website.js.length; i++) {
result.push(checkJS(website.js[i]));
}
for (i = 0; i < result.length; i++) {
if (result[i]) {
test.passed = true;
break;
}
}
}
deferred.resolve(test);
return deferred.promise;
}
module.exports.check = check;

208
lib/checks/compatlist.js Normal file
Просмотреть файл

@ -0,0 +1,208 @@
/**
* Description: Downloads the Microsoft CV lists, which we query during testing to see
* if a website has to be run in compat mode or has any ActiveX/Flash issues.
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
"use strict";
var compatListUrlIE10 = "https://iecvlist.microsoft.com/ie10/1152921505002013023/iecompatviewlist.xml",
compatListUrlIE9 = "http://ie9cvlist.ie.microsoft.com/ie9CompatViewList.xml",
fs = require('fs'),
request = require('request'),
xml2js = require('xml2js'),
parser = new xml2js.Parser(),
Deferred = require('promised-io').Deferred,
ready,
cvlist = {},
cvlistFile = 'cvlists.json',
creationStamp,
expiration = 86400000; //1 day in milliseconds
request = request.defaults({
jar: false,
headers: {
'Accept-Language': 'en-US,en;q=0.5',
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)'}});
function saveCVList() {
var deferred = new Deferred();
fs.writeFile(cvlistFile, JSON.stringify(cvlist), function(err) {
if (err) {
console.log(err);
deferred.reject(err);
} else {
deferred.resolve();
}
});
return deferred.promise;
}
function getCompatListUrl(ieversion) {
var cvlistUrl;
switch (ieversion) {
case 'ie10':
cvlistUrl = compatListUrlIE10;
break;
case 'ie9':
cvlistUrl = compatListUrlIE9;
break;
default:
cvlistUrl = compatListUrlIE9;
break;
}
return cvlistUrl;
}
function addExplicitFlashBlockedSites(result) {
var array,
domain;
if (result.iecompatlistdescription && result.iecompatlistdescription.NoFlash) {
array = result.iecompatlistdescription.NoFlash[0].domain;
for (var i = 0; i < array.length; i++) {
domain = array[i]._ || array[i];
if (domain) {
domain = domain.trim().replace('-', '_');
if (cvlist[domain]) {
cvlist[domain].noFlash = true;
} else {
cvlist[domain] = {
noFlash: true
};
}
}
}
}
}
function addExplicitFlashApprovalSites(result) {
var array,
domain;
if (result.iecompatlistdescription && result.iecompatlistdescription.Flash) {
array = result.iecompatlistdescription.Flash[0].domain;
for (var i = 0; i < array.length; i++) {
domain = array[i]._ || array[i];
if (domain) {
domain = domain.trim().replace('-', '_');
if (cvlist[domain]) {
cvlist[domain].flash = true;
} else {
cvlist[domain] = {
flash: true
};
}
}
}
}
}
function addCompatSites(ieversion, result) {
var array = ieversion.indexOf('1') !== -1 ? result.iecompatlistdescription.domain : result.ie9compatlistdescription.domain;
for (var i = 0; i < array.length; i++) {
if (array[i]._) {
cvlist[array[i]._.replace('-', '_')] = array[i].$;
} else {
cvlist[array[i]] = {};
}
}
}
function downloadCVlist(ieversion) {
var deferred = new Deferred(),
cvlistUrl = getCompatListUrl(ieversion);
request(cvlistUrl, function(error, response, body) {
if (!error && response.statusCode === 200) {
parser.parseString(body, function(err, result) {
if (err) {
deferred.reject(err);
return;
}
addCompatSites(ieversion, result);
addExplicitFlashApprovalSites(result);
addExplicitFlashBlockedSites(result);
deferred.resolve(cvlist);
});
} else {
deferred.reject(error);
}
});
return deferred.promise;
}
function downloadCVlists() {
var deferred = new Deferred();
downloadCVlist('ie10')
.then(function() {
downloadCVlist('ie9');
})
.then(saveCVList).then(function() {
deferred.resolve();
});
return deferred.promise;
}
function getList() {
var deferred = new Deferred();
ready = false;
if (typeof cvlist === "object" && Object.keys(cvlist).length > 0 && Date.now() - creationStamp < expiration) {
deferred.resolve(cvlist);
} else {
fs.exists(cvlistFile, function(exists) {
if (exists) {
fs.stat(cvlistFile, function(err, stats) {
if (err) {
deferred.reject(err);
} else {
if (Date.now() - stats.mtime.getTime() > expiration) {
downloadCVlists().then(function() {
deferred.resolve(cvlist);
}, function(err) {
deferred.reject(err);
});
} else {
cvlist = fs.readFile(cvlistFile, function(err, data) {
if (err) {
cvlist = {};
deferred.reject(err);
}
cvlist = JSON.parse(data);
deferred.resolve(cvlist);
});
}
}
});
} else {
downloadCVlists().then(function() {
deferred.resolve(cvlist);
}, function(err) {
deferred.reject(err);
});
}
});
}
return deferred.promise;
}
module.exports.getList = getList;

31
lib/checks/loadchecks.js Normal file
Просмотреть файл

@ -0,0 +1,31 @@
/**
* Description: Load all the tests ("checks") that are to be done in the scan.
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
"use strict";
var fs = require('fs'),
tests = [],
path = require('path');
//path = process.cwd().indexOf('lib') !== -1 ? './checks/' : './lib/checks/';
fs.readdirSync(__dirname).forEach(function (file) {
if (file.indexOf('check') === 0) {
tests.push(require(path.join(__dirname, file)));
}
});
module.exports.tests = tests;

153
lib/checks/loadcss.js Normal file
Просмотреть файл

@ -0,0 +1,153 @@
/**
* Description: Load the external CSS files and embedded CSS to make them available
* for further analysis. Files added dynamically are not analyzed.
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
"use strict";
var request = require('request'),
cssom = require('cssom'),
promised = require("promised-io/promise"),
Deferred = require('promised-io').Deferred,
url = require('url'),
cssPromises;
request = request.defaults({
jar: false,
headers: {
'Accept-Language': 'en-US,en;q=0.5',
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)'}});
/*
* CSSOM normally eliminates duplicate declarations in a rule, accepting only the last.
* In our case we want to analyze _all_ declarations; this patch allows us to see dups.
* See https://github.com/NV/CSSOM/issues/16
*/
(function(){
var oldSet = cssom.CSSStyleDeclaration.prototype.setProperty;
cssom.CSSStyleDeclaration.prototype.setProperty = function(name, value, priority) {
// When there are multiple props, save their values in an array prefixed by '~'
if ( this[name] ) {
if ( !this["~" + name] ) {
this["~" + name] = [];
}
this["~" + name].push(value);
}
return oldSet.apply(this, arguments);
};
})();
// parseCSS and parseCSSfromUrl call each other so we tell jshint to cool it
/*jshint latedef: false*/
function parseCSSfromUrl(cssUrl, media, auth) {
var deferred = new Deferred(),
params = {
uri: cssUrl,
headers: {'Accept': 'text/html, application/xhtml+xml, */*'}
};
if ( auth ) {
params.auth = auth;
}
request(params, function (error, response, body) {
if (!error && response.statusCode === 200) {
parseCSS(body, cssUrl, media, false, auth).then(function(results){
deferred.resolve(results);
});
} else {
console.warn("Request for " + cssUrl + " returned " + error);
// Silently skip the troublesome file
deferred.resolve([]);
}
}
);
return deferred.promise;
}
function parseCSS(text, cssUrl, media, isInline, auth) {
var sheet,
deferred = new Deferred(),
imports = [];
try {
// Treat the current text as a resolved promise in our imports list
sheet = cssom.parse(text);
imports.push({cssUrl: isInline? "embed" : cssUrl, css: sheet, media: media, cssBody: text});
// Find @import statements in the rules
for ( var i=0; i < sheet.cssRules.length; i++ ) {
var rule = sheet.cssRules[i];
if ( rule.type === 3 && rule.href ) {
// http://www.w3.org/TR/CSS21/syndata.html#uri
// "For CSS style sheets, the base URI is that of the style sheet..."
imports.push(parseCSSfromUrl(url.resolve(cssUrl, rule.href), rule.media.mediaText, auth));
}
}
promised.all(imports).then(function(results){
// Results may be different because @imports may have @imported other files (ad nauseum);
// the .concat() will flatten one level of nested arrays which is all we need
deferred.resolve([].concat.apply([], results));
});
} catch(ex) {
console.warn("CSS from " + cssUrl + " threw " + ex);
// Silently skip the troublesome CSS
deferred.resolve([]);
}
return deferred.promise;
}
function check(website) {
var deferred = new Deferred(),
cssLinks = website.$('link[rel="stylesheet"]'),
cssHref,
cssUrl,
cssTags;
cssPromises = [];
for (var i = 0; i < cssLinks.length; i++) {
cssHref = cssLinks[i].attribs.href;
// If the attributes don't have a space then the library doesn't parse it correctly.
if (cssHref) {
cssUrl = url.resolve(website.url, cssHref);
cssPromises.push(parseCSSfromUrl(url.resolve(website.url, cssUrl), cssLinks[i].attribs.media, website.auth));
}
}
cssTags = website.$('style');
for (i = 0; i < cssTags.length; i++) {
if (cssTags[i].children && cssTags[i].children.length > 0 && cssTags[i].children[0].data) {
cssPromises.push(parseCSS(cssTags[i].children[0].data, website.url, cssTags[i].attribs.media, true, website.auth));
}
}
if (cssPromises.length > 0) {
promised.all(cssPromises).then(function (array) {
// Flatten the nested arrays
array = [].concat.apply([], array);
deferred.resolve(array);
}, function () {
deferred.reject();
});
} else {
// No style sheets
deferred.resolve([]);
}
return deferred.promise;
}
module.exports.loadCssFiles = check;

97
lib/checks/loadjs.js Normal file
Просмотреть файл

@ -0,0 +1,97 @@
/**
* Description: Load the external JavaScript files and embedded script blocks to make
* them available for further analysis. Files added dynamically are not analyzed.
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
"use strict";
var request = require('request'),
promised = require("promised-io/promise"),
Deferred = require('promised-io').Deferred,
url = require('url'),
jsPromises;
request = request.defaults({
jar: false,
headers: {
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)'}});
function downloadJS(jsUrl, jsHref, auth) {
var jsDeferred = new Deferred(),
parameters = {uri: jsUrl,
headers: {
'Accept': 'text/html, application/xhtml+xml, */*'}};
if (auth) {
parameters.auth = auth;
}
request(parameters, function (error, response, body) {
if (!error && response.statusCode === 200) {
response.on('error', function (e) {
console.log('loading CSS' + e);
});
jsDeferred.resolve({url: url, href: jsHref, finalUrl: response.request.href, code: body});
} else {
jsDeferred.resolve({});
}
});
return jsDeferred.promise;
}
function check(website) {
var deferred = new Deferred(),
js = [];
var jsLinks = website.$('script');
jsPromises = [];
for (var i = 0; i < jsLinks.length; i++) {
var jsHref = jsLinks[i].attribs.src,
jsUrl;
if (jsHref) {
if (jsHref) {
jsUrl = url.resolve(website.url, jsHref);
jsPromises.push(downloadJS(jsUrl, jsHref, website.auth));
}
} else if (jsLinks[i].children[0] && jsLinks[i].children[0].data) {
// Some <script> tags that do not contain anything. We ignore those
js.push({jsUrl: 'embed', code: jsLinks[i].children[0].data});
}
}
if (jsPromises.length > 0) {
promised.all(jsPromises).then(function (array) {
for (i = 0; i < array.length; i++) {
if (array[i].finalUrl) {
js.push(array[i]);
}
}
deferred.resolve(js);
}, function () {
deferred.reject();
});
} else {
// There aren't any external JS so we resolve an empty list
deferred.resolve(js);
}
return deferred.promise;
}
module.exports.loadjsFiles = check;

182
lib/index.html Normal file
Просмотреть файл

@ -0,0 +1,182 @@
<!doctype html>
<!--
* Main HTML file interface for Modern.IE local scans. Prompts the user for a URL
* to scan, sends the URL to the local service, and retrieves the JSON results.
* The user can then submit the results to the Modern.IE site for a report.
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
-->
<html>
<head>
<title>Modern.ie Local Scan</title>
<style>
html, body {
height: 100%;
margin: 0;
}
body {
font-family: Verdana, Arial, sans-serif;
color: #114477;
padding: 1em;
background: rgb(222,239,255); /* Old browsers */
background: -webkit-linear-gradient(top, rgba(222,239,255,1) 0%,rgba(152,190,222,1) 100%); /* Chrome10+,Safari5.1+ */
background: linear-gradient(to bottom, rgba(222,239,255,1) 0%,rgba(152,190,222,1) 100%); /* W3C */
}
p {
max-width: 50em;
margin: 0.5em 0;
}
pre {
color: #006611;
background: rgb(192,239,192); /* Old browsers */
background: -webkit-linear-gradient(top, rgba(192,239,192,1) 0%,rgba(171,199,171,1) 100%); /* Chrome10+,Safari5.1+ */
background: linear-gradient(to bottom, rgba(192,239,192,1) 0%,rgba(171,199,171,1) 100%); /* W3C */
}
label {
display: block;
color: #225599;
margin: 0.25em 0;
}
label span {
display: inline-block;
width: 7em;
}
input[type=submit], button {
font-size: 125%;
color: #dfefff;
border: none;
padding: 4px 32px;
margin-bottom: 1em;
background: #225599; /* Old browsers */
background: -webkit-linear-gradient(top, #7db9e8 0%,#207cca 24%,#1e5799 100%); /* Chrome10+,Safari5.1+ */
background: linear-gradient(to bottom, #7db9e8 0%,#207cca 24%,#1e5799 100%); /* W3C */
}
</style>
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script>
$(function () {
$("#step2").hide();
$("#scanform").on("submit", function (event) {
var url = $("#url").val(),
user = $("#user").val(),
password = $("#password").val(),
data;
if ( url.length < 4 ) {
alert("Please enter a URL.");
return false;
}
if ( !/^http/i.test(url) ) {
url = "http://" + url;
}
if ( user && password ) {
data = {
url: url,
user: user,
password: password
};
} else {
data = {
url: url
};
}
event.preventDefault();
$("#step1status").text("Scanning " + url + "...");
$.ajax({
method: "get",
url: "/",
data: data,
dataType: "text"
})
.done(function (results) {
$("#step1").hide();
$("#step1status").text("");
$("#step2").show();
$("#json").val(results);
$("#scanresults").hide().text(results);
try {
$("#scanresults").text(JSON.stringify(JSON.parse(results), null, " "));
} catch (ex) {
}
})
.fail(function (xhr) {
alert("Failed: " + xhr.status + " " + xhr.responseText);
});
});
$("#newscan").on("click", function () {
$("#step2").hide();
$("#step1").show();
});
$("#viewresults").on("click", function () {
$("#scanresults").show();
$("#viewresults").hide();
return false;
});
});
</script>
</head>
<body>
<h1>Modern.ie Local Scan</h1>
<div id="step1">
<h2>Scan a page</h2>
<p>Enter the URL of the page to be scanned. If the page requires authentication for access, enter the username and password; otherwise leave those fields blank. (HTTP Basic and Digest authentication methods are supported.)</p>
<form id="scanform" action="">
<label>
<span>URL to scan:</span>
<input type="text" name="url" id="url" size="70">
</label>
<label>
<span>Username:</span>
<input type="text" name="user" id="user" size="20">
<label>
<span>Password:</span>
<input type="text" name="password" id="password" size="20">
</label>
<input type="submit" name="scan" id="scan" value="Scan">
<p id="step1status"></p>
</form>
</div>
<div id="step2">
<h2>Generate report</h2>
<p>
The scan is complete and the report is ready to be generated.
Press the button below to submit the scan data to the Modern.ie site and create the report.
</p>
<form id="reportform" action="http://www.modern.ie/report/local" method="post">
<input type="submit" id="report" value="Create Report">
<input type="hidden" name="local_test_results" id="json" value="">
</form>
<p><a href="" id="viewresults">See what will be submitted</a></p>
<pre id="scanresults"></pre>
<div>
<button id="newscan">New Scan</button>
</div>
</div>
</body>
</html>

193
lib/service.js Normal file
Просмотреть файл

@ -0,0 +1,193 @@
/*
* Modern.IE main service; runs under node.js.
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
"use strict";
var url = require('url'),
fs = require('fs'),
port = process.env.PORT || 1337,
request = require('request'),
cheerio = require('cheerio'),
promises = require('promised-io/promise'),
Deferred = require('promised-io').Deferred,
cssLoader = require('./checks/loadcss.js'),
jsLoader = require('./checks/loadjs.js'),
tests = require('./checks/loadchecks.js').tests,
http = require('http'),
path = require('path'),
zlib = require('zlib'),
sanitize = require('validator').sanitize,
charset = 'utf-8',
querystring = require('querystring'),
request = request.defaults({followAllRedirects: true,
encoding: null,
jar: false,
//proxy: 'http://localhost:8888',
headers: {
'Accept': 'text/html, application/xhtml+xml, */*',
'Accept-Encoding': 'gzip,deflate',
'Accept-Language': 'en-US,en;q=0.5',
'User-Agent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)'}});
/*
* Since several tests need HTML/JS/CSS content, fetch it all at once
* before calling any of the tests. Note that the tests still could
* retrieve additional content async, since they return a promise.
*/
function analyze(data, body, res) {
var results = {};
var website = {
url: url.parse(data.uri),
auth: data.auth,
content: body,
$: cheerio.load(body, { lowerCaseTags: true, lowerCaseAttributeNames: true })
};
cssLoader.loadCssFiles(website).then(function (css) {
website.css = css;
jsLoader.loadjsFiles(website).then(function (js) {
var promisesTests = [];
website.js = js;
for (var i = 0; i < tests.length; i++) {
// Call each test and save its returned promise
promisesTests.push(tests[i].check(website));
}
promises.all(promisesTests).then(function (array) {
// Generate final results and send back the response
for (var i = 0; i < array.length; i++) {
results[array[i].testName] = array[i];
}
res.writeHeader(200, {"Content-Type": "application/json",
"X-Content-Type-Options": "nosniff" });
res.write(JSON.stringify({url: data, results: results}));
res.end();
});
});
}, function (error) {
res.writeHeader(500, {"Content-Type": "text/plain"});
res.write(JSON.stringify(error) + '\n');
res.end();
});
}
function remoteErrorResponse(response, statusCode, message) {
response.writeHead(200, {"Content-Type": "application/json"});
response.write(JSON.stringify({statusCode: statusCode, message: message}));
response.end();
}
function returnMainPage(req, response) {
fs.readFile(path.join(__dirname, "index.html"), function (err, data) {
if (!err) {
response.writeHeader(200, {"Content-Type": "text/html"});
} else {
response.writeHeader(500, {"Content-Type": "text/plain"});
data = "Server error: " + err + "\n";
}
response.write(data);
response.end();
});
}
function getBody(res, body) {
var deferred = new Deferred();
if (res.headers['content-encoding']) {
if (res.headers['content-encoding'] === 'gzip') {
zlib.gunzip(body, function (err, data) {
if (!err) {
deferred.resolve(data.toString(charset));
} else {
deferred.reject('Error found: can\'t gunzip content ' + err);
}
});
} else if (res.headers['content-encoding'] === 'deflate') {
zlib.inflate(body, function (err, data) {
if (!err) {
deferred.resolve(data.toString(charset));
} else {
deferred.reject('Error found: can\'t deflate content' + err);
}
});
} else {
deferred.reject("Unknown content encoding: "+res.headers['content-encoding']);
}
} else {
if (body) {
deferred.resolve(body.toString(charset));
} else {
deferred.reject('Error found: Empty body');
}
}
return deferred.promise;
}
function processResponse(response, auth) {
return function (err, res, body) {
if (!err && res.statusCode === 200) {
getBody(res, body).then(function (result) {
analyze({uri: res.request.href, auth: auth}, result, response);
},
function (error) {
remoteErrorResponse(response, res.statusCode, error);
});
} else {
remoteErrorResponse(response, res ? res.statusCode : 'No response', 'Error found: ' + err);
}
};
}
function handleRequest(req, response) {
if (req.url === '/') {
// Return the "local scan" page
returnMainPage(req, response);
return;
}
var requestUrl = url.parse(req.url),
parameters = querystring.parse(requestUrl.query),
urlToAnalyze = sanitize(decodeURIComponent(parameters.url)).xss(),
user = sanitize(decodeURIComponent(parameters.user)).xss(),
password = sanitize(decodeURIComponent(parameters.password)).xss(),
auth;
// If the request gave a user/pass, send it along. Wait for 401 response before sending passwords.
if (user !== "undefined" && password !== "undefined") {
auth = {
'user': user,
'pass': password,
'sendImmediately': false
};
request(urlToAnalyze,
{auth: auth},
processResponse(response, auth));
} else {
request(urlToAnalyze, processResponse(response));
}
}
http.createServer(handleRequest).listen(port);
console.log('Server started on port ' + port);
console.log('To scan a private url go to http://localhost:' + port + '/ and follow the instructions');
module.exports.port = port;

51
package.json Normal file
Просмотреть файл

@ -0,0 +1,51 @@
{
"name": "Modern.ie",
"description": "Modern.ie will analyze a website and give hints on how to be more standards compliant",
"version": "0.3.0",
"homepage": "https://github.com/InternetExplorer/modern.IE-static-code-scan",
"author": {
"name": "Microsoft"
},
"repository": {
"type": "git",
"url": "https://github.com/InternetExplorer/modern.IE-static-code-scan.git"
},
"bugs": {
"url": "https://github.com/InternetExplorer/modern.IE-static-code-scan/issues"
},
"licenses": [
{
"type": "Apache v2 License",
"url": "https://github.com/InternetExplorer/modern.IE-static-code-scan/blob/master/LICENSE"
}
],
"main": "modernie",
"engines": {
"node": "0.10.x",
"npm": "1.2.x"
},
"scripts": {
"start": "node lib/service.js",
"test": "grunt test"
},
"dependencies": {
"cheerio": ">=0.10.1",
"request": "2.20.x",
"promised-io": ">=0.3.0",
"xml2js": ">=0.2.0",
"cssom": ">=0.2.5",
"jsdom": "~0.2.19",
"ya-csv": "~0.9.2",
"validator": "~0.4.22",
"http-agent": ">=0.1.2",
"hyperquest": "~0.1.4"
},
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-nodeunit": "~0.1.2",
"grunt-contrib-watch": "~0.3.1",
"grunt-contrib-jshint": "~0.2.0",
"express": "~3.2.4"
},
"keywords": []
}

11
static/auth-1.html Normal file
Просмотреть файл

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="Auth 1" content="Basic Auth">
</head>
<body>
<h1>Simple page with basic auth</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

12
static/auth-2.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="Auth 2" content="Basic Auth - 2">
<script src="/js/jquery-1.4.2.min.js"></script>
</head>
<body>
<h1>Page with resources and basic auth</h1>
<p>Expected result: <b>Fails js version</b></p>
</body>
</html>

12
static/auth-3.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="Auth 3" content="Basic Auth - 3">
<link rel="stylesheet" href="css/msTouch.css" />
</head>
<body>
<h1>Page with resources and basic auth</h1>
<p>Expected result: <b>Passes Touch</b></p>
</body>
</html>

13
static/auth-4.html Normal file
Просмотреть файл

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="Auth 4" content="Basic Auth - 4">
<script src="/js/jquery-1.4.2.min.js"></script>
<link rel="stylesheet" href="css/msTouch.css" />
</head>
<body>
<h1>Page with resources and basic auth</h1>
<p>Expected result: <b>Passes Touch, fails js libs</b></p>
</body>
</html>

34
static/auth-server.js Normal file
Просмотреть файл

@ -0,0 +1,34 @@
/**
* Description: Test that local scans can use authenticated (user/password) pages.
* At the moment, only supports Basic and Digest auth courtesy of node.js request.
*
* Copyright (c) Microsoft Corporation; All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* THIS CODE IS PROVIDED AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS
* OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
*
* See the Apache Version 2.0 License for specific language governing permissions
* and limitations under the License.
*/
"use strict";
var express = require('express'),
app = express(),
port = process.env.PORT || 1000;
// Authenticator
app.use(express.basicAuth(function (user, pass) {
return user === "user" && pass === "password";
}));
app.use("/", express.static(__dirname + "/"));
app.listen(port);
module.exports.port = port;

11
static/buglist-1.html Normal file
Просмотреть файл

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Not in bug list">
</head>
<body>
<h1>Not in bug list</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

11
static/compat-1.html Normal file
Просмотреть файл

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="No compat tag">
</head>
<body>
<h1>No compat tag</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

12
static/compat-10.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="IE=8,edge">
<meta http-equiv="X-UA-Compatible" content="IE=8,edge">
</head>
<body>
<h1>IE=8,edge</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

12
static/compat-11.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="IE=EmulateIE9,edge">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9,edge">
</head>
<body>
<h1>IE=EmulateIE9,edge</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

12
static/compat-12.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="IE=chrome=1">
<meta http-equiv="X-UA-Compatible" content="IE=chrome=1">
</head>
<body>
<h1>IE=chrome=1</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

12
static/compat-13.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="IE=EmulateIE10">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE10">
</head>
<body>
<h1>IE=EmulateIE10</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

12
static/compat-14.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="IE=EmulateIE8">
<meta http-equiv="x-ua-compatible" content="IE=EmulateIE8">
</head>
<body>
<h1>IE=EmulateIE8 lower case</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

12
static/compat-15.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="IE=EmulateIE8">
<meta http-equiv="x-UA-compatible" content="IE=EmulateIE8">
</head>
<body>
<h1>IE=EmulateIE8 bizarre case</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

12
static/compat-16.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="IE=edge bizarre case">
<meta http-equiv="x-Ua-coMpatible" content="IE=edge">
</head>
<body>
<h1>IE=edge bizarre case</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

12
static/compat-2.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="IE=5">
<meta http-equiv="X-UA-Compatible" content="IE=5">
</head>
<body>
<h1>IE=5</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

12
static/compat-3.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="IE=EmulateIE7">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7">
</head>
<body>
<h1>IE=EmulateIE7</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

12
static/compat-4.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="IE=7">
<meta http-equiv="X-UA-Compatible" content="IE=7">
</head>
<body>
<h1>IE=7</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

12
static/compat-5.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="IE=EmulateIE8">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8">
</head>
<body>
<h1>IE=EmulateIE8</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

12
static/compat-6.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="IE=8">
<meta http-equiv="X-UA-Compatible" content="IE=8">
</head>
<body>
<h1>IE=8</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

12
static/compat-7.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="IE=EmulateIE9">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9">
</head>
<body>
<h1>IE=EmulateIE9</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

12
static/compat-8.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="IE=9">
<meta http-equiv="X-UA-Compatible" content="IE=9">
</head>
<body>
<h1>IE=9</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

12
static/compat-9.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="IE=edge">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
</head>
<body>
<h1>IE=edge</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,8 @@
div
{
-webkit-animation: myfirst 5s;
-moz-animation: myfirst 5s;
-o-animation: myfirst 5s;
-ms-animation: myfirst 5s;
animation: myfirst 5s;
}

Просмотреть файл

@ -0,0 +1,40 @@
body {
width:800px;
font-family:'Segoe UI';
font-size: 16px;
}
#id {
float:left;
width:300px;
height:200px;
background-color: #FF0000;
}
@media only screen and (min-width: 780px) {
#id{
width: 650px;
background-color: #F0F0F0;
}
}
@media only screen and (min-width: 480px) {
#id{
width: 600px;
background-color: #00FF00;
}
}
@media only screen and (max-width: 479px) {
#id{
width: 200px;
background-color: #0000FF;
}
}
@media only screen and (min-width: 480px) {
#id{
width: 480px;
background-color: #00FF00;
}
}

17
static/css/gradients.css Normal file
Просмотреть файл

@ -0,0 +1,17 @@
.linearGradient{
background: -moz-linear-gradient(top, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#1e5799), color-stop(50%,#2989d8), color-stop(51%,#207cca), color-stop(100%,#7db9e8)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* IE10+ */
background: linear-gradient(to bottom, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* W3C */
}
.radialGradient{
background: -moz-radial-gradient(center, ellipse cover, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%); /* FF3.6+ */
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,#1e5799), color-stop(50%,#2989d8), color-stop(51%,#207cca), color-stop(100%,#7db9e8)); /* Chrome,Safari4+ */
background: -webkit-radial-gradient(center, ellipse cover, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* Chrome10+,Safari5.1+ */
background: -o-radial-gradient(center, ellipse cover, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* Opera 12+ */
background: -ms-radial-gradient(center, ellipse cover, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* IE10+ */
background: radial-gradient(ellipse at center, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* W3C */
}

Просмотреть файл

@ -0,0 +1 @@
@import 'unprefixed.css'; /* relative to this file */

Просмотреть файл

@ -0,0 +1 @@
@import url("unprefixed.css"); /* relative to this file */

19
static/css/maxWidth.css Normal file
Просмотреть файл

@ -0,0 +1,19 @@
body {
width:800px;
font-family:'Segoe UI';
font-size: 16px;
}
#id {
float:left;
width:300px;
height:200px;
background-color: #FF0000;
}
@media only screen and (max-width: 480px) {
#id{
width: 200px;
background-color: #0000FF;
}
}

Просмотреть файл

@ -0,0 +1,33 @@
body {
width:800px;
font-family:'Segoe UI';
font-size: 16px;
}
#id {
float:left;
width:300px;
height:200px;
background-color: #FF0000;
}
@media only screen and (max-width: 440px) {
#id{
width: 600px;
background-color: #00FF00;
}
}
@media only screen and (max-width: 360px) {
#id{
width: 300px;
background-color: #00FF00;
}
}
@media only screen and (max-width: 720px) {
#id{
width: 700px;
background-color: #00FF00;
}
}

Просмотреть файл

@ -0,0 +1,33 @@
body {
width:800px;
font-family:'Segoe UI';
font-size: 16px;
}
#id {
float:left;
width:300px;
height:200px;
background-color: #FF0000;
}
@media only screen and (min-width: 480px) {
#id{
width: 600px;
background-color: #00FF00;
}
}
@media only screen and (min-width: 780px) {
#id{
width: 650px;
background-color: #F0F0F0;
}
}
@media only screen and (max-width: 479px) {
#id{
width: 200px;
background-color: #0000FF;
}
}

Просмотреть файл

@ -0,0 +1,33 @@
body {
width:800px;
font-family:'Segoe UI';
font-size: 16px;
}
#id {
float:left;
width:300px;
height:200px;
background-color: #FF0000;
}
@media only screen and (min-width: 780px) {
#id{
width: 650px;
background-color: #F0F0F0;
}
}
@media only screen and (min-width: 480px) {
#id{
width: 600px;
background-color: #00FF00;
}
}
@media only screen and (max-width: 479px) {
#id{
width: 200px;
background-color: #0000FF;
}
}

Просмотреть файл

@ -0,0 +1,33 @@
body {
width:800px;
font-family:'Segoe UI';
font-size: 16px;
}
#id {
float:left;
width:300px;
height:200px;
background-color: #FF0000;
}
@media only screen and (min-width: 30em) {
#id{
width: 600px;
background-color: #00FF00;
}
}
@media only screen and (min-width: 48.75em) {
#id{
width: 650px;
background-color: #F0F0F0;
}
}
@media only screen and (max-width: 30em) {
#id{
width: 200px;
background-color: #0000FF;
}
}

19
static/css/minWidth.css Normal file
Просмотреть файл

@ -0,0 +1,19 @@
body {
width:800px;
font-family:'Segoe UI';
font-size: 16px;
}
#id {
float:left;
width:300px;
height:200px;
background-color: #FF0000;
}
@media only screen and (min-width: 480px) {
#id{
width: 600px;
background-color: #00FF00;
}
}

Просмотреть файл

@ -0,0 +1,33 @@
body {
width:800px;
font-family:'Segoe UI';
font-size: 16px;
}
#id {
float:left;
width:300px;
height:200px;
background-color: #FF0000;
}
@media only screen and (min-width: 440px) {
#id{
width: 600px;
background-color: #00FF00;
}
}
@media only screen and (min-width: 360px) {
#id{
width: 300px;
background-color: #00FF00;
}
}
@media only screen and (min-width: 720px) {
#id{
width: 700px;
background-color: #00FF00;
}
}

Просмотреть файл

@ -0,0 +1,33 @@
body {
width:800px;
font-family:'Segoe UI';
font-size: 16px;
}
#id {
float:left;
width:300px;
height:200px;
background-color: #FF0000;
}
@media only screen and (min-width: 100px) {
#id{
width: 600px;
background-color: #00FF00;
}
}
@media only screen and (min-width: 550px) {
#id{
width: 300px;
background-color: #00FF00;
}
}
@media only screen and (min-width: 1120px) {
#id{
width: 700px;
background-color: #00FF00;
}
}

Просмотреть файл

@ -0,0 +1,4 @@
div
{
animation: myfirst 5s;
}

Просмотреть файл

@ -0,0 +1,14 @@
/*
* This comment is here to add some lines before the CSS rules.
*/
.linearGradient{
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#1e5799), color-stop(50%,#2989d8), color-stop(51%,#207cca), color-stop(100%,#7db9e8)); /* Chrome,Safari4+ */
/* background: -ms-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); IE10+ */
background: linear-gradient(to bottom, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* W3C */
}
.radialGradient{
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,#1e5799), color-stop(50%,#2989d8), color-stop(51%,#207cca), color-stop(100%,#7db9e8)); /* Chrome,Safari4+ */
/* background: -ms-radial-gradient(center, ellipse cover, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* IE10+ */
background: radial-gradient(ellipse at center, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* W3C */
}

Просмотреть файл

@ -0,0 +1,3 @@
div{
-webkit-transform: matrix3d(0.359127, -0.469472, 0.806613, 0, 0.190951, 0.882948, 0.428884, 0, -0.913545, 0, 0.406737, 0, 0, 0, 0, 1);
}

Просмотреть файл

@ -0,0 +1,34 @@
div {
-webkit-transition: all 1s ease-in-out;
-moz-transition: all 1s ease-in-out;
-o-transition: all 1s ease-in-out;
-ms-transition: all 1s ease-in-out;
}
.property {
-webkit-transition-property: top, left;
-o-transition-property: top, left;
-ms-transition-property: top, left;
transition-property: top, left;
}
.duration {
-moz-transition-duration: 1s, 1s;
-o-transition-duration: 1s, 1s;
-ms-transition-duration: 1s, 1s;
transition-duration: 1s, 1s;
}
.delay {
-webkit-transition-delay: 0s, 1s;
-moz-transition-delay: 0s, 1s;
-o-transition-delay: 0s, 1s;
transition-delay: 0s, 1s;
}
.timing {
-webkit-timing-function: linear;
-moz-timing-function: linear;
-ms-timing-function: linear;
timing-function: linear;
}

13
static/css/msTouch.css Normal file
Просмотреть файл

@ -0,0 +1,13 @@
body {
width:800px;
font-family:'Segoe UI';
font-size: 16px;
}
#id {
float:left;
width:300px;
height:200px;
background-color: #FF0000;
-ms-touch-action: none;
}

13
static/css/scrollSnap.css Normal file
Просмотреть файл

@ -0,0 +1,13 @@
body {
width: 800px;
font-family: 'Segoe UI';
font-size: 16px;
}
#id {
float: left;
width: 300px;
height: 200px;
background-color: #FF0000;
-ms-scroll-snap-points-x: snapList(100%, 200%, 300%);
}

Просмотреть файл

@ -0,0 +1,12 @@
body {
width:800px;
font-family:'Segoe UI';
font-size: 16px;
}
#id {
float:left;
width:300px;
height:200px;
background-color: #FF0000;
}

11
static/css/transforms.css Normal file
Просмотреть файл

@ -0,0 +1,11 @@
/* comment and extra newlines above */
div{
-webkit-transform: matrix3d(0.359127, -0.469472, 0.806613, 0, 0.190951, 0.882948, 0.428884, 0, -0.913545, 0, 0.406737, 0, 0, 0, 0, 1);
-moz-transform:matrix3d(0.359127, -0.469472, 0.806613, 0, 0.190951, 0.882948, 0.428884, 0, -0.913545, 0, 0.406737, 0, 0, 0, 0, 1);
-o-transform:matrix3d(0.359127, -0.469472, 0.806613, 0, 0.190951, 0.882948, 0.428884, 0, -0.913545, 0, 0.406737, 0, 0, 0, 0, 1);
-ms-transform:matrix3d(0.359127, -0.469472, 0.806613, 0, 0.190951, 0.882948, 0.428884, 0, -0.913545, 0, 0.406737, 0, 0, 0, 0, 1);
transform:matrix3d(0.359127, -0.469472, 0.806613, 0, 0.190951, 0.882948, 0.428884, 0, -0.913545, 0, 0.406737, 0, 0, 0, 0, 1);
}

Просмотреть файл

@ -0,0 +1,39 @@
div {
-webkit-transition: all 1s ease-in-out;
-moz-transition: all 1s ease-in-out;
-o-transition: all 1s ease-in-out;
-ms-transition: all 1s ease-in-out;
transition: all 1s ease-in-out;
}
.property {
-webkit-transition-property: top, left;
-moz-transition-property: top, left;
-o-transition-property: top, left;
-ms-transition-property: top, left;
transition-property: top, left;
}
.duration {
-webkit-transition-duration: 1s, 1s;
-moz-transition-duration: 1s, 1s;
-o-transition-duration: 1s, 1s;
-ms-transition-duration: 1s, 1s;
transition-duration: 1s, 1s;
}
.delay {
-webkit-transition-delay: 0s, 1s;
-moz-transition-delay: 0s, 1s;
-o-transition-delay: 0s, 1s;
-ms-transition-delay: 0s, 1s;
transition-delay: 0s, 1s;
}
.timing {
-webkit-timing-function: linear;
-moz-timing-function: linear;
-o-timing-function: linear;
-ms-timing-function: linear;
timing-function: linear;
}

Просмотреть файл

@ -0,0 +1,5 @@
div{
transform: matrix3d(0.359127, -0.469472, 0.806613, 0, 0.190951, 0.882948, 0.428884, 0, -0.913545, 0, 0.406737, 0, 0, 0, 0, 1);
animation: myAnimation 3s ease-out -1s 2 normal;
transition: opacity 5s linear 1s, background-color 2s ease;
}

11
static/cssprefixes-1.html Normal file
Просмотреть файл

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="No CSS">
</head>
<body>
<h1>No CSS</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Missing Transitions CSS">
<link rel="stylesheet" href="css/missingTransitions.css" />
</head>
<body>
<h1>Missing Transitions CSS</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Missing Gradients CSS">
<link rel="stylesheet" href="css/missingGradients.css" />
</head>
<body>
<h1>Missing Gradients CSS</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Missing Animations CSS">
<link rel="stylesheet" href="css/missingAnimations.css" />
</head>
<body>
<h1>Missing Animations CSS</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Gradients + Transforms">
<link rel="stylesheet" href="css/gradients.css" />
<link rel="stylesheet" href="css/transforms.css" />
</head>
<body>
<h1>Gradients + Transforms</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Gradients + Missing Transforms">
<link rel="stylesheet" href="css/gradients.css" />
<link rel="stylesheet" href="css/missingTransforms.css" />
</head>
<body>
<h1>Gradients + Missing Transforms</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Embed Transform CSS">
<style>
div{
-webkit-transform: matrix3d(0.359127, -0.469472, 0.806613, 0, 0.190951, 0.882948, 0.428884, 0, -0.913545, 0, 0.406737, 0, 0, 0, 0, 1);
-moz-transform:matrix3d(0.359127, -0.469472, 0.806613, 0, 0.190951, 0.882948, 0.428884, 0, -0.913545, 0, 0.406737, 0, 0, 0, 0, 1);
-o-transform:matrix3d(0.359127, -0.469472, 0.806613, 0, 0.190951, 0.882948, 0.428884, 0, -0.913545, 0, 0.406737, 0, 0, 0, 0, 1);
-ms-transform:matrix3d(0.359127, -0.469472, 0.806613, 0, 0.190951, 0.882948, 0.428884, 0, -0.913545, 0, 0.406737, 0, 0, 0, 0, 1);
transform:matrix3d(0.359127, -0.469472, 0.806613, 0, 0.190951, 0.882948, 0.428884, 0, -0.913545, 0, 0.406737, 0, 0, 0, 0, 1);
}
</style>
</head>
<body>
<h1>Embed Transform</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Embed Transform CSS">
<style>
div{
-webkit-transform: matrix3d(0.359127, -0.469472, 0.806613, 0, 0.190951, 0.882948, 0.428884, 0, -0.913545, 0, 0.406737, 0, 0, 0, 0, 1);
transform:matrix3d(0.359127, -0.469472, 0.806613, 0, 0.190951, 0.882948, 0.428884, 0, -0.913545, 0, 0.406737, 0, 0, 0, 0, 1);
}
</style>
</head>
<body>
<h1>Embed Missing Transform</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Inline @import using url()">
<style>
@import url(css/unprefixed.css);
</style>
</head>
<body>
<h1>CSS imported with @import url()</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Import using single quote">
<link rel="stylesheet" href="css/importSingle.css" />
</head>
<body>
<h1>CSS imported with @import 'url'</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Import using double quote">
<link rel="stylesheet" href="css/importUrlDouble.css" />
</head>
<body>
<h1>CSS imported with @import url("url");</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

12
static/cssprefixes-2.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Simple CSS with no CSS3">
<link rel="stylesheet" href="css/simpleStyle.css" />
</head>
<body>
<h1>Simple CSS with no CSS3</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

12
static/cssprefixes-3.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Unprefixed CSS">
<link rel="stylesheet" href="css/unprefixed.css" />
</head>
<body>
<h1>Simple CSS with Unprefixed CSS3 properties</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

13
static/cssprefixes-4.html Normal file
Просмотреть файл

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Unprefixed CSS">
<link rel="stylesheet" href="css/simpleStyle.css" />
<link rel="stylesheet" href="css/unprefixed.css" />
</head>
<body>
<h1>Simple CSS with no CSS3</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

12
static/cssprefixes-5.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Transform CSS">
<link rel="stylesheet" href="css/transforms.css" />
</head>
<body>
<h1>Transform</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

12
static/cssprefixes-6.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Transitions CSS">
<link rel="stylesheet" href="css/transitions.css" />
</head>
<body>
<h1>Transitions CSS</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

12
static/cssprefixes-7.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Gradients CSS">
<link rel="stylesheet" href="css/gradients.css" />
</head>
<body>
<h1>Gradients CSS</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

12
static/cssprefixes-8.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Animations CSS">
<link rel="stylesheet" href="css/animations.css" />
</head>
<body>
<h1>Animations CSS</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

12
static/cssprefixes-9.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="description" content="Missing Transform CSS">
<link rel="stylesheet" href="css/missingTransforms.css" />
</head>
<body>
<h1>Missing Transforms</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

12
static/favicon-1.html Normal file
Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="No high resolution favicon">
</head>
<body>
<h1>No high resolution favicon and no Apple Touch Icon</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

13
static/favicon-2.html Normal file
Просмотреть файл

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="High resolution favicon">
<meta name="msapplication-TileImage" content="images/benthepcguy-144.png"/>
</head>
<body>
<h1>High resolution favicon</h1>
<p>Expected result: <b>Passes</b></p>
</body>
</html>

13
static/favicon-3.html Normal file
Просмотреть файл

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="No favicon but Apple Touch Icon">
<link href="apple-touch-icon-precomposed.png" rel="apple-touch-icon-precomposed">
</head>
<body>
<h1>No favicon but Apple Touch Icon Precomposed</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

14
static/favicon-4.html Normal file
Просмотреть файл

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="No favicon but Apple Touch Icon">
<link href="apple-touch-icon-precomposed.png" rel="apple-touch-icon-precomposed">
<meta name="msapplication-TileImage" content="images/benthepcguy-144.png"/>
</head>
<body>
<h1>Favicon &amp; Apple Touch Icon Precomposed</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

13
static/favicon-5.html Normal file
Просмотреть файл

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="No favicon but Apple Touch Icon">
<link href="apple-touch-icon.png" rel="apple-touch-icon">
</head>
<body>
<h1>No favicon but Apple Touch Icon</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

14
static/favicon-6.html Normal file
Просмотреть файл

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="No favicon but Apple Touch Icon">
<link href="apple-touch-icon.png" rel="apple-touch-icon">
<meta name="msapplication-TileImage" content="images/benthepcguy-144.png"/>
</head>
<body>
<h1>Favicon &amp; Apple Touch Icon</h1>
<p>Expected result: <b>Fails</b></p>
</body>
</html>

15
static/js/dojo-1.7.0.js Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

15
static/js/dojo-1.8.0.js Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

15
static/js/dojo-1.8.3.js Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

154
static/js/jquery-1.4.2.min.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,154 @@
/*!
* jQuery JavaScript Library v1.4.2
* http://jquery.com/
*
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* Includes Sizzle.js
* http://sizzlejs.com/
* Copyright 2010, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
*
* Date: Sat Feb 13 22:33:48 2010 -0500
*/
(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.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".split(" "),
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);

4
static/js/jquery-1.9.0.min.js поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

5
static/js/jquery-1.9.1.min.js поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

14955
static/js/jquery-ui-1.10.2.custom.js поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

14742
static/js/jquery-ui-1.9.0.js поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

5
static/js/jquery-ui-1.9.0.min.js поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше