├── chrome ├── _locales │ └── en │ │ └── messages.json ├── images │ ├── icon.png │ ├── icon128.png │ ├── icon16.png │ └── icon48.png ├── src │ ├── bg │ │ ├── background.html │ │ └── background.js │ ├── inject │ │ ├── inject.css │ │ └── inject.js │ └── options │ │ ├── index.html │ │ ├── options.json │ │ ├── options.js │ │ └── options.css ├── manifest.json └── js │ └── jquery.js ├── firefox ├── github-gmail.xpi ├── data │ ├── index.css │ ├── index.js │ └── jquery.js ├── lib │ └── main.js └── package.json ├── LICENSE └── README.md /chrome/_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /chrome/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/defunkt/github-gmail/master/chrome/images/icon.png -------------------------------------------------------------------------------- /chrome/images/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/defunkt/github-gmail/master/chrome/images/icon128.png -------------------------------------------------------------------------------- /chrome/images/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/defunkt/github-gmail/master/chrome/images/icon16.png -------------------------------------------------------------------------------- /chrome/images/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/defunkt/github-gmail/master/chrome/images/icon48.png -------------------------------------------------------------------------------- /firefox/github-gmail.xpi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/defunkt/github-gmail/master/firefox/github-gmail.xpi -------------------------------------------------------------------------------- /chrome/src/bg/background.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /firefox/data/index.css: -------------------------------------------------------------------------------- 1 | .github-link { 2 | text-decoration: none; 3 | cursor: pointer; 4 | } 5 | .github-link:hover { 6 | border-color: rgba(0,0,0,0.2) !important; 7 | } -------------------------------------------------------------------------------- /chrome/src/inject/inject.css: -------------------------------------------------------------------------------- 1 | .github-link { 2 | text-decoration: none; 3 | cursor: pointer; 4 | } 5 | .github-link:hover { 6 | border-color: rgba(0,0,0,0.2) !important; 7 | } -------------------------------------------------------------------------------- /chrome/src/bg/background.js: -------------------------------------------------------------------------------- 1 | request = new XMLHttpRequest 2 | request.open('GET', '../options/options.json', true) 3 | request.send() 4 | 5 | request.onload = function() { 6 | data = JSON.parse(this.response) 7 | for (var key in data) { 8 | data[key] = data[key].val 9 | if(localStorage[key]) { data[key] = localStorage[key] } 10 | } 11 | 12 | chrome.extension.onMessage.addListener( 13 | function(request, sender, sendMessage) { 14 | sendMessage(data) 15 | } 16 | ) 17 | } 18 | 19 | -------------------------------------------------------------------------------- /firefox/lib/main.js: -------------------------------------------------------------------------------- 1 | var pageMod = require("sdk/page-mod") 2 | var self = require("sdk/self") 3 | var simple = require('sdk/simple-prefs') 4 | 5 | pageMod.PageMod({ 6 | include: "https://mail.google.com/*", 7 | contentStyleFile: self.data.url("index.css"), 8 | contentScriptFile: [self.data.url("jquery.js"), self.data.url("index.js")], 9 | onAttach: function(worker) { 10 | function onPref () { 11 | worker.port.emit('prefload', simple.prefs) 12 | } 13 | simple.on("", onPref) 14 | onPref() 15 | } 16 | }) 17 | -------------------------------------------------------------------------------- /chrome/src/options/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | GitHub for Gmail Options 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
Make sure you refresh both the extensions page (chrome://extensions/) and the gmail tab after updating the settings.
14 | 15 |
16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /chrome/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "GitHub Notification Helper for Gmail", 3 | "short_name": "GitHub4Gmail", 4 | "version": "0.6.1", 5 | "manifest_version": 2, 6 | "description": "Add links to GitHub threads and shortcuts to your Gmail interface.", 7 | "homepage_url": "http://github.com/muan/github-gmail", 8 | "icons": { 9 | "16": "images/icon16.png", 10 | "48": "images/icon48.png", 11 | "128": "images/icon128.png" 12 | }, 13 | "default_locale": "en", 14 | "background": { 15 | "page": "src/bg/background.html", 16 | "persistent": true 17 | }, 18 | "options_page": "src/options/index.html", 19 | "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", 20 | "content_scripts": [ 21 | { 22 | "matches": [ 23 | "https://mail.google.com/*" 24 | ], 25 | "css": [ 26 | "src/inject/inject.css" 27 | ] 28 | }, 29 | { 30 | "matches": [ 31 | "https://mail.google.com/*" 32 | ], 33 | "js": [ 34 | "js/jquery.js", 35 | "src/inject/inject.js" 36 | ] 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Mu-An Chiou 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /firefox/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "github-gmail", 3 | "title": "GitHub for Gmail", 4 | "fullName": "GitHub Notification Helper for Gmail", 5 | "id": "jid1-Zf83KbzewcxGfg", 6 | "description": "Add links to GitHub threads and shortcuts to your Gmail interface.", 7 | "author": "Mu-An Chiou", 8 | "preferences": [{ 9 | "name": "Domains", 10 | "title": "Domains", 11 | "description": "Specify GitHub enterprise domain, or other domains you'd like to grab links for. There's no need to add github.com, protocol is also not required unless you'd like to be explicit.", 12 | "type": "string", 13 | "value": "" 14 | },{ 15 | "name": "Shortcut", 16 | "title": "Shortcut", 17 | "description": "The shortcut that triggers button clicking on the mail view.", 18 | "type": "string", 19 | "value": "shift + 71" 20 | },{ 21 | "name": "backgroundShortcut", 22 | "title": "backgroundShortcut", 23 | "type": "string", 24 | "value": "shift + 66", 25 | "hidden": true 26 | },{ 27 | "name": "RegExp", 28 | "title": "RegExp", 29 | "description": "Custom Regular Expression for matching labeled Organization name.", 30 | "type": "string", 31 | "value": "^\\((.+)\\)" 32 | }], 33 | "license": "MIT", 34 | "version": "0.1.1" 35 | } 36 | -------------------------------------------------------------------------------- /chrome/src/options/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "Domains" : { 3 | "description": "Specify GitHub enterprise domain, or other domains you'd like to grab links for. There's no need to add github.com, protocol is also not required unless you'd like to be explicit.", 4 | "val": "", 5 | "hint": "( comma separated if multiple )" 6 | }, 7 | "Shortcut" : { 8 | "description": "The shortcut that triggers button clicking on the mail view.", 9 | "val": "shift + 71", 10 | "hint": " ( press shortcut in the input field )" 11 | }, 12 | "BackgroundShortcut" : { 13 | "description": "The shortcut that triggers button clicking on the mail view, opens the link in the background.", 14 | "val": "shift + 66", 15 | "hint": " ( press shortcut in the input field )" 16 | }, 17 | "RegExp" : { 18 | "description": "Custom Regular Expression for matching labeled Organization name. Eg. /^\\((.+)\\)/ matches muan in (muan)\\github-gmail, and will be use to build the url https://github.com/muan/github-gmail/issues.", 19 | "val": "^\\((.+)\\)", 20 | "hint": "( advanced function - ? )" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /chrome/src/options/options.js: -------------------------------------------------------------------------------- 1 | $.getJSON('options.json', function(data) { 2 | defaultOptions = data 3 | initOptions(defaultOptions) 4 | }) 5 | 6 | function initOptions (defaultOptions) { 7 | options = defaultOptions 8 | 9 | for (var key in defaultOptions) { 10 | if( localStorage[key] ) { options[key].val = localStorage[key] } 11 | } 12 | 13 | optionsWrapper = document.getElementById('options') 14 | 15 | for (var key in options) { 16 | html = '
' 17 | html += '

' + options[key].description + '

' 18 | html += '
' 19 | $(optionsWrapper).append(html) 20 | } 21 | 22 | } 23 | 24 | $(document).on('keypress', '[name=Shortcut], [name=BackgroundShortcut]', function(e) { 25 | if (e.keyCode == 13 && !e.shiftKey && !e.metaKey && !e.altKey && !e.ctrlKey ) return false 26 | code = '' 27 | keys = ['shift', 'alt', 'meta', 'ctrl'] 28 | keys.map(function(key) { 29 | if( eval('e.' + key + 'Key' ) ) { code += key + " + " } 30 | }) 31 | code += e.keyCode 32 | $(this).val(code) 33 | e.preventDefault() 34 | }) 35 | 36 | $(document).on('keypress', 'input[type]', function(e) { 37 | if( e.keyCode == 13 ) { 38 | $(this).blur() 39 | $('#save').click() 40 | } 41 | }) 42 | 43 | $(document).on('click', '#save', function() { 44 | fields = [] 45 | $('input[name]').map(function(i, e) { 46 | if( localStorage[e.name] != e.value ) fields.push(e) 47 | localStorage[e.name] = e.value 48 | }) 49 | 50 | // Update status to let user know options were saved. 51 | var save = document.getElementById('save') 52 | $('.notice').show() 53 | window.scrollTo(0, 10000) 54 | save.innerHTML = 'Updated!' 55 | $(fields).closest('.option').removeClass('saved').addClass('saved') 56 | setTimeout(function() { 57 | $(fields).closest('.option').removeClass('saved') 58 | save.innerHTML = 'Save' 59 | }, 2050) 60 | }) 61 | -------------------------------------------------------------------------------- /chrome/src/options/options.css: -------------------------------------------------------------------------------- 1 | body, button { 2 | background-color: #fff; 3 | font-family: 'Helvetica Neue', Helvetica, sans-serif; 4 | font-size: 13px; 5 | line-height: 1.6; 6 | } 7 | 8 | body, * { 9 | box-sizing: border-box; 10 | } 11 | 12 | .wrapper { 13 | width: 500px; 14 | margin: 30px auto; 15 | border-radius: 3px; 16 | padding: 0 20px; 17 | overflow: hidden; 18 | border: 1px solid #e0e0e0; 19 | } 20 | 21 | .notice { 22 | display: none; 23 | background: #ffeeee; 24 | border-top: 1px solid #fcc; 25 | border-bottom: 1px solid #fcc; 26 | color: #a00; 27 | padding: 20px; 28 | margin: -1px -20px 0; 29 | font-weight: bold; 30 | } 31 | 32 | .option { 33 | margin: 0 -20px 0; 34 | padding: 20px; 35 | background-color: #f9f9f9; 36 | transition: all 0.6s; 37 | } 38 | 39 | .option:last-child { 40 | border-bottom: 1px solid #e0e0e0; 41 | } 42 | 43 | .option:nth-child(even) { 44 | border-top: 1px solid #e0e0e0; 45 | border-bottom: 1px solid #e0e0e0; 46 | background-color: #fff; 47 | } 48 | 49 | .saved.option { 50 | background: #ffe; 51 | color: #333; 52 | } 53 | 54 | input[type]:focus { 55 | background-color: #fff; 56 | } 57 | 58 | input[type] { 59 | background: none; 60 | border: 1px solid #e0e0e0; 61 | box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); 62 | padding: 9px; 63 | margin-top: 5px; 64 | font-family: monospace; 65 | } 66 | 67 | input[type], button { 68 | display: block; 69 | line-height: 1; 70 | width: 100%; 71 | } 72 | 73 | label { 74 | font-weight: bold; 75 | } 76 | 77 | button { 78 | background: #4a6; 79 | border: 0; 80 | padding: 15px 10px; 81 | color: #fff; 82 | font-weight: bold; 83 | cursor: pointer; 84 | text-transform: uppercase; 85 | box-shadow: inset 0 -4px 0 rgba(0, 0, 0, .1); 86 | transition: all .6s; 87 | margin: 20px 0; 88 | } 89 | 90 | button:active { 91 | box-shadow: inset 0 4px 0 rgba(0, 0, 0, .1); 92 | } 93 | 94 | code { 95 | background-color: #f0f0f0; 96 | padding: 0 3px; 97 | border: 1px solid #ddd; 98 | font-family: monospace; 99 | font-size: 12px; 100 | white-space: nowrap; 101 | border-radius: 2px; 102 | } 103 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GitHub :octocat: :on: :love_letter: Gmail 2 | 3 | This is a **Chrome and Firefox Extension** that allows you to open threads in GitHub notification emails with a shortcut. :sparkles: 4 | 5 | ## Features 6 | 7 | #### Mail View Shortcut 8 | 9 | Open your GitHub notifications using a shortcut (default to `shift + g`, or `shift + b` to open in the background in Chrome), or this button in mail view: 10 | 11 | ![image](https://f.cloud.github.com/assets/1153134/1699454/20634378-5f9f-11e3-999c-c0c5e3e96684.png) 12 | 13 | #### List View Shortcut 14 | 15 | The shortcut is `ctrl + return(enter)`, currently non-customisable. It will trigger one of these two when an email is selected using key navigation(when the blue bar appears): 16 | 17 | 1. [Gmail action buttons](https://github.com/blog/1891-view-issue-pull-request-buttons-for-gmail). 18 | 2. A GitHub Issue/ PR that has an organization named label matching the Regular Expression (default to `^\((.+)\)`). 19 | 20 | The function will only look for a label if there is no action buttons. 21 | 22 | ##### Action button 23 | 24 | ![action button in list view](https://cloud.githubusercontent.com/assets/1153134/4344159/52248e7c-407b-11e4-9c80-fdc9f8a9f8cc.png) 25 | 26 | ##### Label 27 | 28 | ![label in list view](https://f.cloud.github.com/assets/1153134/2073597/f19b6232-8d61-11e3-8e65-b03db4e72217.png) 29 | 30 | ## Installation 31 | 32 | #### The Easy Way 33 | 34 | [Install the extension via Chrome webstore](https://chrome.google.com/webstore/detail/github-notification-helpe/gmhijkhbpihfmkmhmcfebmlkaekgmaje) or [Install the addon via Firefox addons gallery](https://addons.mozilla.org/en-US/firefox/addon/github-for-gmail/) 35 | 36 | #### The Mu-An-might-steal-all-my-data-so-I-want-to-manually-load-it Way (for Chrome) 37 | 38 | 1. Go to [Releases](https://github.com/muan/github-gmail/releases) and download the latest version. 39 | 2. Unzip the folder wherever you'd like. 40 | 3. Read Mu-An's code making sure there is no data stealing. 41 | 4. Go to Chrome extensions page (`chrome://extensions/`) and load the folder as an **Unpacked extension**. 42 | 43 | As: 44 | 45 | ![image](https://f.cloud.github.com/assets/1153134/1749652/ae692df6-652e-11e3-869f-65447bfe1a68.png) 46 | 47 | ## Options and preferences 48 | 49 | There are 3 preference settings: 50 | 51 | 1. Custom domains 52 | 2. Mail view shortcut 53 | 3. List view regular expression 54 | 55 | **Attention** After updating a setting, please refresh both the extensions page and the Gmail page. 56 | 57 | #### Custom Domains (for GitHub Enterprise) 58 | 59 | If you are using GitHub enterprise and have a custom domain, you can set it in the extension options page. 60 | 61 | ![domain option](https://f.cloud.github.com/assets/1153134/2075910/2f9b1f70-8d97-11e3-9798-9afcfb550e22.png) 62 | 63 | #### Mail View Shortcut 64 | 65 | Customize the keyboard shortcut that triggers the `View on GitHub` button. Change the shortcut combination by focusing the input, and press whatever key(s) you want to be the shortcut. It will be displayed in `keyCode` which is why you see `71` here instead of `g`. Don't worry about it. 66 | 67 | ##### To open and focus the new window right away (`shift + g`): 68 | 69 | ![image](https://f.cloud.github.com/assets/1153134/2457119/3a485f38-af2e-11e3-978a-ece296676337.png) 70 | 71 | ##### To open a new window in the background (`shift + b`) – Chrome only: 72 | 73 | ![image](https://f.cloud.github.com/assets/1153134/2466997/e381dbc2-afb7-11e3-9470-bc722133a265.png) 74 | 75 | #### List View Regular Expression 76 | 77 | Custom Regular Expression for matching labeled Organization name. Eg. `/^\((.+)\)/` matches `muan` in `(muan)\github-gmail`, and will be use to build the url: `https://github.com/`**`muan`**`/github-gmail/issues`. 78 | 79 | This is **not needed** if all you need is triggering the action button. 80 | 81 | ![image](https://f.cloud.github.com/assets/1153134/2457127/ac41d204-af2e-11e3-9271-328aeb7a11bf.png) 82 | 83 | ## Code 84 | 85 | Chrome: `chrome/src/inject/inject.js`.
86 | Firefox: `firefox/data/index.js`. 87 | 88 | ## The End 89 | 90 | **Love :heart: it?** Tell this little bird over at [`@muanchiou`](https://twitter.com/muanchiou) and I'll be thrilled. 91 | 92 | **Found a :bug: bug?** [Open an issue](https://github.com/muan/github-gmail/issues/new) with some [emojis](http://emoji.muan.co). Issues without emojis are not valid. :trollface: 93 | -------------------------------------------------------------------------------- /chrome/src/inject/inject.js: -------------------------------------------------------------------------------- 1 | // Retriving user options 2 | chrome.extension.sendMessage({}, function(settings) { 3 | initOnHashChangeAction(settings['Domains']) 4 | initShortcuts(settings['Shortcut'], settings['BackgroundShortcut']) 5 | initListViewShortcut(settings['RegExp']) 6 | }) 7 | 8 | function initOnHashChangeAction(domains) { 9 | allDomains = "//github.com," 10 | if(domains) allDomains += domains 11 | 12 | // Take string -> make array -> make queries -> avoid nil -> join queries to string 13 | selectors = allDomains.replace(/\s/, '').split(',').map(function (name) { 14 | if (name.length) return (".AO [href*='" + name + "']") 15 | }).filter(function(name) { return name }).join(", ") 16 | 17 | intervals = [] 18 | 19 | // Find GitHub link and append it to tool bar on hashchange 20 | window.onhashchange = function() { 21 | fetchAndAppendGitHubLink() 22 | } 23 | 24 | function fetchAndAppendGitHubLink() { 25 | // In case previous intervals got interrupted 26 | clearAllIntervals() 27 | 28 | retryForActiveMailBody = setInterval(function() { 29 | mail_body = $('.nH.hx').filter(function() { return this.clientHeight != 0 })[0] 30 | 31 | if( mail_body ) { 32 | 33 | github_links = mail_body.querySelectorAll(selectors) 34 | github_links = reject_unwanted_paths(github_links) 35 | 36 | // Avoid multple buttons 37 | $('.github-link').remove() 38 | 39 | if( github_links.length ) { 40 | 41 | url = github_links[github_links.length-1].href 42 | // Go to thread instead of .diff link (pull request notifications) 43 | url = url.match(/\.diff/) ? url.slice(0, url.length-5) : url 44 | link = $("Visit Thread on GitHub") 45 | 46 | $(".iH > div").append(link) 47 | window.idled = true 48 | 49 | document.getElementsByClassName('github-link')[0].addEventListener("DOMNodeRemovedFromDocument", function (ev) { 50 | fetchAndAppendGitHubLink() 51 | }, false) 52 | } 53 | 54 | clearInterval(retryForActiveMailBody) 55 | } else if ( $('.nH.hx').length == 0 ) { 56 | // Not in a mail view 57 | clearInterval(retryForActiveMailBody) 58 | } 59 | }, 100) 60 | 61 | intervals.push(retryForActiveMailBody) 62 | } 63 | } 64 | 65 | function initShortcuts(shortcut, backgroundShortcut) { 66 | $(document).on("keydown", function(event) { 67 | // Shortcut: bind user's combination, if a button exist and event not in a textarea 68 | if( processRightCombinationBasedOnShortcut(shortcut, event) && window.idled && getVisible(document.getElementsByClassName('github-link')) && notAnInput(event.target)) { 69 | triggerGitHubLink(false) 70 | } 71 | 72 | // Bacground Shortcut: bind user's combination, if a button exist and event not in a textarea 73 | if( processRightCombinationBasedOnShortcut(backgroundShortcut, event) && window.idled && getVisible(document.getElementsByClassName('github-link')) && notAnInput(event.target)) { 74 | triggerGitHubLink(true) 75 | } 76 | }) 77 | } 78 | 79 | function initListViewShortcut(regexp) { 80 | $(document).on("keypress", function(event) { 81 | // Shortcut: bind ctrl + return 82 | selected = getVisible(document.querySelectorAll('.zA[tabindex="0"]')) 83 | if( event.ctrlKey && event.keyCode == 13 && selected ) { 84 | generateUrlAndGoTo(selected, regexp) 85 | } 86 | }) 87 | } 88 | 89 | // Trigger the appended link in mail view 90 | function triggerGitHubLink (backgroundOrNot) { 91 | // avoid link being appended multiple times 92 | window.idled = false 93 | event = backgroundOrNot ? fakeBackgroundClick() : fakeEvent('click', false) 94 | 95 | getVisible(document.getElementsByClassName('github-link')).dispatchEvent(event) 96 | setTimeout( function(){ window.idled = true }, 100) 97 | } 98 | 99 | // Go to selected email GitHub thread 100 | function generateUrlAndGoTo (selected, regexp) { 101 | gotoaction = selected.querySelectorAll('.aKS [role="button"]')[0] 102 | 103 | if(gotoaction) { 104 | // if there's a gotoaction 105 | gotoaction.dispatchEvent(fakeEvent('mousedown', true)) 106 | 107 | } else if( (title = selected.innerText.match(/\[(.*)\]\s.*\s\(\#(\d*)\)/)) ) { 108 | // If the title looks like a GitHub notification email. 109 | // org name coms from a label 110 | regexp = new RegExp(regexp) 111 | label = selected.querySelectorAll('.av')[0] 112 | 113 | if(label) org = label.innerText.toLowerCase().match(regexp) 114 | 115 | if(org) { 116 | org = org[1] 117 | repo = title[1] 118 | issue_no = title[2] 119 | 120 | url = "https://github.com/" + org + "/" + repo + "/issues/" + issue_no 121 | linkWithUrl(url).dispatchEvent(fakeEvent('click', false)) 122 | } 123 | } 124 | } 125 | 126 | // 127 | // Helpers 128 | // 129 | 130 | function processRightCombinationBasedOnShortcut (shortcut, event) { 131 | // Processing shortcut from preference 132 | combination = shortcut.replace(/\s/g, '').split('+') 133 | 134 | keys = ['shift', 'alt', 'meta', 'ctrl'] 135 | trueOrFalse = [] 136 | 137 | // If a key is in the combination, push the value to trueOrFalse array, and delete it from the combination 138 | keys.map(function(key) { 139 | index = combination.indexOf(key) 140 | if(index >= 0) { 141 | if(key == "shift") trueOrFalse.push(event.shiftKey) 142 | if(key == "alt") trueOrFalse.push(event.altKey) 143 | if(key == "meta") trueOrFalse.push(event.metaKey) 144 | if(key == "crtl") trueOrFalse.push(event.ctrlKey) 145 | 146 | combination.splice(index, 1) 147 | } 148 | }) 149 | 150 | // If there is a keyCode left, add that to the mix. 151 | if(combination.length) trueOrFalse.push(event.keyCode.toString() == combination[0]) 152 | 153 | // Evaluate trueOrFalse by looking for the existence of False 154 | return trueOrFalse = (trueOrFalse.indexOf(false) < 0) 155 | } 156 | 157 | // .click() doesn't usually work as expected 158 | function fakeEvent (event, bubbles) { 159 | var click = new MouseEvent(event, {bubbles: bubbles}) 160 | return click 161 | } 162 | 163 | function fakeBackgroundClick () { 164 | var click = new MouseEvent('click', {metaKey: true}) 165 | return click 166 | } 167 | 168 | function linkWithUrl (url) { 169 | var l = document.createElement('a') 170 | l.href = url 171 | l.target = "_blank" 172 | return l 173 | } 174 | 175 | function getVisible (nodeList) { 176 | if(nodeList.length) { 177 | var node 178 | $(nodeList).map(function() { 179 | if(typeof node == 'undefined' && (this.clientWidth > 0 || this.clientHeight > 0)) { 180 | node = this 181 | } 182 | }) 183 | return node 184 | } 185 | } 186 | 187 | function notAnInput (element) { 188 | return !element.className.match(/editable/) && element.tagName != "TEXTAREA" && element.tagName != "INPUT" 189 | } 190 | 191 | function clearAllIntervals () { 192 | intervals.map(function(num) { 193 | clearInterval(num) 194 | delete intervals[intervals.indexOf(num)] 195 | }) 196 | } 197 | 198 | // Reject unsubscribe, subscription and verification management paths 199 | // Make sure the keywords((un)subscribe) can still be repository names 200 | function reject_unwanted_paths (links) { 201 | paths = ['\/\/[^\/]*\/mailers\/unsubscribe\?', 202 | '\/\/[^\/]*\/.*\/.*\/unsubscribe_via_email', 203 | '\/\/[^\/]*\/.*\/.*\/subscription$', 204 | '\/\/[^\/]*\/.*\/.*\/emails\/.*\/confirm_verification\/.*' 205 | ] 206 | regexp = new RegExp(paths.join('|')) 207 | return $(links).filter(function() { 208 | if(!this.href.match(regexp)) return this 209 | }) 210 | } 211 | -------------------------------------------------------------------------------- /firefox/data/index.js: -------------------------------------------------------------------------------- 1 | self.port.on("prefload", function(prefs) { 2 | initOnHashChangeAction(prefs['Domains']) 3 | initShortcuts(prefs['Shortcut'], prefs['backgroundShortcut']) 4 | initListViewShortcut(prefs['RegExp']) 5 | }) 6 | 7 | // Ported from the Chrome extension 8 | // Avoid editing the following script to prevent divergence 9 | // 10 | 11 | function initOnHashChangeAction(domains) { 12 | allDomains = "//github.com," 13 | if(domains) allDomains += domains 14 | 15 | // Take string -> make array -> make queries -> avoid nil -> join queries to string 16 | selectors = allDomains.replace(/\s/, '').split(',').map(function (name) { 17 | if (name.length) return (".AO [href*='" + name + "']") 18 | }).filter(function(name) { return name }).join(", ") 19 | 20 | intervals = [] 21 | 22 | // Find GitHub link and append it to tool bar on hashchange 23 | window.onhashchange = function() { 24 | fetchAndAppendGitHubLink() 25 | } 26 | 27 | function fetchAndAppendGitHubLink() { 28 | // In case previous intervals got interrupted 29 | clearAllIntervals() 30 | 31 | retryForActiveMailBody = setInterval(function() { 32 | mail_body = $('.nH.hx').filter(function() { return this.clientHeight != 0 })[0] 33 | 34 | if( mail_body ) { 35 | 36 | github_links = mail_body.querySelectorAll(selectors) 37 | github_links = reject_unwanted_paths(github_links) 38 | 39 | // Avoid multple buttons 40 | $('.github-link').remove() 41 | 42 | if( github_links.length ) { 43 | 44 | url = github_links[github_links.length-1].href 45 | // Go to thread instead of .diff link (pull request notifications) 46 | url = url.match(/\.diff/) ? url.slice(0, url.length-5) : url 47 | link = $("Visit Thread on GitHub") 48 | 49 | $(".iH > div").append(link) 50 | window.idled = true 51 | 52 | document.getElementsByClassName('github-link')[0].addEventListener("DOMNodeRemovedFromDocument", function (ev) { 53 | fetchAndAppendGitHubLink() 54 | }, false) 55 | } 56 | 57 | clearInterval(retryForActiveMailBody) 58 | } else if ( $('.nH.hx').length == 0 ) { 59 | // Not in a mail view 60 | clearInterval(retryForActiveMailBody) 61 | } 62 | }, 100) 63 | 64 | intervals.push(retryForActiveMailBody) 65 | } 66 | } 67 | 68 | function initShortcuts(shortcut, backgroundShortcut) { 69 | $(document).on("keydown", function(event) { 70 | // Shortcut: bind user's combination, if a button exist and event not in a textarea 71 | if( processRightCombinationBasedOnShortcut(shortcut, event) && window.idled && getVisible(document.getElementsByClassName('github-link')) && notAnInput(event.target)) { 72 | triggerGitHubLink(false) 73 | } 74 | 75 | // Bacground Shortcut: bind user's combination, if a button exist and event not in a textarea 76 | if( processRightCombinationBasedOnShortcut(backgroundShortcut, event) && window.idled && getVisible(document.getElementsByClassName('github-link')) && notAnInput(event.target)) { 77 | triggerGitHubLink(true) 78 | } 79 | }) 80 | } 81 | 82 | function initListViewShortcut(regexp) { 83 | $(document).on("keypress", function(event) { 84 | // Shortcut: bind ctrl + return 85 | selected = getVisible(document.querySelectorAll('.zA[tabindex="0"]')) 86 | if( event.ctrlKey && event.keyCode == 13 && selected ) { 87 | generateUrlAndGoTo(selected, regexp) 88 | } 89 | }) 90 | } 91 | 92 | // Trigger the appended link in mail view 93 | function triggerGitHubLink (backgroundOrNot) { 94 | // avoid link being appended multiple times 95 | window.idled = false 96 | event = backgroundOrNot ? fakeBackgroundClick() : fakeEvent('click', false) 97 | 98 | getVisible(document.getElementsByClassName('github-link')).dispatchEvent(event) 99 | setTimeout( function(){ window.idled = true }, 100) 100 | } 101 | 102 | // Go to selected email GitHub thread 103 | function generateUrlAndGoTo (selected, regexp) { 104 | gotoaction = selected.querySelectorAll('.aKS [role="button"]')[0] 105 | 106 | if(gotoaction) { 107 | // if there's a gotoaction 108 | gotoaction.dispatchEvent(fakeEvent('mousedown', true)) 109 | 110 | } else if( (title = selected.innerText.match(/\[(.*)\]\s.*\s\(\#(\d*)\)/)) ) { 111 | // If the title looks like a GitHub notification email. 112 | // org name coms from a label 113 | regexp = new RegExp(regexp) 114 | label = selected.querySelectorAll('.av')[0] 115 | 116 | if(label) org = label.innerText.toLowerCase().match(regexp) 117 | 118 | if(org) { 119 | org = org[1] 120 | repo = title[1] 121 | issue_no = title[2] 122 | 123 | url = "https://github.com/" + org + "/" + repo + "/issues/" + issue_no 124 | linkWithUrl(url).dispatchEvent(fakeEvent('click', false)) 125 | } 126 | } 127 | } 128 | 129 | // 130 | // Helpers 131 | // 132 | 133 | function processRightCombinationBasedOnShortcut (shortcut, event) { 134 | // Processing shortcut from preference 135 | combination = shortcut.replace(/\s/g, '').split('+') 136 | 137 | keys = ['shift', 'alt', 'meta', 'ctrl'] 138 | trueOrFalse = [] 139 | 140 | // If a key is in the combination, push the value to trueOrFalse array, and delete it from the combination 141 | keys.map(function(key) { 142 | index = combination.indexOf(key) 143 | if(index >= 0) { 144 | if(key == "shift") trueOrFalse.push(event.shiftKey) 145 | if(key == "alt") trueOrFalse.push(event.altKey) 146 | if(key == "meta") trueOrFalse.push(event.metaKey) 147 | if(key == "crtl") trueOrFalse.push(event.ctrlKey) 148 | 149 | combination.splice(index, 1) 150 | } 151 | }) 152 | 153 | // If there is a keyCode left, add that to the mix. 154 | if(combination.length) trueOrFalse.push(event.keyCode.toString() == combination[0]) 155 | 156 | // Evaluate trueOrFalse by looking for the existence of False 157 | return trueOrFalse = (trueOrFalse.indexOf(false) < 0) 158 | } 159 | 160 | // .click() doesn't usually work as expected 161 | function fakeEvent (event, bubbles) { 162 | var click = new MouseEvent(event, {bubbles: bubbles}) 163 | return click 164 | } 165 | 166 | function fakeBackgroundClick () { 167 | var click = new MouseEvent('click', {metaKey: true}) 168 | return click 169 | } 170 | 171 | function linkWithUrl (url) { 172 | var l = document.createElement('a') 173 | l.href = url 174 | l.target = "_blank" 175 | return l 176 | } 177 | 178 | function getVisible (nodeList) { 179 | if(nodeList.length) { 180 | var node 181 | $(nodeList).map(function() { 182 | if(typeof node == 'undefined' && (this.clientWidth > 0 || this.clientHeight > 0)) { 183 | node = this 184 | } 185 | }) 186 | return node 187 | } 188 | } 189 | 190 | function notAnInput (element) { 191 | return !element.className.match(/editable/) && element.tagName != "TEXTAREA" && element.tagName != "INPUT" 192 | } 193 | 194 | function clearAllIntervals () { 195 | intervals.map(function(num) { 196 | clearInterval(num) 197 | delete intervals[intervals.indexOf(num)] 198 | }) 199 | } 200 | 201 | // Reject unsubscribe, subscription and verification management paths 202 | // Make sure the keywords((un)subscribe) can still be repository names 203 | function reject_unwanted_paths (links) { 204 | paths = ['\/\/[^\/]*\/mailers\/unsubscribe\?', 205 | '\/\/[^\/]*\/.*\/.*\/unsubscribe_via_email', 206 | '\/\/[^\/]*\/.*\/.*\/subscription$', 207 | '\/\/[^\/]*\/.*\/.*\/emails\/.*\/confirm_verification\/.*' 208 | ] 209 | regexp = new RegExp(paths.join('|')) 210 | return $(links).filter(function() { 211 | if(!this.href.match(regexp)) return this 212 | }) 213 | } 214 | -------------------------------------------------------------------------------- /chrome/js/jquery.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v2.1.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ 2 | !function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.1",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(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 ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="
",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.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===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||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 fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.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},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.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=fb.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=fb.selectors={cacheLength:50,createPseudo:hb,match:X,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(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===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]||fb.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]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.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(cb,db).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("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.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+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(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),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.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:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+Math.random()}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b) 3 | },_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),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),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==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,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("