├── firefox
├── data
│ ├── b64.js
│ ├── NeuQuant.js
│ ├── selfie.css
│ ├── selfie.js
│ ├── GIFEncoder.js
│ ├── LZWEncoder.js
│ ├── jquery.min.js
│ └── selfie-base.js
├── .jshintrc
├── package.json
└── lib
│ └── main.js
├── .gitignore
├── chrome
├── .jshintrc
├── icon16.png
├── icon48.png
├── icon128.png
├── b64.js
├── manifest.json
├── background.js
├── selfie.js
├── selfie.css
├── LZWEncoder.js
├── selfie-base.js
├── GIFEncoder.js
├── NeuQuant.js
└── jquery.min.js
├── .tern-project
├── LICENSE.md
└── README.md
/firefox/data/b64.js:
--------------------------------------------------------------------------------
1 | ../../chrome/b64.js
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.xpi
2 | *.zip
3 | .tern-port
4 |
--------------------------------------------------------------------------------
/firefox/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "moz": true
3 | }
4 |
--------------------------------------------------------------------------------
/firefox/data/NeuQuant.js:
--------------------------------------------------------------------------------
1 | ../../chrome/NeuQuant.js
--------------------------------------------------------------------------------
/firefox/data/selfie.css:
--------------------------------------------------------------------------------
1 | ../../chrome/selfie.css
--------------------------------------------------------------------------------
/firefox/data/selfie.js:
--------------------------------------------------------------------------------
1 | ../../chrome/selfie.js
--------------------------------------------------------------------------------
/chrome/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "esnext": true
3 | }
4 |
--------------------------------------------------------------------------------
/firefox/data/GIFEncoder.js:
--------------------------------------------------------------------------------
1 | ../../chrome/GIFEncoder.js
--------------------------------------------------------------------------------
/firefox/data/LZWEncoder.js:
--------------------------------------------------------------------------------
1 | ../../chrome/LZWEncoder.js
--------------------------------------------------------------------------------
/firefox/data/jquery.min.js:
--------------------------------------------------------------------------------
1 | ../../chrome/jquery.min.js
--------------------------------------------------------------------------------
/firefox/data/selfie-base.js:
--------------------------------------------------------------------------------
1 | ../../chrome/selfie-base.js
--------------------------------------------------------------------------------
/chrome/icon16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thieman/github-selfies/HEAD/chrome/icon16.png
--------------------------------------------------------------------------------
/chrome/icon48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thieman/github-selfies/HEAD/chrome/icon48.png
--------------------------------------------------------------------------------
/chrome/icon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thieman/github-selfies/HEAD/chrome/icon128.png
--------------------------------------------------------------------------------
/.tern-project:
--------------------------------------------------------------------------------
1 | {
2 | "libs": [
3 | "browser",
4 | "jquery"
5 | ],
6 | "plugins": {
7 | "chrome-extension": {}
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/firefox/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "github-selfies",
3 | "title": "GitHub Selfies",
4 | "id": "jid1-CYSMA1UvadIZSw@jetpack",
5 | "description": "Selfies! For GitHub! Hooray!",
6 | "author": "Travis Thieman",
7 | "license": "MIT",
8 | "version": "2.0.3",
9 | "main": "lib/main.js",
10 | "permissions": {
11 | "cross-domain-content": ["https://api.imgur.com"]
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/chrome/b64.js:
--------------------------------------------------------------------------------
1 | function encode64(input) {
2 | var output = "", i = 0, l = input.length,
3 | key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
4 | chr1, chr2, chr3, enc1, enc2, enc3, enc4;
5 | while (i < l) {
6 | chr1 = input.charCodeAt(i++);
7 | chr2 = input.charCodeAt(i++);
8 | chr3 = input.charCodeAt(i++);
9 | enc1 = chr1 >> 2;
10 | enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
11 | enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
12 | enc4 = chr3 & 63;
13 | if (isNaN(chr2)) enc3 = enc4 = 64;
14 | else if (isNaN(chr3)) enc4 = 64;
15 | output = output + key.charAt(enc1) + key.charAt(enc2) + key.charAt(enc3) + key.charAt(enc4);
16 | }
17 | return output;
18 | }
--------------------------------------------------------------------------------
/chrome/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 |
4 | "name": "GitHub Selfies",
5 | "description": "Selfies! For GitHub! Hooray!",
6 | "version": "2.0.7",
7 |
8 | "icons": {
9 | "16": "icon16.png",
10 | "48": "icon48.png",
11 | "128": "icon128.png"
12 | },
13 |
14 | "permissions": [
15 | "webRequest",
16 | "webRequestBlocking",
17 | "*://github.com/*",
18 | "https://api.imgur.com/3/image"
19 | ],
20 |
21 | "background": {
22 | "scripts": ["background.js"],
23 | "persistent": true
24 | },
25 |
26 | "content_scripts": [
27 | {
28 | "js": [
29 | "jquery.min.js",
30 | "b64.js",
31 | "NeuQuant.js",
32 | "LZWEncoder.js",
33 | "GIFEncoder.js",
34 | "selfie-base.js",
35 | "selfie.js"
36 | ],
37 | "css": [
38 | "selfie.css"
39 | ],
40 | "matches": ["*://github.com/*"]
41 | }
42 | ],
43 |
44 | "web_accessible_resources": [
45 | "jquery-1.10.1.min.map",
46 | "new-issue.css",
47 | "issues.css"
48 | ]
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Travis Thieman
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/chrome/background.js:
--------------------------------------------------------------------------------
1 | // this idea borrowed from
2 | // https://www.planbox.com/blog/development/coding/bypassing-githubs-content-security-policy-chrome-extension.html
3 |
4 | chrome.webRequest.onHeadersReceived.addListener(function(details) {
5 | for (i = 0; i < details.responseHeaders.length; i++) {
6 |
7 | if (isCSPHeader(details.responseHeaders[i].name.toUpperCase())) {
8 | var csp = details.responseHeaders[i].value;
9 | csp = csp.replace("media-src 'none'", "media-src 'self' blob:");
10 | csp = csp.replace("connect-src 'self' uploads.github.com status.github.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com wss://live.github.com",
11 | "connect-src 'self' uploads.github.com status.github.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com wss://live.github.com api.imgur.com");
12 |
13 | details.responseHeaders[i].value = csp;
14 | }
15 | }
16 |
17 | return { // Return the new HTTP header
18 | responseHeaders: details.responseHeaders
19 | };
20 | }, {
21 | urls: ["*://github.com/*"],
22 | types: ["main_frame"]
23 | }, ["blocking", "responseHeaders"]);
24 |
25 |
26 | function isCSPHeader(headerName) {
27 | return (headerName == 'CONTENT-SECURITY-POLICY') || (headerName == 'X-WEBKIT-CSP');
28 | }
29 |
--------------------------------------------------------------------------------
/firefox/lib/main.js:
--------------------------------------------------------------------------------
1 | var pageMod = require('sdk/page-mod');
2 | var self = require('sdk/self');
3 | var {Cc, Ci} = require("chrome");
4 |
5 | pageMod.PageMod({
6 | include: "*.github.com",
7 | contentStyleFile: [self.data.url("selfie.css")],
8 | contentScriptFile: [
9 | "jquery.min.js",
10 | "b64.js",
11 | "NeuQuant.js",
12 | "LZWEncoder.js",
13 | "GIFEncoder.js",
14 | "selfie-base.js",
15 | "selfie.js"
16 | ].map((path) => self.data.url(path))
17 | });
18 |
19 | // Modify CSP headers from Github so we can inject a script to forward
20 | // pushState info via postMessage.
21 | var httpRequestObserver =
22 | {
23 | observe: function(subject, topic, data) {
24 | if (topic == "http-on-examine-response") {
25 | var httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
26 | if (/^https:\/\/github.com/.test(httpChannel.name)) {
27 | var csp = httpChannel.getResponseHeader('CONTENT-SECURITY-POLICY').toString();
28 | csp = csp.replace("script-src", "script-src 'unsafe-inline'");
29 | httpChannel.setResponseHeader('CONTENT-SECURITY-POLICY', csp, false);
30 | }
31 | }
32 | }
33 | };
34 | var observerService = Cc["@mozilla.org/observer-service;1"]
35 | .getService(Ci.nsIObserverService);
36 | observerService.addObserver(httpRequestObserver, "http-on-examine-response", false);
37 |
38 | exports.onUnload = function (reason) {
39 | observerService.removeObserver(httpRequestObserver, "http-on-examine-response");
40 | };
41 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | github-selfies
2 | ==============
3 |
4 | Add selfies to your pull requests and comments on GitHub!
5 |
6 | * [Get it now on the Chrome Web Store!](https://chrome.google.com/webstore/detail/github-selfies/ldnpkdnkgkogfnahcnldaedcoadjbkbl)
7 | * [Also available for Firefox!](https://addons.mozilla.org/en-US/firefox/addon/github-selfies/)
8 |
9 | 
10 |
11 | ## Developing
12 |
13 | First, clone this repository: `git clone https://github.com/thieman/github-selfies`. Then follow the instructions for your given platform. For convenience, you can run `./build.sh` to build and package both the Chrome and Firefox extensions.
14 |
15 | ### Chrome
16 |
17 | 1. Enable [Chrome Extensions Developer Mode](https://developer.chrome.com/extensions/faq#faq-dev-01) in Chrome.
18 | 2. In Settings > Extensions click "Load unpacked extension" and select the `chrome/` subfolder of this repository.
19 |
20 | ### Firefox
21 |
22 | 1. Install NodeJS and npm.
23 | 2. Install `jpm` (`npm install -g jpm`)
24 | 3. Run `jpm run` from within the `firefox/` subfolder of this repository.
25 |
26 | ## Awesome contributors
27 |
28 | This project is much better now than it was at launch thanks to these people.
29 |
30 | Awesome Person | Selfie
31 | -------------- | ------
32 | [Joe Lepper](https://github.com/joeLepper) | 
33 | [Ben Hollis](https://github.com/bhollis) | 
34 | [Phil Haack](https://github.com/haacked) |
35 |
36 |
--------------------------------------------------------------------------------
/chrome/selfie.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | "use strict";
3 |
4 | // Inject the code from fn into the page, in an IIFE.
5 | function inject(fn) {
6 | var script = document.createElement('script');
7 | var parent = document.documentElement;
8 | script.textContent = '('+ fn +')();';
9 | parent.appendChild(script);
10 | parent.removeChild(script);
11 | }
12 |
13 | // Post a message whenever history.pushState is called. GitHub uses
14 | // pushState to implement page transitions without full page loads.
15 | // This needs to be injected because content scripts run in a sandbox.
16 | inject(function() {
17 | var pushState = history.pushState;
18 | history.pushState = function on_pushState() {
19 | window.postMessage('selfie:pageUpdated', '*');
20 | return pushState.apply(this, arguments);
21 | };
22 | var replaceState = history.replaceState;
23 | history.replaceState = function on_replaceState() {
24 | window.postMessage('selfie:pageUpdated', '*');
25 | return replaceState.apply(this, arguments);
26 | };
27 | });
28 |
29 | var allowedPaths = [
30 | // New issues
31 | /https:\/\/github.com\/.+?\/.+?\/issues\/new/,
32 | // Existing issues (comment)
33 | /https:\/\/github.com\/.+?\/.+?\/issues\/\d+/,
34 | // New pull request
35 | /https:\/\/github.com\/.+?\/.+?\/compare/,
36 | // Existing pull requests (comment)
37 | /https:\/\/github.com\/.+?\/.+?\/pull\/\d+/
38 | ];
39 |
40 | // Return true if predicate(item) returns true for any item in array.
41 | function any(array, predicate) {
42 | for (var i = 0; i < array.length; i++) {
43 | if (predicate(array[i])) {
44 | return true;
45 | }
46 | }
47 | return false;
48 | }
49 |
50 | function addSelfies() {
51 | if (!any(allowedPaths, (path) => path.test(window.location.href))) {
52 | // No selfies here!
53 | return;
54 | }
55 | new GitHubSelfies().setupSelfieStream();
56 | }
57 |
58 | // Add selfies when the extension is loaded into the page,
59 | // and whenever we push/pop new pages.
60 | window.addEventListener("message", function(event) {
61 | if (event.data === 'selfie:pageUpdated') {
62 | addSelfies();
63 | }
64 | });
65 | window.addEventListener("popstate", addSelfies);
66 | addSelfies();
67 | })();
68 |
--------------------------------------------------------------------------------
/chrome/selfie.css:
--------------------------------------------------------------------------------
1 | /*
2 | This is a little nutty - override GitHub's styles to use flexbox
3 | so we can have the video fill the available space!
4 | */
5 | .form-actions {
6 | display: flex;
7 | flex-direction: row-reverse; /* simulate their float: right */
8 | flex-wrap: wrap;
9 | align-items: flex-start;
10 | }
11 |
12 | /*
13 | Trying to get the "Styling with Markdown is supported"
14 | block to not push the flex container to the right.
15 | There's almost certainly a better way, please replace
16 | this if you figure it out.
17 | */
18 | .js-suggester-container > .float-left {
19 | position: absolute;
20 | }
21 |
22 | .hidden {
23 | display: none;
24 | }
25 |
26 | #selfieControls {
27 | float: right;
28 | overflow: auto;
29 | margin-right: 6px;
30 | }
31 |
32 | .selfieTakeButton {
33 | float: right;
34 | margin-right: 6px;
35 | }
36 |
37 | .selfieDuration {
38 | height: auto !important;
39 | float: left;
40 | }
41 |
42 | #selfieVideo {
43 | width: 100%;
44 | transform: rotateY(180deg);
45 | background: black;
46 | }
47 |
48 | .selfieVideoContainer {
49 | position: relative;
50 | flex: 1; /* Take available space */
51 | flex-basis: 100%;
52 | width: 100%;
53 | vertical-align: top;
54 | margin-right: 8px;
55 | margin-top: 8px;
56 | }
57 |
58 | .selfieProgressContainer {
59 | position: absolute;
60 | z-index: 1000;
61 | width: 100%;
62 | }
63 |
64 | .selfieProgress {
65 | height:4px;
66 | width: 0px;
67 | background-color: #60b044;
68 | }
69 |
70 | .selfieVideoOverlay {
71 | z-index:10;
72 | position: absolute;
73 | color: white;
74 | font-size: 22px;
75 | text-align: center;
76 | width: 100%;
77 | top: 1em;
78 | text-shadow: 1px 1px 4px black;
79 | }
80 |
81 | #selfieToggleLabel {
82 | margin-right:5px;
83 | }
84 |
85 | #selfieToggle {
86 | width: 55px;
87 | margin-right: 5px;
88 | }
89 |
90 | div.selfieProgress.newIssueSelfieProgress {
91 | height:2px;
92 | width:0px;
93 | background-color: red;
94 | float:right;
95 | }
96 |
97 | #totallyAwesomeSelfieButton {
98 | margin-right: 5px;
99 | }
100 |
101 | #totallyAwesomeSelfieIcon {
102 | font-size: 22px;
103 | margin-right: 5px;
104 | line-height: 0px;
105 | }
106 |
107 | .selfieVideoContainer .counter-container {
108 | position: absolute;
109 | height: 100%;
110 | width: 100%;
111 | display: flex;
112 | align-items: center;
113 | justify-content: center;
114 | z-index: 999;
115 | }
116 |
117 | .selfie-countdown {
118 | position: relative;
119 | }
120 |
121 | .selfieVideoContainer .counter-container .count {
122 | font-size: 92px;
123 | text-shadow: -1px -1px 1px #999, 1px 1px 1px #222;
124 | color: #fff;
125 | }
126 |
127 | .selfie-flash {
128 | animation-name: flash-animation;
129 | animation-duration: 1s;
130 | animation-timing-function: ease-out;
131 | }
132 |
133 | @keyframes flash-animation {
134 | from { background: white; }
135 | to { background: default; }
136 | }
137 |
138 | // TODO: styles for countown, overlay, etc
139 |
--------------------------------------------------------------------------------
/chrome/LZWEncoder.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This class handles LZW encoding
3 | * Adapted from Jef Poskanzer's Java port by way of J. M. G. Elliott.
4 | * @author Kevin Weiner (original Java version - kweiner@fmsware.com)
5 | * @author Thibault Imbert (AS3 version - bytearray.org)
6 | * @version 0.1 AS3 implementation
7 | */
8 |
9 | //import flash.utils.ByteArray;
10 |
11 | LZWEncoder = function()
12 | {
13 | var exports = {};
14 | /*private_static*/ var EOF/*int*/ = -1;
15 | /*private*/ var imgW/*int*/;
16 | /*private*/ var imgH/*int*/
17 | /*private*/ var pixAry/*ByteArray*/;
18 | /*private*/ var initCodeSize/*int*/;
19 | /*private*/ var remaining/*int*/;
20 | /*private*/ var curPixel/*int*/;
21 |
22 | // GIFCOMPR.C - GIF Image compression routines
23 | // Lempel-Ziv compression based on 'compress'. GIF modifications by
24 | // David Rowley (mgardi@watdcsu.waterloo.edu)
25 | // General DEFINEs
26 |
27 | /*private_static*/ var BITS/*int*/ = 12;
28 | /*private_static*/ var HSIZE/*int*/ = 5003; // 80% occupancy
29 |
30 | // GIF Image compression - modified 'compress'
31 | // Based on: compress.c - File compression ala IEEE Computer, June 1984.
32 | // By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
33 | // Jim McKie (decvax!mcvax!jim)
34 | // Steve Davies (decvax!vax135!petsd!peora!srd)
35 | // Ken Turkowski (decvax!decwrl!turtlevax!ken)
36 | // James A. Woods (decvax!ihnp4!ames!jaw)
37 | // Joe Orost (decvax!vax135!petsd!joe)
38 |
39 | /*private*/ var n_bits/*int*/ // number of bits/code
40 | /*private*/ var maxbits/*int*/ = BITS; // user settable max # bits/code
41 | /*private*/ var maxcode/*int*/ // maximum code, given n_bits
42 | /*private*/ var maxmaxcode/*int*/ = 1 << BITS; // should NEVER generate this code
43 | /*private*/ var htab/*Array*/ = new Array;
44 | /*private*/ var codetab/*Array*/ = new Array;
45 | /*private*/ var hsize/*int*/ = HSIZE; // for dynamic table sizing
46 | /*private*/ var free_ent/*int*/ = 0; // first unused entry
47 |
48 | // block compression parameters -- after all codes are used up,
49 | // and compression rate changes, start over.
50 |
51 | /*private*/ var clear_flg/*Boolean*/ = false;
52 |
53 | // Algorithm: use open addressing double hashing (no chaining) on the
54 | // prefix code / next character combination. We do a variant of Knuth's
55 | // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
56 | // secondary probe. Here, the modular division first probe is gives way
57 | // to a faster exclusive-or manipulation. Also do block compression with
58 | // an adaptive reset, whereby the code table is cleared when the compression
59 | // ratio decreases, but after the table fills. The variable-length output
60 | // codes are re-sized at this point, and a special CLEAR code is generated
61 | // for the decompressor. Late addition: construct the table according to
62 | // file size for noticeable speed improvement on small files. Please direct
63 | // questions about this implementation to ames!jaw.
64 |
65 | /*private*/ var g_init_bits/*int*/;
66 | /*private*/ var ClearCode/*int*/;
67 | /*private*/ var EOFCode/*int*/;
68 |
69 | // output
70 | // Output the given code.
71 | // Inputs:
72 | // code: A n_bits-bit integer. If == -1, then EOF. This assumes
73 | // that n_bits =< wordsize - 1.
74 | // Outputs:
75 | // Outputs code to the file.
76 | // Assumptions:
77 | // Chars are 8 bits long.
78 | // Algorithm:
79 | // Maintain a BITS character long buffer (so that 8 codes will
80 | // fit in it exactly). Use the VAX insv instruction to insert each
81 | // code in turn. When the buffer fills up empty it and start over.
82 |
83 | /*private*/ var cur_accum/*int*/ = 0;
84 | /*private*/ var cur_bits/*int*/ = 0;
85 | /*private*/ var masks/*Array*/ = [ 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF ];
86 |
87 | // Number of characters so far in this 'packet'
88 | /*private*/ var a_count/*int*/;
89 |
90 | // Define the storage for the packet accumulator
91 | /*private*/ var accum/*ByteArray*/ = [];
92 |
93 | var LZWEncoder = exports.LZWEncoder = function LZWEncoder (width/*int*/, height/*int*/, pixels/*ByteArray*/, color_depth/*int*/)
94 | {
95 |
96 | imgW = width;
97 | imgH = height;
98 | pixAry = pixels;
99 | initCodeSize = Math.max(2, color_depth);
100 |
101 | }
102 |
103 | // Add a character to the end of the current packet, and if it is 254
104 | // characters, flush the packet to disk.
105 | var char_out = function char_out(c/*Number*/, outs/*ByteArray*/)/*void*/
106 | {
107 | accum[a_count++] = c;
108 | if (a_count >= 254) flush_char(outs);
109 |
110 | }
111 |
112 | // Clear out the hash table
113 | // table clear for block compress
114 |
115 | var cl_block = function cl_block(outs/*ByteArray*/)/*void*/
116 | {
117 |
118 | cl_hash(hsize);
119 | free_ent = ClearCode + 2;
120 | clear_flg = true;
121 | output(ClearCode, outs);
122 |
123 | }
124 |
125 | // reset code table
126 | var cl_hash = function cl_hash(hsize/*int*/)/*void*/
127 | {
128 |
129 | for (var i/*int*/ = 0; i < hsize; ++i) htab[i] = -1;
130 |
131 | }
132 |
133 | var compress = exports.compress = function compress(init_bits/*int*/, outs/*ByteArray*/)/*void*/
134 |
135 | {
136 | var fcode/*int*/;
137 | var i/*int*/ /* = 0 */;
138 | var c/*int*/;
139 | var ent/*int*/;
140 | var disp/*int*/;
141 | var hsize_reg/*int*/;
142 | var hshift/*int*/;
143 |
144 | // Set up the globals: g_init_bits - initial number of bits
145 | g_init_bits = init_bits;
146 |
147 | // Set up the necessary values
148 | clear_flg = false;
149 | n_bits = g_init_bits;
150 | maxcode = MAXCODE(n_bits);
151 |
152 | ClearCode = 1 << (init_bits - 1);
153 | EOFCode = ClearCode + 1;
154 | free_ent = ClearCode + 2;
155 |
156 | a_count = 0; // clear packet
157 |
158 | ent = nextPixel();
159 |
160 | hshift = 0;
161 | for (fcode = hsize; fcode < 65536; fcode *= 2)
162 | ++hshift;
163 | hshift = 8 - hshift; // set hash code range bound
164 |
165 | hsize_reg = hsize;
166 | cl_hash(hsize_reg); // clear hash table
167 |
168 | output(ClearCode, outs);
169 |
170 | outer_loop: while ((c = nextPixel()) != EOF)
171 |
172 | {
173 |
174 | fcode = (c << maxbits) + ent;
175 | i = (c << hshift) ^ ent; // xor hashing
176 |
177 | if (htab[i] == fcode)
178 | {
179 | ent = codetab[i];
180 | continue;
181 | } else if (htab[i] >= 0) // non-empty slot
182 | {
183 | disp = hsize_reg - i; // secondary hash (after G. Knott)
184 | if (i == 0)
185 | disp = 1;
186 | do
187 | {
188 |
189 | if ((i -= disp) < 0) i += hsize_reg;
190 |
191 | if (htab[i] == fcode)
192 | {
193 | ent = codetab[i];
194 | continue outer_loop;
195 | }
196 | } while (htab[i] >= 0);
197 | }
198 |
199 | output(ent, outs);
200 | ent = c;
201 | if (free_ent < maxmaxcode)
202 | {
203 | codetab[i] = free_ent++; // code -> hashtable
204 | htab[i] = fcode;
205 | } else cl_block(outs);
206 | }
207 |
208 | // Put out the final code.
209 | output(ent, outs);
210 | output(EOFCode, outs);
211 |
212 | }
213 |
214 | // ----------------------------------------------------------------------------
215 | var encode = exports.encode = function encode(os/*ByteArray*/)/*void*/
216 | {
217 | os.writeByte(initCodeSize); // write "initial code size" byte
218 | remaining = imgW * imgH; // reset navigation variables
219 | curPixel = 0;
220 | compress(initCodeSize + 1, os); // compress and write the pixel data
221 | os.writeByte(0); // write block terminator
222 |
223 | }
224 |
225 | // Flush the packet to disk, and reset the accumulator
226 | var flush_char = function flush_char(outs/*ByteArray*/)/*void*/
227 | {
228 |
229 | if (a_count > 0)
230 | {
231 | outs.writeByte(a_count);
232 | outs.writeBytes(accum, 0, a_count);
233 | a_count = 0;
234 | }
235 |
236 | }
237 |
238 | var MAXCODE = function MAXCODE(n_bits/*int*/)/*int*/
239 | {
240 |
241 | return (1 << n_bits) - 1;
242 |
243 | }
244 |
245 | // ----------------------------------------------------------------------------
246 | // Return the next pixel from the image
247 | // ----------------------------------------------------------------------------
248 |
249 | var nextPixel = function nextPixel()/*int*/
250 | {
251 |
252 | if (remaining == 0) return EOF;
253 |
254 | --remaining;
255 |
256 | var pix/*Number*/ = pixAry[curPixel++];
257 |
258 | return pix & 0xff;
259 |
260 | }
261 |
262 | var output = function output(code/*int*/, outs/*ByteArray*/)/*void*/
263 |
264 | {
265 | cur_accum &= masks[cur_bits];
266 |
267 | if (cur_bits > 0) cur_accum |= (code << cur_bits);
268 | else cur_accum = code;
269 |
270 | cur_bits += n_bits;
271 |
272 | while (cur_bits >= 8)
273 |
274 | {
275 |
276 | char_out((cur_accum & 0xff), outs);
277 | cur_accum >>= 8;
278 | cur_bits -= 8;
279 |
280 | }
281 |
282 | // If the next entry is going to be too big for the code size,
283 | // then increase it, if possible.
284 |
285 | if (free_ent > maxcode || clear_flg)
286 | {
287 |
288 | if (clear_flg)
289 | {
290 |
291 | maxcode = MAXCODE(n_bits = g_init_bits);
292 | clear_flg = false;
293 |
294 | } else
295 | {
296 |
297 | ++n_bits;
298 |
299 | if (n_bits == maxbits) maxcode = maxmaxcode;
300 |
301 | else maxcode = MAXCODE(n_bits);
302 |
303 | }
304 |
305 | }
306 |
307 | if (code == EOFCode)
308 | {
309 |
310 | // At EOF, write the rest of the buffer.
311 | while (cur_bits > 0)
312 | {
313 |
314 | char_out((cur_accum & 0xff), outs);
315 | cur_accum >>= 8;
316 | cur_bits -= 8;
317 | }
318 |
319 |
320 | flush_char(outs);
321 |
322 | }
323 |
324 | }
325 | LZWEncoder.apply(this, arguments);
326 | return exports;
327 | }
328 |
--------------------------------------------------------------------------------
/chrome/selfie-base.js:
--------------------------------------------------------------------------------
1 | // A selfie toggle button that can be attached to the document.
2 | function GitHubSelfieButtons() {
3 | this.elem = $(
4 | '
setDelay(1000/fps).
240 | * @param fps
241 | * float frame rate (frames per second)
242 | */
243 |
244 | var setFrameRate = exports.setFrameRate = function setFrameRate(fps)/*void*/
245 | {
246 |
247 | if (fps != 0xf) delay = Math.round(100/fps);
248 |
249 | }
250 |
251 | /**
252 | * Sets quality of color quantization (conversion of images to the maximum 256
253 | * colors allowed by the GIF specification). Lower values (minimum = 1)
254 | * produce better colors, but slow processing significantly. 10 is the
255 | * default, and produces good color mapping at reasonable speeds. Values
256 | * greater than 20 do not yield significant improvements in speed.
257 | * @param quality
258 | * int greater than 0.
259 | * @return
260 | */
261 |
262 | var setQuality = exports.setQuality = function setQuality(quality)/*void*/
263 | {
264 |
265 | if (quality < 1) quality = 1;
266 | sample = quality;
267 |
268 | }
269 |
270 | /**
271 | * Sets the GIF frame size. The default size is the size of the first frame
272 | * added if this method is not invoked.
273 | * @param w
274 | * int frame width.
275 | * @param h
276 | * int frame width.
277 | */
278 |
279 | var setSize = exports.setSize = function setSize(w, h)/*void*/
280 | {
281 |
282 | if (started && !firstFrame) return;
283 | width = w;
284 | height = h;
285 | if (width < 1)width = 320;
286 | if (height < 1)height = 240;
287 | sizeSet = true
288 |
289 | }
290 |
291 | /**
292 | * Initiates GIF file creation on the given stream.
293 | * @param os
294 | * OutputStream on which GIF images are written.
295 | * @return false if initial write failed.
296 | *
297 | */
298 |
299 | var start = exports.start = function start()/*Boolean*/
300 | {
301 | reset();
302 | var ok = true;
303 | closeStream = false;
304 | out = new ByteArray;
305 | try {
306 | out.writeUTFBytes("GIF89a");
307 | } catch (err) {
308 | ok = false;
309 | }
310 | started = ok;
311 | return started;
312 |
313 | }
314 |
315 | var cont = exports.cont = function cont()/*Boolean*/
316 | {
317 |
318 | reset();
319 | var ok/*Boolean*/ = true;
320 | closeStream = false;
321 | out = new ByteArray;
322 | started = ok;
323 | return started;
324 |
325 | }
326 |
327 | /**
328 | * Analyzes image colors and creates color map.
329 | */
330 |
331 | var analyzePixels = function analyzePixels()/*void*/
332 | {
333 |
334 | var len/*int*/ = pixels.length;
335 | var nPix/*int*/ = len / 3;
336 | indexedPixels = [];
337 | var nq/*NeuQuant*/ = new NeuQuant(pixels, len, sample);
338 | // initialize quantizer
339 | colorTab = nq.process(); // create reduced palette
340 | // map image pixels to new palette
341 | var k/*int*/ = 0;
342 | for (var j/*int*/ = 0; j < nPix; j++) {
343 | var index/*int*/ = nq.map(pixels[k++] & 0xff, pixels[k++] & 0xff, pixels[k++] & 0xff);
344 | usedEntry[index] = true;
345 | indexedPixels[j] = index;
346 | }
347 | pixels = null;
348 | colorDepth = 8;
349 | palSize = 7;
350 | // get closest match to transparent color if specified
351 | if (transparent != null) {
352 | transIndex = findClosest(transparent);
353 | }
354 | }
355 |
356 | /**
357 | * Returns index of palette color closest to c
358 | *
359 | */
360 |
361 | var findClosest = function findClosest(c)/*int*/
362 | {
363 |
364 | if (colorTab == null) return -1;
365 | var r/*int*/ = (c & 0xFF0000) >> 16;
366 | var g/*int*/ = (c & 0x00FF00) >> 8;
367 | var b/*int*/ = (c & 0x0000FF);
368 | var minpos/*int*/ = 0;
369 | var dmin/*int*/ = 256 * 256 * 256;
370 | var len/*int*/ = colorTab.length;
371 |
372 | for (var i/*int*/ = 0; i < len;) {
373 | var dr/*int*/ = r - (colorTab[i++] & 0xff);
374 | var dg/*int*/ = g - (colorTab[i++] & 0xff);
375 | var db/*int*/ = b - (colorTab[i] & 0xff);
376 | var d/*int*/ = dr * dr + dg * dg + db * db;
377 | var index/*int*/ = i / 3;
378 | if (usedEntry[index] && (d < dmin)) {
379 | dmin = d;
380 | minpos = index;
381 | }
382 | i++;
383 | }
384 | return minpos;
385 |
386 | }
387 |
388 | /**
389 | * Extracts image pixels into byte array "pixels
390 | */
391 |
392 | var getImagePixels = function getImagePixels()/*void*/
393 | {
394 |
395 | var w/*int*/ = width;
396 | var h/*int*/ = height;
397 | pixels = [];
398 | var data = image;
399 | var count/*int*/ = 0;
400 |
401 | for ( var i/*int*/ = 0; i < h; i++ )
402 | {
403 |
404 | for (var j/*int*/ = 0; j < w; j++ )
405 | {
406 |
407 | var b = (i*w*4)+j*4;
408 | pixels[count++] = data[b];
409 | pixels[count++] = data[b+1];
410 | pixels[count++] = data[b+2];
411 |
412 | }
413 |
414 | }
415 |
416 | }
417 |
418 | /**
419 | * Writes Graphic Control Extension
420 | */
421 |
422 | var writeGraphicCtrlExt = function writeGraphicCtrlExt()/*void*/
423 | {
424 | out.writeByte(0x21); // extension introducer
425 | out.writeByte(0xf9); // GCE label
426 | out.writeByte(4); // data block size
427 | var transp/*int*/
428 | var disp/*int*/;
429 | if (transparent == null) {
430 | transp = 0;
431 | disp = 0; // dispose = no action
432 | } else {
433 | transp = 1;
434 | disp = 2; // force clear if using transparent color
435 | }
436 | if (dispose >= 0) {
437 | disp = dispose & 7; // user override
438 | }
439 | disp <<= 2;
440 | // packed fields
441 | out.writeByte(0 | // 1:3 reserved
442 | disp | // 4:6 disposal
443 | 0 | // 7 user input - 0 = none
444 | transp); // 8 transparency flag
445 |
446 | WriteShort(delay); // delay x 1/100 sec
447 | out.writeByte(transIndex); // transparent color index
448 | out.writeByte(0); // block terminator
449 |
450 | }
451 |
452 | /**
453 | * Writes Comment Extention
454 | */
455 | var writeCommentExt = function writeCommentExt()/*void*/
456 | {
457 |
458 | out.writeByte(0x21); // extension introducer
459 | out.writeByte(0xfe); // comment label
460 | out.writeByte(comment.length); // Block Size (s)
461 | out.writeUTFBytes(comment);
462 | out.writeByte(0); // block terminator
463 | }
464 |
465 |
466 | /**
467 | * Writes Image Descriptor
468 | */
469 |
470 | var writeImageDesc = function writeImageDesc()/*void*/
471 | {
472 |
473 | out.writeByte(0x2c); // image separator
474 | WriteShort(0); // image position x,y = 0,0
475 | WriteShort(0);
476 | WriteShort(width); // image size
477 | WriteShort(height);
478 |
479 | // packed fields
480 | if (firstFrame) {
481 | // no LCT - GCT is used for first (or only) frame
482 | out.writeByte(0);
483 | } else {
484 | // specify normal LCT
485 | out.writeByte(0x80 | // 1 local color table 1=yes
486 | 0 | // 2 interlace - 0=no
487 | 0 | // 3 sorted - 0=no
488 | 0 | // 4-5 reserved
489 | palSize); // 6-8 size of color table
490 | }
491 | }
492 |
493 | /**
494 | * Writes Logical Screen Descriptor
495 | */
496 |
497 | var writeLSD = function writeLSD()/*void*/
498 | {
499 |
500 | // logical screen size
501 | WriteShort(width);
502 | WriteShort(height);
503 | // packed fields
504 | out.writeByte((0x80 | // 1 : global color table flag = 1 (gct used)
505 | 0x70 | // 2-4 : color resolution = 7
506 | 0x00 | // 5 : gct sort flag = 0
507 | palSize)); // 6-8 : gct size
508 |
509 | out.writeByte(0); // background color index
510 | out.writeByte(0); // pixel aspect ratio - assume 1:1
511 |
512 | }
513 |
514 | /**
515 | * Writes Netscape application extension to define repeat count.
516 | */
517 |
518 | var writeNetscapeExt = function writeNetscapeExt()/*void*/
519 | {
520 |
521 | out.writeByte(0x21); // extension introducer
522 | out.writeByte(0xff); // app extension label
523 | out.writeByte(11); // block size
524 | out.writeUTFBytes("NETSCAPE" + "2.0"); // app id + auth code
525 | out.writeByte(3); // sub-block size
526 | out.writeByte(1); // loop sub-block id
527 | WriteShort(repeat); // loop count (extra iterations, 0=repeat forever)
528 | out.writeByte(0); // block terminator
529 |
530 | }
531 |
532 | /**
533 | * Writes color table
534 | */
535 |
536 | var writePalette = function writePalette()/*void*/
537 | {
538 | out.writeBytes(colorTab);
539 | var n/*int*/ = (3 * 256) - colorTab.length;
540 | for (var i/*int*/ = 0; i < n; i++) out.writeByte(0);
541 |
542 | }
543 |
544 | var WriteShort = function WriteShort (pValue)/*void*/
545 | {
546 |
547 | out.writeByte( pValue & 0xFF );
548 | out.writeByte( (pValue >> 8) & 0xFF);
549 |
550 | }
551 |
552 | /**
553 | * Encodes and writes pixel data
554 | */
555 |
556 | var writePixels = function writePixels()/*void*/
557 | {
558 |
559 | var myencoder/*LZWEncoder*/ = new LZWEncoder(width, height, indexedPixels, colorDepth);
560 | myencoder.encode(out);
561 |
562 | }
563 |
564 | /**
565 | * retrieves the GIF stream
566 | */
567 | var stream = exports.stream = function stream ( )/*ByteArray*/
568 | {
569 |
570 | return out;
571 |
572 | }
573 |
574 | var setProperties = exports.setProperties = function setProperties(has_start, is_first){
575 | started = has_start;
576 | firstFrame = is_first;
577 | //out = new ByteArray; //??
578 | }
579 |
580 | return exports;
581 |
582 | }
--------------------------------------------------------------------------------
/chrome/NeuQuant.js:
--------------------------------------------------------------------------------
1 | /*
2 | * NeuQuant Neural-Net Quantization Algorithm
3 | * ------------------------------------------
4 | *
5 | * Copyright (c) 1994 Anthony Dekker
6 | *
7 | * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. See
8 | * "Kohonen neural networks for optimal colour quantization" in "Network:
9 | * Computation in Neural Systems" Vol. 5 (1994) pp 351-367. for a discussion of
10 | * the algorithm.
11 | *
12 | * Any party obtaining a copy of these files from the author, directly or
13 | * indirectly, is granted, free of charge, a full and unrestricted irrevocable,
14 | * world-wide, paid up, royalty-free, nonexclusive right and license to deal in
15 | * this software and documentation files (the "Software"), including without
16 | * limitation the rights to use, copy, modify, merge, publish, distribute,
17 | * sublicense, and/or sell copies of the Software, and to permit persons who
18 | * receive copies from any such party to do so, with the only requirement being
19 | * that this copyright notice remain intact.
20 | */
21 |
22 | /*
23 | * This class handles Neural-Net quantization algorithm
24 | * @author Kevin Weiner (original Java version - kweiner@fmsware.com)
25 | * @author Thibault Imbert (AS3 version - bytearray.org)
26 | * @version 0.1 AS3 implementation
27 | */
28 |
29 | //import flash.utils.ByteArray;
30 |
31 | NeuQuant = function()
32 | {
33 | var exports = {};
34 | /*private_static*/ var netsize/*int*/ = 256; /* number of colours used */
35 |
36 | /* four primes near 500 - assume no image has a length so large */
37 | /* that it is divisible by all four primes */
38 |
39 | /*private_static*/ var prime1/*int*/ = 499;
40 | /*private_static*/ var prime2/*int*/ = 491;
41 | /*private_static*/ var prime3/*int*/ = 487;
42 | /*private_static*/ var prime4/*int*/ = 503;
43 | /*private_static*/ var minpicturebytes/*int*/ = (3 * prime4);
44 |
45 | /* minimum size for input image */
46 | /*
47 | * Program Skeleton ---------------- [select samplefac in range 1..30] [read
48 | * image from input file] pic = (unsigned char*) malloc(3*width*height);
49 | * initnet(pic,3*width*height,samplefac); learn(); unbiasnet(); [write output
50 | * image header, using writecolourmap(f)] inxbuild(); write output image using
51 | * inxsearch(b,g,r)
52 | */
53 |
54 | /*
55 | * Network Definitions -------------------
56 | */
57 |
58 | /*private_static*/ var maxnetpos/*int*/ = (netsize - 1);
59 | /*private_static*/ var netbiasshift/*int*/ = 4; /* bias for colour values */
60 | /*private_static*/ var ncycles/*int*/ = 100; /* no. of learning cycles */
61 |
62 | /* defs for freq and bias */
63 | /*private_static*/ var intbiasshift/*int*/ = 16; /* bias for fractions */
64 | /*private_static*/ var intbias/*int*/ = (1 << intbiasshift);
65 | /*private_static*/ var gammashift/*int*/ = 10; /* gamma = 1024 */
66 | /*private_static*/ var gamma/*int*/ = (1 << gammashift);
67 | /*private_static*/ var betashift/*int*/ = 10;
68 | /*private_static*/ var beta/*int*/ = (intbias >> betashift); /* beta = 1/1024 */
69 | /*private_static*/ var betagamma/*int*/ = (intbias << (gammashift - betashift));
70 |
71 | /* defs for decreasing radius factor */
72 | /*private_static*/ var initrad/*int*/ = (netsize >> 3); /*
73 | * for 256 cols, radius
74 | * starts
75 | */
76 |
77 | /*private_static*/ var radiusbiasshift/*int*/ = 6; /* at 32.0 biased by 6 bits */
78 | /*private_static*/ var radiusbias/*int*/ = (1 << radiusbiasshift);
79 | /*private_static*/ var initradius/*int*/ = (initrad * radiusbias); /*
80 | * and
81 | * decreases
82 | * by a
83 | */
84 |
85 | /*private_static*/ var radiusdec/*int*/ = 30; /* factor of 1/30 each cycle */
86 |
87 | /* defs for decreasing alpha factor */
88 | /*private_static*/ var alphabiasshift/*int*/ = 10; /* alpha starts at 1.0 */
89 | /*private_static*/ var initalpha/*int*/ = (1 << alphabiasshift);
90 | /*private*/ var alphadec/*int*/ /* biased by 10 bits */
91 |
92 | /* radbias and alpharadbias used for radpower calculation */
93 | /*private_static*/ var radbiasshift/*int*/ = 8;
94 | /*private_static*/ var radbias/*int*/ = (1 << radbiasshift);
95 | /*private_static*/ var alpharadbshift/*int*/ = (alphabiasshift + radbiasshift);
96 |
97 | /*private_static*/ var alpharadbias/*int*/ = (1 << alpharadbshift);
98 |
99 | /*
100 | * Types and Global Variables --------------------------
101 | */
102 |
103 | /*private*/ var thepicture/*ByteArray*//* the input image itself */
104 | /*private*/ var lengthcount/*int*/; /* lengthcount = H*W*3 */
105 | /*private*/ var samplefac/*int*/; /* sampling factor 1..30 */
106 |
107 | // typedef int pixel[4]; /* BGRc */
108 | /*private*/ var network/*Array*/; /* the network itself - [netsize][4] */
109 | /*protected*/ var netindex/*Array*/ = new Array();
110 |
111 | /* for network lookup - really 256 */
112 | /*private*/ var bias/*Array*/ = new Array();
113 |
114 | /* bias and freq arrays for learning */
115 | /*private*/ var freq/*Array*/ = new Array();
116 | /*private*/ var radpower/*Array*/ = new Array();
117 |
118 | var NeuQuant = exports.NeuQuant = function NeuQuant(thepic/*ByteArray*/, len/*int*/, sample/*int*/)
119 | {
120 |
121 | var i/*int*/;
122 | var p/*Array*/;
123 |
124 | thepicture = thepic;
125 | lengthcount = len;
126 | samplefac = sample;
127 |
128 | network = new Array(netsize);
129 |
130 | for (i = 0; i < netsize; i++)
131 | {
132 |
133 | network[i] = new Array(4);
134 | p = network[i];
135 | p[0] = p[1] = p[2] = (i << (netbiasshift + 8)) / netsize;
136 | freq[i] = intbias / netsize; /* 1/netsize */
137 | bias[i] = 0;
138 | }
139 |
140 | }
141 |
142 | var colorMap = function colorMap()/*ByteArray*/
143 | {
144 |
145 | var map/*ByteArray*/ = [];
146 | var index/*Array*/ = new Array(netsize);
147 | for (var i/*int*/ = 0; i < netsize; i++)
148 | index[network[i][3]] = i;
149 | var k/*int*/ = 0;
150 | for (var l/*int*/ = 0; l < netsize; l++) {
151 | var j/*int*/ = index[l];
152 | map[k++] = (network[j][0]);
153 | map[k++] = (network[j][1]);
154 | map[k++] = (network[j][2]);
155 | }
156 | return map;
157 |
158 | }
159 |
160 | /*
161 | * Insertion sort of network and building of netindex[0..255] (to do after
162 | * unbias)
163 | * -------------------------------------------------------------------------------
164 | */
165 |
166 | var inxbuild = function inxbuild()/*void*/
167 | {
168 |
169 | var i/*int*/;
170 | var j/*int*/;
171 | var smallpos/*int*/;
172 | var smallval/*int*/;
173 | var p/*Array*/;
174 | var q/*Array*/;
175 | var previouscol/*int*/
176 | var startpos/*int*/
177 |
178 | previouscol = 0;
179 | startpos = 0;
180 | for (i = 0; i < netsize; i++)
181 | {
182 |
183 | p = network[i];
184 | smallpos = i;
185 | smallval = p[1]; /* index on g */
186 | /* find smallest in i..netsize-1 */
187 | for (j = i + 1; j < netsize; j++)
188 | {
189 | q = network[j];
190 | if (q[1] < smallval)
191 | { /* index on g */
192 |
193 | smallpos = j;
194 | smallval = q[1]; /* index on g */
195 | }
196 | }
197 |
198 | q = network[smallpos];
199 | /* swap p (i) and q (smallpos) entries */
200 |
201 | if (i != smallpos)
202 | {
203 |
204 | j = q[0];
205 | q[0] = p[0];
206 | p[0] = j;
207 | j = q[1];
208 | q[1] = p[1];
209 | p[1] = j;
210 | j = q[2];
211 | q[2] = p[2];
212 | p[2] = j;
213 | j = q[3];
214 | q[3] = p[3];
215 | p[3] = j;
216 |
217 | }
218 |
219 | /* smallval entry is now in position i */
220 |
221 | if (smallval != previouscol)
222 |
223 | {
224 |
225 | netindex[previouscol] = (startpos + i) >> 1;
226 |
227 | for (j = previouscol + 1; j < smallval; j++) netindex[j] = i;
228 |
229 | previouscol = smallval;
230 | startpos = i;
231 |
232 | }
233 |
234 | }
235 |
236 | netindex[previouscol] = (startpos + maxnetpos) >> 1;
237 | for (j = previouscol + 1; j < 256; j++) netindex[j] = maxnetpos; /* really 256 */
238 |
239 | }
240 |
241 | /*
242 | * Main Learning Loop ------------------
243 | */
244 |
245 | var learn = function learn()/*void*/
246 |
247 | {
248 |
249 | var i/*int*/;
250 | var j/*int*/;
251 | var b/*int*/;
252 | var g/*int*/
253 | var r/*int*/;
254 | var radius/*int*/;
255 | var rad/*int*/;
256 | var alpha/*int*/;
257 | var step/*int*/;
258 | var delta/*int*/;
259 | var samplepixels/*int*/;
260 | var p/*ByteArray*/;
261 | var pix/*int*/;
262 | var lim/*int*/;
263 |
264 | if (lengthcount < minpicturebytes) samplefac = 1;
265 |
266 | alphadec = 30 + ((samplefac - 1) / 3);
267 | p = thepicture;
268 | pix = 0;
269 | lim = lengthcount;
270 | samplepixels = lengthcount / (3 * samplefac);
271 | delta = (samplepixels / ncycles) | 0;
272 | alpha = initalpha;
273 | radius = initradius;
274 |
275 | rad = radius >> radiusbiasshift;
276 | if (rad <= 1) rad = 0;
277 |
278 | for (i = 0; i < rad; i++) radpower[i] = alpha * (((rad * rad - i * i) * radbias) / (rad * rad));
279 |
280 |
281 | if (lengthcount < minpicturebytes) step = 3;
282 |
283 | else if ((lengthcount % prime1) != 0) step = 3 * prime1;
284 |
285 | else
286 |
287 | {
288 |
289 | if ((lengthcount % prime2) != 0) step = 3 * prime2;
290 |
291 | else
292 |
293 | {
294 |
295 | if ((lengthcount % prime3) != 0) step = 3 * prime3;
296 |
297 | else step = 3 * prime4;
298 |
299 | }
300 |
301 | }
302 |
303 | i = 0;
304 |
305 | while (i < samplepixels)
306 |
307 | {
308 |
309 | b = (p[pix + 0] & 0xff) << netbiasshift;
310 | g = (p[pix + 1] & 0xff) << netbiasshift;
311 | r = (p[pix + 2] & 0xff) << netbiasshift;
312 | j = contest(b, g, r);
313 |
314 | altersingle(alpha, j, b, g, r);
315 |
316 | if (rad != 0) alterneigh(rad, j, b, g, r); /* alter neighbours */
317 |
318 | pix += step;
319 |
320 | if (pix >= lim) pix -= lengthcount;
321 |
322 | i++;
323 |
324 | if (delta == 0) delta = 1;
325 |
326 | if (i % delta == 0)
327 |
328 | {
329 |
330 | alpha -= alpha / alphadec;
331 | radius -= radius / radiusdec;
332 | rad = radius >> radiusbiasshift;
333 |
334 | if (rad <= 1) rad = 0;
335 |
336 | for (j = 0; j < rad; j++) radpower[j] = alpha * (((rad * rad - j * j) * radbias) / (rad * rad));
337 |
338 | }
339 |
340 | }
341 |
342 | }
343 |
344 | /*
345 | ** Search for BGR values 0..255 (after net is unbiased) and return colour
346 | * index
347 | * ----------------------------------------------------------------------------
348 | */
349 |
350 | var map = exports.map = function map(b/*int*/, g/*int*/, r/*int*/)/*int*/
351 |
352 | {
353 |
354 | var i/*int*/;
355 | var j/*int*/;
356 | var dist/*int*/
357 | var a/*int*/;
358 | var bestd/*int*/;
359 | var p/*Array*/;
360 | var best/*int*/;
361 |
362 | bestd = 1000; /* biggest possible dist is 256*3 */
363 | best = -1;
364 | i = netindex[g]; /* index on g */
365 | j = i - 1; /* start at netindex[g] and work outwards */
366 |
367 | while ((i < netsize) || (j >= 0))
368 |
369 | {
370 |
371 | if (i < netsize)
372 |
373 | {
374 |
375 | p = network[i];
376 |
377 | dist = p[1] - g; /* inx key */
378 |
379 | if (dist >= bestd) i = netsize; /* stop iter */
380 |
381 | else
382 |
383 | {
384 |
385 | i++;
386 |
387 | if (dist < 0) dist = -dist;
388 |
389 | a = p[0] - b;
390 |
391 | if (a < 0) a = -a;
392 |
393 | dist += a;
394 |
395 | if (dist < bestd)
396 |
397 | {
398 |
399 | a = p[2] - r;
400 |
401 | if (a < 0) a = -a;
402 |
403 | dist += a;
404 |
405 | if (dist < bestd)
406 |
407 | {
408 |
409 | bestd = dist;
410 | best = p[3];
411 |
412 | }
413 |
414 | }
415 |
416 | }
417 |
418 | }
419 |
420 | if (j >= 0)
421 | {
422 |
423 | p = network[j];
424 |
425 | dist = g - p[1]; /* inx key - reverse dif */
426 |
427 | if (dist >= bestd) j = -1; /* stop iter */
428 |
429 | else
430 | {
431 |
432 | j--;
433 | if (dist < 0) dist = -dist;
434 | a = p[0] - b;
435 | if (a < 0) a = -a;
436 | dist += a;
437 |
438 | if (dist < bestd)
439 |
440 | {
441 |
442 | a = p[2] - r;
443 | if (a < 0)a = -a;
444 | dist += a;
445 | if (dist < bestd)
446 | {
447 | bestd = dist;
448 | best = p[3];
449 | }
450 |
451 | }
452 |
453 | }
454 |
455 | }
456 |
457 | }
458 |
459 | return (best);
460 |
461 | }
462 |
463 | var process = exports.process = function process()/*ByteArray*/
464 | {
465 |
466 | learn();
467 | unbiasnet();
468 | inxbuild();
469 | return colorMap();
470 |
471 | }
472 |
473 | /*
474 | * Unbias network to give byte values 0..255 and record position i to prepare
475 | * for sort
476 | * -----------------------------------------------------------------------------------
477 | */
478 |
479 | var unbiasnet = function unbiasnet()/*void*/
480 |
481 | {
482 |
483 | var i/*int*/;
484 | var j/*int*/;
485 |
486 | for (i = 0; i < netsize; i++)
487 | {
488 | network[i][0] >>= netbiasshift;
489 | network[i][1] >>= netbiasshift;
490 | network[i][2] >>= netbiasshift;
491 | network[i][3] = i; /* record colour no */
492 | }
493 |
494 | }
495 |
496 | /*
497 | * Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2)) in
498 | * radpower[|i-j|]
499 | * ---------------------------------------------------------------------------------
500 | */
501 |
502 | var alterneigh = function alterneigh(rad/*int*/, i/*int*/, b/*int*/, g/*int*/, r/*int*/)/*void*/
503 |
504 | {
505 |
506 | var j/*int*/;
507 | var k/*int*/;
508 | var lo/*int*/;
509 | var hi/*int*/;
510 | var a/*int*/;
511 | var m/*int*/;
512 |
513 | var p/*Array*/;
514 |
515 | lo = i - rad;
516 | if (lo < -1) lo = -1;
517 |
518 | hi = i + rad;
519 |
520 | if (hi > netsize) hi = netsize;
521 |
522 | j = i + 1;
523 | k = i - 1;
524 | m = 1;
525 |
526 | while ((j < hi) || (k > lo))
527 |
528 | {
529 |
530 | a = radpower[m++];
531 |
532 | if (j < hi)
533 |
534 | {
535 |
536 | p = network[j++];
537 |
538 | try {
539 |
540 | p[0] -= (a * (p[0] - b)) / alpharadbias;
541 | p[1] -= (a * (p[1] - g)) / alpharadbias;
542 | p[2] -= (a * (p[2] - r)) / alpharadbias;
543 |
544 | } catch (e/*Error*/) {} // prevents 1.3 miscompilation
545 |
546 | }
547 |
548 | if (k > lo)
549 |
550 | {
551 |
552 | p = network[k--];
553 |
554 | try
555 | {
556 |
557 | p[0] -= (a * (p[0] - b)) / alpharadbias;
558 | p[1] -= (a * (p[1] - g)) / alpharadbias;
559 | p[2] -= (a * (p[2] - r)) / alpharadbias;
560 |
561 | } catch (e/*Error*/) {}
562 |
563 | }
564 |
565 | }
566 |
567 | }
568 |
569 | /*
570 | * Move neuron i towards biased (b,g,r) by factor alpha
571 | * ----------------------------------------------------
572 | */
573 |
574 | var altersingle = function altersingle(alpha/*int*/, i/*int*/, b/*int*/, g/*int*/, r/*int*/)/*void*/
575 | {
576 |
577 | /* alter hit neuron */
578 | var n/*Array*/ = network[i];
579 | n[0] -= (alpha * (n[0] - b)) / initalpha;
580 | n[1] -= (alpha * (n[1] - g)) / initalpha;
581 | n[2] -= (alpha * (n[2] - r)) / initalpha;
582 |
583 | }
584 |
585 | /*
586 | * Search for biased BGR values ----------------------------
587 | */
588 |
589 | var contest = function contest(b/*int*/, g/*int*/, r/*int*/)/*int*/
590 | {
591 |
592 | /* finds closest neuron (min dist) and updates freq */
593 | /* finds best neuron (min dist-bias) and returns position */
594 | /* for frequently chosen neurons, freq[i] is high and bias[i] is negative */
595 | /* bias[i] = gamma*((1/netsize)-freq[i]) */
596 |
597 | var i/*int*/;
598 | var dist/*int*/;
599 | var a/*int*/;
600 | var biasdist/*int*/;
601 | var betafreq/*int*/;
602 | var bestpos/*int*/;
603 | var bestbiaspos/*int*/;
604 | var bestd/*int*/;
605 | var bestbiasd/*int*/;
606 | var n/*Array*/;
607 |
608 | bestd = ~(1 << 31);
609 | bestbiasd = bestd;
610 | bestpos = -1;
611 | bestbiaspos = bestpos;
612 |
613 | for (i = 0; i < netsize; i++)
614 |
615 | {
616 |
617 | n = network[i];
618 | dist = n[0] - b;
619 |
620 | if (dist < 0) dist = -dist;
621 |
622 | a = n[1] - g;
623 |
624 | if (a < 0) a = -a;
625 |
626 | dist += a;
627 |
628 | a = n[2] - r;
629 |
630 | if (a < 0) a = -a;
631 |
632 | dist += a;
633 |
634 | if (dist < bestd)
635 |
636 | {
637 |
638 | bestd = dist;
639 | bestpos = i;
640 |
641 | }
642 |
643 | biasdist = dist - ((bias[i]) >> (intbiasshift - netbiasshift));
644 |
645 | if (biasdist < bestbiasd)
646 |
647 | {
648 |
649 | bestbiasd = biasdist;
650 | bestbiaspos = i;
651 |
652 | }
653 |
654 | betafreq = (freq[i] >> betashift);
655 | freq[i] -= betafreq;
656 | bias[i] += (betafreq << gammashift);
657 |
658 | }
659 |
660 | freq[bestpos] += beta;
661 | bias[bestpos] -= betagamma;
662 | return (bestbiaspos);
663 |
664 | }
665 |
666 | NeuQuant.apply(this, arguments);
667 | return exports;
668 | }
--------------------------------------------------------------------------------
/chrome/jquery.min.js:
--------------------------------------------------------------------------------
1 | /*! jQuery v1.10.1 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license
2 | //@ sourceMappingURL=jquery-1.10.1.min.map
3 | */
4 | (function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.1",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=lt(),k=lt(),E=lt(),S=!1,A=function(){return 0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=bt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+xt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return At(e.replace(z,"$1"),t,n,i)}function st(e){return K.test(e+"")}function lt(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function ut(e){return e[b]=!0,e}function ct(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function pt(e,t,n){e=e.split("|");var r,i=e.length,a=n?null:t;while(i--)(r=o.attrHandle[e[i]])&&r!==t||(o.attrHandle[e[i]]=a)}function ft(e,t){var n=e.getAttributeNode(t);return n&&n.specified?n.value:e[t]===!0?t.toLowerCase():null}function dt(e,t){return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}function ht(e){return"input"===e.nodeName.toLowerCase()?e.defaultValue:t}function gt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function mt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function yt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function vt(e){return ut(function(t){return t=+t,ut(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.parentWindow;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.frameElement&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ct(function(e){return e.innerHTML="",pt("type|href|height|width",dt,"#"===e.firstChild.getAttribute("href")),pt(B,ft,null==e.getAttribute("disabled")),e.className="i",!e.getAttribute("className")}),r.input=ct(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")}),pt("value",ht,r.attributes&&r.input),r.getElementsByTagName=ct(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ct(function(e){return e.innerHTML="",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ct(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=st(n.querySelectorAll))&&(ct(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ct(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=st(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ct(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=st(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},r.sortDetached=ct(function(e){return 1&e.compareDocumentPosition(n.createElement("div"))}),A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return gt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?gt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:ut,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=bt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?ut(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ut(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?ut(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ut(function(e){return function(t){return at(e,t).length>0}}),contains:ut(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:ut(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:vt(function(){return[0]}),last:vt(function(e,t){return[t-1]}),eq:vt(function(e,t,n){return[0>n?n+t:n]}),even:vt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:vt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:vt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:vt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=mt(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=yt(n);function bt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function xt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function wt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function Tt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function Ct(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function Nt(e,t,n,r,i,o){return r&&!r[b]&&(r=Nt(r)),i&&!i[b]&&(i=Nt(i,o)),ut(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||St(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:Ct(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=Ct(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=Ct(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function kt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=wt(function(e){return e===t},s,!0),p=wt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[wt(Tt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return Nt(l>1&&Tt(f),l>1&&xt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&kt(e.slice(l,r)),i>r&&kt(e=e.slice(r)),i>r&&xt(e))}f.push(n)}return Tt(f)}function Et(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=Ct(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?ut(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=bt(e)),n=t.length;while(n--)o=kt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Et(i,r))}return o};function St(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function At(e,t,n,i){var a,s,u,c,p,f=bt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&xt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}o.pseudos.nth=o.pseudos.eq;function jt(){}jt.prototype=o.filters=o.pseudos,o.setFilters=new jt,r.sortStable=b.split("").sort(A).join("")===b,p(),[0,0].sort(A),r.detectDuplicates=S,x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!l||i&&!u||(n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML=" | t |