├── HACKING ├── LICENSE ├── README.markdown ├── Rakefile ├── bin └── djsd ├── com.github.dotjs.plist └── ext ├── dotjs.js ├── icon128.png ├── icon48.png ├── jquery.js ├── jquery.min.map └── manifest.json /HACKING: -------------------------------------------------------------------------------- 1 | WEBrick hacking: http://microjet.ath.cx/webrickguide/pdf/pdf_webrick.pdf 2 | 3 | Chrome Manifest: http://code.google.com/chrome/extensions/manifest.html 4 | 5 | Chrome DevGuide: http://code.google.com/chrome/extensions/devguide.html -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Chris Wanstrath 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | Software), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | This project is archived and no longer mainted. 2 | 3 | Check out its successor, which is way better and 4 | runs on all platforms: 5 | 6 | [Witchcraft](https://github.com/luciopaiva/witchcraft) 7 | 8 | dotjs 9 | ===== 10 | 11 | dotjs is a Google Chrome extension that executes 12 | JavaScript files in `~/.js` based on their filename. 13 | 14 | If you navigate to `http://www.google.com/`, dotjs 15 | will execute `~/.js/google.com.js`. 16 | 17 | This makes it super easy to spruce up your favorite 18 | pages using JavaScript. 19 | 20 | On subdomains such as `http://gist.github.com` dotjs 21 | will try to load `~/.js/gist.github.com.js` as well 22 | as `~/.js/github.com.js` and `~/.js/com.js`. 23 | 24 | Bonus: files in `~/.js` have jQuery 1.9 loaded, 25 | regardless of whether the site you're hacking 26 | uses jQuery. 27 | 28 | Double bonus: `~/.js/default.js` is loaded on every 29 | request, meaning you can stick plugins or helper 30 | functions in it. 31 | 32 | GreaseMonkey user scripts are great, but you need to 33 | publish them somewhere and re-publish after making 34 | modifications. With dotjs, just add or edit files in 35 | `~/.js`. 36 | 37 | ## Example 38 | 39 | $ cat ~/.js/github.com.js 40 | // swap github logo with trollface 41 | $('a[class^=header-logo-]').html( 42 | $('') 43 | .attr('src', '//bit.ly/ghD24e') 44 | .css({'width': 'auto', 'height': '22px'}) 45 | ); 46 | 47 | ![](http://puu.sh/1Kjvw) 48 | 49 | ## How It Works 50 | 51 | Chrome extensions can't access the local filesystem, 52 | so dotjs runs a tiny web server on port 3131 that 53 | serves files out of ~/.js. 54 | 55 | You don't have to worry about starting or stopping 56 | this web server because we put a pretty great plist 57 | into ~/Library/LaunchAgents that handles all that 58 | for us. 59 | 60 | The dotjs Chrome extension then makes ajax requests 61 | to http://localhost:3131/convore.com.js any time you 62 | hit a page on convore.com, for example, and executes 63 | the returned JavaScript. 64 | 65 | ## Requires 66 | 67 | - OS X 68 | - Ruby 1.8 69 | - rake (gem install rake) 70 | - Google Chrome 71 | - `/usr/local/bin` in your $PATH 72 | 73 | ## Install it 74 | 75 | git clone http://github.com/defunkt/dotjs 76 | cd dotjs 77 | rake install 78 | 79 | Now open in Chrome and follow these steps: 80 | 81 | - Click the "X" Padlock icon in the address bar 82 | - Click "Certificate Information" 83 | - Drag the large cert icon to your desktop 84 | - Open it with Keychain 85 | - Configure its **Trust** section as shown: http://cl.ly/Pdny 86 | 87 | Finally install the Google Chrome extension: 88 | 89 | http://bit.ly/dotjs 90 | 91 | ## Uninstall it 92 | 93 | rake uninstall 94 | 95 | ## Credits 96 | 97 | - Icon: 98 | - jQuery: 99 | - Ryan Tomayko for: 100 | 101 | > "I almost wish you could just 102 | stick JavaScript in ~/.js. Do 103 | you know what I'm saying?" 104 | 105 | ## Linux 106 | 107 | - [dotjs-ubuntu](https://github.com/glenbot/dotjs-ubuntu) 108 | 109 | ## Windows 110 | 111 | - [dotjs-universal](https://github.com/p3lim/dotjs-universal) 112 | 113 | ## Other Browsers 114 | 115 | - [Firefox Add-on](https://github.com/rlr/dotjs-addon) 116 | - [Safari Extension](https://github.com/wfarr/dotjs.safariextension) 117 | - [Fluid UserScript](https://github.com/sj26/dotjs-fluid) 118 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'erb' 2 | 3 | desc "Install dotjs" 4 | task :install => 'install:all' 5 | 6 | DAEMON_INSTALL_DIR = ENV['PREFIX'] || "/usr/local/bin" 7 | 8 | namespace :install do 9 | task :all => [ :prompt, :daemon, :create_dir, :agent, :chrome, :done ] 10 | 11 | task :prompt do 12 | puts "\e[1m\e[32mdotjs\e[0m" 13 | puts "\e[1m-----\e[0m" 14 | puts "I will install:", "" 15 | puts "1. djsd(1) in #{DAEMON_INSTALL_DIR}" 16 | puts "2. com.github.dotjs in ~/Library/LaunchAgents","" 17 | print "Ok? (y/n) " 18 | 19 | begin 20 | until %w( k ok y yes n no ).include?(answer = $stdin.gets.chomp.downcase) 21 | puts "(psst... please type y or n)" 22 | puts "Install dotjs? (y/n)" 23 | end 24 | rescue Interrupt 25 | exit 1 26 | end 27 | 28 | exit 1 if answer =~ /n/ 29 | end 30 | 31 | task :done do 32 | if system("curl -k https://localhost:3131 &> /dev/null") 33 | puts "\e[1m\e[32mdotjs installation worked\e[0m" 34 | puts "open https://localhost:3131 in chrome to enable ssl" 35 | puts "then drop files like google.com.js in ~/.js and enjoy hacking the web" 36 | else 37 | puts "\e[31mdotjs installation failed\e[0m" 38 | puts "check console.app or open an issue" 39 | end 40 | end 41 | 42 | desc "Install launch agent" 43 | task :agent do 44 | plist = "com.github.dotjs.plist" 45 | agent_dir = File.expand_path("~/Library/LaunchAgents/") 46 | agent = File.join(agent_dir, plist) 47 | Dir.mkdir(agent_dir) unless File.exists?(agent_dir) 48 | File.open(agent, "w") do |f| 49 | f.puts ERB.new(IO.read(plist)).result(binding) 50 | end 51 | 52 | chmod 0644, agent 53 | puts "starting djdb..." 54 | sh "launchctl load -w #{agent}" 55 | # wait for server to start 56 | sleep 5 57 | end 58 | 59 | desc "Install dotjs daemon" 60 | task :daemon => :install_dir_writeable do 61 | cp "bin/djsd", DAEMON_INSTALL_DIR, :verbose => true, :preserve => true 62 | end 63 | 64 | desc "Create ~/.js" 65 | task :create_dir do 66 | if !File.directory? js_dir = File.join(ENV['HOME'], ".js") 67 | mkdir js_dir 68 | chmod 0755, js_dir 69 | end 70 | end 71 | 72 | desc "Install Google Chrome extension" 73 | task :chrome do 74 | puts "", "\e[31mIMPORTANT!\e[0m Install the Google Chrome extension:" 75 | puts "http://bit.ly/dotjs", "" 76 | end 77 | end 78 | 79 | desc "Uninstall dotjs" 80 | task :uninstall => 'uninstall:all' 81 | 82 | namespace :uninstall do 83 | task :all => [ :prompt, :daemon, :agent, :chrome, :done ] 84 | 85 | task :prompt do 86 | puts "\e[1m\e[32mdotjs\e[0m" 87 | puts "\e[1m-----\e[0m" 88 | puts "I will remove:", "" 89 | puts "1. djsd(1) from #{DAEMON_INSTALL_DIR}" 90 | puts "2. com.github.dotjs from ~/Library/LaunchAgents" 91 | puts "3. The 'dotjs' Google Chrome Extension","" 92 | puts "I will not remove:", "" 93 | puts "1. ~/.js", "" 94 | print "Ok? (y/n) " 95 | 96 | begin 97 | until %w( k ok y yes n no ).include?(answer = $stdin.gets.chomp.downcase) 98 | puts "(psst... please type y or n)" 99 | puts "Uninstall dotjs? (y/n)" 100 | end 101 | rescue Interrupt 102 | exit 1 103 | end 104 | 105 | exit 1 if answer =~ /n/ 106 | end 107 | 108 | task :done do 109 | if system("curl http://localhost:3131 &> /dev/null") 110 | puts "\e[31mdotjs uninstall failed\e[0m" 111 | puts "djsd is still running" 112 | else 113 | puts "\e[1m\e[32mdotjs uninstall worked\e[0m" 114 | puts "your ~/.js was not touched" 115 | end 116 | end 117 | 118 | desc "Uninstall launch agent" 119 | task :agent do 120 | plist = "com.github.dotjs.plist" 121 | agent = File.expand_path("~/Library/LaunchAgents/#{plist}") 122 | sh "launchctl unload #{agent}" 123 | rm agent, :verbose => true 124 | end 125 | 126 | desc "Uninstall dotjs daemon" 127 | task :daemon => :install_dir_writeable do 128 | rm File.join(DAEMON_INSTALL_DIR, "djsd"), :verbose => true 129 | end 130 | 131 | desc "Uninstall Google Chrome extension" 132 | task :chrome do 133 | puts "\e[1mplease uninstall the google chrome extension manually:\e[0m" 134 | puts "google chrome > window > extensions > dotjs > uninstall" 135 | end 136 | end 137 | 138 | # Check write permissions on DAEMON_INSTALL_DIR 139 | task :install_dir_writeable do 140 | if not File.writable?(DAEMON_INSTALL_DIR) 141 | abort "Error: Can't write to #{DAEMON_INSTALL_DIR}. Try again using `sudo`." 142 | end 143 | end 144 | -------------------------------------------------------------------------------- /bin/djsd: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | if (%w( -h --help -help help ) & ARGV).length > 0 4 | puts "usage: djsd [-hv]" 5 | puts "starts dotjs server in the foreground. kill with ^C" 6 | exit 7 | end 8 | 9 | if ARGV.include?('-v') 10 | puts "djsd 2.0" 11 | exit 12 | end 13 | 14 | require 'webrick' 15 | require 'webrick/https' 16 | 17 | dotjs = Class.new(WEBrick::HTTPServlet::AbstractServlet) do 18 | def do_GET(request, response) 19 | body = build_body(request.path) 20 | 21 | response.status = body.empty? ? 204 : 200 22 | if origin = detect_origin(request) 23 | response['Access-Control-Allow-Origin'] = origin 24 | end 25 | response['Content-Type'] = 'text/javascript' 26 | response.body = body 27 | end 28 | 29 | def build_body(path) 30 | files = [File.expand_path("default.js")] 31 | paths = path.gsub('/','').split('.') 32 | 33 | until paths.empty? 34 | file = File.expand_path(paths.join('.')) 35 | files << file if File.file?(file) 36 | paths.shift 37 | end 38 | 39 | body = "// dotjs is working! //\n" 40 | 41 | files.each do |file| 42 | body << File.read(file) + "\n" if File.file?(file) 43 | end 44 | 45 | body 46 | end 47 | 48 | def detect_origin(req) 49 | path = req.path 50 | origin = req.header['origin'] 51 | search = path.gsub('/','').gsub(/\.js$/,'') + '$' 52 | 53 | if origin.length == 1 && path.length != 1 && origin[0].match(search) 54 | origin[0] 55 | end 56 | end 57 | end 58 | 59 | ssl_info = DATA.read 60 | ssl_cert = ssl_info.scan(/(-----BEGIN CERTIFICATE-----.+?-----END CERTIFICATE-----)/m)[0][0] 61 | ssl_key = ssl_info.scan(/(-----BEGIN RSA PRIVATE KEY-----.+?-----END RSA PRIVATE KEY-----)/m)[0][0] 62 | 63 | server_options = { 64 | :BindAddress => "127.0.0.1", 65 | :Port => 3131, 66 | :AccessLog => [], 67 | :SSLEnable => true, 68 | :SSLVerifyClient => OpenSSL::SSL::VERIFY_NONE, 69 | :SSLPrivateKey => OpenSSL::PKey::RSA.new(ssl_key), 70 | :SSLCertificate => OpenSSL::X509::Certificate.new(ssl_cert), 71 | :SSLCertName => [["CN", WEBrick::Utils::getservername]], 72 | } 73 | 74 | server = WEBrick::HTTPServer.new(server_options) 75 | server.mount('/', dotjs) 76 | 77 | %w( INT TERM ).each do |sig| 78 | trap(sig) { server.shutdown } 79 | end 80 | 81 | server.start 82 | 83 | __END__ 84 | -----BEGIN CERTIFICATE----- 85 | MIICHTCCAYYCCQClZE2IvNWbtDANBgkqhkiG9w0BAQUFADBTMQswCQYDVQQGEwJV 86 | UzETMBEGA1UECBMKQ2FsaWZvcm5pYTELMAkGA1UEBxMCTEExDjAMBgNVBAoTBWRv 87 | dGpzMRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMTMwMjIwMjMzNzUzWhcNMjIxMTIw 88 | MjMzNzUzWjBTMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTELMAkG 89 | A1UEBxMCTEExDjAMBgNVBAoTBWRvdGpzMRIwEAYDVQQDEwlsb2NhbGhvc3QwgZ8w 90 | DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMNgNijoFmD5TX7NMd2pGEeEmwRifWRc 91 | 45jVS1a5kUncfRfgr4ehygPQDS2XrUkd+OYneFIXOcANW9WAWAlfeLs8DiSgs+9m 92 | tuVjZ58RAsRXkW7H3vqQv5sAxmmwwVGN9WfKW+II/xLhpMtVGQH+MOucGbssODzk 93 | 0vwXEGSeEqYdAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAgCW2RBZgDMikQenSF3sz 94 | u7KDe8+t8qnEFvrwCEpLUzvedSZxkaKzHrrCnIYlDnXRZBveKngWoejGzqtyIXup 95 | YKzBZaZWH8cV72RdDwgM1owWi3KZBKpxfphYkWSRRx59djHZY/Yjudnb3oT/3c8/ 96 | NHsFbLbrZaGriLshIwrjEGs= 97 | -----END CERTIFICATE----- 98 | -----BEGIN RSA PRIVATE KEY----- 99 | MIICXAIBAAKBgQDDYDYo6BZg+U1+zTHdqRhHhJsEYn1kXOOY1UtWuZFJ3H0X4K+H 100 | ocoD0A0tl61JHfjmJ3hSFznADVvVgFgJX3i7PA4koLPvZrblY2efEQLEV5Fux976 101 | kL+bAMZpsMFRjfVnylviCP8S4aTLVRkB/jDrnBm7LDg85NL8FxBknhKmHQIDAQAB 102 | AoGAZDw9LRl9Ob1No+t0VOuG+FIxEbvR5ya84dE0OMc1ofZL+28bvvMjaHdZ+3Ug 103 | wy1sX/AKC9u8liqEXfHduNlRX59WfhS1DBIqpezpg3Hj35sCmuGvtiJVMHbZBX0I 104 | S0P14vXxaGJ/Sw04CgbGJs08P5ITTleZ9HioHhCkUObP5kUCQQD3auQTo/oqbNXz 105 | FbL1ckP65wUz7ean+YcXDYgKM2jnyEfATMWjjQkMEzO4MJdfuLi+5UbEfup1c1zB 106 | SmIijzN7AkEAyicud3X+HoV2dwRPzsquvR27fjEsIttzjNJ0Kcm+YAtIQcJQti9e 107 | E9OMjSsxa8LQ1V8HMWmDYyoAEhdYG1BtRwJAczlTmJYANmvTQ87yNf6ODDY0pReB 108 | GO9La4AAwAdrLq6GQ9c9H8rZ0MbMilYO2SRU3Yo3Z+FXXXVpWBdFFqUsKwJAKNYn 109 | bdx5HENLvhkx4g1RpUR3VrOqPdRlEEKHUtW9TnuY+ie91D/XWlv23aGnFyTAuQm8 110 | U0AEWajnYMA0fTgPCwJBAI1J6nOjlE5jcKKzBAE33iL8lXj5FlGX3hhPM4jm3BCN 111 | bpmhcfRVwyhqWwYChEQ5Y25Lv0i7Lxpud/UbLE0x/x8= 112 | -----END RSA PRIVATE KEY----- 113 | -------------------------------------------------------------------------------- /com.github.dotjs.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Label 6 | com.github.dotjs 7 | KeepAlive 8 | 9 | ProgramArguments 10 | 11 | <%= DAEMON_INSTALL_DIR %>/djsd 12 | 13 | RunAtLoad 14 | 15 | WorkingDirectory 16 | <%= File.join(ENV['HOME'], ".js") %> 17 | 18 | 19 | -------------------------------------------------------------------------------- /ext/dotjs.js: -------------------------------------------------------------------------------- 1 | $.ajax({ 2 | url: 'https://localhost:3131/'+location.hostname.replace(/^www\./,'')+'.js', 3 | dataType: 'text', 4 | success: function(d){ 5 | $(function(){ eval(d) }) 6 | }, 7 | error: function(){ 8 | console.log('no dotjs server found at localhost:3131') 9 | } 10 | }) 11 | -------------------------------------------------------------------------------- /ext/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/defunkt/dotjs/434eaba374b02a3ee7e056408bb1c0fe76e837d3/ext/icon128.png -------------------------------------------------------------------------------- /ext/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/defunkt/dotjs/434eaba374b02a3ee7e056408bb1c0fe76e837d3/ext/icon48.png -------------------------------------------------------------------------------- /ext/jquery.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v1.9.0 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license */(function(e,t){"use strict";function n(e){var t=e.length,n=st.type(e);return st.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}function r(e){var t=Tt[e]={};return st.each(e.match(lt)||[],function(e,n){t[n]=!0}),t}function i(e,n,r,i){if(st.acceptData(e)){var o,a,s=st.expando,u="string"==typeof n,l=e.nodeType,c=l?st.cache:e,f=l?e[s]:e[s]&&s;if(f&&c[f]&&(i||c[f].data)||!u||r!==t)return f||(l?e[s]=f=K.pop()||st.guid++:f=s),c[f]||(c[f]={},l||(c[f].toJSON=st.noop)),("object"==typeof n||"function"==typeof n)&&(i?c[f]=st.extend(c[f],n):c[f].data=st.extend(c[f].data,n)),o=c[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[st.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[st.camelCase(n)])):a=o,a}}function o(e,t,n){if(st.acceptData(e)){var r,i,o,a=e.nodeType,u=a?st.cache:e,l=a?e[st.expando]:st.expando;if(u[l]){if(t&&(r=n?u[l]:u[l].data)){st.isArray(t)?t=t.concat(st.map(t,st.camelCase)):t in r?t=[t]:(t=st.camelCase(t),t=t in r?[t]:t.split(" "));for(i=0,o=t.length;o>i;i++)delete r[t[i]];if(!(n?s:st.isEmptyObject)(r))return}(n||(delete u[l].data,s(u[l])))&&(a?st.cleanData([e],!0):st.support.deleteExpando||u!=u.window?delete u[l]:u[l]=null)}}}function a(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(Nt,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:wt.test(r)?st.parseJSON(r):r}catch(o){}st.data(e,n,r)}else r=t}return r}function s(e){var t;for(t in e)if(("data"!==t||!st.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}function u(){return!0}function l(){return!1}function c(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function f(e,t,n){if(t=t||0,st.isFunction(t))return st.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return st.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=st.grep(e,function(e){return 1===e.nodeType});if(Wt.test(t))return st.filter(t,r,!n);t=st.filter(t,r)}return st.grep(e,function(e){return st.inArray(e,t)>=0===n})}function p(e){var t=zt.split("|"),n=e.createDocumentFragment();if(n.createElement)for(;t.length;)n.createElement(t.pop());return n}function d(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function h(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function g(e){var t=nn.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function m(e,t){for(var n,r=0;null!=(n=e[r]);r++)st._data(n,"globalEval",!t||st._data(t[r],"globalEval"))}function y(e,t){if(1===t.nodeType&&st.hasData(e)){var n,r,i,o=st._data(e),a=st._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)st.event.add(t,n,s[n][r])}a.data&&(a.data=st.extend({},a.data))}}function v(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!st.support.noCloneEvent&&t[st.expando]){r=st._data(t);for(i in r.events)st.removeEvent(t,i,r.handle);t.removeAttribute(st.expando)}"script"===n&&t.text!==e.text?(h(t).text=e.text,g(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),st.support.html5Clone&&e.innerHTML&&!st.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Zt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}function b(e,n){var r,i,o=0,a=e.getElementsByTagName!==t?e.getElementsByTagName(n||"*"):e.querySelectorAll!==t?e.querySelectorAll(n||"*"):t;if(!a)for(a=[],r=e.childNodes||e;null!=(i=r[o]);o++)!n||st.nodeName(i,n)?a.push(i):st.merge(a,b(i,n));return n===t||n&&st.nodeName(e,n)?st.merge([e],a):a}function x(e){Zt.test(e.type)&&(e.defaultChecked=e.checked)}function T(e,t){if(t in e)return t;for(var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Nn.length;i--;)if(t=Nn[i]+n,t in e)return t;return r}function w(e,t){return e=t||e,"none"===st.css(e,"display")||!st.contains(e.ownerDocument,e)}function N(e,t){for(var n,r=[],i=0,o=e.length;o>i;i++)n=e[i],n.style&&(r[i]=st._data(n,"olddisplay"),t?(r[i]||"none"!==n.style.display||(n.style.display=""),""===n.style.display&&w(n)&&(r[i]=st._data(n,"olddisplay",S(n.nodeName)))):r[i]||w(n)||st._data(n,"olddisplay",st.css(n,"display")));for(i=0;o>i;i++)n=e[i],n.style&&(t&&"none"!==n.style.display&&""!==n.style.display||(n.style.display=t?r[i]||"":"none"));return e}function C(e,t,n){var r=mn.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function k(e,t,n,r,i){for(var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;4>o;o+=2)"margin"===n&&(a+=st.css(e,n+wn[o],!0,i)),r?("content"===n&&(a-=st.css(e,"padding"+wn[o],!0,i)),"margin"!==n&&(a-=st.css(e,"border"+wn[o]+"Width",!0,i))):(a+=st.css(e,"padding"+wn[o],!0,i),"padding"!==n&&(a+=st.css(e,"border"+wn[o]+"Width",!0,i)));return a}function E(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=ln(e),a=st.support.boxSizing&&"border-box"===st.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=un(e,t,o),(0>i||null==i)&&(i=e.style[t]),yn.test(i))return i;r=a&&(st.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+k(e,t,n||(a?"border":"content"),r,o)+"px"}function S(e){var t=V,n=bn[e];return n||(n=A(e,t),"none"!==n&&n||(cn=(cn||st("