├── .eslintignore
├── icons
├── icon.png
├── newshelper48x48.png
├── newshelper96x96.png
└── newshelper128x128.png
├── .gitmodules
├── githook
├── pre-commit
└── hook.sh
├── .editorconfig
├── .eslintrc
├── README.md
├── popup.html
├── _locales
├── zh_TW
│ └── messages.json
└── en
│ └── messages.json
├── LICENSE
├── g0v.json
├── content_style.css
├── manifest.json
├── background.js
├── content_script.js
└── vendor
└── jquery-3.2.1.min.js
/.eslintignore:
--------------------------------------------------------------------------------
1 | vendor/*
2 | libs/*
3 |
--------------------------------------------------------------------------------
/icons/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g0v/newshelper-extension/HEAD/icons/icon.png
--------------------------------------------------------------------------------
/icons/newshelper48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g0v/newshelper-extension/HEAD/icons/newshelper48x48.png
--------------------------------------------------------------------------------
/icons/newshelper96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g0v/newshelper-extension/HEAD/icons/newshelper96x96.png
--------------------------------------------------------------------------------
/icons/newshelper128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/g0v/newshelper-extension/HEAD/icons/newshelper128x128.png
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "libs/url-normalizer.js"]
2 | path = libs/url-normalizer.js
3 | url = git@github.com:g0v/url-normalizer.js.git
4 |
--------------------------------------------------------------------------------
/githook/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | for file in `git diff --cached --diff-filter=ACMRTUXB --name-only HEAD`
3 | do
4 | extension=`echo $file|awk -F . '{print $2}'`
5 |
6 | if [[ "$file" == *.js ]] && ! /usr/local/bin/gjslint --jslint_error all $file
7 | then
8 | echo $file
9 | invalid=true;
10 | fi
11 | done
12 |
13 | if [ "$invalid" = "true" ]
14 | then
15 | exit 1;
16 | fi
17 |
18 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Unix-style newlines with a newline ending every file
7 | [*]
8 | end_of_line = lf
9 | insert_final_newline = true
10 |
11 | # Matches multiple files with brace expansion notation
12 | # Set default charset
13 | [*]
14 | charset = utf-8
15 | indent_style = space
16 | indent_size = 2
17 |
18 | [*.html]
19 | indent_size = 4
20 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es6": true,
5 | "jquery": true,
6 | "webextensions": true
7 | },
8 | "globals": {
9 | "chrome": true,
10 | "URLNormalizer": false
11 | },
12 | "extends": [
13 | "eslint:recommended"
14 | ],
15 | rules: {
16 | "indent": ["warn", 2],
17 | "no-console": ["warn", { allow: [ "error"] }],
18 | "no-constant-condition": ["error", { "checkLoops": false }]
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/githook/hook.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #https://developers.google.com/closure/utilities/docs/linter_howto
4 |
5 | # check if gjslint exist or not.
6 | if ! type gjslint
7 | then
8 | echo "install closure-linter via easy_install"
9 | curDir=$PWD
10 | cd /tmp
11 | sudo easy_install http://closure-linter.googlecode.com/files/closure_linter-latest.tar.gz
12 | cd $PWD
13 | fi
14 |
15 | if [ -f ../.git/hooks/pre-commit ]
16 | then
17 | echo "pre-commit hook exists. Please merge the hook manually"
18 | return 1;
19 | fi
20 |
21 | echo "copy pre-commit to .git/hooks/"
22 | cp pre-commit ../.git/hooks/
23 |
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 新聞小幫手
2 | ==========
3 | 協助您判別含有誤導資訊的新聞,目前仍屬測試版。
4 |
5 |
6 | Download
7 | --------
8 | * [Chrome 瀏覽器擴充元件](https://chrome.google.com/webstore/detail/%E6%96%B0%E8%81%9E%E5%B0%8F%E5%B9%AB%E6%89%8B/hkenpfplphndcndhhhldecaammpmopoc)
9 | * [Firefox 瀏覽器擴充元件](https://addons.mozilla.org/zh-TW/firefox/addon/newshelper/)
10 |
11 |
12 | Backend
13 | -------
14 | 新聞小幫手需要從 [後端伺服器](https://github.com/g0v/newshelper-backend) 更新資料庫。但新聞小幫手的所有判斷動作都是在您的瀏覽器內完成的,因此您不用擔心因此而造成您的上網隱私外洩。
15 |
16 | Development
17 | -------
18 | 開發時可以至 https://www.facebook.com/新聞小幫手測試專用-494676360619618 測試本套件。
19 |
20 | License
21 | -------
22 | MIT http://g0v.mit-license.org/
23 |
--------------------------------------------------------------------------------
/popup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 新聞小幫手設定
6 |
15 |
16 |
17 |
18 | 您好,這是新聞小幫手
19 |
20 | 新聞小幫手會幫助您記住您最近看了哪些新聞,而要是有任何一篇新聞被人回報內容有錯,
21 | 新聞小幫手就會跳出通知提醒您,以避免讓您被錯誤的新聞所騙。
22 | 新聞小幫手的所有判斷動作都是在您的瀏覽器內完成的,因此您不用擔心因此而造成您的隱私被偷走。
23 |
24 |
25 |
26 | 想測試看看新聞小幫手有沒有用嗎?趕快到 新聞小幫手測試專用粉絲專頁 看看會不會出現訊息吧!
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/_locales/zh_TW/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "extensionName": {
3 | "message": "新聞小幫手",
4 | "description": "Name of the extension."
5 | },
6 | "extensionDescription": {
7 | "message": "揪出問題新聞、守護您的網路閱聽品質",
8 | "description": "Description of the extension."
9 | },
10 | "extensionPageActionTitle": {
11 | "message": "設定新聞小幫手",
12 | "description": "Title of pageAction button"
13 | },
14 |
15 | "secondAgo": {
16 | "message": " 秒前",
17 | "description": "before how many seconds"
18 | },
19 | "minuteAgo": {
20 | "message": " 分鐘前",
21 | "description": "before how many minutes"
22 | },
23 | "hourAgo": {
24 | "message": " 小時前",
25 | "description": "before how many hours"
26 | },
27 | "dayAgo": {
28 | "message": " 天前",
29 | "description": "before how many days"
30 | },
31 |
32 | "warning": {
33 | "message": "注意!您可能是問題新聞的受害者",
34 | "description": "tell user he/she is reading false news."
35 | },
36 | "reportCTA": {
37 | "message": "回報給新聞小幫手",
38 | "description": "button text for reporting"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright © 2017 g0v Contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 「Software」), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED 「AS IS」, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
11 |
--------------------------------------------------------------------------------
/_locales/en/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "extensionName": {
3 | "message": "Newshelper",
4 | "description": "Name of the extension."
5 | },
6 | "extensionDescription": {
7 | "message": "Safeguard news reading experience",
8 | "description": "Description of the extension."
9 | },
10 | "extensionPageActionTitle": {
11 | "message": "newshelper setting",
12 | "description": "Title of pageAction button"
13 | },
14 |
15 | "secondAgo": {
16 | "message": " s ago",
17 | "description": "before how many seconds"
18 | },
19 | "minuteAgo": {
20 | "message": " m ago",
21 | "description": "before how many minutes"
22 | },
23 | "hourAgo": {
24 | "message": " h ago",
25 | "description": "before how many hours"
26 | },
27 | "dayAgo": {
28 | "message": " d ago",
29 | "description": "before how many days"
30 | },
31 |
32 | "warning": {
33 | "message": "Caution: you could be a victim of doubious news",
34 | "description": "tell user he/she is reading false news."
35 | },
36 | "reportCTA": {
37 | "message": "Report to News Helper",
38 | "description": "button text for reporting"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/g0v.json:
--------------------------------------------------------------------------------
1 | {
2 | "repo":"g0v/newshelper-extension",
3 | "author": "ronnywang",
4 | "status": "production",
5 | "name": "newshelper-extension",
6 | "name_zh": "新聞小幫手",
7 | "description": "newshelper-extension: a chrome extension helps you to identify incorrect news",
8 | "description_zh": "newshelper-extension: 告訴你你正受到有害新聞所害",
9 | "homepage": "http://newshelper.g0v.tw",
10 | "document": "https://docs.google.com/spreadsheet/ccc?key=0AvCxAZD9rYXMdGFrSjBHb2IxTW5mSE5vQVhGaThiX3c",
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/g0v/newshelper-extension"
14 | },
15 | "licenses": [
16 | {
17 | "type": "MIT"
18 | }
19 | ],
20 | "keywords": [
21 | "javascript",
22 | "jquery",
23 | "php",
24 | "bootstrap"
25 | ],
26 | "audience": [
27 | "public"
28 | ],
29 | "products": [
30 | "extension",
31 | "website"
32 | ],
33 | "projects": [
34 | "新聞小幫手"
35 | ],
36 | "contributors": [
37 | "ronnywang",
38 | "Wonder",
39 | "dannvix",
40 | "Kirsten",
41 | "Wahaho",
42 | "Natata",
43 | "kcwu",
44 | "Lois",
45 | "Miaout17",
46 | "Michael LI",
47 | "wychi",
48 | "wildsky"
49 | ],
50 | "needs": [
51 | "designer",
52 | "writer",
53 | "progammer",
54 | "內容管理"
55 | ]
56 | }
57 |
58 |
--------------------------------------------------------------------------------
/content_style.css:
--------------------------------------------------------------------------------
1 | .newshelper-warning {
2 | background: hsl(0, 50%, 50%);
3 | color: white;
4 | font-size: large;
5 | text-align: center;
6 | width: 100%;
7 | padding: 5px 0;
8 | }
9 |
10 | .newshelper-warning-facebook {
11 | background: hsl(50, 100%, 70%);
12 | color: hsl(0, 0%, 20%);
13 | font-size: medium;
14 | text-align: center;
15 | margin: 20px 0 10px 0;
16 | padding: 0 0 10px 0;
17 | -webkit-border-radius: 5px;
18 | -moz-border-radius: 5px;
19 | border-radius: 5px;
20 | }
21 |
22 | .newshelper-description {
23 | display: block;
24 | font-size: small;
25 | margin-top: 5px;
26 | }
27 |
28 | .newshelper-description a {
29 | color: hsl(0, 100%, 50%);
30 | font-weight: bold;
31 | padding-right: 20px;
32 | background: transparent url(data:image/gif;base64,R0lGODlhEQDcAKIAAP////8AAGYAmQAzZv///wAAAAAAAAAAACH5BAUUAAQALAAAAAARANwAAAPmSLrc/m7IOeEAON/x9gQXGGVa1XgSyRGSEpLa0qIUSH1w7HL0t7asnI7RS62IQsxRdrtBntCodEqtWq/YrHbL7Xq/4LB4TC6bz+i0es1uu9/wuHxOr9vv+Lx+zxcL/oCAEAI5hAIPhoAAhIsOjCSBjouKGYcEfwqPhQuYiYGen0mNmYegipaYl6KWDKZ/o62rjp+ffba3uLm6u7y9vr/AwcLDxMXGx8jJynIBzc7OEAE50gEP1M4A0tkO2iTP3NnYGdUEzQrd0wvm18/s7aLk5dXu2OTm5fDg7c3bDegw8dTt+7ZsSgIAOw==) no-repeat 100% -200px;
33 | }
34 |
35 | .newshelper-arrow-up {
36 | width: 0;
37 | height: 0;
38 | border-left: 15px solid transparent;
39 | border-right: 15px solid transparent;
40 | border-bottom: 15px solid hsl(50, 100%, 70%);
41 | position: relative;
42 | top: -10px;
43 | margin: 0 auto;
44 | }
45 |
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "applications": {
3 | "gecko": {
4 | "id": "newshelper@g0v.tw",
5 | "strict_min_version": "51.0"
6 | }
7 | },
8 |
9 | "manifest_version": 2,
10 |
11 | "default_locale": "en",
12 | "name": "__MSG_extensionName__",
13 | "description": "__MSG_extensionDescription__",
14 | "version": "1.7.1",
15 | "author": "ronnywang, wildsky, racklin",
16 | "permissions": [
17 | "notifications",
18 | "http://newshelper.g0v.tw/*",
19 | "https://www.facebook.com/*",
20 | "http://www.facebook.com/*",
21 | "http://*/*",
22 | "https://*/*"
23 | ],
24 |
25 | "background": { "scripts": ["vendor/jquery-3.2.1.min.js", "libs/url-normalizer.js/url-normalizer.js", "background.js"] },
26 |
27 | "page_action" : {
28 | "default_icon" : "icons/icon.png",
29 | "default_title" : "__MSG_extensionPageActionTitle__",
30 | "default_popup" : "popup.html"
31 | },
32 |
33 | "web_accessible_resources" : [
34 | "libs/url-normalizer.js/map.csv"
35 | ],
36 | "content_scripts" : [
37 | {
38 | "matches": [
39 | "http://www.facebook.com/*",
40 | "https://www.facebook.com/*",
41 | "http://*/*",
42 | "https://*/*"
43 | ],
44 | "js": [
45 | "vendor/jquery-3.2.1.min.js",
46 | "content_script.js"
47 | ],
48 | "css": [
49 | "content_style.css"
50 | ],
51 | "run_at" : "document_idle",
52 | "all_frames" : false
53 | }
54 | ],
55 |
56 | "homepage_url": "https://addons.mozilla.org/zh-TW/firefox/addon/newshelper/",
57 |
58 | "repository": {
59 | "type": "git",
60 | "url": "git://github.com/g0v/newshelper-extension.git"
61 | },
62 | "bugs": {
63 | "url": "https://github.com/g0v/newshelper-extension/issues"
64 | },
65 | "keywords": [
66 | "newshelper",
67 | "g0v-tw"
68 | ],
69 |
70 | "icons" : {
71 | "128" : "icons/newshelper128x128.png",
72 | "96" : "icons/newshelper96x96.png",
73 | "48" : "icons/newshelper48x48.png"
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/background.js:
--------------------------------------------------------------------------------
1 | /* global add_notification */
2 |
3 | var newshelper_bg = {
4 | opened_db: null,
5 | last_sync_at: -1,
6 | next_fetch_at: 0,
7 |
8 | check_recent_seen: report => {
9 | // check recent seen news with report
10 | if (parseInt(report.deleted_at, 10)) return;
11 | var me = newshelper_bg;
12 |
13 | me.get_newshelper_db( opened_db => {
14 | var transaction = opened_db.transaction("read_news", 'readonly');
15 | var objectStore = transaction.objectStore("read_news");
16 | var index = objectStore.index('link');
17 | var get_request = index.get(report.news_link);
18 | get_request.onsuccess = () => {
19 | if (!get_request.result) return;
20 |
21 | // skip if deleted
22 | add_notification(
23 | '新聞小幫手提醒您',
24 | '您於' + me.get_time_diff(get_request.result.last_seen_at) + ' 看的新聞「' + (get_request.result.title?get_request.result.title:report.news_title) + '」 被人回報有錯誤:' + report.report_title,
25 | report.report_link
26 | );
27 | };
28 | });
29 | },
30 |
31 | get_time_diff: time => {
32 | // get time diff message
33 | var delta = Math.floor((new Date()).getTime() / 1000) - time;
34 | if (delta < 60) {
35 | return delta + chrome.i18n.getMessage("secondAgo");
36 | }
37 | else if (delta < 60 * 60) {
38 | return Math.floor(delta / 60) + chrome.i18n.getMessage("minuteAgo");
39 | }
40 | else if (delta < 60 * 60 * 24) {
41 | return Math.floor(delta / 60 / 60) + chrome.i18n.getMessage("hourAgo");
42 | }
43 | else {
44 | return Math.floor(delta / 60 / 60 / 24) + chrome.i18n.getMessage("dayAgo");
45 | }
46 | },
47 |
48 | get_newshelper_db: cb => {
49 | // open db
50 | var me = newshelper_bg;
51 | if (null !== me.opened_db) {
52 | cb(me.opened_db);
53 | return;
54 | }
55 |
56 | var request = indexedDB.open('newshelper', '8');
57 | request.onsuccess = () => {
58 | me.opened_db = request.result;
59 | cb(me.opened_db);
60 | return;
61 | };
62 |
63 | request.onerror = event => {
64 | console.error("IndexedDB error: " + event.target.errorCode);
65 | };
66 |
67 | request.onupgradeneeded = event => {
68 | try {
69 | event.currentTarget.result.deleteObjectStore('report');
70 | }
71 | catch (e) {
72 | console.error(e);
73 | }
74 |
75 | var objectStore = event.currentTarget.result.createObjectStore("report", { keyPath: "id" });
76 | objectStore.createIndex("news_title", "news_title", { unique: false });
77 | objectStore.createIndex("news_link", "news_link", { unique: false });
78 | objectStore.createIndex("news_link_unique", "news_link_unique", { unique: false });
79 | objectStore.createIndex("updated_at", "updated_at", { unique: false });
80 |
81 | try {
82 | objectStore = event.currentTarget.result.createObjectStore("read_news", { keyPath: "id", autoIncrement: true });
83 | objectStore.createIndex("title", "title", { unique: false });
84 | objectStore.createIndex("link", "link", { unique: true });
85 | objectStore.createIndex("last_seen_at", "last_seen_at", { unique: false });
86 | }
87 | catch (e) {
88 | console.error(e);
89 | }
90 | };
91 | },
92 |
93 | sync_db: force_notification => {
94 | // sync db from api server
95 | var me = newshelper_bg;
96 |
97 | me.get_newshelper_db( opened_db => {
98 | me.get_recent_report( latest_report => {
99 | var version_time = Math.max(me.next_fetch_at, (latest_report ? parseInt(latest_report.updated_at) : 0));
100 | if (version_time) {
101 | // facebook is disabled, only update one time
102 | return;
103 | }
104 | $.get('http://d3n4xylkjv5pnb.cloudfront.net/index/data?time=' + version_time, ret => {
105 | var transaction = opened_db.transaction("report", 'readwrite');
106 | var objectStore = transaction.objectStore("report");
107 | me.next_fetch_at = ret.time;
108 | if (ret.data) {
109 | for (var i = 0; i < ret.data.length; i ++) {
110 | objectStore.put(ret.data[i]);
111 |
112 | // 檢查最近幾天看過的內容是否有被加進去的
113 | // (有 latest_report 才檢查,避免 indexeddb 清空後會被洗板, 如果 force_notification 為 true 就不檢查)
114 | if (force_notification || latest_report) {
115 | // 只讓 notification 通知一次,如果之後再更新就不通知了
116 | if (parseInt(ret.data[i].created_at, 10) > parseInt(latest_report.updated_at, 10)) {
117 | me.check_recent_seen(ret.data[i]);
118 | }
119 | }
120 | }
121 | }
122 | }, 'json');
123 | });
124 | });
125 | },
126 |
127 | add_notification: (title, body, link) => {
128 | // show notification
129 |
130 | if(!window.Notification) return;
131 |
132 | var notification = new Notification('' + title, { icon: "newshelper48x48.png", body: '' + body });
133 | notification.onclick = () => {
134 | window.open(link);
135 | };
136 |
137 | setTimeout(() => {
138 | notification.close();
139 | }, 5000);
140 |
141 | },
142 |
143 | check_url: (url, cb) => {
144 | var me = newshelper_bg;
145 | var transaction = me.opened_db.transaction("report", 'readonly');
146 | var objectStore = transaction.objectStore("report");
147 | var index = objectStore.index('news_link');
148 | var get_request = index.get(url);
149 | get_request.onsuccess = () => {
150 | // find result && not deleted
151 | if (get_request.result && !parseInt(get_request.result.deleted_at, 10)) {
152 | return cb(get_request.result);
153 | }
154 | cb(false);
155 | };
156 | },
157 |
158 | check_report: (title, url, cb) => {
159 | // check report by title & url
160 | var me = newshelper_bg;
161 | me.get_newshelper_db( opened_db => {
162 |
163 | URLNormalizer.setCSVMapPath(chrome.extension.getURL('libs/url-normalizer.js/map.csv'));
164 | URLNormalizer.query(url, normalized_data => {
165 | if (normalized_data) {
166 | // 如果有 normalized_data, 就先檢查 normalized_id 是否有符合的,沒有再去找完整網址
167 | var transaction = opened_db.transaction("report", 'readonly');
168 | var objectStore = transaction.objectStore("report");
169 | var index = objectStore.index('news_link_unique');
170 | var get_request = index.get(normalized_data.normalized_id);
171 | get_request.onsuccess = () => {
172 | // find result && not deleted
173 | if (get_request.result && !parseInt(get_request.result.deleted_at, 10)) {
174 | return cb(get_request.result);
175 | }
176 | me.check_url(url, cb);
177 | };
178 | }
179 | else {
180 | me.check_url(url, cb);
181 | }
182 | });
183 | });
184 | },
185 |
186 | get_recent_report: cb => {
187 | // get newest report in db
188 | var me = newshelper_bg;
189 | me.get_newshelper_db( opened_db => {
190 | var transaction = opened_db.transaction('report', 'readonly');
191 | var objectStore = transaction.objectStore('report');
192 | var index = objectStore.index("updated_at");
193 | var request = index.openCursor(null, 'prev');
194 | request.onsuccess = () => {
195 | if (request.result) {
196 | cb(request.result.value);
197 | return;
198 | }
199 | cb(null);
200 | };
201 | });
202 | },
203 |
204 | log_browsed_link: (link, title) => {
205 | // log link in read_news table
206 | var me = newshelper_bg;
207 | var seen_link = {};
208 | if (!link || seen_link[link]) return;
209 |
210 | seen_link[link] = true;
211 |
212 | me.get_newshelper_db( opened_db => {
213 | var transaction = opened_db.transaction("read_news", 'readwrite');
214 | var objectStore = transaction.objectStore("read_news");
215 | var request = objectStore.put({
216 | title: title,
217 | link: link,
218 | last_seen_at: Math.floor((new Date()).getTime() /1000)
219 | });
220 |
221 | // link 重覆
222 | request.onerror = () => {
223 | var transaction = opened_db.transaction("read_news", 'readwrite');
224 | var objectStore = transaction.objectStore("read_news");
225 | var index = objectStore.index('link');
226 | var get_request = index.get(link);
227 | get_request.onsuccess = () => {
228 | if (!get_request.result) {
229 | console.error('link=' + link + ' is not found in IndexedDB');
230 | return;
231 | }
232 | // update last_seen_at
233 | // var put_request = objectStore.put({
234 | // id: get_request.result.id,
235 | // title: title,
236 | // last_seen_at: Math.floor((new Date()).getTime() /1000)
237 | // });
238 | };
239 | };
240 | });
241 | },
242 |
243 | onRequest: (request, sender, sendResponse) => {
244 | var me = newshelper_bg;
245 |
246 | switch (request.method) {
247 | case 'page':
248 | // show newshelper page action
249 | chrome.pageAction.show(sender.tab.id);
250 | break;
251 | case 'add_notification':
252 | me.add_notification(request.title, request.body, request.link);
253 | break;
254 | case 'start_sync_db':
255 | if (me.last_sync_at < 0) {
256 | me.last_sync_at = 0;
257 | setInterval(() => {
258 | if ((new Date()).getTime() - me.last_sync_at < 300 * 1000) return;
259 |
260 | me.last_sync_at = (new Date()).getTime();
261 | me.sync_db(false);
262 | }, 10000);
263 | }
264 | break;
265 | case 'log_browsed_link':
266 | me.log_browsed_link(request.link, request.title);
267 | break;
268 | case 'check_report':
269 | me.check_report(request.title, request.url, sendResponse);
270 | return true;
271 | }
272 |
273 | // Return nothing to let the connection be cleaned up.
274 | sendResponse({});
275 | return true;
276 | },
277 |
278 | init: () => {
279 | var me = newshelper_bg;
280 | // Listen for the content script to send a message to the background page.
281 | chrome.runtime.onMessage.addListener(me.onRequest);
282 | }
283 | };
284 |
285 | newshelper_bg.init();
286 |
--------------------------------------------------------------------------------
/content_script.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 |
3 | var DEBUG_ = false;
4 |
5 | var newshelper_cs = {
6 |
7 | registerObserver: () => {
8 | /* deal with changed DOMs (i.e. AJAX-loaded content) */
9 | var me = newshelper_cs;
10 | var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
11 |
12 | var throttle = ( () => {
13 | var timer_;
14 | return (fn, wait) => {
15 | if (timer_) clearTimeout(timer_);
16 | timer_ = setTimeout(fn, wait);
17 | };
18 | })();
19 |
20 | // 直接 censor 整個 document
21 | // 這樣才能偵測到滑鼠點選換頁的事件
22 | var target = document;
23 | var config = {
24 | attributes: true,
25 | childList: true,
26 | characterData: true,
27 | subtree: true
28 | };
29 |
30 | var mutationObserver = new MutationObserver( mutations => {
31 | chrome.runtime.sendMessage({method: 'page'});
32 |
33 | var hasNewNode = false;
34 | mutations.forEach( mutation => {
35 | if (mutation.type == 'childList' && mutation.addedNodes.length > 0) hasNewNode = true;
36 | });
37 | if (hasNewNode) {
38 | throttle( () => {
39 | me.censorFacebook(target);
40 | }, 1000);
41 | }
42 | });
43 |
44 | mutationObserver.observe(target, config);
45 | },
46 |
47 | buildWarningMessage: options => `
48 |
49 | ${chrome.i18n.getMessage('warning')}
50 |
51 | ${options.title}
52 |
53 |
`,
54 |
55 | buildActionBar: options => {
56 | var url = 'http://newshelper.g0v.tw';
57 |
58 | if ('undefined' !== typeof(options.title) && 'undefined' !== typeof(options.link)) {
59 | url += '?news_link=' + encodeURIComponent(options.link) + '&news_title= ' + encodeURIComponent(options.title);
60 | }
61 | if (DEBUG_) {
62 | if ('undefined' !== typeof(options.rule)) url += '&rule=' + encodeURIComponent(options.rule);
63 | if ('undefined' !== typeof(options.action)) url += '&action=' + encodeURIComponent(options.action);
64 | }
65 | return `${chrome.i18n.getMessage('reportCTA')}`;
66 | },
67 |
68 | censorFacebook: baseNode => {
69 | var me = newshelper_cs;
70 | /*
71 | See FB DOM Tree hierarchy
72 | https://github.com/g0v/newshelper-extension/wiki/Facebook-DOM
73 | */
74 |
75 | var t1_ = Date.now();
76 | if (window.location.host.indexOf("www.facebook.com") !== -1) {
77 | /* log browsing history into local database for further warning */
78 | /* add warning message to a Facebook post if necessary */
79 | var censorFacebookNode = (containerNode, titleText, linkHref, rule) => {
80 | if (DEBUG_) console.log('censorFacebookNode', containerNode[0], titleText);
81 | while (true) {
82 | var matches = ('' + linkHref).match('^https?://(l|www).facebook.com/l.php\\?u=([^&]*)');
83 | if (matches) {
84 | linkHref = decodeURIComponent(matches[2]);
85 | continue;
86 | }
87 | break;
88 | }
89 | // 處理被加上 ?fb_action_ids=xxxxx 的情況
90 | matches = ('' + linkHref).match('(.*)[?&]fb_action_ids=.*');
91 | if (matches) linkHref = matches[1];
92 |
93 | containerNode = $(containerNode);
94 | var className = "newshelper-checked";
95 | if (containerNode.hasClass(className)) return;
96 | else containerNode.addClass(className);
97 |
98 | // 先看看是不是 uiStreamActionFooter, 表示是同一個新聞有多人分享, 那只要最上面加上就好了
99 | var addedAction = false;
100 | containerNode.parents('div[role=article]').find('.uiStreamActionFooter').each( (idx, uiStreamSource) => {
101 | $(uiStreamSource).find('li:first').append(' · ' + me.buildActionBar({
102 | title: titleText,
103 | link: linkHref,
104 | rule: rule,
105 | action: 1
106 | }));
107 | addedAction = true;
108 | });
109 |
110 | // 再看看單一動態,要加在 .uiStreamSource
111 | if (!addedAction) {
112 | containerNode.parents('div[role=article]').find('.uiStreamSource').each( (idx, uiStreamSource) => {
113 | $($('').html(me.buildActionBar({
114 | title: titleText,
115 | link: linkHref,
116 | rule: rule,
117 | action: 2
118 | }) + ' · ')).insertBefore(uiStreamSource);
119 |
120 | addedAction = true;
121 | // should only have one uiStreamSource
122 | if (idx != 0) console.error(idx + titleText);
123 | });
124 | }
125 |
126 | // 再來有可能是有人說某個連結讚
127 | if (!addedAction) {
128 | containerNode.parents('div.storyInnerContent').find('.uiStreamSource').each( (idx, uiStreamSource) => {
129 | $(
130 | $('').html(me.buildActionBar({
131 | title: titleText,
132 | link: linkHref,
133 | rule: rule,
134 | action: 3
135 | }) + ' · ')
136 | ).insertBefore(uiStreamSource);
137 | addedAction = true;
138 | });
139 | }
140 |
141 | // 再來是個人頁面
142 | if (!addedAction) {
143 | containerNode.parents('div[role="article"]').siblings('.uiCommentContainer').find('.UIActionLinks').each( (idx, uiStreamSource) => {
144 | $(uiStreamSource).append(' · ').append(me.buildActionBar({
145 | title: titleText,
146 | link: linkHref,
147 | rule: rule,
148 | action: 4
149 | }));
150 | addedAction = true;
151 | });
152 | }
153 |
154 | // 新版Timeline
155 | if (!addedAction) {
156 | containerNode.parents('._4q_').find('._6p-').find('._5ciy').find('._6j_').each( (idx, shareAction) => {
157 | $(
158 | $('').html(me.buildActionBar({
159 | title: titleText,
160 | link: linkHref,
161 | rule: rule,
162 | action: 5
163 | }))
164 | ).insertAfter(shareAction);
165 | addedAction = true;
166 | });
167 | }
168 |
169 | if (!addedAction) {
170 | containerNode.parents('.UFICommentContentBlock').find('.UFICommentActions').each( (idx, foo) => {
171 | $(foo).append(' · ', me.buildActionBar({
172 | title: titleText,
173 | link: linkHref,
174 | rule: rule,
175 | action: 6
176 | }));
177 | addedAction = true;
178 | });
179 | }
180 | if (!addedAction) {
181 | // this check should be after UFICommentContent
182 | containerNode.parents('._5pax').find('._5pcp').each( (idx, foo) => {
183 | $(foo).append(' · ', me.buildActionBar({
184 | title: titleText,
185 | link: linkHref,
186 | rule: rule,
187 | action: 7
188 | }));
189 | addedAction = true;
190 | });
191 | }
192 |
193 | // 再來是single post
194 | if (!addedAction) {
195 | containerNode.parents('div[role="article"]').find('._5pcp._5lel').each( (idx, uiStreamSource) => {
196 | $(uiStreamSource).append(' · ').append(me.buildActionBar({
197 | title: titleText,
198 | link: linkHref,
199 | rule: rule,
200 | action: 8
201 | }));
202 | addedAction = true;
203 | });
204 | }
205 |
206 | if (!addedAction) {
207 | containerNode.siblings().find('.uiCommentContainer').find('.UIActionLinks').each( (idx, foo) => {
208 | $(foo).append(' · ', me.buildActionBar({
209 | title: titleText,
210 | link: linkHref,
211 | rule: rule,
212 | action: 9
213 | }));
214 | addedAction = true;
215 | });
216 | }
217 |
218 | if (!addedAction) {
219 | containerNode.parents('.userContentWrapper').find('._5vsi > div').each( (idx, foo) => {
220 | $(foo).append(' · ', me.buildActionBar({
221 | title: titleText,
222 | link: linkHref,
223 | rule: rule,
224 | action: 10
225 | }));
226 | addedAction = true;
227 | });
228 | }
229 |
230 | if (DEBUG_ && !addedAction) console.error('fail to insert actionbar ' + rule);
231 |
232 | /* log the link first */
233 | chrome.runtime.sendMessage({
234 | method: 'log_browsed_link',
235 | title: titleText,
236 | link: linkHref
237 | });
238 |
239 | me.check_report(titleText, linkHref, report => {
240 | containerNode.addClass(className);
241 | containerNode.append(me.buildWarningMessage({
242 | title: report.report_title,
243 | link: report.report_link
244 | }));
245 | });
246 | };
247 |
248 |
249 | /* my timeline */
250 | $(baseNode)
251 | .find(".uiStreamAttachments")
252 | .not(".newshelper-checked")
253 | .each( (idx, uiStreamAttachment) => {
254 | uiStreamAttachment = $(uiStreamAttachment);
255 | var titleText = uiStreamAttachment.find(".uiAttachmentTitle").text();
256 | var linkHref = uiStreamAttachment.find("a").attr("href");
257 | censorFacebookNode(uiStreamAttachment, titleText, linkHref, 'rule1');
258 | });
259 |
260 | $(baseNode)
261 | .find("._5rwo")
262 | .not(".newshelper-checked")
263 | .each( (idx, userContent) => {
264 | userContent = $(userContent);
265 | var titleText = userContent.find(".fwb").text();
266 | var linkHref = userContent.find("a").attr("href");
267 | censorFacebookNode(userContent, titleText, linkHref, 'rule2');
268 | });
269 |
270 | /* 這個規則會讓按讚也被誤判是連結
271 | $(baseNode)
272 | .find("._42ef")
273 | .not(".newshelper-checked")
274 | .each( (idx, userContent) => {
275 | userContent = $(userContent);
276 | var titleText = userContent.find(".fwb").text();
277 | var linkHref = userContent.find("a").attr("href");
278 | censorFacebookNode(userContent, titleText, linkHref, 'rule3');
279 | });*/
280 |
281 | /* others' timeline, fan page */
282 | $(baseNode)
283 | .find(".shareUnit")
284 | .not(".newshelper-checked")
285 | .each( (idx, shareUnit) => {
286 | shareUnit = $(shareUnit);
287 | var titleText = shareUnit.find(".fwb").text();
288 | var linkHref = shareUnit.find("a").attr("href");
289 | censorFacebookNode(shareUnit, titleText, linkHref, 'rule4');
290 | });
291 |
292 | $(baseNode)
293 | .find("._5rny")
294 | .not(".newshelper-checked")
295 | .each( (idx, userContent) => {
296 | userContent = $(userContent);
297 | var titleText = userContent.find(".fwb").text();
298 | var linkHref = userContent.find("a").attr("href");
299 | censorFacebookNode(userContent, titleText, linkHref, 'rule5');
300 | });
301 |
302 | /* post page (single post) */
303 | $(baseNode)
304 | .find("._6kv")
305 | .not(".newshelper-checked")
306 | .each( (idx, userContent) => {
307 | userContent = $(userContent);
308 | var titleText = userContent.find(".mbs").text();
309 | var linkHref = userContent.find("a").attr("href");
310 | censorFacebookNode(userContent, titleText, linkHref, 'rule6');
311 | });
312 |
313 | /* post page (single post) */
314 | $(baseNode)
315 | .find("._6m3")
316 | .not(".newshelper-checked")
317 | .each( (idx, userContent) => {
318 | userContent = $(userContent);
319 | var titleText = userContent.find("a").text();
320 | var linkHref = userContent.find("a").attr("href");
321 | censorFacebookNode(userContent.parents('._2r3x').find('._6m3').parents('._6m2').parent(), titleText, linkHref, 'rule7');
322 | });
323 | }
324 |
325 | if (DEBUG_) console.log('censorFacebook time', Date.now() - t1_);
326 | },
327 |
328 | check_report: (title, url, cb) => {
329 | // 從 db 中判斷 title, url 是否是錯誤新聞,是的話執行 cb 並傳入資訊
330 | if (!url) return;
331 |
332 | chrome.runtime.sendMessage({
333 | method: 'check_report',
334 | title: title,
335 | url: url
336 | }).then( ret => {
337 | if (ret !== false && ret)
338 | cb(ret);
339 | }, error => {
340 | console.error(`Error: ${error}`);
341 | });
342 | },
343 |
344 | sync_report_data: () => {
345 | // 叫 background 開始跟 api server 同步資料
346 | chrome.runtime.sendMessage({method: 'start_sync_db'});
347 | },
348 |
349 | init: () => {
350 | var me = newshelper_cs;
351 |
352 | if (document.location.hostname == 'www.facebook.com') {
353 | var target = document.getElementById("contentArea") || document.getElementById("content");
354 | if (target) {
355 | me.censorFacebook(target);
356 | me.registerObserver();
357 | }
358 | else {
359 | console.error('#contentArea or #content is not ready');
360 | }
361 | }
362 | else {
363 | me.check_report('', document.location.href, report => {
364 | chrome.runtime.sendMessage({ method: 'page' });
365 | document.body.style.border = "5px solid red";
366 | chrome.runtime.sendMessage({
367 | method: 'add_notification',
368 | title: chrome.i18n.getMessage("warning").replace(/<\/?b>/g, ''),
369 | body: report.report_title,
370 | link: report.report_link
371 | });
372 | });
373 | }
374 |
375 | me.sync_report_data();
376 | }
377 | };
378 | newshelper_cs.init();
379 |
380 |
--------------------------------------------------------------------------------
/vendor/jquery-3.2.1.min.js:
--------------------------------------------------------------------------------
1 | /*! jQuery v3.2.1 | (c) JS Foundation and other contributors | jquery.org/license */
2 | !function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.2.1",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a<0?this[a+this.length]:this[a]},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext;function B(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()}var C=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,D=/^.[^:#\[\.,]*$/;function E(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):D.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(E(this,a||[],!1))},not:function(a){return this.pushStack(E(this,a||[],!0))},is:function(a){return!!E(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var F,G=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,H=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||F,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:G.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),C.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};H.prototype=r.fn,F=r(d);var I=/^(?:parents|prev(?:Until|All))/,J={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function K(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return K(a,"nextSibling")},prev:function(a){return K(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return B(a,"iframe")?a.contentDocument:(B(a,"template")&&(a=a.content||a),r.merge([],a.childNodes))}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(J[a]||r.uniqueSort(e),I.test(a)&&e.reverse()),this.pushStack(e)}});var L=/[^\x20\t\r\n\f]+/g;function M(a){var b={};return r.each(a.match(L)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?M(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=e||a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function N(a){return a}function O(a){throw a}function P(a,b,c,d){var e;try{a&&r.isFunction(e=a.promise)?e.call(a).done(b).fail(c):a&&r.isFunction(e=a.then)?e.call(a,b,c):b.apply(void 0,[a].slice(d))}catch(a){c.apply(void 0,[a])}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==O&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:N,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:N)),c[2][3].add(g(0,a,r.isFunction(d)?d:O))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(P(a,g.done(h(c)).resolve,g.reject,!b),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)P(e[c],h(c),g.reject);return g.promise()}});var Q=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&Q.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var R=r.Deferred();r.fn.ready=function(a){return R.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||R.resolveWith(d,[r]))}}),r.ready.then=R.then;function S(){d.removeEventListener("DOMContentLoaded",S),
3 | a.removeEventListener("load",S),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",S),a.addEventListener("load",S));var T=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)T(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){X.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=W.get(a,b),c&&(!d||Array.isArray(c)?d=W.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return W.get(a,c)||W.access(a,c,{empty:r.Callbacks("once memory").add(function(){W.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length\x20\t\r\n\f]+)/i,la=/^$|\/(?:java|ecma)script/i,ma={option:[1,""],thead:[1,""],col:[2,""],tr:[2,""],td:[3,""],_default:[0,"",""]};ma.optgroup=ma.option,ma.tbody=ma.tfoot=ma.colgroup=ma.caption=ma.thead,ma.th=ma.td;function na(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&B(a,b)?r.merge([a],c):c}function oa(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=na(l.appendChild(f),"script"),j&&oa(g),c){k=0;while(f=g[k++])la.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var ra=d.documentElement,sa=/^key/,ta=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ua=/^([^.]*)(?:\.(.+)|)/;function va(){return!0}function wa(){return!1}function xa(){try{return d.activeElement}catch(a){}}function ya(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ya(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=wa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(ra,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(L)||[""],j=b.length;while(j--)h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=W.hasData(a)&&W.get(a);if(q&&(i=q.events)){b=(b||"").match(L)||[""],j=b.length;while(j--)if(h=ua.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&W.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(W.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i\x20\t\r\n\f]*)[^>]*)\/>/gi,Aa=/