From 58e41f8fc9a98c52e2b27064428d7317331a70c1 Mon Sep 17 00:00:00 2001 From: matteo78 Date: Sat, 8 Nov 2014 18:52:36 +0100 Subject: [PATCH] :on: Initial commit --- .gitignore | 3 + App.js | 207 + Gruntfile.js | 96 + LICENSE | 19 + README.md | 17 + css/dialog-theme.css | 147 + css/forms.css | 99 + css/lib/vex/vex-theme-bottom-right-corner.css | 631 + css/lib/vex/vex-theme-default.css | 528 + css/lib/vex/vex-theme-flat-attack.css | 461 + css/lib/vex/vex-theme-os.css | 533 + css/lib/vex/vex-theme-plain.css | 259 + css/lib/vex/vex-theme-top.css | 613 + css/lib/vex/vex-theme-wireframe.css | 262 + css/lib/vex/vex.css | 335 + css/piano.css | 458 + grunt/contrib-clean.js | 20 + grunt/contrib-copy.js | 13 + grunt/contrib-watch.js | 16 + grunt/curl.js | 12 + grunt/http.js | 67 + grunt/mkdir.js | 13 + grunt/rebrand.js | 33 + grunt/rename.js | 12 + grunt/zip.js | 12 + images/empty.png | Bin 0 -> 467 bytes images/icons/channels.png | Bin 0 -> 548 bytes images/icons/close.png | Bin 0 -> 268 bytes images/icons/instruments/bass.png | Bin 0 -> 551 bytes images/icons/instruments/brass.png | Bin 0 -> 806 bytes images/icons/instruments/effect.png | Bin 0 -> 256 bytes images/icons/instruments/guitar.png | Bin 0 -> 866 bytes images/icons/instruments/orchestra.png | Bin 0 -> 520 bytes images/icons/instruments/organ.png | Bin 0 -> 1089 bytes images/icons/instruments/percussion.png | Bin 0 -> 582 bytes images/icons/instruments/percussive.png | Bin 0 -> 520 bytes images/icons/instruments/piano.png | Bin 0 -> 809 bytes images/icons/instruments/pipe.png | Bin 0 -> 680 bytes images/icons/instruments/string.png | Bin 0 -> 610 bytes images/icons/instruments/synth.png | Bin 0 -> 353 bytes images/icons/pause.png | Bin 0 -> 233 bytes images/icons/play.png | Bin 0 -> 366 bytes images/logos/logo.ico | Bin 0 -> 30742 bytes images/logos/logo.svg | 137 + images/logos/logo128.png | Bin 0 -> 1132 bytes images/logos/logo16.png | Bin 0 -> 478 bytes images/logos/logo256.png | Bin 0 -> 1690 bytes images/logos/logo32.png | Bin 0 -> 624 bytes images/logos/logo64.png | Bin 0 -> 835 bytes images/logos/logo_u.svg | 123 + images/logos/logo_u128.png | Bin 0 -> 1057 bytes images/logos/logo_u16.png | Bin 0 -> 375 bytes images/logos/logo_u256.png | Bin 0 -> 1488 bytes images/logos/logo_u32.png | Bin 0 -> 481 bytes images/logos/logo_u64.png | Bin 0 -> 750 bytes index.html | 43 + js/app.js | 96 + js/components/Channel/Channel.js | 228 + js/components/Channel/Modal.js | 58 + js/components/Control.js | 129 + js/components/Error.js | 107 + js/components/Key/Board.js | 163 + js/components/Key/Key.js | 172 + js/components/Main.js | 464 + js/components/Note/Board.js | 191 + js/components/Note/Score.js | 218 + js/components/UI/Scroll.js | 156 + js/components/UI/Selector.js | 91 + js/init.js | 94 + js/lib/jasmid/LICENSE | 24 + js/lib/jasmid/jasmid.js | 308 + js/lib/jasmid/jasmid.min.js | 1 + js/lib/jquery/jquery.js | 10308 ++++++++ js/lib/jquery/jquery.min.js | 4 + js/lib/react/react-with-addons.js | 20276 ++++++++++++++++ js/lib/react/react-with-addons.min.js | 22 + js/lib/react/react.js | 18484 ++++++++++++++ js/lib/react/react.min.js | 21 + js/lib/vex/build-test-amd.html | 20 + js/lib/vex/build-test.html | 11 + js/lib/vex/vex.combined.min.js | 2 + js/lib/vex/vex.dialog.js | 151 + js/lib/vex/vex.dialog.min.js | 2 + js/lib/vex/vex.js | 190 + js/lib/vex/vex.min.js | 2 + js/midi/file.js | 349 + js/midi/io.js | 167 + js/modal.js | 67 + main.js | 7 + package.json | 32 + 90 files changed, 57784 insertions(+) create mode 100644 .gitignore create mode 100644 App.js create mode 100644 Gruntfile.js create mode 100644 LICENSE create mode 100644 README.md create mode 100644 css/dialog-theme.css create mode 100644 css/forms.css create mode 100644 css/lib/vex/vex-theme-bottom-right-corner.css create mode 100644 css/lib/vex/vex-theme-default.css create mode 100644 css/lib/vex/vex-theme-flat-attack.css create mode 100644 css/lib/vex/vex-theme-os.css create mode 100644 css/lib/vex/vex-theme-plain.css create mode 100644 css/lib/vex/vex-theme-top.css create mode 100644 css/lib/vex/vex-theme-wireframe.css create mode 100644 css/lib/vex/vex.css create mode 100644 css/piano.css create mode 100644 grunt/contrib-clean.js create mode 100644 grunt/contrib-copy.js create mode 100644 grunt/contrib-watch.js create mode 100644 grunt/curl.js create mode 100644 grunt/http.js create mode 100644 grunt/mkdir.js create mode 100644 grunt/rebrand.js create mode 100644 grunt/rename.js create mode 100644 grunt/zip.js create mode 100644 images/empty.png create mode 100644 images/icons/channels.png create mode 100644 images/icons/close.png create mode 100644 images/icons/instruments/bass.png create mode 100644 images/icons/instruments/brass.png create mode 100644 images/icons/instruments/effect.png create mode 100644 images/icons/instruments/guitar.png create mode 100644 images/icons/instruments/orchestra.png create mode 100644 images/icons/instruments/organ.png create mode 100644 images/icons/instruments/percussion.png create mode 100644 images/icons/instruments/percussive.png create mode 100644 images/icons/instruments/piano.png create mode 100644 images/icons/instruments/pipe.png create mode 100644 images/icons/instruments/string.png create mode 100644 images/icons/instruments/synth.png create mode 100644 images/icons/pause.png create mode 100644 images/icons/play.png create mode 100644 images/logos/logo.ico create mode 100644 images/logos/logo.svg create mode 100644 images/logos/logo128.png create mode 100644 images/logos/logo16.png create mode 100644 images/logos/logo256.png create mode 100644 images/logos/logo32.png create mode 100644 images/logos/logo64.png create mode 100644 images/logos/logo_u.svg create mode 100644 images/logos/logo_u128.png create mode 100644 images/logos/logo_u16.png create mode 100644 images/logos/logo_u256.png create mode 100644 images/logos/logo_u32.png create mode 100644 images/logos/logo_u64.png create mode 100644 index.html create mode 100644 js/app.js create mode 100644 js/components/Channel/Channel.js create mode 100644 js/components/Channel/Modal.js create mode 100644 js/components/Control.js create mode 100644 js/components/Error.js create mode 100644 js/components/Key/Board.js create mode 100644 js/components/Key/Key.js create mode 100644 js/components/Main.js create mode 100644 js/components/Note/Board.js create mode 100644 js/components/Note/Score.js create mode 100644 js/components/UI/Scroll.js create mode 100644 js/components/UI/Selector.js create mode 100644 js/init.js create mode 100644 js/lib/jasmid/LICENSE create mode 100644 js/lib/jasmid/jasmid.js create mode 100644 js/lib/jasmid/jasmid.min.js create mode 100644 js/lib/jquery/jquery.js create mode 100644 js/lib/jquery/jquery.min.js create mode 100644 js/lib/react/react-with-addons.js create mode 100644 js/lib/react/react-with-addons.min.js create mode 100644 js/lib/react/react.js create mode 100644 js/lib/react/react.min.js create mode 100644 js/lib/vex/build-test-amd.html create mode 100644 js/lib/vex/build-test.html create mode 100644 js/lib/vex/vex.combined.min.js create mode 100644 js/lib/vex/vex.dialog.js create mode 100644 js/lib/vex/vex.dialog.min.js create mode 100644 js/lib/vex/vex.js create mode 100644 js/lib/vex/vex.min.js create mode 100644 js/midi/file.js create mode 100644 js/midi/io.js create mode 100644 js/modal.js create mode 100644 main.js create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0250522 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +build/* +node_modules/* +music/* \ No newline at end of file diff --git a/App.js b/App.js new file mode 100644 index 0000000..cc6337c --- /dev/null +++ b/App.js @@ -0,0 +1,207 @@ +/*jshint node:true, nomen:true */ + +'use strict'; + +var app = require('app'); +var BrowserWindow = require('browser-window'); +var ipc = require('ipc'); +var net = require('net'); +var util = require('util'); +var events = require('events'); + +/** + * App + * + * Controls the app flow + */ +function App() { + this.windows = []; + this.ready = false; + this.visible = true; + + app.on('ready', function () { + this.ready = true; + }.bind(this)); + + app.on('window-all-closed', function () { + app.quit(); + }); + + events.EventEmitter.call(this); +} + +util.inherits(App, events.EventEmitter); +module.exports = App; +App.socket = '\\\\.\\pipe\\piano-sock'; + +/** + * Add a new window + * + * Open a window and add it to the + * window stack. Returns window instance. + * + * @param {options: Object} Window options (see atom-shell docs) + */ +App.prototype.addWindow = function (options) { + var window = new BrowserWindow(options), + index = this.windows.length; + + window.on('closed', function () { + this.windows.splice(index, 1); + }.bind(this)); + + this.windows.push(window); + return window; +}; + +/** + * Fetch options + * + * Gather options in a litteral from + * argv parameters. + */ +App.prototype.fetchOptions = function () { + var argv, i, arg, options = {}; + argv = process.argv.slice(1); + + for (i in argv) { + if (argv.hasOwnProperty(i)) { + arg = argv[i]; + + if (arg[0] !== '-') { + options.file = arg; + } + } + } + + this.emit('options', options); + return options; +}; + +/** + * Chain options + * + * Pass current options to the instance that + * is already opened, if there is one. + * Otherwise, code in callback is executed, + * and server is launched. + * + * @param {callback: function} Function to call if this is the first instance + */ +App.prototype.chainOptions = function (callback) { + var client; + + client = net.connect({ + path: App.socket + }, function () { + // if the connection is established, + // an instance is already running. + // Pass on parameters and close app. + client.write( + JSON.stringify(this.fetchOptions()), + function () { + client.end(); + app.terminate(); + } + ); + }.bind(this)); + + client.on('error', function (err) { + // if an error occurred, that means no + // server was created yet: this is the + // first instance + this.startServer(); + + if (this.ready) { + callback(); + } else { + app.on('ready', callback); + } + }.bind(this)); +}; + +/** + * Start app server + * + * Start a server on App.socket path, waiting + * for new instances to pass their options. + */ +App.prototype.startServer = function () { + var server; + + server = net.createServer(function (connection) { + connection.on('data', function (data) { + this.windows[0].focus(); + this.emit('options', JSON.parse(data)); + }.bind(this)); + }.bind(this)); + + server.listen(App.socket); +}; + +/** + * Add a switch + * + * @param {switch: string} Switch name + * @param {value: mixed} Switch value + */ +App.prototype.addSwitch = function (name, value) { + app.commandLine.appendSwitch(name, value); +}; + +/** + * Start the app + * + * Check if another instance is already opened, + * if so, transmit options and close instantly. + * Otherwise, open main window. + */ +App.prototype.start = function () { + this.chainOptions(function () { + // enable MIDI support + this.addSwitch('enable-web-midi'); + + // create main window + var window = this.addWindow({ + title: 'Piano', + icon: __dirname + '/images/logos/logo32.png', + + 'min-width': 750, + 'min-height': 400, + width: 937, + height: 500, + show: false + }); + + window.loadUrl('file://' + __dirname + '/index.html'); + + // FIXME: atom-shell currently doesn't have a + // minimize/restore event, so we poll + // + // https://github.com/atom/atom-shell/issues/73 + setInterval(function () { + if (this.visible && window.isMinimized()) { + this.visible = false; + window.webContents.send('visible', false); + } + + if (!this.visible && !window.isMinimized()) { + this.visible = true; + window.webContents.send('visible', true); + } + }.bind(this), 500); + + // start sending options + this.on('options', function (options) { + window.webContents.send('options', options); + }); + + ipc.on('ready', function () { + window.show(); + window.focus(); + window.webContents.send('visible', true); + + this.fetchOptions(); + }.bind(this)); + }.bind(this)); +}; \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..b612896 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,96 @@ +/*jshint node:true */ + +'use strict'; + +module.exports = function (grunt) { + grunt.initConfig({ + repo: 'atom/atom-shell', + releases: 'https://api.github.com/repos/<%= repo %>/releases', + pkg: grunt.file.readJSON('package.json'), + + meta: { + CompanyName: '<%= pkg.author.name %>', + FileDescription: '<%= pkg.name %>', + FileVersion: '<%= pkg.version %>', + InternalName: '<%= pkg.name.toLowerCase() %>.exe', + LegalCopyright: 'Copyright (C) <%= grunt.template.' + + 'today("yyyy") %> <%= pkg.author.name %>', + OriginalFilename: '<%= pkg.name.toLowerCase() %>.exe', + ProductName: '<%= pkg.name %>', + ProductVersion: '<%= pkg.version %>' + }, + + files: [ + 'css/**', + 'js/**', + 'images/**', + 'App.js', + 'index.html', + 'LICENSE', + 'main.js', + 'package.json' + ], + + paths: { + resources: { + win: 'win/resources', + mac: 'mac/Atom.app/Contents/Resources', + linux: 'linux/resources' + }, + + originalExe: { + win: 'win/atom.exe', + mac: 'mac/Atom.app', + linux: 'linux/atom' + }, + + exe: { + win: 'win/<%= pkg.name.toLowerCase() %>.exe', + mac: 'mac/<%= pkg.name %>.app', + linux: 'linux/<%= pkg.name.toLowerCase() %>' + } + }, + + platforms: { + win: 'win32-ia32', + mac: 'darwin-x64', + linux: 'linux-x64' + } + }); + + // load tasks defined in grunt/ + grunt.loadTasks('grunt'); + + // create aliases + grunt.registerTask( + 'build', + 'Fetch last shell release and build application', + function (platform) { + var tasks = [ + 'clean:clean-build', + 'mkdir:create-build', + 'http:find-asset', + 'curl:fetch-asset', + 'unzip:extract-asset', + 'clean:clean-default', + 'rename:rename-exe', + 'rebrand:rebrand-exe', + 'copy:copy-files' + ], length = tasks.length, i; + + for (i = 0; i < length; i += 1) { + tasks[i] = tasks[i] + ':' + platform; + } + + grunt.task.run(tasks); + } + ); + + grunt.registerTask( + 'auto-update', + 'Automatically rebuild application whenever a file changes', + function (platform) { + grunt.task.run('watch:watch-changes:' + platform); + } + ); +}; \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b53631a --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 Mattéo DELABRE + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..5aad40e --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# Building + +Using Grunt: + +```sh +$ npm install +$ grunt build:win # use build:linux or build:mac for other systems +``` + +Then run the app in `build/win` folder. + +# Credits + +Icons made by: + +- Freepik (http://freepik.com) from http://flaticon.com (CC BY 3.0); +- Icons8 (http://icons8.com) from http://flaticon.com (CC BY 3.0). \ No newline at end of file diff --git a/css/dialog-theme.css b/css/dialog-theme.css new file mode 100644 index 0000000..2d1f050 --- /dev/null +++ b/css/dialog-theme.css @@ -0,0 +1,147 @@ +/** + * Dialog Theme + * Based on top theme + */ + +/** + * Animations + */ + +/* drop in */ +@-webkit-keyframes vex-dropin { + 0% { + transform: translateY(0); + opacity: 0; + } + + 1% { + transform: translateY(-800px); + opacity: 0; + } + + 2% { + transform: translateY(-800px); + opacity: 1; + } + + 100% { + transform: translateY(0); + opacity: 1; + } +} + +/* drop out */ +@-webkit-keyframes vex-dropout { + 0% { + transform: translateY(0); + } + + 100% { + transform: translateY(-800px); + } +} + +/** + * Content + */ + +.vex.dialog-theme.vex-closing .vex-content { + -webkit-animation: vex-dropout 0.5s; + backface-visibility: hidden; +} + +.vex.dialog-theme .vex-content { + -webkit-animation: vex-dropin 0.5s; + backface-visibility: hidden; +} + +.vex.dialog-theme .vex-content { + position: relative; + padding: 1em 1em 0 1em; + background: white; + + margin: 0 auto; + max-width: 100%; + width: 450px; + max-height: 80%; + overflow: auto; + + font-family: "Helvetica Neue", sans-serif; + color: #282828; + + font-size: 1.1em; + line-height: 1.5em; +} + +.vex.dialog-theme .vex-content .main-title { + border-bottom: 1px solid currentColor; + margin-top: 0; + margin-bottom: 0.5em; +} + +/* closing button */ +.vex.dialog-theme .vex-close { + position: absolute; + top: 0; + right: 0; + + cursor: pointer; +} + +.vex.dialog-theme .vex-close:before { + content: "\00D7"; + + position: absolute; + top: 3px; + right: 3px; + background: transparent; + + text-align: center; + height: 30px; + width: 30px; + + color: #bbbbbb; + font-size: 26px; + font-weight: normal; + line-height: 31px; +} + +.vex.dialog-theme .vex-close:hover:before, .vex.dialog-theme .vex-close:active:before { + color: #282828; + background: #e0e0e0; +} + +/* inputs, forms, buttons */ +.vex.dialog-theme .vex-dialog-form .vex-dialog-message { + margin-bottom: 0.5em; +} + +.vex.dialog-theme .vex-dialog-form .vex-dialog-input { + margin-bottom: 1em; +} + +.vex.dialog-theme .vex-dialog-form .vex-dialog-buttons:after { + content: ""; + display: table; + clear: both; +} + +.vex.dialog-theme .bt { + float: right; + margin: 0 0 0 0.5em; +} + +.vex.dialog-theme .bt:last-child { + margin-left: 0; +} + +.vex-loading-spinner.dialog-theme { + box-shadow: 0 0 0 0.5em #f0f0f0, 0 0 1px 0.5em rgba(0, 0, 0, 0.3); + border-radius: 100%; + + background: #f0f0f0; + border: 0.2em solid transparent; + border-top-color: #bbbbbb; + top: -1.1em; + bottom: auto; +} \ No newline at end of file diff --git a/css/forms.css b/css/forms.css new file mode 100644 index 0000000..e22bee6 --- /dev/null +++ b/css/forms.css @@ -0,0 +1,99 @@ +/** + * Forms + */ + +/** inputs **/ +textarea, input[type="date"], input[type="datetime"], +input[type="datetime-local"], input[type="email"], input[type="month"], +input[type="number"], input[type="password"], input[type="search"], +input[type="tel"], input[type="text"], input[type="time"], +input[type="url"], input[type="week"] { + background: white; + width: 100%; + margin: 0 0 0.25em; + padding: 0.25em 0.67em; + border: 0; + + font-family: inherit; + font-weight: inherit; + font-size: inherit; + min-height: 2.5em; +} + +textarea:focus, input[type="date"]:focus, input[type="datetime"]:focus, +input[type="datetime-local"]:focus, input[type="email"]:focus, +input[type="month"]:focus, input[type="number"]:focus, +input[type="password"]:focus, input[type="search"]:focus, +input[type="tel"]:focus, input[type="text"]:focus, input[type="time"]:focus, +input[type="url"]:focus, input[type="week"]:focus { + box-shadow: inset 0 0 0 2px #8dbdf1; + outline: none; +} + +/** buttons **/ +.bt { + margin: 0 0.5em; + + font-family: inherit; + text-transform: uppercase; + letter-spacing: 0.1em; + + font-size: 0.8em; + line-height: 1em; + + padding: 0.75em 2em; +} + +/* primary button */ +.bt.primary { + border: 1px solid #e0e0e0; + background: transparent; + color: #e0e0e0; +} + +.bt.primary.inverse { + border-color: #262626; + color: #262626; +} + +.bt.primary:hover { + background: rgba(255, 255, 255, 0.1); +} + +.bt.primary.inverse:hover { + background: rgba(0, 0, 0, 0.1); +} + +.bt.primary:active, .bt.secondary:active { + background: #e0e0e0; + color: #262626; +} + +.bt.primary.inverse:active, .bt.secondary.inverse:active { + background: #262626; + color: #e0e0e0; +} + +/* secondary button */ +.bt.secondary { + border: 1px solid transparent; + background: transparent; + color: #e0e0e0; +} + +.bt.secondary.inverse { + color: #262626; +} + +.bt.secondary:hover, .bt.secondary:active { + border: 1px solid #e0e0e0; +} + +.bt.secondary.inverse:hover, .bt.secondary.inverse:active { + border-color: #262626; +} + +.bt.secondary:active { + background: #e0e0e0; + color: #262626; +} \ No newline at end of file diff --git a/css/lib/vex/vex-theme-bottom-right-corner.css b/css/lib/vex/vex-theme-bottom-right-corner.css new file mode 100644 index 0000000..237aa09 --- /dev/null +++ b/css/lib/vex/vex-theme-bottom-right-corner.css @@ -0,0 +1,631 @@ +@keyframes vex-slideup { + /* line 83, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 0; + } + + /* line 86, ../sass/_keyframes.sass */ + 1% { + transform: translateY(800px); + -webkit-transform: translateY(800px); + -moz-transform: translateY(800px); + -ms-transform: translateY(800px); + -o-transform: translateY(800px); + opacity: 0; + } + + /* line 91, ../sass/_keyframes.sass */ + 2% { + transform: translateY(800px); + -webkit-transform: translateY(800px); + -moz-transform: translateY(800px); + -ms-transform: translateY(800px); + -o-transform: translateY(800px); + opacity: 1; + } + + /* line 94, ../sass/_keyframes.sass */ + 100% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 1; + } +} + +@-webkit-keyframes vex-slideup { + /* line 83, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 0; + } + + /* line 86, ../sass/_keyframes.sass */ + 1% { + transform: translateY(800px); + -webkit-transform: translateY(800px); + -moz-transform: translateY(800px); + -ms-transform: translateY(800px); + -o-transform: translateY(800px); + opacity: 0; + } + + /* line 91, ../sass/_keyframes.sass */ + 2% { + transform: translateY(800px); + -webkit-transform: translateY(800px); + -moz-transform: translateY(800px); + -ms-transform: translateY(800px); + -o-transform: translateY(800px); + opacity: 1; + } + + /* line 94, ../sass/_keyframes.sass */ + 100% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 1; + } +} + +@-moz-keyframes vex-slideup { + /* line 83, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 0; + } + + /* line 86, ../sass/_keyframes.sass */ + 1% { + transform: translateY(800px); + -webkit-transform: translateY(800px); + -moz-transform: translateY(800px); + -ms-transform: translateY(800px); + -o-transform: translateY(800px); + opacity: 0; + } + + /* line 91, ../sass/_keyframes.sass */ + 2% { + transform: translateY(800px); + -webkit-transform: translateY(800px); + -moz-transform: translateY(800px); + -ms-transform: translateY(800px); + -o-transform: translateY(800px); + opacity: 1; + } + + /* line 94, ../sass/_keyframes.sass */ + 100% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 1; + } +} + +@-ms-keyframes vex-slideup { + /* line 83, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 0; + } + + /* line 86, ../sass/_keyframes.sass */ + 1% { + transform: translateY(800px); + -webkit-transform: translateY(800px); + -moz-transform: translateY(800px); + -ms-transform: translateY(800px); + -o-transform: translateY(800px); + opacity: 0; + } + + /* line 91, ../sass/_keyframes.sass */ + 2% { + transform: translateY(800px); + -webkit-transform: translateY(800px); + -moz-transform: translateY(800px); + -ms-transform: translateY(800px); + -o-transform: translateY(800px); + opacity: 1; + } + + /* line 94, ../sass/_keyframes.sass */ + 100% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 1; + } +} + +@-o-keyframes vex-slideup { + /* line 83, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 0; + } + + /* line 86, ../sass/_keyframes.sass */ + 1% { + transform: translateY(800px); + -webkit-transform: translateY(800px); + -moz-transform: translateY(800px); + -ms-transform: translateY(800px); + -o-transform: translateY(800px); + opacity: 0; + } + + /* line 91, ../sass/_keyframes.sass */ + 2% { + transform: translateY(800px); + -webkit-transform: translateY(800px); + -moz-transform: translateY(800px); + -ms-transform: translateY(800px); + -o-transform: translateY(800px); + opacity: 1; + } + + /* line 94, ../sass/_keyframes.sass */ + 100% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 1; + } +} + +@keyframes vex-slidedown { + /* line 100, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 102, ../sass/_keyframes.sass */ + 100% { + transform: translateY(800px); + -webkit-transform: translateY(800px); + -moz-transform: translateY(800px); + -ms-transform: translateY(800px); + -o-transform: translateY(800px); + } +} + +@-webkit-keyframes vex-slidedown { + /* line 100, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 102, ../sass/_keyframes.sass */ + 100% { + transform: translateY(800px); + -webkit-transform: translateY(800px); + -moz-transform: translateY(800px); + -ms-transform: translateY(800px); + -o-transform: translateY(800px); + } +} + +@-moz-keyframes vex-slidedown { + /* line 100, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 102, ../sass/_keyframes.sass */ + 100% { + transform: translateY(800px); + -webkit-transform: translateY(800px); + -moz-transform: translateY(800px); + -ms-transform: translateY(800px); + -o-transform: translateY(800px); + } +} + +@-ms-keyframes vex-slidedown { + /* line 100, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 102, ../sass/_keyframes.sass */ + 100% { + transform: translateY(800px); + -webkit-transform: translateY(800px); + -moz-transform: translateY(800px); + -ms-transform: translateY(800px); + -o-transform: translateY(800px); + } +} + +@-o-keyframes vex-slidedown { + /* line 100, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 102, ../sass/_keyframes.sass */ + 100% { + transform: translateY(800px); + -webkit-transform: translateY(800px); + -moz-transform: translateY(800px); + -ms-transform: translateY(800px); + -o-transform: translateY(800px); + } +} + +@keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-webkit-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-moz-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-ms-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-o-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +/* line 13, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner { + top: auto; + bottom: 0; + right: 0; + overflow: visible; +} +/* line 19, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-overlay { + display: none; +} +/* line 22, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner.vex-closing .vex-content { + animation: vex-slidedown 0.5s; + -webkit-animation: vex-slidedown 0.5s; + -moz-animation: vex-slidedown 0.5s; + -ms-animation: vex-slidedown 0.5s; + -o-animation: vex-slidedown 0.5s; + -webkit-backface-visibility: hidden; +} +/* line 25, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-content { + animation: vex-slideup 0.5s; + -webkit-animation: vex-slideup 0.5s; + -moz-animation: vex-slideup 0.5s; + -ms-animation: vex-slideup 0.5s; + -o-animation: vex-slideup 0.5s; + -webkit-backface-visibility: hidden; +} +/* line 28, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-content { + -webkit-border-radius: 5px 0 0 0; + -moz-border-radius: 5px 0 0 0; + -ms-border-radius: 5px 0 0 0; + -o-border-radius: 5px 0 0 0; + border-radius: 5px 0 0 0; + font-family: "Helvetica Neue", sans-serif; + background: #f0f0f0; + color: #444444; + padding: 1em; + max-width: 100%; + width: 450px; + font-size: 1.1em; + line-height: 1.5em; + position: fixed; + bottom: 0; + right: 0; + left: auto; +} +/* line 43, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-content h1, .vex.vex-theme-bottom-right-corner .vex-content h2, .vex.vex-theme-bottom-right-corner .vex-content h3, .vex.vex-theme-bottom-right-corner .vex-content h4, .vex.vex-theme-bottom-right-corner .vex-content h5, .vex.vex-theme-bottom-right-corner .vex-content h6, .vex.vex-theme-bottom-right-corner .vex-content p, .vex.vex-theme-bottom-right-corner .vex-content ul, .vex.vex-theme-bottom-right-corner .vex-content li { + color: inherit; +} +/* line 46, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-close { + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -ms-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; + position: absolute; + top: 0; + right: 0; + cursor: pointer; +} +/* line 53, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-close:before { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + position: absolute; + content: "\00D7"; + font-size: 26px; + font-weight: normal; + line-height: 31px; + height: 30px; + width: 30px; + text-align: center; + top: 3px; + right: 3px; + color: #bbbbbb; + background: transparent; +} +/* line 68, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-close:hover:before, .vex.vex-theme-bottom-right-corner .vex-close:active:before { + color: #777777; + background: #e0e0e0; +} +/* line 74, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-message { + margin-bottom: 0.5em; +} +/* line 77, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input { + margin-bottom: 1em; +} +/* line 80, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input textarea, .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="date"], .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="datetime"], .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="datetime-local"], .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="email"], .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="month"], .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="number"], .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="password"], .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="search"], .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="tel"], .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="text"], .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="time"], .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="url"], .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="week"] { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + background: white; + width: 100%; + padding: 0.25em 0.67em; + border: 0; + font-family: inherit; + font-weight: inherit; + font-size: inherit; + min-height: 2.5em; + margin: 0 0 0.25em; +} +/* line 92, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input textarea:focus, .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="date"]:focus, .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="datetime"]:focus, .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="datetime-local"]:focus, .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="email"]:focus, .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="month"]:focus, .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="number"]:focus, .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="password"]:focus, .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="search"]:focus, .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="tel"]:focus, .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="text"]:focus, .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="time"]:focus, .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="url"]:focus, .vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-input input[type="week"]:focus { + -webkit-box-shadow: inset 0 0 0 2px #8dbdf1; + -moz-box-shadow: inset 0 0 0 2px #8dbdf1; + box-shadow: inset 0 0 0 2px #8dbdf1; + outline: none; +} +/* line 96, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-buttons { + *zoom: 1; +} +/* line 38, ../../../../../.rvm/gems/ruby-1.9.3-p194/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss */ +.vex.vex-theme-bottom-right-corner .vex-dialog-form .vex-dialog-buttons:after { + content: ""; + display: table; + clear: both; +} +/* line 99, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-dialog-button { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + border: 0; + float: right; + margin: 0 0 0 0.5em; + font-family: inherit; + text-transform: uppercase; + letter-spacing: 0.1em; + font-size: 0.8em; + line-height: 1em; + padding: 0.75em 2em; +} +/* line 111, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-dialog-button.vex-last { + margin-left: 0; +} +/* line 114, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-dialog-button:focus { + animation: vex-pulse 1.1s infinite; + -webkit-animation: vex-pulse 1.1s infinite; + -moz-animation: vex-pulse 1.1s infinite; + -ms-animation: vex-pulse 1.1s infinite; + -o-animation: vex-pulse 1.1s infinite; + -webkit-backface-visibility: hidden; + outline: none; +} +@media (max-width: 568px) { + /* line 114, ../sass/vex-theme-bottom-right-corner.sass */ + .vex.vex-theme-bottom-right-corner .vex-dialog-button:focus { + animation: none; + -webkit-animation: none; + -moz-animation: none; + -ms-animation: none; + -o-animation: none; + -webkit-backface-visibility: hidden; + } +} +/* line 123, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-dialog-button.vex-dialog-button-primary { + background: #3288e6; + color: white; +} +/* line 127, ../sass/vex-theme-bottom-right-corner.sass */ +.vex.vex-theme-bottom-right-corner .vex-dialog-button.vex-dialog-button-secondary { + background: #e0e0e0; + color: #777777; +} + +/* line 131, ../sass/vex-theme-bottom-right-corner.sass */ +.vex-loading-spinner.vex-theme-bottom-right-corner { + -webkit-box-shadow: 0 0 0 0.5em #f0f0f0, 0 0 1px 0.5em rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 0 0 0.5em #f0f0f0, 0 0 1px 0.5em rgba(0, 0, 0, 0.3); + box-shadow: 0 0 0 0.5em #f0f0f0, 0 0 1px 0.5em rgba(0, 0, 0, 0.3); + -webkit-border-radius: 100%; + -moz-border-radius: 100%; + -ms-border-radius: 100%; + -o-border-radius: 100%; + border-radius: 100%; + background: #f0f0f0; + border: 0.2em solid transparent; + border-top-color: #bbbbbb; + top: -1.1em; + bottom: auto; +} + +/* line 140, ../sass/vex-theme-bottom-right-corner.sass */ +body.vex-open { + overflow: initial; +} diff --git a/css/lib/vex/vex-theme-default.css b/css/lib/vex/vex-theme-default.css new file mode 100644 index 0000000..83a1f8f --- /dev/null +++ b/css/lib/vex/vex-theme-default.css @@ -0,0 +1,528 @@ +@keyframes vex-flyin { + /* line 25, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } + + /* line 28, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } +} + +@-webkit-keyframes vex-flyin { + /* line 25, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } + + /* line 28, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } +} + +@-moz-keyframes vex-flyin { + /* line 25, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } + + /* line 28, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } +} + +@-ms-keyframes vex-flyin { + /* line 25, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } + + /* line 28, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } +} + +@-o-keyframes vex-flyin { + /* line 25, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } + + /* line 28, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } +} + +@keyframes vex-flyout { + /* line 34, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 37, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } +} + +@-webkit-keyframes vex-flyout { + /* line 34, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 37, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } +} + +@-moz-keyframes vex-flyout { + /* line 34, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 37, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } +} + +@-ms-keyframes vex-flyout { + /* line 34, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 37, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } +} + +@-o-keyframes vex-flyout { + /* line 34, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 37, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } +} + +@keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-webkit-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-moz-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-ms-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-o-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +/* line 13, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default { + padding-top: 160px; + padding-bottom: 160px; +} +/* line 17, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default.vex-closing .vex-content { + animation: vex-flyout 0.5s; + -webkit-animation: vex-flyout 0.5s; + -moz-animation: vex-flyout 0.5s; + -ms-animation: vex-flyout 0.5s; + -o-animation: vex-flyout 0.5s; + -webkit-backface-visibility: hidden; +} +/* line 20, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-content { + animation: vex-flyin 0.5s; + -webkit-animation: vex-flyin 0.5s; + -moz-animation: vex-flyin 0.5s; + -ms-animation: vex-flyin 0.5s; + -o-animation: vex-flyin 0.5s; + -webkit-backface-visibility: hidden; +} +/* line 23, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-content { + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -ms-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; + font-family: "Helvetica Neue", sans-serif; + background: #f0f0f0; + color: #444444; + padding: 1em; + position: relative; + margin: 0 auto; + max-width: 100%; + width: 450px; + font-size: 1.1em; + line-height: 1.5em; +} +/* line 36, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-content h1, .vex.vex-theme-default .vex-content h2, .vex.vex-theme-default .vex-content h3, .vex.vex-theme-default .vex-content h4, .vex.vex-theme-default .vex-content h5, .vex.vex-theme-default .vex-content h6, .vex.vex-theme-default .vex-content p, .vex.vex-theme-default .vex-content ul, .vex.vex-theme-default .vex-content li { + color: inherit; +} +/* line 39, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-close { + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -ms-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; + position: absolute; + top: 0; + right: 0; + cursor: pointer; +} +/* line 46, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-close:before { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + position: absolute; + content: "\00D7"; + font-size: 26px; + font-weight: normal; + line-height: 31px; + height: 30px; + width: 30px; + text-align: center; + top: 3px; + right: 3px; + color: #bbbbbb; + background: transparent; +} +/* line 61, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-close:hover:before, .vex.vex-theme-default .vex-close:active:before { + color: #777777; + background: #e0e0e0; +} +/* line 67, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-dialog-form .vex-dialog-message { + margin-bottom: 0.5em; +} +/* line 70, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-dialog-form .vex-dialog-input { + margin-bottom: 1em; +} +/* line 73, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-dialog-form .vex-dialog-input textarea, .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="date"], .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="datetime"], .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="datetime-local"], .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="email"], .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="month"], .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="number"], .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="password"], .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="search"], .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="tel"], .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="text"], .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="time"], .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="url"], .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="week"] { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + background: white; + width: 100%; + padding: 0.25em 0.67em; + border: 0; + font-family: inherit; + font-weight: inherit; + font-size: inherit; + min-height: 2.5em; + margin: 0 0 0.25em; +} +/* line 85, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-dialog-form .vex-dialog-input textarea:focus, .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="date"]:focus, .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="datetime"]:focus, .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="datetime-local"]:focus, .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="email"]:focus, .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="month"]:focus, .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="number"]:focus, .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="password"]:focus, .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="search"]:focus, .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="tel"]:focus, .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="text"]:focus, .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="time"]:focus, .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="url"]:focus, .vex.vex-theme-default .vex-dialog-form .vex-dialog-input input[type="week"]:focus { + -webkit-box-shadow: inset 0 0 0 2px #8dbdf1; + -moz-box-shadow: inset 0 0 0 2px #8dbdf1; + box-shadow: inset 0 0 0 2px #8dbdf1; + outline: none; +} +/* line 89, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-dialog-form .vex-dialog-buttons { + *zoom: 1; +} +/* line 38, ../../../../../.rvm/gems/ruby-1.9.3-p194/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss */ +.vex.vex-theme-default .vex-dialog-form .vex-dialog-buttons:after { + content: ""; + display: table; + clear: both; +} +/* line 92, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-dialog-button { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + border: 0; + float: right; + margin: 0 0 0 0.5em; + font-family: inherit; + text-transform: uppercase; + letter-spacing: 0.1em; + font-size: 0.8em; + line-height: 1em; + padding: 0.75em 2em; +} +/* line 104, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-dialog-button.vex-last { + margin-left: 0; +} +/* line 107, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-dialog-button:focus { + animation: vex-pulse 1.1s infinite; + -webkit-animation: vex-pulse 1.1s infinite; + -moz-animation: vex-pulse 1.1s infinite; + -ms-animation: vex-pulse 1.1s infinite; + -o-animation: vex-pulse 1.1s infinite; + -webkit-backface-visibility: hidden; + outline: none; +} +@media (max-width: 568px) { + /* line 107, ../sass/vex-theme-default.sass */ + .vex.vex-theme-default .vex-dialog-button:focus { + animation: none; + -webkit-animation: none; + -moz-animation: none; + -ms-animation: none; + -o-animation: none; + -webkit-backface-visibility: hidden; + } +} +/* line 116, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-dialog-button.vex-dialog-button-primary { + background: #3288e6; + color: white; +} +/* line 120, ../sass/vex-theme-default.sass */ +.vex.vex-theme-default .vex-dialog-button.vex-dialog-button-secondary { + background: #e0e0e0; + color: #777777; +} + +/* line 124, ../sass/vex-theme-default.sass */ +.vex-loading-spinner.vex-theme-default { + -webkit-box-shadow: 0 0 0 0.5em #f0f0f0, 0 0 1px 0.5em rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 0 0 0.5em #f0f0f0, 0 0 1px 0.5em rgba(0, 0, 0, 0.3); + box-shadow: 0 0 0 0.5em #f0f0f0, 0 0 1px 0.5em rgba(0, 0, 0, 0.3); + -webkit-border-radius: 100%; + -moz-border-radius: 100%; + -ms-border-radius: 100%; + -o-border-radius: 100%; + border-radius: 100%; + background: #f0f0f0; + border: 0.2em solid transparent; + border-top-color: #bbbbbb; + top: -1.1em; + bottom: auto; +} diff --git a/css/lib/vex/vex-theme-flat-attack.css b/css/lib/vex/vex-theme-flat-attack.css new file mode 100644 index 0000000..6e41dd6 --- /dev/null +++ b/css/lib/vex/vex-theme-flat-attack.css @@ -0,0 +1,461 @@ +@keyframes vex-flipin-horizontal { + /* line 107, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + transform: rotateY(-90deg); + -webkit-transform: rotateY(-90deg); + -moz-transform: rotateY(-90deg); + -ms-transform: rotateY(-90deg); + -o-transform: rotateY(-90deg); + } + + /* line 110, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -o-transform: rotateY(0deg); + } +} + +@-webkit-keyframes vex-flipin-horizontal { + /* line 107, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + transform: rotateY(-90deg); + -webkit-transform: rotateY(-90deg); + -moz-transform: rotateY(-90deg); + -ms-transform: rotateY(-90deg); + -o-transform: rotateY(-90deg); + } + + /* line 110, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -o-transform: rotateY(0deg); + } +} + +@-moz-keyframes vex-flipin-horizontal { + /* line 107, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + transform: rotateY(-90deg); + -webkit-transform: rotateY(-90deg); + -moz-transform: rotateY(-90deg); + -ms-transform: rotateY(-90deg); + -o-transform: rotateY(-90deg); + } + + /* line 110, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -o-transform: rotateY(0deg); + } +} + +@-ms-keyframes vex-flipin-horizontal { + /* line 107, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + transform: rotateY(-90deg); + -webkit-transform: rotateY(-90deg); + -moz-transform: rotateY(-90deg); + -ms-transform: rotateY(-90deg); + -o-transform: rotateY(-90deg); + } + + /* line 110, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -o-transform: rotateY(0deg); + } +} + +@-o-keyframes vex-flipin-horizontal { + /* line 107, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + transform: rotateY(-90deg); + -webkit-transform: rotateY(-90deg); + -moz-transform: rotateY(-90deg); + -ms-transform: rotateY(-90deg); + -o-transform: rotateY(-90deg); + } + + /* line 110, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -o-transform: rotateY(0deg); + } +} + +@keyframes vex-flipout-horizontal { + /* line 116, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -o-transform: rotateY(0deg); + } + + /* line 119, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -o-transform: rotateY(90deg); + } +} + +@-webkit-keyframes vex-flipout-horizontal { + /* line 116, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -o-transform: rotateY(0deg); + } + + /* line 119, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -o-transform: rotateY(90deg); + } +} + +@-moz-keyframes vex-flipout-horizontal { + /* line 116, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -o-transform: rotateY(0deg); + } + + /* line 119, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -o-transform: rotateY(90deg); + } +} + +@-ms-keyframes vex-flipout-horizontal { + /* line 116, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -o-transform: rotateY(0deg); + } + + /* line 119, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -o-transform: rotateY(90deg); + } +} + +@-o-keyframes vex-flipout-horizontal { + /* line 116, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + transform: rotateY(0deg); + -webkit-transform: rotateY(0deg); + -moz-transform: rotateY(0deg); + -ms-transform: rotateY(0deg); + -o-transform: rotateY(0deg); + } + + /* line 119, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + transform: rotateY(90deg); + -webkit-transform: rotateY(90deg); + -moz-transform: rotateY(90deg); + -ms-transform: rotateY(90deg); + -o-transform: rotateY(90deg); + } +} + +/* line 31, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack { + -webkit-perspective: 1300px; + -moz-perspective: 1300px; + -ms-perspective: 1300px; + -o-perspective: 1300px; + perspective: 1300px; + -webkit-perspective-origin: 50% 150px; + -moz-perspective-origin: 50% 150px; + -ms-perspective-origin: 50% 150px; + -o-perspective-origin: 50% 150px; + perspective-origin: 50% 150px; + padding-top: 100px; + padding-bottom: 100px; + font-size: 1.5em; +} +/* line 38, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack.vex-closing .vex-content { + animation: vex-flipout-horizontal 0.5s; + -webkit-animation: vex-flipout-horizontal 0.5s; + -moz-animation: vex-flipout-horizontal 0.5s; + -ms-animation: vex-flipout-horizontal 0.5s; + -o-animation: vex-flipout-horizontal 0.5s; + -webkit-backface-visibility: hidden; +} +/* line 41, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-content { + -webkit-transform-style: preserve-3d; + -moz-transform-style: preserve-3d; + transform-style: preserve-3d; + animation: vex-flipin-horizontal 0.5s; + -webkit-animation: vex-flipin-horizontal 0.5s; + -moz-animation: vex-flipin-horizontal 0.5s; + -ms-animation: vex-flipin-horizontal 0.5s; + -o-animation: vex-flipin-horizontal 0.5s; + -webkit-backface-visibility: hidden; +} +/* line 45, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-content { + font-family: "Helvetica Neue", sans-serif; + font-weight: 200; + background: white; + color: #444444; + padding: 2em 2em 3em 2em; + line-height: 1.5em; + position: relative; + margin: 0 auto; + max-width: 100%; + width: 600px; +} +/* line 57, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-content h1, .vex.vex-theme-flat-attack .vex-content h2, .vex.vex-theme-flat-attack .vex-content h3, .vex.vex-theme-flat-attack .vex-content h4, .vex.vex-theme-flat-attack .vex-content h5, .vex.vex-theme-flat-attack .vex-content h6, .vex.vex-theme-flat-attack .vex-content p, .vex.vex-theme-flat-attack .vex-content ul, .vex.vex-theme-flat-attack .vex-content li { + color: inherit; +} +/* line 60, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-close { + position: absolute; + top: 0; + right: 0; + cursor: pointer; +} +/* line 66, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-close:before { + font-family: "Helvetica Neue", sans-serif; + font-weight: 100; + line-height: 1px; + padding-top: 0.5em; + display: block; + font-size: 2em; + text-indent: 1px; + overflow: hidden; + height: 1.25em; + width: 1.25em; + text-align: center; + top: 0; + right: 0; + color: white; + background: #666666; +} +/* line 85, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-message { + margin-bottom: 0.5em; +} +/* line 88, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input { + margin-bottom: 0.5em; +} +/* line 91, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input textarea, .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="date"], .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="datetime"], .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="datetime-local"], .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="email"], .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="month"], .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="number"], .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="password"], .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="search"], .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="tel"], .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="text"], .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="time"], .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="url"], .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="week"] { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + background: #f0f0f0; + width: 100%; + padding: 0.25em 0.67em; + border: 0; + font-family: inherit; + font-weight: inherit; + font-size: inherit; + min-height: 2.5em; + margin: 0 0 0.25em; +} +/* line 103, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input textarea:focus, .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="date"]:focus, .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="datetime"]:focus, .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="datetime-local"]:focus, .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="email"]:focus, .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="month"]:focus, .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="number"]:focus, .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="password"]:focus, .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="search"]:focus, .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="tel"]:focus, .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="text"]:focus, .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="time"]:focus, .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="url"]:focus, .vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-input input[type="week"]:focus { + -webkit-box-shadow: inset 0 0 0 2px #666666; + -moz-box-shadow: inset 0 0 0 2px #666666; + box-shadow: inset 0 0 0 2px #666666; + outline: none; +} +/* line 107, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-buttons { + *zoom: 1; + padding-top: 1em; + margin-bottom: -3em; + margin-left: -2em; + margin-right: -2em; +} +/* line 38, ../../../../../.rvm/gems/ruby-1.9.3-p194/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss */ +.vex.vex-theme-flat-attack .vex-dialog-form .vex-dialog-buttons:after { + content: ""; + display: table; + clear: both; +} +/* line 114, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-dialog-button { + -webkit-border-radius: 0; + -moz-border-radius: 0; + -ms-border-radius: 0; + -o-border-radius: 0; + border-radius: 0; + border: 0; + margin: 0; + float: right; + padding: 0.5em 1em; + font-size: 1.13em; + text-transform: uppercase; + font-weight: 200; + letter-spacing: 0.1em; + line-height: 1em; + font-family: inherit; +} +/* line 127, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-dialog-button.vex-last { + margin-left: 0; +} +/* line 130, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-dialog-button:focus { + outline: none; +} +/* line 133, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-dialog-button.vex-dialog-button-primary { + background: #666666; + color: white; +} +/* line 137, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-dialog-button.vex-dialog-button-primary:focus { + -webkit-box-shadow: inset 0 3px rgba(0, 0, 0, 0.2); + -moz-box-shadow: inset 0 3px rgba(0, 0, 0, 0.2); + box-shadow: inset 0 3px rgba(0, 0, 0, 0.2); +} +/* line 140, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-dialog-button.vex-dialog-button-secondary { + background: white; + color: #cccccc; +} +/* line 144, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-dialog-button.vex-dialog-button-secondary:focus { + -webkit-box-shadow: inset 0 3px #aaaaaa; + -moz-box-shadow: inset 0 3px #aaaaaa; + box-shadow: inset 0 3px #aaaaaa; + background: #eeeeee; + color: #777777; +} +/* line 149, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack .vex-dialog-button.vex-dialog-button-secondary:hover, .vex.vex-theme-flat-attack .vex-dialog-button.vex-dialog-button-secondary:active { + color: #777777; +} +/* line 16, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-close:before { + background: #ff7ea7; +} +/* line 25, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-dialog-form .vex-dialog-input textarea:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-dialog-form .vex-dialog-input input[type="date"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-dialog-form .vex-dialog-input input[type="datetime"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-dialog-form .vex-dialog-input input[type="datetime-local"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-dialog-form .vex-dialog-input input[type="email"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-dialog-form .vex-dialog-input input[type="month"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-dialog-form .vex-dialog-input input[type="number"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-dialog-form .vex-dialog-input input[type="password"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-dialog-form .vex-dialog-input input[type="search"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-dialog-form .vex-dialog-input input[type="tel"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-dialog-form .vex-dialog-input input[type="text"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-dialog-form .vex-dialog-input input[type="time"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-dialog-form .vex-dialog-input input[type="url"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-dialog-form .vex-dialog-input input[type="week"]:focus { + -webkit-box-shadow: inset 0 0 0 2px #ff7ea7; + -moz-box-shadow: inset 0 0 0 2px #ff7ea7; + box-shadow: inset 0 0 0 2px #ff7ea7; +} +/* line 28, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack.vex-theme-flat-attack-pink .vex-dialog-form .vex-dialog-buttons .vex-dialog-button.vex-dialog-button-primary { + background: #ff7ea7; +} +/* line 16, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-close:before { + background: #ce4a55; +} +/* line 25, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-dialog-form .vex-dialog-input textarea:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-dialog-form .vex-dialog-input input[type="date"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-dialog-form .vex-dialog-input input[type="datetime"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-dialog-form .vex-dialog-input input[type="datetime-local"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-dialog-form .vex-dialog-input input[type="email"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-dialog-form .vex-dialog-input input[type="month"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-dialog-form .vex-dialog-input input[type="number"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-dialog-form .vex-dialog-input input[type="password"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-dialog-form .vex-dialog-input input[type="search"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-dialog-form .vex-dialog-input input[type="tel"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-dialog-form .vex-dialog-input input[type="text"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-dialog-form .vex-dialog-input input[type="time"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-dialog-form .vex-dialog-input input[type="url"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-dialog-form .vex-dialog-input input[type="week"]:focus { + -webkit-box-shadow: inset 0 0 0 2px #ce4a55; + -moz-box-shadow: inset 0 0 0 2px #ce4a55; + box-shadow: inset 0 0 0 2px #ce4a55; +} +/* line 28, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack.vex-theme-flat-attack-red .vex-dialog-form .vex-dialog-buttons .vex-dialog-button.vex-dialog-button-primary { + background: #ce4a55; +} +/* line 16, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-close:before { + background: #34b989; +} +/* line 25, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-dialog-form .vex-dialog-input textarea:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-dialog-form .vex-dialog-input input[type="date"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-dialog-form .vex-dialog-input input[type="datetime"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-dialog-form .vex-dialog-input input[type="datetime-local"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-dialog-form .vex-dialog-input input[type="email"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-dialog-form .vex-dialog-input input[type="month"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-dialog-form .vex-dialog-input input[type="number"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-dialog-form .vex-dialog-input input[type="password"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-dialog-form .vex-dialog-input input[type="search"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-dialog-form .vex-dialog-input input[type="tel"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-dialog-form .vex-dialog-input input[type="text"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-dialog-form .vex-dialog-input input[type="time"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-dialog-form .vex-dialog-input input[type="url"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-dialog-form .vex-dialog-input input[type="week"]:focus { + -webkit-box-shadow: inset 0 0 0 2px #34b989; + -moz-box-shadow: inset 0 0 0 2px #34b989; + box-shadow: inset 0 0 0 2px #34b989; +} +/* line 28, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack.vex-theme-flat-attack-green .vex-dialog-form .vex-dialog-buttons .vex-dialog-button.vex-dialog-button-primary { + background: #34b989; +} +/* line 16, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-close:before { + background: #477fa5; +} +/* line 25, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-dialog-form .vex-dialog-input textarea:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-dialog-form .vex-dialog-input input[type="date"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-dialog-form .vex-dialog-input input[type="datetime"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-dialog-form .vex-dialog-input input[type="datetime-local"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-dialog-form .vex-dialog-input input[type="email"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-dialog-form .vex-dialog-input input[type="month"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-dialog-form .vex-dialog-input input[type="number"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-dialog-form .vex-dialog-input input[type="password"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-dialog-form .vex-dialog-input input[type="search"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-dialog-form .vex-dialog-input input[type="tel"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-dialog-form .vex-dialog-input input[type="text"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-dialog-form .vex-dialog-input input[type="time"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-dialog-form .vex-dialog-input input[type="url"]:focus, .vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-dialog-form .vex-dialog-input input[type="week"]:focus { + -webkit-box-shadow: inset 0 0 0 2px #477fa5; + -moz-box-shadow: inset 0 0 0 2px #477fa5; + box-shadow: inset 0 0 0 2px #477fa5; +} +/* line 28, ../sass/vex-theme-flat-attack.sass */ +.vex.vex-theme-flat-attack.vex-theme-flat-attack-blue .vex-dialog-form .vex-dialog-buttons .vex-dialog-button.vex-dialog-button-primary { + background: #477fa5; +} + +/* line 166, ../sass/vex-theme-flat-attack.sass */ +.vex-loading-spinner.vex-theme-flat-attack { + height: 4em; + width: 4em; +} diff --git a/css/lib/vex/vex-theme-os.css b/css/lib/vex/vex-theme-os.css new file mode 100644 index 0000000..5a3a336 --- /dev/null +++ b/css/lib/vex/vex-theme-os.css @@ -0,0 +1,533 @@ +@keyframes vex-flyin { + /* line 25, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } + + /* line 28, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } +} + +@-webkit-keyframes vex-flyin { + /* line 25, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } + + /* line 28, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } +} + +@-moz-keyframes vex-flyin { + /* line 25, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } + + /* line 28, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } +} + +@-ms-keyframes vex-flyin { + /* line 25, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } + + /* line 28, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } +} + +@-o-keyframes vex-flyin { + /* line 25, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } + + /* line 28, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } +} + +@keyframes vex-flyout { + /* line 34, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 37, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } +} + +@-webkit-keyframes vex-flyout { + /* line 34, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 37, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } +} + +@-moz-keyframes vex-flyout { + /* line 34, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 37, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } +} + +@-ms-keyframes vex-flyout { + /* line 34, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 37, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } +} + +@-o-keyframes vex-flyout { + /* line 34, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 37, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + transform: translateY(-40px); + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + } +} + +@keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-webkit-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-moz-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-ms-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-o-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +/* line 13, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os { + padding-top: 160px; + padding-bottom: 160px; +} +/* line 17, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os.vex-closing .vex-content { + animation: vex-flyout 0.5s; + -webkit-animation: vex-flyout 0.5s; + -moz-animation: vex-flyout 0.5s; + -ms-animation: vex-flyout 0.5s; + -o-animation: vex-flyout 0.5s; + -webkit-backface-visibility: hidden; +} +/* line 20, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-content { + animation: vex-flyin 0.5s; + -webkit-animation: vex-flyin 0.5s; + -moz-animation: vex-flyin 0.5s; + -ms-animation: vex-flyin 0.5s; + -o-animation: vex-flyin 0.5s; + -webkit-backface-visibility: hidden; +} +/* line 23, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-content { + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -ms-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; + -webkit-box-shadow: inset 0 1px #a6a6a6, 0 0 0 1px rgba(0, 0, 0, 0.08); + -moz-box-shadow: inset 0 1px #a6a6a6, 0 0 0 1px rgba(0, 0, 0, 0.08); + box-shadow: inset 0 1px #a6a6a6, 0 0 0 1px rgba(0, 0, 0, 0.08); + font-family: "Helvetica Neue", sans-serif; + border-top: 20px solid #bbbbbb; + background: #f0f0f0; + color: #444444; + padding: 1em; + position: relative; + margin: 0 auto; + max-width: 100%; + width: 450px; + font-size: 1.1em; + line-height: 1.5em; +} +/* line 38, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-content h1, .vex.vex-theme-os .vex-content h2, .vex.vex-theme-os .vex-content h3, .vex.vex-theme-os .vex-content h4, .vex.vex-theme-os .vex-content h5, .vex.vex-theme-os .vex-content h6, .vex.vex-theme-os .vex-content p, .vex.vex-theme-os .vex-content ul, .vex.vex-theme-os .vex-content li { + color: inherit; +} +/* line 41, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-close { + -webkit-border-radius: 0 5px 0 0; + -moz-border-radius: 0 5px 0 0; + -ms-border-radius: 0 5px 0 0; + -o-border-radius: 0 5px 0 0; + border-radius: 0 5px 0 0; + position: absolute; + top: 0; + right: 0; + cursor: pointer; +} +/* line 48, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-close:before { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + position: absolute; + content: "\00D7"; + font-size: 26px; + font-weight: normal; + line-height: 31px; + height: 30px; + width: 30px; + text-align: center; + top: 3px; + right: 3px; + color: #bbbbbb; + background: transparent; +} +/* line 63, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-close:hover:before, .vex.vex-theme-os .vex-close:active:before { + color: #777777; + background: #e0e0e0; +} +/* line 69, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-dialog-form .vex-dialog-message { + margin-bottom: 0.5em; +} +/* line 72, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-dialog-form .vex-dialog-input { + margin-bottom: 1em; +} +/* line 75, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-dialog-form .vex-dialog-input textarea, .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="date"], .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="datetime"], .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="datetime-local"], .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="email"], .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="month"], .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="number"], .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="password"], .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="search"], .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="tel"], .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="text"], .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="time"], .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="url"], .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="week"] { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + background: white; + width: 100%; + padding: 0.25em 0.67em; + border: 0; + font-family: inherit; + font-weight: inherit; + font-size: inherit; + min-height: 2.5em; + margin: 0 0 0.25em; +} +/* line 87, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-dialog-form .vex-dialog-input textarea:focus, .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="date"]:focus, .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="datetime"]:focus, .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="datetime-local"]:focus, .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="email"]:focus, .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="month"]:focus, .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="number"]:focus, .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="password"]:focus, .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="search"]:focus, .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="tel"]:focus, .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="text"]:focus, .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="time"]:focus, .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="url"]:focus, .vex.vex-theme-os .vex-dialog-form .vex-dialog-input input[type="week"]:focus { + -webkit-box-shadow: inset 0 0 0 1px #3288e6; + -moz-box-shadow: inset 0 0 0 1px #3288e6; + box-shadow: inset 0 0 0 1px #3288e6; + outline: none; +} +/* line 91, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-dialog-form .vex-dialog-buttons { + *zoom: 1; +} +/* line 38, ../../../../../.rvm/gems/ruby-1.9.3-p194/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss */ +.vex.vex-theme-os .vex-dialog-form .vex-dialog-buttons:after { + content: ""; + display: table; + clear: both; +} +/* line 94, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-dialog-button { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + border: 0; + float: right; + margin: 0 0 0 0.5em; + font-family: inherit; + text-transform: uppercase; + letter-spacing: 0.1em; + font-size: 0.8em; + line-height: 1em; + padding: 0.75em 2em; +} +/* line 106, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-dialog-button.vex-last { + margin-left: 0; +} +/* line 109, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-dialog-button:focus { + animation: vex-pulse 1.1s infinite; + -webkit-animation: vex-pulse 1.1s infinite; + -moz-animation: vex-pulse 1.1s infinite; + -ms-animation: vex-pulse 1.1s infinite; + -o-animation: vex-pulse 1.1s infinite; + -webkit-backface-visibility: hidden; + outline: none; +} +@media (max-width: 568px) { + /* line 109, ../sass/vex-theme-os.sass */ + .vex.vex-theme-os .vex-dialog-button:focus { + animation: none; + -webkit-animation: none; + -moz-animation: none; + -ms-animation: none; + -o-animation: none; + -webkit-backface-visibility: hidden; + } +} +/* line 118, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-dialog-button.vex-dialog-button-primary { + background: #3288e6; + color: white; +} +/* line 122, ../sass/vex-theme-os.sass */ +.vex.vex-theme-os .vex-dialog-button.vex-dialog-button-secondary { + background: #e0e0e0; + color: #777777; +} + +/* line 126, ../sass/vex-theme-os.sass */ +.vex-loading-spinner.vex-theme-os { + -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2), 0 0 0.5em rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2), 0 0 0.5em rgba(0, 0, 0, 0.2); + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2), 0 0 0.5em rgba(0, 0, 0, 0.2); + -webkit-border-radius: 100%; + -moz-border-radius: 100%; + -ms-border-radius: 100%; + -o-border-radius: 100%; + border-radius: 100%; + background: rgba(255, 255, 255, 0.2); + width: 0; + height: 0; + border: 1.2em solid #bbbbbb; + border-top-color: #f0f0f0; + border-bottom-color: #f0f0f0; +} diff --git a/css/lib/vex/vex-theme-plain.css b/css/lib/vex/vex-theme-plain.css new file mode 100644 index 0000000..d4a3dc4 --- /dev/null +++ b/css/lib/vex/vex-theme-plain.css @@ -0,0 +1,259 @@ +@keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-webkit-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-moz-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-ms-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-o-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +/* line 11, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain { + padding-top: 160px; + padding-bottom: 160px; +} +/* line 15, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain .vex-content { + font-family: "Helvetica Neue", sans-serif; + background: white; + color: #444444; + padding: 1em; + position: relative; + margin: 0 auto; + max-width: 100%; + width: 450px; + font-size: 1.1em; + line-height: 1.5em; +} +/* line 27, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain .vex-content h1, .vex.vex-theme-plain .vex-content h2, .vex.vex-theme-plain .vex-content h3, .vex.vex-theme-plain .vex-content h4, .vex.vex-theme-plain .vex-content h5, .vex.vex-theme-plain .vex-content h6, .vex.vex-theme-plain .vex-content p, .vex.vex-theme-plain .vex-content ul, .vex.vex-theme-plain .vex-content li { + color: inherit; +} +/* line 30, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain .vex-close { + position: absolute; + top: 0; + right: 0; + cursor: pointer; +} +/* line 36, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain .vex-close:before { + position: absolute; + content: "\00D7"; + font-size: 26px; + font-weight: normal; + line-height: 31px; + height: 30px; + width: 30px; + text-align: center; + top: 3px; + right: 3px; + color: #bbbbbb; + background: transparent; +} +/* line 50, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain .vex-close:hover:before, .vex.vex-theme-plain .vex-close:active:before { + color: #777777; + background: #e0e0e0; +} +/* line 56, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain .vex-dialog-form .vex-dialog-message { + margin-bottom: 0.5em; +} +/* line 59, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain .vex-dialog-form .vex-dialog-input { + margin-bottom: 1em; +} +/* line 62, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain .vex-dialog-form .vex-dialog-input textarea, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="date"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="datetime"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="datetime-local"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="email"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="month"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="number"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="password"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="search"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="tel"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="text"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="time"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="url"], .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="week"] { + background: #f0f0f0; + width: 100%; + padding: 0.25em 0.67em; + border: 0; + font-family: inherit; + font-weight: inherit; + font-size: inherit; + min-height: 2.5em; + margin: 0 0 0.25em; +} +/* line 73, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain .vex-dialog-form .vex-dialog-input textarea:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="date"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="datetime"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="datetime-local"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="email"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="month"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="number"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="password"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="search"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="tel"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="text"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="time"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="url"]:focus, .vex.vex-theme-plain .vex-dialog-form .vex-dialog-input input[type="week"]:focus { + -webkit-box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.2); + -moz-box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.2); + box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.2); + outline: none; +} +/* line 77, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain .vex-dialog-form .vex-dialog-buttons { + *zoom: 1; +} +/* line 38, ../../../../../.rvm/gems/ruby-1.9.3-p194/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss */ +.vex.vex-theme-plain .vex-dialog-form .vex-dialog-buttons:after { + content: ""; + display: table; + clear: both; +} +/* line 80, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain .vex-dialog-button { + -webkit-border-radius: 0; + -moz-border-radius: 0; + -ms-border-radius: 0; + -o-border-radius: 0; + border-radius: 0; + border: 0; + float: right; + margin: 0 0 0 0.5em; + font-family: inherit; + text-transform: uppercase; + letter-spacing: 0.1em; + font-size: 0.8em; + line-height: 1em; + padding: 0.75em 2em; +} +/* line 92, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain .vex-dialog-button.vex-last { + margin-left: 0; +} +/* line 95, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain .vex-dialog-button:focus { + animation: vex-pulse 1.1s infinite; + -webkit-animation: vex-pulse 1.1s infinite; + -moz-animation: vex-pulse 1.1s infinite; + -ms-animation: vex-pulse 1.1s infinite; + -o-animation: vex-pulse 1.1s infinite; + -webkit-backface-visibility: hidden; + outline: none; +} +@media (max-width: 568px) { + /* line 95, ../sass/vex-theme-plain.sass */ + .vex.vex-theme-plain .vex-dialog-button:focus { + animation: none; + -webkit-animation: none; + -moz-animation: none; + -ms-animation: none; + -o-animation: none; + -webkit-backface-visibility: hidden; + } +} +/* line 104, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain .vex-dialog-button.vex-dialog-button-primary { + background: #3288e6; + color: white; +} +/* line 108, ../sass/vex-theme-plain.sass */ +.vex.vex-theme-plain .vex-dialog-button.vex-dialog-button-secondary { + background: #e0e0e0; + color: #777777; +} + +/* line 112, ../sass/vex-theme-plain.sass */ +.vex-loading-spinner.vex-theme-plain { + height: 2.5em; + width: 2.5em; +} diff --git a/css/lib/vex/vex-theme-top.css b/css/lib/vex/vex-theme-top.css new file mode 100644 index 0000000..e541d87 --- /dev/null +++ b/css/lib/vex/vex-theme-top.css @@ -0,0 +1,613 @@ +@keyframes vex-dropin { + /* line 51, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 0; + } + + /* line 54, ../sass/_keyframes.sass */ + 1% { + transform: translateY(-800px); + -webkit-transform: translateY(-800px); + -moz-transform: translateY(-800px); + -ms-transform: translateY(-800px); + -o-transform: translateY(-800px); + opacity: 0; + } + + /* line 59, ../sass/_keyframes.sass */ + 2% { + transform: translateY(-800px); + -webkit-transform: translateY(-800px); + -moz-transform: translateY(-800px); + -ms-transform: translateY(-800px); + -o-transform: translateY(-800px); + opacity: 1; + } + + /* line 62, ../sass/_keyframes.sass */ + 100% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 1; + } +} + +@-webkit-keyframes vex-dropin { + /* line 51, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 0; + } + + /* line 54, ../sass/_keyframes.sass */ + 1% { + transform: translateY(-800px); + -webkit-transform: translateY(-800px); + -moz-transform: translateY(-800px); + -ms-transform: translateY(-800px); + -o-transform: translateY(-800px); + opacity: 0; + } + + /* line 59, ../sass/_keyframes.sass */ + 2% { + transform: translateY(-800px); + -webkit-transform: translateY(-800px); + -moz-transform: translateY(-800px); + -ms-transform: translateY(-800px); + -o-transform: translateY(-800px); + opacity: 1; + } + + /* line 62, ../sass/_keyframes.sass */ + 100% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 1; + } +} + +@-moz-keyframes vex-dropin { + /* line 51, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 0; + } + + /* line 54, ../sass/_keyframes.sass */ + 1% { + transform: translateY(-800px); + -webkit-transform: translateY(-800px); + -moz-transform: translateY(-800px); + -ms-transform: translateY(-800px); + -o-transform: translateY(-800px); + opacity: 0; + } + + /* line 59, ../sass/_keyframes.sass */ + 2% { + transform: translateY(-800px); + -webkit-transform: translateY(-800px); + -moz-transform: translateY(-800px); + -ms-transform: translateY(-800px); + -o-transform: translateY(-800px); + opacity: 1; + } + + /* line 62, ../sass/_keyframes.sass */ + 100% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 1; + } +} + +@-ms-keyframes vex-dropin { + /* line 51, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 0; + } + + /* line 54, ../sass/_keyframes.sass */ + 1% { + transform: translateY(-800px); + -webkit-transform: translateY(-800px); + -moz-transform: translateY(-800px); + -ms-transform: translateY(-800px); + -o-transform: translateY(-800px); + opacity: 0; + } + + /* line 59, ../sass/_keyframes.sass */ + 2% { + transform: translateY(-800px); + -webkit-transform: translateY(-800px); + -moz-transform: translateY(-800px); + -ms-transform: translateY(-800px); + -o-transform: translateY(-800px); + opacity: 1; + } + + /* line 62, ../sass/_keyframes.sass */ + 100% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 1; + } +} + +@-o-keyframes vex-dropin { + /* line 51, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 0; + } + + /* line 54, ../sass/_keyframes.sass */ + 1% { + transform: translateY(-800px); + -webkit-transform: translateY(-800px); + -moz-transform: translateY(-800px); + -ms-transform: translateY(-800px); + -o-transform: translateY(-800px); + opacity: 0; + } + + /* line 59, ../sass/_keyframes.sass */ + 2% { + transform: translateY(-800px); + -webkit-transform: translateY(-800px); + -moz-transform: translateY(-800px); + -ms-transform: translateY(-800px); + -o-transform: translateY(-800px); + opacity: 1; + } + + /* line 62, ../sass/_keyframes.sass */ + 100% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + opacity: 1; + } +} + +@keyframes vex-dropout { + /* line 68, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 70, ../sass/_keyframes.sass */ + 100% { + transform: translateY(-800px); + -webkit-transform: translateY(-800px); + -moz-transform: translateY(-800px); + -ms-transform: translateY(-800px); + -o-transform: translateY(-800px); + } +} + +@-webkit-keyframes vex-dropout { + /* line 68, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 70, ../sass/_keyframes.sass */ + 100% { + transform: translateY(-800px); + -webkit-transform: translateY(-800px); + -moz-transform: translateY(-800px); + -ms-transform: translateY(-800px); + -o-transform: translateY(-800px); + } +} + +@-moz-keyframes vex-dropout { + /* line 68, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 70, ../sass/_keyframes.sass */ + 100% { + transform: translateY(-800px); + -webkit-transform: translateY(-800px); + -moz-transform: translateY(-800px); + -ms-transform: translateY(-800px); + -o-transform: translateY(-800px); + } +} + +@-ms-keyframes vex-dropout { + /* line 68, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 70, ../sass/_keyframes.sass */ + 100% { + transform: translateY(-800px); + -webkit-transform: translateY(-800px); + -moz-transform: translateY(-800px); + -ms-transform: translateY(-800px); + -o-transform: translateY(-800px); + } +} + +@-o-keyframes vex-dropout { + /* line 68, ../sass/_keyframes.sass */ + 0% { + transform: translateY(0); + -webkit-transform: translateY(0); + -moz-transform: translateY(0); + -ms-transform: translateY(0); + -o-transform: translateY(0); + } + + /* line 70, ../sass/_keyframes.sass */ + 100% { + transform: translateY(-800px); + -webkit-transform: translateY(-800px); + -moz-transform: translateY(-800px); + -ms-transform: translateY(-800px); + -o-transform: translateY(-800px); + } +} + +@keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-webkit-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-moz-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-ms-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-o-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +/* line 15, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top.vex-closing .vex-content { + animation: vex-dropout 0.5s; + -webkit-animation: vex-dropout 0.5s; + -moz-animation: vex-dropout 0.5s; + -ms-animation: vex-dropout 0.5s; + -o-animation: vex-dropout 0.5s; + -webkit-backface-visibility: hidden; +} +/* line 18, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-content { + animation: vex-dropin 0.5s; + -webkit-animation: vex-dropin 0.5s; + -moz-animation: vex-dropin 0.5s; + -ms-animation: vex-dropin 0.5s; + -o-animation: vex-dropin 0.5s; + -webkit-backface-visibility: hidden; +} +/* line 21, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-content { + -webkit-border-radius: 0 0 5px 5px; + -moz-border-radius: 0 0 5px 5px; + -ms-border-radius: 0 0 5px 5px; + -o-border-radius: 0 0 5px 5px; + border-radius: 0 0 5px 5px; + font-family: "Helvetica Neue", sans-serif; + background: #f0f0f0; + color: #444444; + padding: 1em; + position: relative; + margin: 0 auto; + max-width: 100%; + width: 450px; + font-size: 1.1em; + line-height: 1.5em; +} +/* line 34, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-content h1, .vex.vex-theme-top .vex-content h2, .vex.vex-theme-top .vex-content h3, .vex.vex-theme-top .vex-content h4, .vex.vex-theme-top .vex-content h5, .vex.vex-theme-top .vex-content h6, .vex.vex-theme-top .vex-content p, .vex.vex-theme-top .vex-content ul, .vex.vex-theme-top .vex-content li { + color: inherit; +} +/* line 37, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-close { + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + -ms-border-radius: 5px; + -o-border-radius: 5px; + border-radius: 5px; + position: absolute; + top: 0; + right: 0; + cursor: pointer; +} +/* line 44, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-close:before { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + position: absolute; + content: "\00D7"; + font-size: 26px; + font-weight: normal; + line-height: 31px; + height: 30px; + width: 30px; + text-align: center; + top: 3px; + right: 3px; + color: #bbbbbb; + background: transparent; +} +/* line 59, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-close:hover:before, .vex.vex-theme-top .vex-close:active:before { + color: #777777; + background: #e0e0e0; +} +/* line 65, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-dialog-form .vex-dialog-message { + margin-bottom: 0.5em; +} +/* line 68, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-dialog-form .vex-dialog-input { + margin-bottom: 1em; +} +/* line 71, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-dialog-form .vex-dialog-input textarea, .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="date"], .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="datetime"], .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="datetime-local"], .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="email"], .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="month"], .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="number"], .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="password"], .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="search"], .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="tel"], .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="text"], .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="time"], .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="url"], .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="week"] { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + background: white; + width: 100%; + padding: 0.25em 0.67em; + border: 0; + font-family: inherit; + font-weight: inherit; + font-size: inherit; + min-height: 2.5em; + margin: 0 0 0.25em; +} +/* line 83, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-dialog-form .vex-dialog-input textarea:focus, .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="date"]:focus, .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="datetime"]:focus, .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="datetime-local"]:focus, .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="email"]:focus, .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="month"]:focus, .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="number"]:focus, .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="password"]:focus, .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="search"]:focus, .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="tel"]:focus, .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="text"]:focus, .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="time"]:focus, .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="url"]:focus, .vex.vex-theme-top .vex-dialog-form .vex-dialog-input input[type="week"]:focus { + -webkit-box-shadow: inset 0 0 0 2px #8dbdf1; + -moz-box-shadow: inset 0 0 0 2px #8dbdf1; + box-shadow: inset 0 0 0 2px #8dbdf1; + outline: none; +} +/* line 87, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-dialog-form .vex-dialog-buttons { + *zoom: 1; +} +/* line 38, ../../../../../.rvm/gems/ruby-1.9.3-p194/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss */ +.vex.vex-theme-top .vex-dialog-form .vex-dialog-buttons:after { + content: ""; + display: table; + clear: both; +} +/* line 90, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-dialog-button { + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; + border: 0; + float: right; + margin: 0 0 0 0.5em; + font-family: inherit; + text-transform: uppercase; + letter-spacing: 0.1em; + font-size: 0.8em; + line-height: 1em; + padding: 0.75em 2em; +} +/* line 102, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-dialog-button.vex-last { + margin-left: 0; +} +/* line 105, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-dialog-button:focus { + animation: vex-pulse 1.1s infinite; + -webkit-animation: vex-pulse 1.1s infinite; + -moz-animation: vex-pulse 1.1s infinite; + -ms-animation: vex-pulse 1.1s infinite; + -o-animation: vex-pulse 1.1s infinite; + -webkit-backface-visibility: hidden; + outline: none; +} +@media (max-width: 568px) { + /* line 105, ../sass/vex-theme-top.sass */ + .vex.vex-theme-top .vex-dialog-button:focus { + animation: none; + -webkit-animation: none; + -moz-animation: none; + -ms-animation: none; + -o-animation: none; + -webkit-backface-visibility: hidden; + } +} +/* line 114, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-dialog-button.vex-dialog-button-primary { + background: #3288e6; + color: white; +} +/* line 118, ../sass/vex-theme-top.sass */ +.vex.vex-theme-top .vex-dialog-button.vex-dialog-button-secondary { + background: #e0e0e0; + color: #777777; +} + +/* line 122, ../sass/vex-theme-top.sass */ +.vex-loading-spinner.vex-theme-top { + -webkit-box-shadow: 0 0 0 0.5em #f0f0f0, 0 0 1px 0.5em rgba(0, 0, 0, 0.3); + -moz-box-shadow: 0 0 0 0.5em #f0f0f0, 0 0 1px 0.5em rgba(0, 0, 0, 0.3); + box-shadow: 0 0 0 0.5em #f0f0f0, 0 0 1px 0.5em rgba(0, 0, 0, 0.3); + -webkit-border-radius: 100%; + -moz-border-radius: 100%; + -ms-border-radius: 100%; + -o-border-radius: 100%; + border-radius: 100%; + background: #f0f0f0; + border: 0.2em solid transparent; + border-top-color: #bbbbbb; + top: -1.1em; + bottom: auto; +} diff --git a/css/lib/vex/vex-theme-wireframe.css b/css/lib/vex/vex-theme-wireframe.css new file mode 100644 index 0000000..e70816a --- /dev/null +++ b/css/lib/vex/vex-theme-wireframe.css @@ -0,0 +1,262 @@ +@keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-webkit-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-moz-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-ms-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +@-o-keyframes vex-pulse { + /* line 136, ../sass/_keyframes.sass */ + 0% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } + + /* line 138, ../sass/_keyframes.sass */ + 70% { + -webkit-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + box-shadow: inset 0 0 0 300px rgba(255, 255, 255, 0.25); + } + + /* line 140, ../sass/_keyframes.sass */ + 100% { + -webkit-box-shadow: inset 0 0 0 300px transparent; + -moz-box-shadow: inset 0 0 0 300px transparent; + box-shadow: inset 0 0 0 300px transparent; + } +} + +/* line 9, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe { + padding-top: 160px; + padding-bottom: 160px; +} +/* line 13, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-overlay { + background: rgba(255, 255, 255, 0.4); +} +/* line 16, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-content { + font-family: "Helvetica Neue", sans-serif; + background: white; + color: black; + border: 2px solid black; + padding: 2em; + position: relative; + margin: 0 auto; + max-width: 100%; + width: 400px; + font-size: 1.1em; + line-height: 1.5em; +} +/* line 29, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-content h1, .vex.vex-theme-wireframe .vex-content h2, .vex.vex-theme-wireframe .vex-content h3, .vex.vex-theme-wireframe .vex-content h4, .vex.vex-theme-wireframe .vex-content h5, .vex.vex-theme-wireframe .vex-content h6, .vex.vex-theme-wireframe .vex-content p, .vex.vex-theme-wireframe .vex-content ul, .vex.vex-theme-wireframe .vex-content li { + color: inherit; +} +/* line 32, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-close { + position: absolute; + top: 0; + right: 0; + cursor: pointer; +} +/* line 38, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-close:before { + position: absolute; + content: "\00D7"; + font-size: 40px; + font-weight: normal; + line-height: 80px; + height: 80px; + width: 80px; + text-align: center; + top: 3px; + right: 3px; + color: black; +} +/* line 51, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-close:hover:before, .vex.vex-theme-wireframe .vex-close:active:before { + color: black; +} +/* line 56, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-message { + margin-bottom: 0.5em; +} +/* line 59, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input { + margin-bottom: 1em; +} +/* line 62, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input textarea, .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="date"], .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="datetime"], .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="datetime-local"], .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="email"], .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="month"], .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="number"], .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="password"], .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="search"], .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="tel"], .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="text"], .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="time"], .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="url"], .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="week"] { + background: white; + width: 100%; + padding: 0.25em 0.67em; + font-family: inherit; + font-weight: inherit; + font-size: inherit; + min-height: 2.5em; + margin: 0 0 0.25em; + border: 2px solid black; +} +/* line 73, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input textarea:focus, .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="date"]:focus, .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="datetime"]:focus, .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="datetime-local"]:focus, .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="email"]:focus, .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="month"]:focus, .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="number"]:focus, .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="password"]:focus, .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="search"]:focus, .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="tel"]:focus, .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="text"]:focus, .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="time"]:focus, .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="url"]:focus, .vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-input input[type="week"]:focus { + border-style: dashed; + outline: none; +} +/* line 77, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-buttons { + *zoom: 1; +} +/* line 38, ../../../../../.rvm/gems/ruby-1.9.3-p194/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss */ +.vex.vex-theme-wireframe .vex-dialog-form .vex-dialog-buttons:after { + content: ""; + display: table; + clear: both; +} +/* line 80, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-dialog-button { + -webkit-border-radius: 0; + -moz-border-radius: 0; + -ms-border-radius: 0; + -o-border-radius: 0; + border-radius: 0; + border: 0; + float: right; + margin: 0 0 0 0.5em; + font-family: inherit; + text-transform: uppercase; + letter-spacing: 0.1em; + font-size: 0.8em; + line-height: 1em; + padding: 0.75em 2em; +} +/* line 92, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-dialog-button.vex-last { + margin-left: 0; +} +/* line 95, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-dialog-button:focus { + animation: vex-pulse 1.1s infinite; + -webkit-animation: vex-pulse 1.1s infinite; + -moz-animation: vex-pulse 1.1s infinite; + -ms-animation: vex-pulse 1.1s infinite; + -o-animation: vex-pulse 1.1s infinite; + -webkit-backface-visibility: hidden; + outline: none; +} +@media (max-width: 568px) { + /* line 95, ../sass/vex-theme-wireframe.sass */ + .vex.vex-theme-wireframe .vex-dialog-button:focus { + animation: none; + -webkit-animation: none; + -moz-animation: none; + -ms-animation: none; + -o-animation: none; + -webkit-backface-visibility: hidden; + } +} +/* line 104, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-dialog-button.vex-dialog-button-primary { + background: black; + color: white; + border: 2px solid transparent; +} +/* line 109, ../sass/vex-theme-wireframe.sass */ +.vex.vex-theme-wireframe .vex-dialog-button.vex-dialog-button-secondary { + background: white; + color: black; + border: 2px solid black; +} + +/* line 114, ../sass/vex-theme-wireframe.sass */ +.vex-loading-spinner.vex-theme-wireframe { + height: 2.5em; + width: 2.5em; +} diff --git a/css/lib/vex/vex.css b/css/lib/vex/vex.css new file mode 100644 index 0000000..b7ae6cf --- /dev/null +++ b/css/lib/vex/vex.css @@ -0,0 +1,335 @@ +@keyframes vex-fadein { + /* line 9, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + } + + /* line 11, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + } +} + +@-webkit-keyframes vex-fadein { + /* line 9, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + } + + /* line 11, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + } +} + +@-moz-keyframes vex-fadein { + /* line 9, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + } + + /* line 11, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + } +} + +@-ms-keyframes vex-fadein { + /* line 9, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + } + + /* line 11, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + } +} + +@-o-keyframes vex-fadein { + /* line 9, ../sass/_keyframes.sass */ + 0% { + opacity: 0; + } + + /* line 11, ../sass/_keyframes.sass */ + 100% { + opacity: 1; + } +} + +@keyframes vex-fadeout { + /* line 16, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + } + + /* line 18, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + } +} + +@-webkit-keyframes vex-fadeout { + /* line 16, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + } + + /* line 18, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + } +} + +@-moz-keyframes vex-fadeout { + /* line 16, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + } + + /* line 18, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + } +} + +@-ms-keyframes vex-fadeout { + /* line 16, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + } + + /* line 18, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + } +} + +@-o-keyframes vex-fadeout { + /* line 16, ../sass/_keyframes.sass */ + 0% { + opacity: 1; + } + + /* line 18, ../sass/_keyframes.sass */ + 100% { + opacity: 0; + } +} + +@keyframes vex-rotation { + /* line 127, ../sass/_keyframes.sass */ + 0% { + transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); + } + + /* line 129, ../sass/_keyframes.sass */ + 100% { + transform: rotate(359deg); + -webkit-transform: rotate(359deg); + -moz-transform: rotate(359deg); + -ms-transform: rotate(359deg); + -o-transform: rotate(359deg); + } +} + +@-webkit-keyframes vex-rotation { + /* line 127, ../sass/_keyframes.sass */ + 0% { + transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); + } + + /* line 129, ../sass/_keyframes.sass */ + 100% { + transform: rotate(359deg); + -webkit-transform: rotate(359deg); + -moz-transform: rotate(359deg); + -ms-transform: rotate(359deg); + -o-transform: rotate(359deg); + } +} + +@-moz-keyframes vex-rotation { + /* line 127, ../sass/_keyframes.sass */ + 0% { + transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); + } + + /* line 129, ../sass/_keyframes.sass */ + 100% { + transform: rotate(359deg); + -webkit-transform: rotate(359deg); + -moz-transform: rotate(359deg); + -ms-transform: rotate(359deg); + -o-transform: rotate(359deg); + } +} + +@-ms-keyframes vex-rotation { + /* line 127, ../sass/_keyframes.sass */ + 0% { + transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); + } + + /* line 129, ../sass/_keyframes.sass */ + 100% { + transform: rotate(359deg); + -webkit-transform: rotate(359deg); + -moz-transform: rotate(359deg); + -ms-transform: rotate(359deg); + -o-transform: rotate(359deg); + } +} + +@-o-keyframes vex-rotation { + /* line 127, ../sass/_keyframes.sass */ + 0% { + transform: rotate(0deg); + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -o-transform: rotate(0deg); + } + + /* line 129, ../sass/_keyframes.sass */ + 100% { + transform: rotate(359deg); + -webkit-transform: rotate(359deg); + -moz-transform: rotate(359deg); + -ms-transform: rotate(359deg); + -o-transform: rotate(359deg); + } +} + +/* line 11, ../sass/vex.sass */ +.vex, .vex *, .vex *:before, .vex *:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +/* line 14, ../sass/vex.sass */ +.vex { + position: fixed; + overflow: auto; + -webkit-overflow-scrolling: touch; + z-index: 1111; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +/* line 25, ../sass/vex.sass */ +.vex-overlay { + background: black; + filter: alpha(opacity=40); + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=40)"; +} + +/* line 30, ../sass/vex.sass */ +.vex-overlay { + animation: vex-fadein 0.5s; + -webkit-animation: vex-fadein 0.5s; + -moz-animation: vex-fadein 0.5s; + -ms-animation: vex-fadein 0.5s; + -o-animation: vex-fadein 0.5s; + -webkit-backface-visibility: hidden; + position: fixed; + background: rgba(0, 0, 0, 0.4); + top: 0; + right: 0; + bottom: 0; + left: 0; +} +/* line 39, ../sass/vex.sass */ +.vex.vex-closing .vex-overlay { + animation: vex-fadeout 0.5s; + -webkit-animation: vex-fadeout 0.5s; + -moz-animation: vex-fadeout 0.5s; + -ms-animation: vex-fadeout 0.5s; + -o-animation: vex-fadeout 0.5s; + -webkit-backface-visibility: hidden; +} + +/* line 42, ../sass/vex.sass */ +.vex-content { + animation: vex-fadein 0.5s; + -webkit-animation: vex-fadein 0.5s; + -moz-animation: vex-fadein 0.5s; + -ms-animation: vex-fadein 0.5s; + -o-animation: vex-fadein 0.5s; + -webkit-backface-visibility: hidden; + background: white; +} +/* line 46, ../sass/vex.sass */ +.vex.vex-closing .vex-content { + animation: vex-fadeout 0.5s; + -webkit-animation: vex-fadeout 0.5s; + -moz-animation: vex-fadeout 0.5s; + -ms-animation: vex-fadeout 0.5s; + -o-animation: vex-fadeout 0.5s; + -webkit-backface-visibility: hidden; +} + +/* line 49, ../sass/vex.sass */ +.vex-close:before { + font-family: Arial, sans-serif; + content: "\00D7"; +} + +/* line 53, ../sass/vex.sass */ +.vex-dialog-form { + margin: 0; +} + +/* line 56, ../sass/vex.sass */ +.vex-dialog-button { + -webkit-appearance: none; + cursor: pointer; +} + +/* line 60, ../sass/vex.sass */ +.vex-loading-spinner { + animation: vex-rotation 0.7s linear infinite; + -webkit-animation: vex-rotation 0.7s linear infinite; + -moz-animation: vex-rotation 0.7s linear infinite; + -ms-animation: vex-rotation 0.7s linear infinite; + -o-animation: vex-rotation 0.7s linear infinite; + -webkit-backface-visibility: hidden; + -webkit-box-shadow: 0 0 1em rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 0 1em rgba(0, 0, 0, 0.1); + box-shadow: 0 0 1em rgba(0, 0, 0, 0.1); + position: fixed; + z-index: 1112; + margin: auto; + top: 0; + right: 0; + bottom: 0; + left: 0; + height: 2em; + width: 2em; + background: white; +} + +/* line 76, ../sass/vex.sass */ +body.vex-open { + overflow: hidden; +} diff --git a/css/piano.css b/css/piano.css new file mode 100644 index 0000000..cdac3ec --- /dev/null +++ b/css/piano.css @@ -0,0 +1,458 @@ +body, html, #content { + margin: 0; + padding: 0; + height: 100%; + + background: #262626; + font-family: Helvetica, sans-serif; +} + +*, *:before, *:after { + box-sizing: border-box; + cursor: default; +} + +*:not(input):not(button):not(select):not(textarea) { + -webkit-user-select: none; +} + +:focus { + outline: none; +} + +a { + cursor: pointer; + color: inherit; +} + +/** + * Animations + */ + +@-webkit-keyframes reveal-controls { + 0% { + transform: translate(-50%, 10em); + } + + 100% { + transform: translate(-50%, -50%); + } +} + +@-webkit-keyframes reveal-notes { + 0% { + transform: translate(0, -20em); + } + + 100% { + transform: translate(0, 0); + } +} + +/** + * Main + */ + +.main { + position: relative; + + width: calc(100% - 65px); + height: 100%; + + margin-left: 65px; +} + +.main p { + position: relative; + margin: 0; +} + +.main .roll { + display: flex; + height: 100%; + + flex-direction: column; +} + +/** noteboard **/ +.main .noteboard { + position: relative; + overflow: hidden; + + flex-basis: 100%; +} + +.main .noteboard .inner { + backface-visibility: hidden; + perspective: 1000; +} + +/* closed controls */ +.main .noteboard .controls { + position: absolute; + top: 50%; + left: 50%; + + -webkit-animation: reveal-controls 0.5s ease forwards; + + width: 100%; + text-align: center; + transform: translate(-50%, 10em); +} + +.main .noteboard .controls img { + display: block; + margin: 0 auto 1em auto; +} + +/* notes */ +.main .noteboard canvas { + -webkit-animation: reveal-notes 0.5s ease; +} + +.main .noteboard .note { + display: block; + position: absolute; + + left: 0; + bottom: 0; + width: calc(100% / 52); + + border: 1px solid #262626; +} + +/* black */ +.main .noteboard [data-black="true"] { + width: calc(100% / 52 * 0.6); + border-radius: 5px; + + margin-left: calc(-100% / 52 * 0.6 / 2); + z-index: 1; + overflow: hidden; + + box-shadow: inset 1000em 1000em rgba(0, 0, 0, 0.2); +} + +/* percussion */ +.main .noteboard [data-channel="9"] { + border-radius: 20px; + min-height: 10px; +} + +/** channel colors **/ +[data-channel="0"] { + background-color: hsl(225, 49%, 44%) !important; +} + +[data-channel="1"] { + background-color: hsl(22.5, 84%, 56%) !important; +} + +[data-channel="2"] { + background-color: hsl(45, 53%, 39%) !important; +} + +[data-channel="3"] { + background-color: hsl(67.5, 84%, 56%) !important; +} + +[data-channel="4"] { + background-color: hsl(90, 84%, 56%) !important; +} + +[data-channel="5"] { + background-color: hsl(112.5, 84%, 56%) !important; +} + +[data-channel="6"] { + background-color: hsl(135, 84%, 56%) !important; +} + +[data-channel="7"] { + background-color: hsl(157.5, 84%, 56%) !important; +} + +[data-channel="8"] { + background-color: hsl(180, 84%, 56%) !important; +} + +[data-channel="9"] { + background-color: hsl(202.5, 84%, 56%) !important; +} + +[data-channel="10"] { + background-color: hsl(247.5, 84%, 56%) !important; +} + +[data-channel="11"] { + background-color: hsl(270, 84%, 56%) !important; +} + +[data-channel="12"] { + background-color: hsl(292.5, 84%, 56%) !important; +} + +[data-channel="13"] { + background-color: hsl(315, 84%, 56%) !important; +} + +[data-channel="14"] { + background-color: hsl(337.5, 84%, 56%) !important; +} + +[data-channel="15"] { + background-color: hsl(0, 84%, 56%) !important; +} + +/** keyboard **/ +.main .keyboard { + width: 100%; + padding-bottom: 13%; +} + +.main .key { + position: absolute; + left: 0; + bottom: 0; + + background: white; + display: inline-block; + height: 100%; +} + +.main [data-black="false"]:not(:last-child) { + border-right: 1px solid #262626; +} + +.main [data-black="true"] { + bottom: 40%; + background: #262626; + + border: 1px solid #262626; + border-top: 0; + + margin-left: calc(-100% / 52 * 0.6 / 2); + width: calc(100% / 52 * 0.6); + height: 60%; +} + +.main .key:not([data-channel="false"]) { + box-shadow: inset 1000em 1000em rgba(0, 0, 0, 0.1); +} + +.main [data-black="true"][data-channel="-1"] { + box-shadow: inset 1000em 1000em rgba(255, 255, 255, 0.1); +} + +/** sidebar controls **/ +.main .control { + position: absolute; + top: 0; + left: -65px; + + height: 100%; + width: 50px; + padding: 9px; + + background: #1e1e1e; + text-align: center; +} + +.main .control button { + -webkit-appearance: none; + + width: 32px; + height: 32px; + + border: 0; + cursor: pointer; + color: white; + + background: none; +} + +.main .control .switch-play-state, .main .control .open-channels-window, +.main .control .close { + background: center center no-repeat; + text-indent: -10000em; +} + +.main .control > * { + display: block; + margin: 0 auto 1em auto; +} + +/* playback control */ +.main .control .switch-play-state { + background-image: url('../images/icons/play.png'); +} + +.main .control .switch-play-state.pause { + background-image: url('../images/icons/pause.png'); +} + +/* channels */ +.main .control .open-channels-window { + background-image: url('../images/icons/channels.png'); +} + +/* set play speed */ +.main .control .selector { + text-align: center; + line-height: 32px; + + border: 1px solid white; + border-radius: 3px; + overflow: hidden; + + padding: 0; +} + +.main .control .selector:hover { + background: rgba(255, 255, 255, 0.05); +} + +.main .control .selector:active { + padding: 1px 0 0 0; +} + +.main .control .selector:before { + content: '×'; + cursor: pointer; +} + +/* close opened file */ +.main .control .close { + background-image: url('../images/icons/close.png'); + position: absolute; + left: 9px; + bottom: 0; +} + +/** scroll **/ +.main .scroll { + position: absolute; + top: 0; + left: -15px; + + height: 100%; + background: #1e1e1e; +} + +/** + * Channels modal + */ +.vex.vex .channels ul { + list-style: none; + padding: 0; + + width: calc(100% + 2em); + margin: 0 0 0 -1em; +} + +.vex .channels ul li { + display: block; + width: 100%; + + padding: 0 0 0 44px; + background-position: 6px center; + background-repeat: no-repeat; +} + +.vex .channels ul li span { + display: block; + height: 100%; + padding: 9px; + + background: white; +} + +.vex .channels ul li:nth-child(2n) span { + background: #e2e2e2; +} + +.vex .channels ul li:hover, .vex .channels ul li:hover span { + box-shadow: inset 1000em 1000em rgba(0, 0, 0, 0.15); +} + +/** icons **/ +.vex .channels ul li.piano { + background-image: url('../images/icons/instruments/piano.png'); +} + +.vex .channels ul li.percussive { + background-image: url('../images/icons/instruments/percussive.png'); +} + +.vex .channels ul li.percussion { + background-image: url('../images/icons/instruments/percussion.png'); +} + +.vex .channels ul li.effect { + background-image: url('../images/icons/instruments/effect.png'); +} + +.vex .channels ul li.brass { + background-image: url('../images/icons/instruments/brass.png'); +} + +.vex .channels ul li.pipe { + background-image: url('../images/icons/instruments/pipe.png'); +} + +.vex .channels ul li.string { + background-image: url('../images/icons/instruments/string.png'); +} + +.vex .channels ul li.synth { + background-image: url('../images/icons/instruments/synth.png'); +} + +.vex .channels ul li.guitar { + background-image: url('../images/icons/instruments/guitar.png'); +} + +.vex .channels ul li.orchestra { + background-image: url('../images/icons/instruments/orchestra.png'); +} + +.vex .channels ul li.bass { + background-image: url('../images/icons/instruments/bass.png'); +} + +.vex .channels ul li.organ { + background-image: url('../images/icons/instruments/organ.png'); +} + +/** + * UI Components + */ + +/** scroll **/ +.scroll, ::-webkit-scrollbar { + height: 200px; + width: 15px; + + overflow: hidden; + position: relative; +} + +::-webkit-scrollbar-track { + background: #262626; +} + +.scroll .position, ::-webkit-scrollbar-thumb { + display: block; + width: 100%; + + position: absolute; + height: 5%; + min-height: 20px; + + transform: translate(0, 50%); + background: rgba(255, 255, 255, 0.15); +} + +.scroll .position:hover, ::-webkit-scrollbar-thumb:hover { + background: rgba(255, 255, 255, 0.3); +} \ No newline at end of file diff --git a/grunt/contrib-clean.js b/grunt/contrib-clean.js new file mode 100644 index 0000000..6c89dfa --- /dev/null +++ b/grunt/contrib-clean.js @@ -0,0 +1,20 @@ +/*jshint node:true */ + +'use strict'; + +module.exports = function (grunt) { + grunt.loadNpmTasks('grunt-contrib-clean'); + + grunt.config('clean.clean-build', [ + 'build/<%= grunt.task.current.args[0] %>' + ]); + + grunt.config('clean.clean-files', [ + 'build/<%= paths.resources[grunt.task.current.args[0]] %>/app' + ]); + + grunt.config('clean.clean-default', [ + 'build/<%= paths.resources[grunt.task.current.args[0]] %>/default_app', + 'build/<%= grunt.task.current.args[0] %>.zip' + ]); +}; \ No newline at end of file diff --git a/grunt/contrib-copy.js b/grunt/contrib-copy.js new file mode 100644 index 0000000..97930b9 --- /dev/null +++ b/grunt/contrib-copy.js @@ -0,0 +1,13 @@ +/*jshint node:true */ + +'use strict'; + +module.exports = function (grunt) { + grunt.loadNpmTasks('grunt-contrib-copy'); + + grunt.config('copy.copy-files', { + expand: true, + dest: 'build/<%= paths.resources[grunt.task.current.args[0]] %>/app', + src: grunt.config.get('files') + }); +}; \ No newline at end of file diff --git a/grunt/contrib-watch.js b/grunt/contrib-watch.js new file mode 100644 index 0000000..5bd8535 --- /dev/null +++ b/grunt/contrib-watch.js @@ -0,0 +1,16 @@ +/*jshint node:true */ + +'use strict'; + +module.exports = function (grunt) { + grunt.loadNpmTasks('grunt-contrib-watch'); + + grunt.config('watch.watch-changes', { + files: grunt.config.get('files'), + tasks: [ + 'clean:clean-files:<%= grunt.task.current.args[1] %>', + 'copy:copy-files:<%= grunt.task.current.args[1] %>', + 'rebrand:rebrand-exe:<%= grunt.task.current.args[1] %>' + ] + }); +}; \ No newline at end of file diff --git a/grunt/curl.js b/grunt/curl.js new file mode 100644 index 0000000..85b3a54 --- /dev/null +++ b/grunt/curl.js @@ -0,0 +1,12 @@ +/*jshint node:true */ + +'use strict'; + +module.exports = function (grunt) { + grunt.loadNpmTasks('grunt-curl'); + + grunt.config('curl.fetch-asset', { + src: '<%= asset %>', + dest: 'build/<%= grunt.task.current.args[0] %>.zip' + }); +}; \ No newline at end of file diff --git a/grunt/http.js b/grunt/http.js new file mode 100644 index 0000000..5286647 --- /dev/null +++ b/grunt/http.js @@ -0,0 +1,67 @@ +/*jshint node:true */ + +'use strict'; + +module.exports = function (grunt) { + grunt.loadNpmTasks('grunt-http'); + + /** + * Select matching asset from last release in releases list + * from GitHub API + * + * @param {releases: array} Releases list + * @return {string|false} Asset download URL, false if none found + */ + function selectAsset(releases) { + var assets, asset, release, + assetsLength, releasesLength, + name, types = grunt.config.get('platforms'), + type = types[grunt.task.current.args[0]], + i, j; + + releasesLength = releases.length; + + for (i = 0; i < releasesLength; i += 1) { + release = releases[i]; + name = 'atom-shell-' + release.tag_name + '-' + type + '.zip'; + + // we only want stable releases + if (release.prerelease === false && release.draft === false) { + assets = release.assets; + assetsLength = assets.length; + + for (j = 0; j < assetsLength; j += 1) { + asset = assets[j]; + + if (asset.name === name) { + return asset.browser_download_url; + } + } + } + } + + return false; + } + + grunt.config('http.find-asset', { + options: { + url: '<%= releases %>', + headers: { + 'User-Agent': 'Grunt' + }, + callback: function (err, res, body) { + if (err) { + throw err; + } + + var releases = JSON.parse(body), asset = selectAsset(releases); + + if (asset !== false) { + grunt.config.set('asset', asset); + } else { + grunt.fail.warn(new Error('No recent release found')); + } + } + } + }); +}; \ No newline at end of file diff --git a/grunt/mkdir.js b/grunt/mkdir.js new file mode 100644 index 0000000..947d023 --- /dev/null +++ b/grunt/mkdir.js @@ -0,0 +1,13 @@ +/*jshint node:true */ + +'use strict'; + +module.exports = function (grunt) { + grunt.loadNpmTasks('grunt-mkdir'); + + grunt.config('mkdir.create-build', { + options: { + create: ['build/<%= grunt.task.current.args[0] %>'] + } + }); +}; \ No newline at end of file diff --git a/grunt/rebrand.js b/grunt/rebrand.js new file mode 100644 index 0000000..479a30a --- /dev/null +++ b/grunt/rebrand.js @@ -0,0 +1,33 @@ +/*jshint node:true */ + +'use strict'; + +var rcedit = require('rcedit'); + +module.exports = function (grunt) { + grunt.registerMultiTask('rebrand', 'Rebrand .exe', function (platform) { + if (platform !== 'win') { + return; + } + + var done = this.async(); + + rcedit(this.data.src, { + 'icon': this.data.icon, + 'version-string': this.data.meta + }, function (err) { + if (err) { + grunt.fail.warn(err); + return; + } + + done(); + }); + }); + + grunt.config('rebrand.rebrand-exe', { + src: 'build/<%= paths.exe[grunt.task.current.args[0]] %>', + icon: 'images/logos/logo.ico', + meta: grunt.config.get('meta') + }); +}; \ No newline at end of file diff --git a/grunt/rename.js b/grunt/rename.js new file mode 100644 index 0000000..5a6735d --- /dev/null +++ b/grunt/rename.js @@ -0,0 +1,12 @@ +/*jshint node:true */ + +'use strict'; + +module.exports = function (grunt) { + grunt.loadNpmTasks('grunt-rename'); + + grunt.config('rename.rename-exe', { + src: 'build/<%= paths.originalExe[grunt.task.current.args[0]] %>', + dest: 'build/<%= paths.exe[grunt.task.current.args[0]] %>' + }); +}; \ No newline at end of file diff --git a/grunt/zip.js b/grunt/zip.js new file mode 100644 index 0000000..a8c1a7b --- /dev/null +++ b/grunt/zip.js @@ -0,0 +1,12 @@ +/*jshint node:true */ + +'use strict'; + +module.exports = function (grunt) { + grunt.loadNpmTasks('grunt-zip'); + + grunt.config('unzip.extract-asset', { + src: 'build/<%= grunt.task.current.args[0] %>.zip', + dest: 'build/<%= grunt.task.current.args[0] %>/' + }); +}; \ No newline at end of file diff --git a/images/empty.png b/images/empty.png new file mode 100644 index 0000000000000000000000000000000000000000..97684dd5869b2110ccbb2ec2234b0dd1b9002877 GIT binary patch literal 467 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4%caKYZ?lYt_f1s;*b zKpodXn9)gNb_Gz7y~NYkmHi%Kp&SosO<=U|Y)-x^l+NM3sZl55wzl|$4i(7BHpZRfY&Gnu8t?bfk%&Z%{ zDKHqTV;%*zw)O`l0cWhbZkl`%|j;MnbOcJu$2 z)(sr5bn9G>7}OWZ9sJ|^W#b3$*R!JY7x2&bdtq%7ms^{*dV(wi5O})!xvXkdg00002VoOIv03RoX zF2?`>010qNS#tmY3ljhU3ljkVnw%H_000McNliru-U=BJA3Bxu$shm#0kug)K~zY` z#g(l~LtzxgpDQwOIEx4}E?CzL15IKSn;QH`f(B(E{s#s@Fo{JNvx&te1!2h`7zCMu zL1YGt&L9|6aAEQ@c)4HiJE!8u6K*&k&pq#Z&Us$xzv0-;q%^ESxk^i_>PCkuIZvPD zBtwxJanvZ1X`Y-UPaS{=3!NX( z+b~5-P`vh(){}BN({zZp!}wELdzOQc2jBvSZtfWJ?VH$;H*db~xwc6#z$JYQv&25n zR)Tu0BNRi<19~{28H$myG5Y=rRLGGfOOA?#phhYn7`Fs$(dPTx*s?^72Lv02vl66x z6lN70K^x7{Sa)6|TnZF$CFe!!Mof@pxw5PzQ2?MINo0+flgJ=_7p;<{s$uU}S<W^IF54AC65sEaj?aro^tL!lN09#>iGtiDr> zXFAuuoX6X{+j=ug??uD)&ptaF)y!C?!10eEMS=H)(1iY3`VOpN3p7fWW@>Gav8+t( zFM09AIk?^GV$_aLy&7jStCw8V6RA_4`z*t4x#iV$9rH}nTxZNK7fH-tr{lDy+4G#q z{P|+1i@yJiuVX%9%6z8zglX4ZdFAiVZ~S#G>ei1G*we(z6Rv!1H6v>r(2)$Du6{1- HoD!Mt<74`dEkklUI9@~LM@ zkY6wZBMTcR7dMZfh`6MjqLR9%wvMizv4y3zy_2iEhj(CDcw}^DNqJ>kXWz6%OO~%% zvvJeb-B+$&yMFiK^B1pPzkC1T)7S66e*gK)eZxl+Xy|%R7srr_TSqS)7itO+aJd+0 zsF-H>e9q=YGXgLE{4YOAXj*?<NJ) z<&nyX^#7JRecr{N-k-awPj2|Ftov@E_U$T_Yw7K`^>uCrDr{u6o}?mXf4lazvUuaQ iQwi5XoK%iF+ka=2Oq2U3!*BB)6xW`velF{r5}E*%9F9K# literal 0 HcmV?d00001 diff --git a/images/icons/instruments/brass.png b/images/icons/instruments/brass.png new file mode 100644 index 0000000000000000000000000000000000000000..8c76b0bd3a540d2a7c0957c8fc0618db44616bc1 GIT binary patch literal 806 zcmV+>1KIqEP)X_eV$wuSVgw&WgeY3rh=TY) zv=g)xEEH@)EQBa1wlQd7VIdO4N`e-G*r}*Rj25OzPzXqLA%Vz7%^r(;Hq7qMy*qbz zJuuAU%>B? zC7Njf4B`~9R73DFpt(XXEr3BB1{PBUzXxQzTD1Te#37&%5d3MPPOSh2akonFAHc@{ z39ttEngDRRszzX-PFwdAz;>X?@m-DyJ{_c8C2%+J$|F7r3|OCCaT~8L0N?=dD`9#U zY-R+Q^Y~BJ3;<+-FOJxK;2_WsTnCnm?biQ|2cWMWfI&y-w#Q$*7e0jo02hJb^7CL7 ze%ojHcY{GhdVm3-1NdY99uXO|wh9xGqrgs}6}V>0^^#~`MHVvyQ#Oimt6#C8X^!4L z;DM*TWN%d5h9c4eY_aNl5$ObOLhNkCnTB-oUB_)ela*(H-9WR|hkKE|8b~c;;XPGZg%o{NDGMX@<9I)EjjsuTuMn-{dYwz&DO@;(d z0vK_`ZdG}-jCcT^)C;hU(iiWLr;h-ai1ti5z}Zj$F|i60k>|h>r)d^=LA3LGfxW;E z&!^+6ddw^8vxKSL0DSa}E-B3cn?gq)y95qIJJFxXYJum08$f%S;E7A%EJZ7D#!?rs k)|TU&rDkdg0002TNkl5azxo zSm?R+2mkd~RC5b6?oC@ND4_BLi8ILOXuQ zzS^f7L31llY5;ff{QWLLBYBmaNAm}3ISaN;zT{&Z=xA!?%A}Q(bawPHeyjrQNnRw^ zIyi3sPISS^H#rwNn6>k`(_hWc%JO+xPE(dcQ?L1aNe7z$QQDU(uYl9qok z87q|1hTQZ=H$v1V0%_4Iv_&lniZ<0o5tI@f7uup0no%xlF*P9-6gBwMG)r%bcb+~T z?>F<_O#Uuhe!O$;`F_9W+Hg1qqv0A_yGOkf4T$tqm_6K$zLgf zUnvnC!@qUO8wtQ2k@02h#jTiyP52P!OT-hBHx;liK;NnGZE2c$BLQ)uQ#6koOTNt& zGonvIjC=batwm18*6u9%=y zJs7FTegr+S<|e!!_Dfh)XA8cLfVm~d4NBJt_m)Kbi2GzWV=w*+`vvT%*<+lEpcy5{ zyR!DWqM{N5F?(faXt*HiW87AUJQr{x0_T++D0KR>@S7Z;c0fH{DVk57nCKwt@w$w7>IZfpBY1dtwD|b>rxJ9mfItIK z-7g^i2@JVPYKMe3FF$`NE_q&FUSXic-+}l)6n_>H65^w(BX|V_ih&Nv0%BDRNf{YV zpr!AS9Pkn-%0~S(!O#C2h(7{@SQ(20^CycG=(pH2fcm#Rz;Hh|i!o>JYKnm=s4;0S%uH3VKdqVQC=y50a%{kt}}-r8fYz zG1IQV;^+SX4f1b5dL_&OAO|9`{b=ccpKu58@y&;afPlbcDEl5z87nOv@Czvl{vsDh zVBhoer_i>}fRqpaabVi|9_oNUSS<%d2Opm)?Q2ccV25L>mjQSj@Nb|U088~-fC+9d zj4voC$WLzvGyvm#0*o&rBEmbM4xoBvM5+U%q@=h8)B#klgvf9J+dw;jb)X%@&cBCt)RXD&;f#=kN}p#4x^o0VgUfR!o(^_M}BAk0000< KMNUMnLSTYf5Ym_c literal 0 HcmV?d00001 diff --git a/images/icons/instruments/organ.png b/images/icons/instruments/organ.png new file mode 100644 index 0000000000000000000000000000000000000000..428293ca0c41d7decaee8f8fe37781b77a9da8d4 GIT binary patch literal 1089 zcmV-H1it%;P)H>aju}{(QaaeL@sv`(7ZzbXp2w$HhcB_F0D88puVYu)--p#Wr!U)eOArx_5iukp zHsQn)Z7a^gXXUpYHTAOY#c^eS3NFFihv|t=I;{3ASj+qfL zy*~g|h3ks(E%*wj$+aIN*Sel;kxR81XXB${_j`O85z8ZD(jfp5F*+g^M8xBmQ!z9Y zx8W&_#4jc4>BVS0X~skxEcy*HZ_X&^*JEo$%&KMJUOa)5<#wvJ&mA)BC*aMJg+K5k zj=G+=}1mO2Q7gbYEjUM#!CXLq%sr zN@)p&11Y67cn_zRXdlJO$^%zotelz6C6e)SDVn>1-7aTT3FaEPb80QPTb`s20VuMl ztTXVAoVNCgUK5@v&M&~80;b9VGT9~;y`9*PNtN@vQc62}07xmVD^YjIY2GELu_p86 zdJn_L1;ById2I;&hD|c#N8&}?QgmKTDJ`o!(_;=Sl50CgX8eP4nw8&f#1fe!4LS!A z?9(}hTjb$$Rms9Q{Dix^`RfWGrL>_qo`hMr2(MIB=F8B{sw@j`Jnx&YZBXW$2!|hbxh=nyXTd1BQ_huV$qrneQrcfP`o1zyfGw>={iNKc zQwR7OH)23~{TP{y#WItJ4#eQUz3P_Wzmh@!E;tNe&;k4dViF52nS^%n00000NkvXX Hu0mjf0f_QM literal 0 HcmV?d00001 diff --git a/images/icons/instruments/percussion.png b/images/icons/instruments/percussion.png new file mode 100644 index 0000000000000000000000000000000000000000..046ca6bb957252433954605e95b037f56deda825 GIT binary patch literal 582 zcmV-M0=fN(P)W9Ki9RT|1e(q$Anx_PB_C2mX{&<$=t^Lwb!Xq~3;X%@*Z* zHSB*X7N~GvIf1lc6+ZNhKkV5wr_cAkP(Y=8N7~d`Q3HsIy6Sm7*1T5A8}zwmOpRP; zd~3>V@xa$My`+%4OzL%5EbxJk1pI2=5r77LCgcV*$@aTL4*~Yv@`x+yBmmqrE!)|! zhppN27hu(M0NyYwg)J{z13YO%8vJcXQbeFyowRn-(#P|Jfbn2^?%zp@2rD41*+lT@ zMFF$H_GzpL6R)rz=2iMTD@*ar)RADQBe)j+5sda1SE9; z!n*Bi7Xre72PJ%E$cRtX`)}thc~pZ&OPU0j@veJukAB~QxVV4?*Fl?FK&{*G558QQ U_gOSfg8%>k07*qoM6N<$f@qx#dH?_b literal 0 HcmV?d00001 diff --git a/images/icons/instruments/percussive.png b/images/icons/instruments/percussive.png new file mode 100644 index 0000000000000000000000000000000000000000..16fa12f809ab74bf86773df36db3af5d4a84d2cc GIT binary patch literal 520 zcmV+j0{8uiP)kdg0005cNkl$e!E5>OsX%`dSlB#yi z2#0J+A1M;)(qm2#Q_!qv*tEW}0f3x7>%NGOZq0~r2*GZxQXpv~oz!h1OVXG=B?C_L z9HkAvEIT=)<#Zt2yj|x=^9)^#+6}pI^+1NWyvu7JSNXvQy(h!3-~~C_X}1B_Ll13w z87zpH=mqsL4s=lDnC{6%v)gn4(3^fi+7e~TZj%lXS+pg9fFz@J{{#OfP^ERtv4E+}Z(+m|k001|Zo0000< KMNUMnLSTX@FztN+ literal 0 HcmV?d00001 diff --git a/images/icons/instruments/piano.png b/images/icons/instruments/piano.png new file mode 100644 index 0000000000000000000000000000000000000000..7842a5d211b15fb2b5af0aecd16ff4e6295f367c GIT binary patch literal 809 zcmV+^1J?YBP) zf(>{Zd+|H6hwkX-Bihb^h**fVb!8(}SGP>g-&mcQ=UZg}fi-v$@8gJ)&R(l)tDj=< zwpfk819%=E;AAELFF~979oBWnY!=}I*sbj4_xKW5a1-}p7>{B_%hWez7%xP`@yxt} zTWcU9R^jI<9GtCSCvi<_f2&CJWUc7A@Sr5sF?*~Nam-17{mGSwV7hNYe0J>+6$ z9>P}@ZoM)K#w+*)-s*b{w**)+m2pGH>gNxcd8)0^bO1wb9cAWk5pk~CwU+4s7IiKn z;({_`yJG;Ec{w8XbluvbOva%u9c-8#ohd-;e?+aEMQp-1nR#`t n0AjkT|6c)SBXj;000B>0jC>@O#lD@8FWQhbW?9;ba!ELWdL_~cP?peYja~^ zaAhuUa%Y?FJQ@H10wqaAK~z|Uz1F#FltCEB@z3PI12KpgEyRQ*MjNpdv=bDGiAPEi z{{aydEVQu@Y%DxFu}FeZ>?Eavf}Pq38Wmhqcz{=@g%}}>#XD=(&8~az0}uN$J2T(s z`OQ2JBgUxJjup6pjwS!KDS$CVOcw{yp*?mW{T{_s2w{=ihU^1ACk668l~9jouW*m2&W=22cRcOa2n;Dy?fuBTBdZk*wywr{Nx~uDG~~nLkUCuf^>D zWN(@R1)2BZM~ra+%Wyl!I2S@#R%wr}Ccr=81x7;%H?bV!A%t1HlBrYP8kGGjy3*KH z45J(8RCxrA-u7SEnEZaqelG^9-mgyhJ)DxY)f`U9ZvO=g*0g7xnXgY{$FU`Sk6?4n ziq-*-ID_r7{=N_Ut3C6Y%dp_KKgUko#cA0)?+y+k7h{~Ov{y;1A@h+mwi~@_2jbrVE#~5|WI^DJepJ}+RYqUQo+CaScy{4i7 O0000%xDq$x^S7%Lkqi50U^78atE2piKJi~C;P%bj`u+&gzpow~j6d7kg@ zJm)#*y^)z#(?*63jEKz z8nMT#1XUIg5nC};L%{C71VqH%h}cy8p2Qq>))4TqQq&T)UXK^}fah9sylU+e3)o+~ z4Y3FJ@U14W)4$+s<%`_`Kc&3C%X}JJ>U36Qrid8FJB(JUTerQ&Bkan|)3sL@+23iH z@f=2*jPtG%V7>wTJ9hK~?;J!6wU3TxnOUvXma(>g_YKzWi-?Vb5-`(X?Hg?GS3vs? zjNp~(^`Gyz_FZ=%GZ%4E>py!Hd)Rm8ohQ&Sj1J;+N%o(xZBQrB>pL)^HC%eZf8yAn w;5`KtBGzb)=9gOi{tFKgcyqV(DCY@~pS0t0+P zT>t<74`fmi=yWVA02(J%666=mU|`}9kdRT((9$oua?G=y|LcFZ^y%=clYrTk28mirSYMa{c( zz**|#xppQ-;i4Pi36s4V_6vv`sJCgFevzzG)Qc#(qkT9^dRp7|CvuBxf9lCi6tp#) Rm#hc!oTsaw%Q~loCIHJ&UsM19 literal 0 HcmV?d00001 diff --git a/images/icons/pause.png b/images/icons/pause.png new file mode 100644 index 0000000000000000000000000000000000000000..597d273f057cfb501bf7b6e2921096f4cab28d95 GIT binary patch literal 233 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzwj^(N7l!{JxM1({$v_d#0*}aI z1_qWq5N5ovcvA*YkiEpy*OmPqm$(=Y?@B`-ZlF+^r;B4q#NoHo47nN%cwFmaZe10& zs6Kq}%1z-N+k$sp3&?Qj=J=n>Y5%ZSUg1gd5#gY#ya#Tr;S4rJFPO12eEX*d&yFvhGGS)O Y+J3vIKkuFVdQ&MBb@08Rl?-v9sr literal 0 HcmV?d00001 diff --git a/images/icons/play.png b/images/icons/play.png new file mode 100644 index 0000000000000000000000000000000000000000..70b904e78265ba66214ea57dcb026e9c4c722bfc GIT binary patch literal 366 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzwj^(N7l!{JxM1({$v_d#0*}aI z1_qWq5N5ovcvA*YkiEpy*OmPqm$(>@;RSn=caiqfwEu_uHqzRpeGI#aRWsY3dzoWSq?Jb{}T@2p-O$;9y4!ToNy z`f0g?;Z|8|-|*F>@m2I3FEv{o%Sm%>qVf$80qr8eAdyHw>=*zZ9v%?s;RIpc zZZO2h9x{9#p`V`%r208QKtKT4^n43O1v-H&FaYd*lOQw11EQj$U|LL17~3ll>>?&W z|Ni~KF?I$F95@ihr6htvp@2!La@d*{1zA~HFmmKb$j;6Nx1pP0+_-TtWy%zI|J_`e zHfKeFd^FR^L2h_KjDzeu-ehh8#S44CMKgvAEgg&IZa#Qb6%;B9Pc=Hk&) zYVB&_Y2+QCr)TbLgF)#T{)Lv<8!GFl%6$U6E499Xh$9-U%++Y3g1fIJGQC&*ytz2* zj9WZzT>O0zx^?RYW@cu5oVCID>LE4(Pu$FU*n(Ir2C3Krxdfz^-NDS#0c>q;`50_x zX9o@r4&dnM2u@B;cx-S67Z(?Zc9XzBPYKAq93a`piI2-81Dqf!z>|;1fq{WAEXWmt zf`TAB*cFC`c|(4TH#mfi1G}g^aEP4=4so+!Wl}I7hn?U0Be)Fw7{+I1z&oQy@bP%; z*s{FPXn*(#^%z?Rc=R#3Y5gvbvVZnk0uyEl*2+aQhKK$@QJ|3@Fu>wj;N?^l= z4X|m`Ca9{af-k@Pl8?=M_Uz%~^WnpX;mDCAP+MCIXU?1fN-12wejOSc8~Ip$|Neb= z@ZbTow6s8bd%F;?U(~6DvfqUV`X(eK^s&cL>x(1|w}fEaLU4 z&|%9BAXHiI1o4Up2oTDZ{=xV!Hg$G&b+ziwQL)(Ew1>F6sfAc?d`37 za8w=Kl*zAKZfs&=LSC@{o{^D}9xo{O!BYg!UsSGVghx<)b(81Yt4oyWuUu}~5$<^S zbyH`)@;u{JgB&+ciN~!Nx0jix;D-yQrly+tiUppanp#+bw1*iuiOu-=ib)R#aIrK8 zD=RB7v2+C+8yhgOa_8qQo)Sw4l62S1U&0;4Ah!1asZZ4n;WLK;O_1Ya(4+NdD!yjp8a|{L8iYHMg&MT^P1q`U`UP#0IR@}U==hPWHK2{ zi}nIrSuXVH(+B4F@q@m7`$BSZGNh)a^7EUtv^2=b$bihuOc*t46ik>f0rK+lVAiZz z{Jf^Hun^|Wn+G3!@Bu%kS-Ny7Kd1TVqmN+i+O@E5-8$I3c{7xkm-FYFd-v{znwlCo zc<>+`I&=uW`Q{rqdh{rqI(3Ra_pGa{_lH*dnjhY$HVjd1>nolwAU(*wN{ zmFVN(tAu@TRZf5^O;nS9!K$3FSQUu@NW{^_VVDOVtT;FhQD$UDsZtF|@1@F#PgRjb zp}pWgWncK6_n$!nBvMc8{a(@@@)YGeic%&+lS7l!II2hrPtL$}cye_Afy%OH{oe(n zgB07lVQQ-^j8Z0%m=niQuF6}O4#u>*vg}!VZb`WF_A)H#%~j{BsM}i#?Kuw!{!_jg8rhFA7mPo8by85arP5>em^a3N4 z2+>t%y+kUsS361Y-+!$Cbi<1PJc!!an)IdmpC6vs^03gfQ%?#BEWv*-@Lx~7Lf8fD@PZ%@n~oKI`1L_N zFVHDQgAmgHGCy$Z#Kqiu*6DhkSVu<(aIGEidOPUoiTL}7boC9vScG{Z5g3W|!O%bi z-3;`>z`y`Zkn0&3gRX%I;I((;CLkgvU}$IvMn*RemOreJ{0b^rh;I5fl zm>2^FV$E8#6Rtty!a7)6TZ6xiIXK!_@oUb(5(@~o@4;Uu=hm6I>*P3t7tSjfKI3 z2W!@m)%PoL_bK^|KMFHv&IG^Q^AIrgiss&=RjXFP>eZ`Z&6+j*+A()seEs_M{I&6o z8#ijMkE`!nI(hOWziwP#Uk_KVToJB&bNx`jZ`A`Kc+G`{j~-sY(SmMIwj8;?s6&R# z!n;FG@N-qfULC50C_NIQT(i>Hp-y5!2brdq$# zcoBL2`K?D_qpNs@}h+DkGe2sXhO}e_i7dsHuYY5AjG)=O|PezUmAv z?QH+is*2C;U&glVeE-inQZLo3Jh%S<_Em)a^KN?PHgt~Qe`VJZ`kyKQsK>uB{+Q4q z#2>~Pnd^uKjK{AO4!nEkr@PaMzz!v4GZ0AB0oFZf^Re_9?8#^3LC{23{~py8P{ zm2~x1q}H!*{CByp&MFA|*BX2%{_XMCnR~m;6Z|juU)uvh|Lbbd{EPWlSIs&t7sj7< z?-SymF#b9nC`_g>{yJTMU_A8lRER(ScKk8K?__>u7?^kO0R1jslY7bq<-35!5J78v z!4X2yFd&o>NC`#5fKWytB@_(r zlu$Gb2xSCPLeVfFlo3b?MZNC`#5fKWytB@_(rlu$Gb2xSCPLeVfFlo3b?MZNC`#5fKWytB@_(rlu$Gb2xSCPLeVfFlo3b?MZNC`#5fKWyt zB@_(rlq^XdBsVp-Ge&NjG$3IJ z|Ak@PlO+r=XJr1i9IWG&l+b6`to3*5zs*fs?)bL{*@+8=I+h;}et+Aie;qt>z+e9K zVN7@b0q;%Oy^WU7{{wy4uJ?}-mzRv0m@YcFe3@}|+QeMzH=$dL#CWty|~JiHmWX_i5dvw2HcN z$K1t}lCuAKZ|woafzQgz@oTjft(~#*>Hfq!$D5Z{<5L7DeY?tI*{-EeyG^~acYE`_ zhVvWdM-GWOXBHm2_1u&DyKddSU2*-`+Q`_=x%gPYvyF|D(@NS#dAfWI@j*JpV|3x5 zKD=)P`eHEj1dD;-{3{l;rlfQu2|_nWukFuc&)ua`WR#^Z2y7liBSXTgjS;*s>=Nk2IXWy!d=dZSjhC zo*eTzW&6r+tZCHGneXmy*k^O^e@kn04Z-ojrDLm86k~Msi>vmWx~%vC+ZBR-t&H5lNEPnQng*tlb^!cXa8Zt zKa!gV*A|}lJNd^Ce*E#1T|*m&<=*XgMoe=HXCA1vFZR#cd3LFluk~z2UHzW-a&vNi z@Qv%Mcs$eFV)|$1Y1t1(9jU2_zw_N+%G|Q{e}CbN36EPITpO`(PC?#xpN~Dg;og;f zb04=pzAeheM^Dh{mD(k``d^F~ri`5lwS<<+|;epxv8<+ZLhs4BW z;n&Nh_4a^_%8}cz9a$N8>+|yRqPC{G6D5&0g+)(mc3gaPtYOCZW7p=lZ_mkA1h%wd z$@vAuJbK6VM#z>sDPwxBc_lTOU9E{@c|nCP&R| z9KL+zN^Dth`&`|lM~AYnJuP_n{kOXdf6C98{L`u>OP1J4B-8y$kW zVERt=h!n-PCtFBk!+`@iIXM@lC8ed6TNNA98*2W3>yG{8xhHE*m9NOl+%Y5XL{Z`S zrtdBsWX}q+nYRi@_7o~HX8Z%Q;QtHanDkh!T zl9E?@VP{^}k)4h8dv@KuvhPyUcmKRmd;4^mygL8-(Th9YPQEmK(c;B1JKwG?jV-uw z@{^rMM(>-GhOw;5$~XP&xzDmLm3}ep+TZX`*j74QI(5`n`I}cb^?s6ar0`bbg)a*3 zUjC}}r~6g87s~UNPnjLuzH(07+JU3?_TX& zmK891@9?dIJ}F=Ar8u`ad97W2NJK=s*P!*=%H%80wY1DC%fhc%oHTy?r{yQw@5 + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/logos/logo128.png b/images/logos/logo128.png new file mode 100644 index 0000000000000000000000000000000000000000..72417a9f617da3d3b6fb92d3741bf2ab559c5ca3 GIT binary patch literal 1132 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4P@*w`2}1t`K<;1OBO zz`!jG!i)^F=12eq*-JcqUD@w(GxC|MB};UAFfcIx^mK6yskrs_uD!?Na+%{F{r^>I zMkVi9@Kov$XOfACV2O}6qdF%f-zwghz?WH2LZtYrK&q?3+Yj3)_=1<-JJ#qT(d%v7` z`ThN_t9Kq0ny78sq(kCZf6Q@rIfKf}!jb_0>iwlAkDp%5-(~e{=HkP_ zm}Zq8eCeR|K`U7^{U*x?!%eYyy*AcG{{mhY2_M*7)Axn_mC^Cy@bCT3XSyA5y9DM= zey5MV3tOEWk4Z=-zdQ5j-K8iwuH+uBR;R+OiC5g)H_4UD(Nul{x)O-jqj>A4OGWqnk|_IsU%HtNE7AF)^{O>;3)x_brk$GFGJMYHMptNk|0L*Y8(ZxpCvg zkN?E{U(WPV+q!*wIv*cjmfW_D8yDsW-CwQxY3X9uzlDER&-=e&-N}5n z%-p<^mw`!v;T;nZi53!w?>29@le}`_Lcr$@uU}{Htteb|;jx)}_pjGiynUB@sEY#k|M4EyH~xVY^_ z`5*`&`ZA0~!^G0eIF#Nkf}r!ECL&V=6h#Hu1Ne-uGSU|_v5w`9Bg8XBdPLeE_%gp6+tX8W`r_=O(pF#+R zVMr+@f4##04-fz#gg|Cx4SshNv+)Halga44Ez5%Ix=17vux%TfrXiotLx{HzkW!K) zclQpNTrF~QYlkGGBfj^+_$Nmcp63Ao!r%#GY8QOzz;PV7t_#O;03hmcNB{r;07*qoM6N<$g5Qe3jsO4v literal 0 HcmV?d00001 diff --git a/images/logos/logo256.png b/images/logos/logo256.png new file mode 100644 index 0000000000000000000000000000000000000000..bf1da07a9496c65c459b4885bde887ac136bd23a GIT binary patch literal 1690 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G$6&6|FB^`vv7S!YWg%(4$oI-MPD?{7KQyj*cTwi*nb! zesy*A`+awmg=nSrVk_f6n@Rpyg|} z1v__I&YC^@t(^RqXJ=AwfwIk!WF0^c6!}O zm7GK-1||j$1_g!&25K=H7;Z2LFgSohpM~MZ9iy){cW!UbPp+)oxh~CX`Q?qt$NALR z8Gi@?y>hqu*CNHx-{#ufoA# zfSgK;is~c#J+Cuza(eFFySM87%{zBu_EdaSx^?T;qRpE( zzuN!)6`B7pe+s-Gu>V(eudA8l*>*KB- z)sYX<5lb#AGAet2@9#&3FWPkn+2y@iy6(@tz15E|E_M&Szj@=vjS^B)U7OR-yXj3|{p-DT-Jgm(yGpYU_vh#5 zufMU6hmY^rks~g#XNrD(dAXzRZ&mD>Pl`Wl?D*vEWNdA1->>~CB(TkZ5uBKa4Six1 zqr?zAswiZ@v(nXRDxPQ4Ph6>LSnS^KwlF|rx0$uIw0``)o|4DkJeJNrb?@?ywOf-m zo8-Um*m^bS=GLuKoz|=qS+sYrt(CR)>3f&2U*E3D|LVX2hcjo+Oo^R6dv^ECnKLtT zb9-xlf1A2@IS?dmma!~SS+;E1sdZ=1pFjTj`T6AQ>tZk7y&L;&9y2>%NY1o>|Nd3{ z`B8Xt>(Qe}XUv<|H*MOq8~f|)Z&vTxwTtD!rKR4l*TwEAP}GatBas_>|484pd8^J} zx@Ibn`+AM;8N05ZGv_}(Gt+qD>8IPS)UV1hlfId=?ai$lHzIg=d5=DLkPx%4X6LKT zJv}`~PMq+#xm7!S-I1Ne&mSG>6fS&wYwN1>Mm9DwhYuf4y?*TY@yAzI1{c1$v2n(X z86N~m&1nJ*(Ug}>HOtOaaW7uH*wD@{?(#!9yBY~W!S(-t*>ZK)Un`jwlxU}<^zP11 z;pgY)uYalYvu5ABw4K%8^UkKvoHM7Vqoex!yQ?+RUcP);f4*RCdSpbzk1wrVItU@gMn>FVdQ&MBb@0KRBts{jB1 literal 0 HcmV?d00001 diff --git a/images/logos/logo32.png b/images/logos/logo32.png new file mode 100644 index 0000000000000000000000000000000000000000..0576283c430616c3ef8fe776450e26ee8a034572 GIT binary patch literal 624 zcmV-$0+0QPP) zWAh-l;px|w&6_WgOLK<9A^Q2vb!~e)#ltPb(;q&cF#LFR-4K7-0swuPQ`1c}ZK1`n z5qG>E01;v9{xfbQGM?|#`&XPDxBsJ0@FzBN1$*Xt+Lbi}yl4-3`F3~#2tZpOz;{Oj zC)fx6#Z{0@CVh_ac+BbXJAT|$p3j+`VHgJCaCm8v$z+1-y2N5JG)=>C9H!GLx~`+^ z^ER_>8-Q3W=1=Z)I&#sJQUb{BVny!UeJTl66hL-&cfFYX{e53fsZv^M@L5z^gsX*00aQP0WcrzuIsLj5LtS?ENA67K0G|6^5i+_ zn*by;_jvrMOub%TS>)j0fM&Bvxm*UIR;v+-M5tD)02B%Z8jS|UV)5!Xkk97{M>jY> zm4@^viCdePrnwRzo6Vw>^7eVdFi=XN)O?XZos5pkMJ)GN7~IbH=)%pTXIDO&urzON@}?PTvYR;mF}h}WDtL3U zX)O%!%3^lfqLJP+>Ga*be2WD3SO+gv`t|!D@5Ap;_a0||_wkbu8^gtnDe^Kh53EA! zv)NxwxNrJ-<+Zk}x9e9{{`&Q6!@hmzBp6tj82hq=^ygP>{8Dqm^z)a){BK?yTKfEw zNpEGr>23y&1}MtQ|5_saXb!XO-vqgXs>zIRZ8tnV{PZky#fm+L{<v<$Itz(EjYI^_Ak%cf4n_&_kMVA$7T0Y+50k#94t)RlD9_bdQ3{WoozPTfQNZm zrjr0m#oo9dHFmeR&Pn-GXYUed^H#d8F>N#FWs`>=D-K8$$8>9ST`+n3!`W!&6F=3{ zM(hQ@c=~)k9lv;e`FZA_uI}{}6*mgkynLB?{N9x-A;&Gaxw)UOOD!$kx;S2My7jMx z0VfLgr5K%jDGGNh24l9>&gZ}Hr$%1e`T5`Ls9h)L|NdNIHP>xz*x@^~zdv}ypi;kK z@%yj52?Z%a&mQLQ@jc@hIE9;0MTqmvnKKE6g@T_yf1Z%~(?@Oc$%O1|?wv7wn>TNk zkbeE=`m9A75z*1kX0uyYt&)(H-D`8;$PpGZb92SJp3L_y%(P2ps(Rm+FrzvkRCJ=p z6DNj;1rk7X`t<3JEwSVJ>lrr>D~5%I1?Y&$8eh%2S~@S!sMn2IT3UMD%%GJlvDX8& irpg#UEs|vTAU@lvGw+Doxl6$0&fw|l=d#Wzp$P!R1ZVpI literal 0 HcmV?d00001 diff --git a/images/logos/logo_u.svg b/images/logos/logo_u.svg new file mode 100644 index 0000000..ffd8cf7 --- /dev/null +++ b/images/logos/logo_u.svg @@ -0,0 +1,123 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/images/logos/logo_u128.png b/images/logos/logo_u128.png new file mode 100644 index 0000000000000000000000000000000000000000..2cb8db0264a4cd07d0193c219b4cf194e46bf386 GIT binary patch literal 1057 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSEX7WqAsj$Z!;#Vf4nJ zu*HKgqwnD*Q-Ok#C9V-A!TD(=<%vb94CUqJdYO6I#mR{Use1WE>9gP2NHH)l&+~L~ z45^s&_U`^{;X;{XAD{ou<#KP1X6OE@cXZ*hZfAD!kL-M6F?aq5|6%^aeC6!bwcQJ% z9hY-8b#dtN@%c&ZesTBWwNnE8_It03@y?kPmvP{ErS9G@Rq}S_wa&(-=gu%N zcuulmEf93z`#HaoL4UEvE*^%hmpT~^{O|~yv{+1py>3eMi5Hp-MO+PYm=u;XoES{Z zaK40`l;{(IxBtdYx3?_ea$q~aXSjyrWa++X={esGFTcH=`d{Yt8A%sIW9uiSq2-$P z)056EIL~_Hcjmgo6?zO8H2BK$uULLpJO5d`*X{9Pg~^vpVvROu|K9i3>v;MijjHMk zJu04Q3^i|xPL-BL^Bw;1N}>8_Va>Jb{{}pVS30hXj*Ohi+4NvR?7Y^*9T&3wW-aSZ zE8Ba!r|)y1$X>e)x7Al?&6+VI;{SC$hB(*2l7-jxQVV6|zu&vBANSgp!IIU%k8wgU z!xIr2Ggp88H?g_$eg2y_Z|<-$7+XKzyFW8+de`U3X{EpCS6Aoc<*oDc^E)THes1yk z&o=uXi)NKQ`Pzv|u1^<}&FO0hUrPFJs-r*HLq8smbn)mwkhDPA47{yr;%@$9en z?i+93e6-T|_myn7%{TwdQt_;ue!Oy?eZe_frUsky_228$?}qXvR8>{+9*|-4~17KY#KZcxRe9D~%zHeXcQ2Y}rrdgxU+S&z?OqW5{7}kU9RCVH%*?PPb5}~*a>ks{8Ra|&I2qn+zq`t^f$u?jt7ItyFT;DS zcSWbp?6Y`Y7cxVT!NRg7Htp=2*~RawTP01O-^r3_<7W6E9%yyKlkH#ZIbe2X@O1Ta JS?83{1OOu@pEUpg literal 0 HcmV?d00001 diff --git a/images/logos/logo_u16.png b/images/logos/logo_u16.png new file mode 100644 index 0000000000000000000000000000000000000000..36d7b7096be19bf039e557bb4c9dfdf06f70aa5f GIT binary patch literal 375 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf2?- zGa$_Pnjt_F$dD{?jVKAuPb(=;EJ|f4FE7{2%*!rLPAo{(%P&fw{mw=TsOXEQi(`mI z@7swRy_gdPTGFS9WUk3+I{J2EHRHk6Z*o3aT>q(JrnGG%ubI%64IE8QYl0$W+dEi9 zY8w7nn~8T$c*SvJ$Js+hpAC1P-nDMM=ez~Zp1a=9oauS%HIsqyX1!za6Y3eNCdn~g zVQ@<;6Bj%_N$hR;J`X+>S%wP60*(icmpY!TU9!|uYIn72=8PaK)(h+fd=C!YUEQ%m z@u%WT9*6sPwHXdyGyeBm`VC(~T6pEW^$b42Uis3WSsTxXqt&tp7u=kMGnDbBlRi{3Cf8|YHwrR90C@5Lt8c`CQpH@mmtT}V`<;yx0|TqC zr;B4q#hkY{c6ZN7WjOj!nA62XAtG~fIFA$8!46je9iFh4ixMUt3JU1nq7)HX!RY9y z645y~?4sL-3lSb0I07#yFsjxa^A<97`@?+gknXk8a;|iv%};FnjpgsBJ~P<;C!zfM zty@uMvzEPFsiMwwC!?>|@ZQ~uN6SKW8N>V;7R+F9Fl1~`&z)-(BPwtcAr+uj0uCg<`@43GE&sxLaqT)%rpI7|z znsh(!fbQluo}27X&Y!KHBif*UExy0s@ZSD;t0$$*TBhu2H|MeLJo)53dl%@oPp&aK z9=*rln8n5p-OWCizxYftpS;KXSVa}*{O<{qE*I}Ps-4_(U2MzKe=6zEE4r^Am(ahP z5uG-3*-M8>`IBn)|D09N?)SCpKQ!sC+q#GViNzPJ;slJy8f&>HqCvq z&BP~*Rq}I-&rj#RvuX02^WW~Do~YulW;yjqZ|=LFS&h+pXKs8dnDp4wPrb5qcJ(>k z%+m{1&Z}8YesWYb=VyGFT!Z1Urz+~(cbWNKKKS);{&9)udz&BV?mu^<==`sTt*JRT zJ&#F*Z~pte==raQM^*p!tUG&SQ~BQy%VjsD=KlR~$?sq7NA*FUd2g)Sx^-*)+!@PW zW=xvw>8JWLQFO7H#f&HWRGv?o6Zvsk^<ON z8`ZgC!EWpCH&Uj370Hv0DicgRWhXg%ddV$OWjJs~O~sdCg)xf(XM)Pf z$+=xiyroRP&3Eo8j1+nmDRMM8P^8Q7oVQcYN0XO}Zv{_#dT;uf+D|&m&(vLd?&+`o z_tu%C65-MIO<;@Iey}}w=RK*+nM0pJz{x^!r?}IOA8S4L-@m_N)hmUT4-<^0d&;Z- zRm;47H~b%q!cV`V3mUz5YB?7C;$3k2EuRM;;}v3e#^e>uqor3}+j zcfNb~`1GT9o71*&JjlyYGFQE8Rus*UXJ@KZt`ckdW!sY1ZK=EtEFU7o&*Xe#zEFAV Vd92KqY+!USc)I$ztaD0e0syPc!vFvP literal 0 HcmV?d00001 diff --git a/images/logos/logo_u64.png b/images/logos/logo_u64.png new file mode 100644 index 0000000000000000000000000000000000000000..61dbede2aa875069d3c7d9541f8d56f7414d9091 GIT binary patch literal 750 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=EX7WqAsj$Z!;#Vf4nJ zFdKj{Bh&Y0JD{LsiEBhjaDG}zd16s2LwR|*US?i)adKios$PCk`s{Z$QVa}C*`6+r zAr*7p&bG}K2^49&Z*0sbC18Ib>Bfwmt_f><#9rp8gdR9_OYO$e&*DG$U0i0HG?_Iu z{cz3^aojN5@rvq6rA0SW&OX^^CLB5KF9Y{|rRR;h)2hGSNtd6Ime{NEYFAx;ns`Bz z!cG0tpQ^6y%lC+zCiS;|ACtqPZ2^xNuP|lVG(GqVF#wx+a-V8E~5)2Pc>|~5!m@uh_VbM%pHC?04bDq4H zOkaLRN41hAfn&kUr%pxp&pi65=xMx}l|i%N#y+)O3_HGhY!cX^tAm+J%67*eLA=D`!8ke;jV7iu(f`Ez0aq|R}?pQGvrOG zvCUQUoOD~|{-i%f$>-TlJ};hQ#^5v8aPww{Yo7aNJuKor&@Pc|oBZt7rAwEd$**d9 W`fRSmQCDEvWbkzLb6Mw<&;$S;2s>#2 literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 0000000..4baa031 --- /dev/null +++ b/index.html @@ -0,0 +1,43 @@ + + + + + Piano + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/js/app.js b/js/app.js new file mode 100644 index 0000000..302a326 --- /dev/null +++ b/js/app.js @@ -0,0 +1,96 @@ +/*jshint es5: true */ +/*globals MIDI, React, App, $ */ + +/** + * app.js + * + * Bootstrap app: + * - connect to MIDI device; + * - config vendors; + * - instantiate main component; + * - integrate with shell. + */ +(function () { + 'use strict'; + + var remote, ipc, shell; + + // shell integration + if (window.atom) { + remote = window.atom.require('remote'); + shell = window.atom.require('shell'); + ipc = window.atom.require('ipc'); + } + + // configs + window.vex.defaultOptions.className = 'dialog-theme'; + window.vex.dialog.buttons.YES.text = 'OK'; + window.vex.dialog.buttons.NO.text = 'Annuler'; + + // bootstrap + function bootstrap() { + var main = React.renderComponent( + App.components.Main(), + $('#content')[0] + ); + + // we're ready to receive shell options + // and to show the window + if (ipc) { + ipc.send('ready'); + + ipc.on('options', function (options) { + main.setProps({ + url: options.file + }); + }); + + ipc.on('visible', function (state) { + if (state) { + main.resume(); + } else { + main.halt(); + } + }); + + window.onkeydown = function (e) { + if (e.keyCode === 123 && remote) { + remote.getCurrentWindow().toggleDevTools(); + } + }; + } + + // handle links in default navigator, not in app + if (shell) { + $(document).on('click', 'a', function (e) { + shell.openExternal($(this).attr('href')); + e.preventDefault(); + }); + } + } + + // on error, offer choice to retry or ignore + function error(err) { + var modal = App.components.Error({ + title: "Erreur d'initialisation", + error: err, + canRetry: true, + + onRetry: function () { + window.location.reload(); + }, + + onClose: function () { + bootstrap(); + } + }); + + ipc.send('ready'); + modal.open(); + } + + // establish connection to MIDI device + App.MIDI.connect() + .then(bootstrap) + .catch(error); +}()); \ No newline at end of file diff --git a/js/components/Channel/Channel.js b/js/components/Channel/Channel.js new file mode 100644 index 0000000..ef11546 --- /dev/null +++ b/js/components/Channel/Channel.js @@ -0,0 +1,228 @@ +/*globals React, App */ + +(function () { + 'use strict'; + + /** + * Display channel + */ + App.components.create('Channel', { + displayName: 'Channel', + mixins: [React.addons.PureRenderMixin], + + statics: { + programs: [ + 'Grand piano acoustique', + 'Piano acoustique', + 'Grand piano électrique', + 'Piano bastringue', + 'Piano électrique', + 'Piano - effet chorus', + 'Clavecin', + 'Clavinet', + 'Celesta', + 'Glockenspiel', + 'Boîte à musique', + 'Vibraphone', + 'Marimba', + 'Xylophone', + 'Cloches tubulaires', + 'Tympanon', + 'Orgue Hammond', + 'Orgue à percussion', + 'Orgue - Rock', + 'Grandes orgues', + 'Harmonium', + 'Accordéon', + 'Harmonica', + 'Accordéon tango', + 'Guitare classique', + 'Guitare sèche', + 'Guitare électrique - Jazz', + 'Guitare électrique - son clair', + 'Guitare électrique - sourdine', + 'Guitare saturée', + 'Guitare avec distorsion', + 'Harmoniques de guitare', + 'Basse acoustique sans frettes', + 'Basse électrique', + 'Basse électrique - médiator', + 'Basse sans frettes', + 'Basse - slap 1', + 'Basse - slap 2', + 'Basse synthé 1', + 'Basse synthé 2', + 'Violon', + 'Violon alto', + 'Violoncelle', + 'Contrebasse', + 'Cordes - trémolo', + 'Cordes - pizzicato', + 'Harpe', + 'Timbales', + 'Ensemble acoustique à Cordes 1', + 'Ensemble acoustique à Cordes 2', + 'Cordes synthé 1', + 'Cordes synthé 2', + 'Chœur - "Aah"', + 'Voix - "Ooh"', + 'Voix synthétique', + 'Coup d\'orchestre', + 'Trompette', + 'Trombone', + 'Tuba', + 'trompette en sourdine', + 'Cor d\'harmonie', + 'Section de cuivres', + 'Cuivres synthé', + 'Cuivres synthé', + 'Saxophone soprano', + 'Saxophone alto', + 'Saxophone ténor', + 'Saxophone baryton', + 'Hautbois', + 'Cor anglais', + 'Basson', + 'Clarinette', + 'Piccolo', + 'Flûte', + 'Flûte à bec', + 'Flûte de pan', + 'Bouteille - souffle', + 'Shakuhachi', + 'Sifflet', + 'Ocarina', + 'Signal carré', + 'Signal dents de scie', + 'Orgue à vapeur', + 'Chiffer', + 'Charang', + 'Voix solo', + 'Signal dent de scie en quinte', + 'Basse & Solo', + 'Fantaisie', + 'Son chaleureux', + 'Polysynthé', + 'Chœur', + 'Archet', + 'Métallique', + 'Halo', + 'Balai', + 'Pluie de glace', + 'Trames sonores', + 'Cristal', + 'Atmosphère', + 'Brillance', + 'Gobelins', + 'Échos', + 'Espace', + 'Sitar', + 'Banjo', + 'Shamisen', + 'Koto', + 'Kalimba', + 'Cornemuse', + 'Viole', + 'Shehnai', + 'Clochettes', + 'Agogo', + 'Batterie métallique', + 'Planchettes', + 'Timbales', + 'Tom mélodique', + 'Tambour synthétique', + 'Cymbale - inversée', + 'Guitare - bruit de frette', + 'Respiration', + 'Rivage', + 'Gazouilli', + 'Sonnerie de téléphone', + 'Hélicoptère', + 'Applaudissements', + 'Coup de feu' + ], + + types: [ + 'piano', + 'percussive', + 'percussion', + 'effect', + 'brass', + 'pipe', + 'string', + 'synth', + 'guitar', + 'orchestra', + 'bass', + 'organ' + ], + + getType: function (id) { + var types = App.components.Channel.Channel.types; + + if (id >= 0 && id <= 7) { + return types[0]; + } else if ((id >= 8 && id <= 15) || (id >= 104 && id <= 119)) { + return types[1]; + } else if (id >= 16 && id <= 23) { + return types[11]; + } else if (id >= 24 && id <= 31) { + return types[8]; + } else if (id >= 32 && id <= 39) { + return types[10]; + } else if (id >= 40 && id <= 47) { + return types[6]; + } else if (id >= 48 && id <= 55) { + return types[9]; + } else if (id >= 56 && id <= 71) { + return types[4]; + } else if (id >= 72 && id <= 79) { + return types[5]; + } else if (id >= 80 && id <= 95) { + return types[7]; + } else if ((id >= 96 && id <= 103) || (id >= 120 && id <= 127)) { + return types[3]; + } else { + return ''; + } + } + }, + + propTypes: { + id: React.PropTypes.number.isRequired, + program: React.PropTypes.number.isRequired, + muted: React.PropTypes.bool, + solo: React.PropTypes.bool + }, + + getDefaultProps: function () { + return { + id: 0, + program: 0, + muted: false, + solo: false + }; + }, + + /** + * Render channel + */ + render: function () { + var title = 'Gestion des canaux', type, name, + channel = App.components.Channel.Channel; + + if (this.props.id === 9) { + type = channel.types[2]; + name = 'Percussions'; + } else { + type = channel.getType(this.props.program); + name = channel.programs[this.props.program]; + } + + return React.DOM.li({ + className: 'channel ' + type, + 'data-channel': this.props.id + }, React.DOM.span(null, name)); + } + }); +}()); \ No newline at end of file diff --git a/js/components/Channel/Modal.js b/js/components/Channel/Modal.js new file mode 100644 index 0000000..d603171 --- /dev/null +++ b/js/components/Channel/Modal.js @@ -0,0 +1,58 @@ +/*jshint nomen:true */ +/*globals React, App */ + +(function () { + 'use strict'; + + /** + * Modal for managing channels + * + * @prop {channels: Array} List of channels + * @prop {open: func} Called to open the window + * @prop {close: func} Called to close the window + */ + App.components.modal('Channel', { + displayName: 'Modal', + mixins: [React.addons.PureRenderMixin], + + propTypes: { + channels: React.PropTypes.array, + + open: React.PropTypes.func, + close: React.PropTypes.func + }, + + getDefaultProps: function () { + return { + channels: [], + + open: function () {}, + close: function () {} + }; + }, + + /** + * Render modal + */ + render: function () { + var title = 'Gestion des canaux', channels; + + channels = this.props.channels.map(function (channel) { + channel.key = 'channel-' + channel.id; + return App.components.Channel.Channel(channel); + }); + + return React.DOM.form({ + className: 'vex-dialog-form channels' + }, [ + React.DOM.h4({ + key: 'title', + className: 'main-title' + }, title), + React.DOM.ul({ + key: 'channels' + }, channels) + ]); + } + }); +}()); \ No newline at end of file diff --git a/js/components/Control.js b/js/components/Control.js new file mode 100644 index 0000000..56cd224 --- /dev/null +++ b/js/components/Control.js @@ -0,0 +1,129 @@ +/*globals App, React */ + +(function () { + 'use strict'; + + /** + * Sidebar controls + * + * @prop {playing: bool} Whether a song is playing or not + * @prop {opened: bool} Whether a file is opened + * @prop {speed: number} Current speed rate + * @prop {play: function} Called to start playback + * @prop {pause: function} Called to pause playback + * @prop {showChannelsModal: function} Called to show channels manager + * @prop {setPlaySpeed: function} Called to set play speed + * @prop {close: function} Called to close + */ + App.components.create({ + displayName: 'Control', + mixins: [React.addons.PureRenderMixin], + + propTypes: { + playing: React.PropTypes.bool, + opened: React.PropTypes.bool, + speed: React.PropTypes.number, + + play: React.PropTypes.func, + pause: React.PropTypes.func, + showChannelsModal: React.PropTypes.func, + setPlaySpeed: React.PropTypes.func, + close: React.PropTypes.func + }, + + getDefaultProps: function () { + return { + playing: false, + opened: false, + + play: function () {}, + pause: function () {}, + showChannelsModal: function () {}, + setPlaySpeed: function () {}, + close: function () {} + }; + }, + + /** + * Keyboard shortcuts + */ + componentDidMount: function () { + window.addEventListener('keyup', this.keyUp); + }, + + componentWillUnmount: function () { + window.removeEventListener('keyup', this.keyUp); + }, + + keyUp: function (e) { + var code = e.keyCode, index; + + // space: switch state + if (code === 32) { + this.switchPlayState(); + e.preventDefault(); + } + }, + + /** + * Delegates + */ + switchPlayState: function () { + if (this.props.playing) { + this.props.pause(); + } else { + this.props.play(); + } + }, + + /** + * Render control + */ + render: function () { + var controls = []; + + if (this.props.opened) { + controls.push(React.DOM.button({ + key: 'switchPlayState', + className: (this.props.playing) ? + 'switch-play-state pause' : 'switch-play-state', + onClick: this.switchPlayState + }, 'Play/pause')); + + controls.push(React.DOM.button({ + key: 'openChannelsWindow', + className: 'open-channels-window', + onClick: this.props.showChannelsModal + }, 'Ouvrir le gestionnaire de canaux')); + + controls.push(App.components.UI.Selector({ + key: 'setPlaySpeed', + className: 'set-play-speed', + + values: [1, 0.5, 0.3, 1, 2, 3], + value: this.props.speed, + + onChange: this.props.setPlaySpeed + })); + + controls.push(React.DOM.button({ + key: 'close', + className: 'close', + + onClick: this.props.close + })); + } else { + controls.push(React.DOM.button({ + key: 'close', + className: 'close', + + onClick: window.close + })); + } + + return React.DOM.div({ + className: 'control' + }, controls); + } + }); +}()); \ No newline at end of file diff --git a/js/components/Error.js b/js/components/Error.js new file mode 100644 index 0000000..416b4b8 --- /dev/null +++ b/js/components/Error.js @@ -0,0 +1,107 @@ +/*jshint nomen:true */ +/*globals React, App */ + +(function () { + 'use strict'; + + /** + * Modal for displaying Error objects + * + * @prop {title: string} Error title, category or extra data + * @prop {error: Error} Error object to format + * @prop {canRetry: bool} Whether the user can ask to recover from this error + * @prop {open: func} Called to open the window + * @prop {close: func} Called to close the window + * @prop {onRetry: func} Called when the user asks for retrying + */ + App.components.modal({ + displayName: 'Error', + mixins: [React.addons.PureRenderMixin], + + modal: { + showCloseButton: false + }, + + propTypes: { + title: React.PropTypes.string, + error: React.PropTypes.object, + canRetry: React.PropTypes.bool, + + open: React.PropTypes.func, + close: React.PropTypes.func, + onRetry: React.PropTypes.func + }, + + getDefaultProps: function () { + return { + title: 'Erreur', + error: new Error('Erreur'), + canRetry: false, + + open: function () {}, + close: function () {}, + onRetry: function () {} + }; + }, + + /** + * Retry handler + */ + retry: function (e) { + this.props.onRetry(); + e.preventDefault(); + }, + + /** + * Close handler + */ + close: function (e) { + this.props.close(); + e.preventDefault(); + }, + + /** + * Render modal + */ + render: function () { + var buttons = []; + + buttons = [ + React.DOM.button({ + key: 'retry', + className: 'bt primary inverse', + style: { + display: (this.props.canRetry) ? + 'inline-block' : 'none' + }, + onClick: this.retry + }, 'Réessayer'), + React.DOM.button({ + key: 'continue', + className: 'bt secondary inverse', + onClick: this.close + }, 'Continuer') + ]; + + return React.DOM.form({ + className: 'vex-dialog-form' + }, [ + React.DOM.h4({ + key: 'title', + className: 'main-title' + }, this.props.title), + React.DOM.p({ + key: 'description', + dangerouslySetInnerHTML: { + __html: this.props.error.message + } + }), + + React.DOM.p({ + key: 'buttons', + className: 'vex-dialog-buttons' + }, buttons) + ]); + } + }); +}()); \ No newline at end of file diff --git a/js/components/Key/Board.js b/js/components/Key/Board.js new file mode 100644 index 0000000..e143964 --- /dev/null +++ b/js/components/Key/Board.js @@ -0,0 +1,163 @@ +/*globals React, App */ + +(function () { + 'use strict'; + + /** + * Display keyboard + */ + App.components.create('Key', { + displayName: 'Board', + mixins: [React.addons.PureRenderMixin], + clicked: false, + + statics: { + offset: 27 + App.MIDI.keyOffset, + keysToNotes: [ + 65, 50, 90, 51, 69, 82, 53, 84, 54, 89, 55, 85, 73, + 57, 79, 48, 80, 87, 83, 88, 68, 67, 70, 86, 66, 72, + 78, 74, 188, 190, 76, 191, 77, 223, 192, 16 + ] + }, + + /** + * Set given note on given channel + * + * @param {note: number} Note number + * @param {channel: number} Channel ID + * @param {velocity: number} Note velocity + */ + on: function (note, channel, velocity) { + var key = this.refs['key-' + note]; + + if (key) { + key.on(channel, velocity); + } + }, + + /** + * Check whether given note plays on given channel + * + * @param {note: number} Note number + * @param {channel: number} Channel ID + */ + isOn: function (note, channel) { + var key = this.refs['key-' + note]; + return (key.state.channels.indexOf(channel) > -1); + }, + + /** + * Set given note off given channel + * + * @param {note: number} Note number + * @param {channel: number} Channel ID + */ + off: function (note, channel) { + var key = this.refs['key-' + note]; + + if (key) { + key.off(channel); + } + }, + + /** + * Set all notes off + */ + allOff: function () { + var i, keys = this.refs; + + for (i in keys) { + if (keys.hasOwnProperty(i) && i.substr(0, 4) === 'key-') { + keys[i].off(); + } + } + }, + + /** + * Events + */ + componentDidMount: function () { + window.addEventListener('keydown', this.keyDown); + window.addEventListener('keyup', this.keyUp); + window.addEventListener('mouseup', this.release); + }, + + componentWillUnmount: function () { + window.removeEventListener('keydown', this.keyDown); + window.removeEventListener('keyup', this.keyUp); + window.removeEventListener('mouseup', this.release); + }, + + /* mouse click */ + click: function (e) { + if (e.button !== 0) { + return; + } + + this.clicked = true; + }, + + /* mouse release */ + release: function () { + this.clicked = false; + }, + + /* play keys with keyboard (the real one) */ + keyDown: function (e) { + var code = e.keyCode, index, + Keyboard = App.components.Key.Board; + + // play note + if ((index = Keyboard.keysToNotes.indexOf(code)) > -1) { + index += Keyboard.offset; + + if (!this.isOn(index, -1)) { + this.on(index, -1, 127); + } + + e.preventDefault(); + } + }, + + /* release keys */ + keyUp: function (e) { + var index, Keyboard = App.components.Key.Board; + + if ((index = Keyboard.keysToNotes.indexOf(e.keyCode)) > -1) { + this.off(index + Keyboard.offset, -1); + + e.preventDefault(); + } + }, + + /** + * Whether keys should be played on mouse over + */ + canPlay: function () { + return this.clicked; + }, + + /** + * Render keyboard + */ + render: function () { + var i, offset = App.MIDI.keyOffset, + length = 88 + offset, keys = []; + + for (i = offset; i < length; i += 1) { + keys.push(App.components.Key.Key({ + key: i, + ref: 'key-' + i, + + note: i, + canPlay: this.canPlay + })); + } + + return React.DOM.p({ + className: 'keyboard', + onMouseDown: this.click + }, keys); + } + }); +}()); \ No newline at end of file diff --git a/js/components/Key/Key.js b/js/components/Key/Key.js new file mode 100644 index 0000000..aaac665 --- /dev/null +++ b/js/components/Key/Key.js @@ -0,0 +1,172 @@ +/*globals React, App */ + +(function () { + 'use strict'; + + /** + * Displays a key on keyboard + * + * @prop {note: int} MIDI note identifier + * @prop {canPlay: function} Whether the note can be manually played + */ + App.components.create('Key', { + displayName: 'Key', + mixins: [React.addons.PureRenderMixin], + + propTypes: { + note: React.PropTypes.number.isRequired + }, + + getInitialState: function () { + return { + channels: [] + }; + }, + + getDefaultProps: function () { + return { + note: 0, + canPlay: function () {} + }; + }, + + /** + * Start playing note on given channel with given velocity + * + * @param {channel: number} Channel ID + * @param {velocity: number} Note velocity + */ + on: function (channel, velocity) { + if (this.state.channels.indexOf(channel) > -1) { + return; + } + + App.MIDI.output.noteOn( + (channel === -1) ? 0 : channel, + this.props.note, + velocity, + 0 + ); + + this.setState({ + channels: this.state.channels.concat([ + channel + ]) + }); + }, + + /** + * Stop playing note on previous channel + * + * @param {channel: number} Channel ID + * @param {channel: Array} Channels IDs (default: all current) + */ + off: function (channels) { + var i, length, channel, current, + index; + + current = this.state.channels.slice(0); + + if (channels === undefined) { + channels = this.state.channels; + } else if (!Array.isArray(channels)) { + channels = [channels]; + } + + length = channels.length; + + for (i = 0; i < length; i += 1) { + channel = channels[i]; + + App.MIDI.output.noteOff( + (channel === -1) ? 0 : channel, + this.props.note, + 0 + ); + + index = current.indexOf(channel); + + // remove channels from current playing + if (index > -1) { + current.splice(index, 1); + } + } + + this.setState({ + channels: current + }); + }, + + /** + * Start playing note on mouse over + */ + mouseOver: function () { + if (!this.props.canPlay()) { + return; + } + + this.mouseDown(); + }, + + /** + * Play on mouse down + */ + mouseDown: function (e) { + if (e && e.button !== 0) { + return; + } + + this.on(-1, 127); + }, + + /** + * Render key + */ + render: function () { + var black = App.components.Note.Board.black, offset, + pianoNote = this.props.note, style, channels, channel, + isBlack = (black.indexOf(this.props.note) > -1); + + offset = pianoNote - black.filter(function (el) { + return el < pianoNote; + }).length - App.MIDI.keyOffset; + + // if it is a black key, we position it absolutely; + // otherwise we just play on its width to avoid rounding + // errors causing display glitches + if (isBlack) { + style = { + left: 'calc(100% / 52 * ' + offset + ')', + zIndex: App.MIDI.keyOffset + 88 + }; + } else { + style = { + width: 'calc(100% / 52 * ' + (offset + 1) + ')', + zIndex: App.MIDI.keyOffset + 88 - pianoNote + }; + } + + // get channel ID + channels = this.state.channels; + + if (channels.length > 0) { + channel = channels[channels.length - 1]; + } else { + channel = false; + } + + return React.DOM.span({ + className: 'key', + + onMouseDown: this.mouseDown, + onMouseOver: this.mouseOver, + onMouseUp: this.off.bind(this, -1), + onMouseOut: this.off.bind(this, -1), + + style: style, + 'data-channel': channel, + 'data-black': isBlack + }); + } + }); +}()); \ No newline at end of file diff --git a/js/components/Main.js b/js/components/Main.js new file mode 100644 index 0000000..c5f1e35 --- /dev/null +++ b/js/components/Main.js @@ -0,0 +1,464 @@ +/*jshint es5: true */ +/*globals App, React */ + +(function () { + 'use strict'; + + /** + * Display main view + * + * @prop {url: string} URL to MIDI file + */ + App.components.create({ + displayName: 'Main', + animation: false, + lastTime: null, + wheeling: false, + wasPlaying: false, + + /** + * State and props config + */ + propTypes: { + url: React.PropTypes.string + }, + + getDefaultProps: function () { + return { + url: '' + }; + }, + + getInitialState: function () { + return { + opened: false, + name: '', + + meta: {}, + timeline: [], + + playing: false, + speed: 1, + time: 0 + }; + }, + + /** + * Open a file + * + * @param {url: string} File path + * @param {showDialog: bool} Whether to show an open dialog (will ignore url param) + */ + open: function (url, showDialog) { + var remote, dialog, selection; + + if (showDialog === true) { + remote = window.atom.require('remote'); + dialog = remote.require('dialog'); + + selection = dialog.showOpenDialog(remote.getCurrentWindow(), { + title: 'Ouvrir', + filters: [ + { + name: 'Fichiers MIDI', + extensions: ['mid', 'midi'] + }, + { + name: 'Tous les fichiers', + extensions: [] + } + ] + }); + + if (!selection || !selection.length) { + return; + } else { + url = selection[0]; + } + } else if (url === '') { + this.close(); + return; + } + + if (this.state.opened) { + this.close(); + } + + App.MIDI.file.load(url) + .then(App.MIDI.file.parse) + .then(function (data) { + var parts, name; + + parts = url.split(/\\|\//g); + name = parts[parts.length - 1]; + + this.setState({ + name: name, + opened: true, + + meta: data.meta, + timeline: data.timeline + }, function () { + this.stop(); + this.setupChannels(); + }); + }.bind(this)) + .catch(function (err) { + var modal = App.components.Modal.Error({ + title: "Erreur d'ouverture du fichier", + error: err + }); + + modal.open(); + }); + }, + + /** + * Create a new file + */ + create: function () { + this.setState({ + name: 'Nouvelle composition', + opened: true, + + meta: {}, + timeline: [] + }, function () { + this.stop(); + this.setupChannels(); + }); + }, + + /** + * Close opened file + */ + close: function () { + this.setState({ + name: '', + opened: false, + + meta: {}, + timeline: [] + }, function () { + this.stop(); + this.setupChannels(); + }); + }, + + /** + * Load file when mounted + * Set up keyboard listener + */ + componentDidMount: function () { + this.open(this.props.url); + window.addEventListener('keyup', this.keyUp); + }, + + /** + * Remove keyboard listener + */ + componentWillUnmount: function () { + window.removeEventListener('keyup', this.keyUp); + }, + + /** + * Load file when changed + */ + componentWillReceiveProps: function (props) { + if (props.url !== this.state.url) { + this.open(props.url); + } + }, + + /** + * Update window title on name change + */ + componentWillUpdate: function (nextProps, nextState) { + var name = nextState.name; + + if (nextState.name !== this.state.name) { + if (typeof name === 'string' && name !== '') { + document.title = name + ' - Piano'; + } else { + document.title = 'Piano'; + } + } + }, + + /** + * Playback control + */ + + /* start playback */ + play: function () { + if (this.state.playing || this.state.url === '') { + return; + } + + this.wasPlaying = false; + this.startedTime = window.performance.now(); + this.animation = window.requestAnimationFrame(this.move); + + this.setState({ + playing: true + }); + }, + + /* only plays if it was previously paused with halt() */ + resume: function () { + if (this.wasPlaying) { + this.wasPlaying = false; + this.play(); + } + }, + + /* pause playing */ + pause: function () { + if (!this.state.playing) { + return; + } + + window.cancelAnimationFrame(this.animation); + + this.animation = false; + this.lastTime = null; + + this.setState({ + playing: false + }); + }, + + /* halt play for future resuming */ + halt: function () { + if (this.state.playing) { + this.wasPlaying = true; + this.pause(); + } + }, + + /* pause and reset time */ + stop: function () { + this.pause(); + this.setTime(0); + }, + + /* update current time and play last notes */ + move: function () { + var previous = this.state.time, next = previous, + time, speed = this.state.speed; + + time = window.performance.now(); + + if (this.lastTime) { + next += (time - this.lastTime) / 1000 * speed; + } + + if (previous > this.state.meta.length) { + this.stop(); + return; + } + + this.do(previous, next); + + this.setState({ + time: next + }, function () { + this.animation = window.requestAnimationFrame(this.move); + this.lastTime = time; + }.bind(this)); + }, + + /* set up channel meta */ + setupChannels: function () { + var channels = this.state.meta.channels || {}, channel, + length = 16, i; + + for (i = 0; i < length; i += 1) { + channel = channels[i] || {}; + + App.MIDI.output.programChange( + channel.id || i, + channel.program || 0 + ); + } + }, + + /* do events in given interval */ + do: function (start, end) { + var timeline = this.state.timeline, i, + length = timeline.length, event; + + for (i = 0; i < length; i += 1) { + event = timeline[i]; + + if (event.time >= start && event.time < end) { + switch (event.type) { + case 'noteOn': + this.refs.keyboard.on( + event.note, + event.channel, + event.velocity + ); + break; + case 'noteOff': + this.refs.keyboard.off( + event.note, + event.channel + ); + break; + case 'noteAftertouch': + this.refs.keyboard.change( + event.note, + event.channel, + event.amount + ); + break; + case 'controller': + App.MIDI.output.controller( + event.channel, + event.subtype, + event.value + ); + break; + } + } + } + }, + + /** + * Allow file dropping + */ + dragOver: function (e) { + e.stopPropagation(); + e.preventDefault(); + }, + + /** + * Handle drop + */ + drop: function (e) { + var files = e.dataTransfer.files, file, + length = files.length, reader; + + if (length) { + this.open(files[0].path); + } + + e.stopPropagation(); + e.preventDefault(); + }, + + /** + * Delegates + */ + scrollNoteboard: function (delta) { + this.refs.noteboard.scroll(delta); + }, + + startWheel: function () { + if (this.wheeling !== false) { + clearTimeout(this.wheeling); + } + + this.halt(); + this.wheeling = setTimeout(this.resume, 250); + }, + + setPlaySpeed: function (speed) { + this.setState({ + speed: speed + }); + }, + + setTime: function (time) { + this.refs.keyboard.allOff(); + this.setState({ + time: time + }); + }, + + showChannelsModal: function () { + if (this.state.url === '') { + return; + } + + var modal = App.components.Channel.Modal({ + channels: this.state.meta.channels + }); + + modal.open(); + }, + + /** + * Render panel + */ + render: function () { + var control, noteboard, keyboard, scroll; + + keyboard = App.components.Key.Board({ + key: 'keyboard', + ref: 'keyboard' + }); + + noteboard = App.components.Note.Board({ + key: 'noteboard', + ref: 'noteboard', + + notes: this.state.meta.notes, + + playing: this.state.playing, + speed: this.state.speed, + time: this.state.time, + length: this.state.meta.length, + opened: this.state.opened, + + startWheel: this.startWheel, + setTime: this.setTime, + open: this.open, + create: this.create + }); + + control = App.components.Control({ + key: 'control', + ref: 'control', + + playing: this.state.playing, + opened: this.state.opened, + speed: this.state.speed, + + play: this.play, + pause: this.pause, + showChannelsModal: this.showChannelsModal, + setPlaySpeed: this.setPlaySpeed, + close: this.close + }); + + scroll = App.components.UI.Scroll({ + className: 'scroll', + key: 'scroll', + + current: this.state.time, + max: this.state.meta.length, + onChange: this.scrollNoteboard, + onDragStart: this.halt, + onDragEnd: this.resume + }); + + return React.DOM.div({ + className: 'main', + onDragOver: this.dragOver, + onDrop: this.drop + }, [ + control, + scroll, + React.DOM.div({ + key: 'roll', + className: 'roll' + }, [ + noteboard, + keyboard + ]) + ]); + } + }); +}()); \ No newline at end of file diff --git a/js/components/Note/Board.js b/js/components/Note/Board.js new file mode 100644 index 0000000..472ab0d --- /dev/null +++ b/js/components/Note/Board.js @@ -0,0 +1,191 @@ +/*globals React, App */ + +(function () { + 'use strict'; + + /** + * Displays a noteboard from given notes + * + * @prop {notes: array} Array of notes to show + * @prop {time: int} Playback time + * @prop {length: int} Playback length + * @prop {speed: int} Playback speed + * @prop {opened: bool} Whether a file is opened + * @prop {startWheel: function} Called when wheeling starts + * @prop {setTime: function} Called to change time + * @prop {open: function} Called to load a file + * @child Note + */ + App.components.create('Note', { + displayName: 'Board', + mixins: [React.addons.PureRenderMixin], + + statics: { + /** + * List of black keys + */ + black: [22, 25, 27, 30, 32, 34, 37, 39, 42, 44, + 46, 49, 51, 54, 56, 58, 61, 63, 66, 68, + 70, 73, 75, 78, 80, 82, 85, 87, 90, 92, + 94, 97, 99, 102, 104, 106] + }, + + /** + * State and props config + */ + propTypes: { + notes: React.PropTypes.array.isRequired, + + time: React.PropTypes.number, + length: React.PropTypes.number, + speed: React.PropTypes.number, + opened: React.PropTypes.bool, + + startWheel: React.PropTypes.func, + setTime: React.PropTypes.func, + open: React.PropTypes.func, + create: React.PropTypes.func + }, + + getDefaultProps: function () { + return { + notes: [], + + playing: false, + time: 0, + length: 0, + speed: 1, + opened: false, + + startWheel: function () {}, + setTime: function () {}, + open: function () {}, + create: function () {} + }; + }, + + /** + * Events + */ + componentDidMount: function () { + window.addEventListener('keyup', this.keyUp); + window.addEventListener('keydown', this.keyDown); + }, + + componentWillUnmount: function () { + window.removeEventListener('keyup', this.keyUp); + window.removeEventListener('keydown', this.keyDown); + }, + + /* keyboard shortcuts */ + keyDown: function (e) { + var code = e.keyCode; + + // top arrow: scroll top + if (code === 38) { + this.scroll(-0.5); + e.preventDefault(); + } + + // bottom arrow: scroll bottom + if (code === 40) { + this.scroll(0.5); + e.preventDefault(); + } + }, + + keyUp: function (e) { + var code = e.keyCode; + + // home: go to start + if (code === 36) { + this.props.setTime(0); + e.preventDefault(); + } + + // end: go to end + if (code === 35) { + this.props.setTime(this.props.length - 1); + e.preventDefault(); + } + }, + + /* scroll noteboard */ + scroll: function (delta) { + var nextValue = this.props.time - delta; + + if (nextValue < 0) { + nextValue = 0; + } + + if (nextValue > this.props.length) { + nextValue = this.props.length; + } + + this.props.setTime(nextValue); + }, + + /* reduce wheel amplitude */ + wheel: function (e) { + this.props.startWheel(); + this.scroll(e.deltaY * 0.01); + }, + + /* trigger opening window */ + open: function () { + this.props.open('', true); + }, + + /** + * Render noteboard + */ + render: function () { + var children, notes, + controls = [], id = -1, className = 'noteboard'; + + if (this.props.opened) { + className += ' opened'; + + children = App.components.Note.Score({ + key: 'score', + className: 'score', + + notes: this.props.notes, + time: this.props.time + }); + } else { + className += ' closed'; + + // add opening controls + controls.push(React.DOM.button({ + key: 'create', + className: 'bt primary', + onClick: this.props.create + }, 'Composer')); + + controls.push(React.DOM.button({ + key: 'open', + className: 'bt primary', + onClick: this.open + }, 'Ouvrir un fichier')); + + children = React.DOM.p({ + key: 'controls', + className: 'controls' + }, [ + React.DOM.img({ + key: 'image', + src: 'images/logos/logo_u128.png', + alt: 'Aucun fichier ouvert' + }) + ].concat(controls)); + } + + return React.DOM.div({ + className: className, + onWheel: this.wheel, + onClick: this.click + }, children); + } + }); +}()); \ No newline at end of file diff --git a/js/components/Note/Score.js b/js/components/Note/Score.js new file mode 100644 index 0000000..c5a95df --- /dev/null +++ b/js/components/Note/Score.js @@ -0,0 +1,218 @@ +/*globals React, Kinetic, App */ + +(function () { + 'use strict'; + + /** + * Display a set of notes + * + * @prop {notes: array} List of notes + * @prop {time: int} Current playing time + */ + App.components.create('Note', { + displayName: 'Score', + + statics: { + channels: [ + 'hsl(225, 49%, 44%)', + 'hsl(22.5, 84%, 56%)', + 'hsl(45, 53%, 39%)', + 'hsl(67.5, 84%, 56%)', + 'hsl(90, 84%, 56%)', + 'hsl(112.5, 84%, 56%)', + 'hsl(135, 84%, 56%)', + 'hsl(157.5, 84%, 56%)', + 'hsl(180, 84%, 56%)', + 'hsl(202.5, 84%, 56%)', + 'hsl(247.5, 84%, 56%)', + 'hsl(270, 84%, 56%)', + 'hsl(292.5, 84%, 56%)', + 'hsl(315, 84%, 56%)', + 'hsl(337.5, 84%, 56%)', + 'hsl(0, 84%, 56%)' + ] + }, + + propTypes: { + notes: React.PropTypes.array.isRequired, + time: React.PropTypes.number + }, + + getDefaultProps: function () { + return { + notes: [], + time: 0 + }; + }, + + getInitialState: function () { + return { + notes: [], + time: 0, + + width: 0, + height: 0 + }; + }, + + /** + * When component is mounted, create Kinetic stage and + * attach resizing event + */ + componentDidMount: function () { + var notes; + + window.addEventListener('resize', this.resize); + + notes = this.props.notes; + this.sort(notes); + + this.setState({ + notes: notes, + time: this.props.time + }, this.resize); + }, + + componentWillUnmount: function () { + window.removeEventListener('resize', this.resize); + }, + + /** + * Redraw canvas on each props update + */ + componentWillReceiveProps: function (nextProps) { + if (nextProps.notes !== this.props.notes) { + this.sort(); + } + + this.setState({ + notes: nextProps.notes, + time: nextProps.time + }, this.draw); + }, + + /** + * Never rebuild canvas element + */ + shouldComponentUpdate: function (props) { + return false; + }, + + /** + * Set canvas size + * + * @param {callback: func} Called when size is updated + */ + resize: function (callback) { + var canvas = this.getDOMNode(), + parent = canvas.parentNode, + width = parent.clientWidth, + height = parent.clientHeight, + ctx = canvas.getContext('2d'); + + canvas.width = width; + canvas.height = height; + + this.setState({ + width: width, + height: height + }, this.draw); + }, + + /** + * Get note offset by note ID + * + * @param {id: int} Note ID + */ + getOffset: function (id) { + return id - App.MIDI.keyOffset - + App.components.Note.Board.black.filter(function (el) { + return el < id; + }).length; + }, + + /** + * Get whether a note is black or not + * + * @param {id: int} Note ID + */ + isBlack: function (id) { + return (App.components.Note.Board.black.indexOf(id) > -1); + }, + + /** + * Sort notes by length + * + * @param {notes: array} Notes list + */ + sort: function (notes) { + var length = notes.length, i; + + for (i = 0; i < length; i += 1) { + notes[i].id = i; + } + + notes.sort(function (a, b) { + if (a.length === b.length) { + return b.start - a.start; + } + + return b.length - a.length; + }); + }, + + /** + * Draw notes + */ + draw: function () { + var notes = this.state.notes, time = this.state.time, + width = this.state.width, height = this.state.height, + xUnit = width / 52, yUnit = xUnit * 5, + maxTime = Math.ceil(height / yUnit), + note, length, i, ctx, offset, x, y, noteWidth, noteHeight, + channels = App.components.Note.Score.channels, count = 0; + + ctx = this.getDOMNode().getContext('2d'); + ctx.clearRect(0, 0, width, height); + ctx.strokeStyle = '#262626'; + ctx.lineWidth = 2; + + length = notes.length; + + for (i = 0; i < length; i += 1) { + note = notes[i]; + + if (note.start + note.length > time && + note.start < time + maxTime) { + offset = this.getOffset(note.note); + count += 1; + + x = Math.floor(xUnit * offset); + y = Math.floor(height - yUnit * (note.start + note.length - time)); + noteWidth = Math.floor(xUnit); + noteHeight = Math.floor(yUnit * note.length); + + if (note.channel === 9 && noteHeight < 10) { + noteHeight = 10; + } + + if (this.isBlack(note.note)) { + x -= Math.floor(xUnit / 4); + noteWidth = Math.floor(xUnit / 2); + } + + ctx.fillStyle = channels[note.channel]; + ctx.strokeRect(x, y, noteWidth, noteHeight); + ctx.fillRect(x, y, noteWidth, noteHeight); + } + } + }, + + /** + * Render score canvas + */ + render: function () { + return React.DOM.canvas(); + } + }); +}()); \ No newline at end of file diff --git a/js/components/UI/Scroll.js b/js/components/UI/Scroll.js new file mode 100644 index 0000000..3c11237 --- /dev/null +++ b/js/components/UI/Scroll.js @@ -0,0 +1,156 @@ +/*globals React, App */ + +(function () { + 'use strict'; + + /** + * Display a scrollbar + * + * @prop {current: int} Current position + * @prop {max: int} Maximum number we can reach + * @prop {onChange: function} Called on scrolling attempt + * @prop {onDragStart: function} Called on start of scrolling + * @prop {onDragEnd: function} Called on end of scrolling + */ + App.components.create('UI', { + displayName: 'Scroll', + mixins: [React.addons.PureRenderMixin], + position: null, + dragging: false, + + propTypes: { + current: React.PropTypes.number, + max: React.PropTypes.number, + onChange: React.PropTypes.func, + onDragStart: React.PropTypes.func, + onDragEnd: React.PropTypes.func + }, + + getDefaultProps: function () { + return { + current: 0, + max: 0, + onChange: function () {}, + onDragStart: function () {}, + onDragEnd: function () {} + }; + }, + + componentDidMount: function () { + window.addEventListener('mousemove', this.mouseMove); + window.addEventListener('mouseup', this.mouseUp); + }, + + componentWillUnmount: function () { + window.removeEventListener('mousemove', this.mouseMove); + window.removeEventListener('mouseup', this.mouseUp); + }, + + /** + * Convert distance to value + */ + convert: function (input) { + return input * this.props.max / this.getDOMNode().clientHeight; + }, + + /** + * Convert value to distance + */ + reverseConvert: function (output) { + return output * this.getDOMNode().clientHeight / this.props.max; + }, + + /** + * Scroll by given position + * + * @param {position: int} Current position + */ + scrollBy: function (position) { + var current = this.props.max - this.props.current, + delta = this.convert(position - this.reverseConvert(current)); + + this.props.onChange(delta); + }, + + /** + * Start scroll dragging + */ + mouseDown: function (e) { + if (e.button !== 0) { + return; + } + + this.position = e.clientY; + this.props.onDragStart(); + }, + + /** + * Move scroll + */ + mouseMove: function (e) { + if (this.position === null) { + return; + } + + if (Math.abs(e.clientY - this.position) >= 3) { + this.dragging = true; + } + + if (!this.dragging) { + return; + } + + this.scrollBy(e.clientY); + }, + + /** + * Mouse release + */ + mouseUp: function (e) { + if (this.dragging) { + this.props.onDragEnd(); + + this.dragging = false; + this.position = null; + } + }, + + /** + * Click on track + */ + click: function (e) { + if (e.button === 0) { + this.scrollBy(e.clientY); + } + }, + + /** + * Render scroll + */ + render: function () { + var bottom; + + if (this.props.max === 0) { + bottom = '-100%'; + } else { + bottom = 'calc(100% / ' + this.props.max + ' * ' + + this.props.current + ')'; + } + + return React.DOM.div({ + className: 'scroll', + onClick: this.click + }, [ + React.DOM.span({ + key: 'position', + className: 'position', + onMouseDown: this.mouseDown, + + style: { + bottom: bottom + } + }) + ]); + } + }); +}()); \ No newline at end of file diff --git a/js/components/UI/Selector.js b/js/components/UI/Selector.js new file mode 100644 index 0000000..69865a6 --- /dev/null +++ b/js/components/UI/Selector.js @@ -0,0 +1,91 @@ +/*globals React, App */ + +(function () { + 'use strict'; + + /** + * Display a value that can be changed on click + * + * @prop {values: array} List of values + * @prop {value: number} Current value + * @prop {onChange: function} Called whenever value changes + */ + App.components.create('UI', { + displayName: 'Selector', + mixins: [React.addons.PureRenderMixin], + + propTypes: { + values: React.PropTypes.array.isRequired, + value: React.PropTypes.number, + onChange: React.PropTypes.func + }, + + getDefaultProps: function () { + return { + value: null, + onChange: function () {} + }; + }, + + getInitialState: function () { + return { + value: null, + index: null + }; + }, + + componentDidMount: function () { + if (this.props.value === null) { + this.setState({ + value: this.props.values[0], + index: 0 + }); + } else { + this.setState({ + value: this.props.value, + index: this.props.values.indexOf(this.props.value) + }); + } + }, + + componentWillReceiveProps: function (nextProps) { + if (nextProps.value !== this.state.value) { + this.setState({ + value: nextProps.value, + index: nextProps.values.indexOf(nextProps.value) + }); + } + }, + + /** + * Change value on click + */ + click: function () { + var values = this.props.values, + index = this.state.index; + + if (index + 1 < values.length) { + index += 1; + } else { + index = 0; + } + + this.setState({ + value: values[index], + index: index + }, function () { + this.props.onChange(values[index]); + }.bind(this)); + }, + + /** + * Render handle + */ + render: function () { + return React.DOM.button({ + className: 'selector', + onClick: this.click + }, this.state.value); + } + }); +}()); \ No newline at end of file diff --git a/js/init.js b/js/init.js new file mode 100644 index 0000000..e646863 --- /dev/null +++ b/js/init.js @@ -0,0 +1,94 @@ +/*globals React */ + +/** + * init.js + * + * Initialize app global + */ + +(function () { + 'use strict'; + + var App = window.App = {}; + + // move module methods out of the global namespace to + // prevent libraries like jQuery from creating AMD modules + if (window.module !== undefined) { + window.atom = { + require: window.require, + module: window.module + }; + + delete window.require; + delete window.module; + } + + // components creation + App.components = { + /** + * Add React class to given namespace + * + * @param {namespace: string} Class namespace, skip to assign to global namespace + * @param {options: Object} Class options + * @return {Object} Object containing namespace object and created class + */ + create: function (namespace, options) { + var cclass; + + if (typeof namespace === 'object') { + options = namespace; + namespace = App.components; + } else { + if (App.components[namespace] === undefined) { + App.components[namespace] = {}; + } + + namespace = App.components[namespace]; + } + + cclass = React.createClass(options); + namespace[options.displayName] = cclass; + + return { + namespace: namespace, + cclass: cclass + }; + }, + + /** + * Add Modal class to given namespace + * + * @param {namespace: string} Class namespace, skip to assign to global namespace + * @param {options: Object} Class options + * @return {Object} Object containing namespace object and created modal + */ + modal: function (namespace, options) { + var component, cclass, modal; + + if (options === undefined) { + options = namespace; + } + + modal = options.modal || {}; + delete options.modal; + + component = App.components.create(namespace, options); + cclass = function (props) { + return new App.Modal(component.cclass, modal, props); + }; + + component.namespace[options.displayName] = cclass; + + return { + namespace: component.namespace, + cclass: cclass + }; + } + }; + + // other globals + App.lang = navigator.language; + App.MIDI = { + keyOffset: 21 + }; +}()); \ No newline at end of file diff --git a/js/lib/jasmid/LICENSE b/js/lib/jasmid/LICENSE new file mode 100644 index 0000000..407a442 --- /dev/null +++ b/js/lib/jasmid/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2010, Matt Westcott & Ben Firshman +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * The names of its contributors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/js/lib/jasmid/jasmid.js b/js/lib/jasmid/jasmid.js new file mode 100644 index 0000000..bac7c74 --- /dev/null +++ b/js/lib/jasmid/jasmid.js @@ -0,0 +1,308 @@ +/* Wrapper for accessing strings through sequential reads */ +function Stream(str) { + var position = 0; + + function read(length) { + var result = str.substr(position, length); + position += length; + return result; + } + + /* read a big-endian 32-bit integer */ + function readInt32() { + var result = ( + (str.charCodeAt(position) << 24) + + (str.charCodeAt(position + 1) << 16) + + (str.charCodeAt(position + 2) << 8) + + str.charCodeAt(position + 3)); + position += 4; + return result; + } + + /* read a big-endian 16-bit integer */ + function readInt16() { + var result = ( + (str.charCodeAt(position) << 8) + + str.charCodeAt(position + 1)); + position += 2; + return result; + } + + /* read an 8-bit integer */ + function readInt8(signed) { + var result = str.charCodeAt(position); + if (signed && result > 127) result -= 256; + position += 1; + return result; + } + + function eof() { + return position >= str.length; + } + + /* read a MIDI-style variable-length integer + (big-endian value in groups of 7 bits, + with top bit set to signify that another byte follows) + */ + function readVarInt() { + var result = 0; + while (true) { + var b = readInt8(); + if (b & 0x80) { + result += (b & 0x7f); + result <<= 7; + } else { + /* b is the last byte */ + return result + b; + } + } + } + + return { + 'eof': eof, + 'read': read, + 'readInt32': readInt32, + 'readInt16': readInt16, + 'readInt8': readInt8, + 'readVarInt': readVarInt + } +} + +/* +class to parse the .mid file format +(depends on stream.js) +*/ +function MidiFile(data) { + function readChunk(stream) { + var id = stream.read(4); + var length = stream.readInt32(); + return { + 'id': id, + 'length': length, + 'data': stream.read(length) + }; + } + + var lastEventTypeByte; + + function readEvent(stream) { + var event = {}; + event.deltaTime = stream.readVarInt(); + var eventTypeByte = stream.readInt8(); + if ((eventTypeByte & 0xf0) == 0xf0) { + /* system / meta event */ + if (eventTypeByte == 0xff) { + /* meta event */ + event.type = 'meta'; + var subtypeByte = stream.readInt8(); + var length = stream.readVarInt(); + switch(subtypeByte) { + case 0x00: + event.subtype = 'sequenceNumber'; + if (length != 2) throw "Expected length for sequenceNumber event is 2, got " + length; + event.number = stream.readInt16(); + return event; + case 0x01: + event.subtype = 'text'; + event.text = stream.read(length); + return event; + case 0x02: + event.subtype = 'copyrightNotice'; + event.text = stream.read(length); + return event; + case 0x03: + event.subtype = 'trackName'; + event.text = stream.read(length); + return event; + case 0x04: + event.subtype = 'instrumentName'; + event.text = stream.read(length); + return event; + case 0x05: + event.subtype = 'lyrics'; + event.text = stream.read(length); + return event; + case 0x06: + event.subtype = 'marker'; + event.text = stream.read(length); + return event; + case 0x07: + event.subtype = 'cuePoint'; + event.text = stream.read(length); + return event; + case 0x20: + event.subtype = 'midiChannelPrefix'; + if (length != 1) throw "Expected length for midiChannelPrefix event is 1, got " + length; + event.channel = stream.readInt8(); + return event; + case 0x2f: + event.subtype = 'endOfTrack'; + if (length != 0) throw "Expected length for endOfTrack event is 0, got " + length; + return event; + case 0x51: + event.subtype = 'setTempo'; + if (length != 3) throw "Expected length for setTempo event is 3, got " + length; + event.microsecondsPerBeat = ( + (stream.readInt8() << 16) + + (stream.readInt8() << 8) + + stream.readInt8() + ) + return event; + case 0x54: + event.subtype = 'smpteOffset'; + if (length != 5) throw "Expected length for smpteOffset event is 5, got " + length; + var hourByte = stream.readInt8(); + event.frameRate = { + 0x00: 24, 0x20: 25, 0x40: 29, 0x60: 30 + }[hourByte & 0x60]; + event.hour = hourByte & 0x1f; + event.min = stream.readInt8(); + event.sec = stream.readInt8(); + event.frame = stream.readInt8(); + event.subframe = stream.readInt8(); + return event; + case 0x58: + event.subtype = 'timeSignature'; + if (length != 4) throw "Expected length for timeSignature event is 4, got " + length; + event.numerator = stream.readInt8(); + event.denominator = Math.pow(2, stream.readInt8()); + event.metronome = stream.readInt8(); + event.thirtyseconds = stream.readInt8(); + return event; + case 0x59: + event.subtype = 'keySignature'; + if (length != 2) throw "Expected length for keySignature event is 2, got " + length; + event.key = stream.readInt8(true); + event.scale = stream.readInt8(); + return event; + case 0x7f: + event.subtype = 'sequencerSpecific'; + event.data = stream.read(length); + return event; + default: + // console.log("Unrecognised meta event subtype: " + subtypeByte); + event.subtype = 'unknown' + event.data = stream.read(length); + return event; + } + event.data = stream.read(length); + return event; + } else if (eventTypeByte == 0xf0) { + event.type = 'sysEx'; + var length = stream.readVarInt(); + event.data = stream.read(length); + return event; + } else if (eventTypeByte == 0xf7) { + event.type = 'dividedSysEx'; + var length = stream.readVarInt(); + event.data = stream.read(length); + return event; + } else { + throw "Unrecognised MIDI event type byte: " + eventTypeByte; + } + } else { + /* channel event */ + var param1; + if ((eventTypeByte & 0x80) == 0) { + /* running status - reuse lastEventTypeByte as the event type. + eventTypeByte is actually the first parameter + */ + param1 = eventTypeByte; + eventTypeByte = lastEventTypeByte; + } else { + param1 = stream.readInt8(); + lastEventTypeByte = eventTypeByte; + } + var eventType = eventTypeByte >> 4; + event.channel = eventTypeByte & 0x0f; + event.type = 'channel'; + switch (eventType) { + case 0x08: + event.subtype = 'noteOff'; + event.noteNumber = param1; + event.velocity = stream.readInt8(); + return event; + case 0x09: + event.noteNumber = param1; + event.velocity = stream.readInt8(); + if (event.velocity == 0) { + event.subtype = 'noteOff'; + } else { + event.subtype = 'noteOn'; + } + return event; + case 0x0a: + event.subtype = 'noteAftertouch'; + event.noteNumber = param1; + event.amount = stream.readInt8(); + return event; + case 0x0b: + event.subtype = 'controller'; + event.controllerType = param1; + event.value = stream.readInt8(); + return event; + case 0x0c: + event.subtype = 'programChange'; + event.programNumber = param1; + return event; + case 0x0d: + event.subtype = 'channelAftertouch'; + event.amount = param1; + return event; + case 0x0e: + event.subtype = 'pitchBend'; + event.value = param1 + (stream.readInt8() << 7); + return event; + default: + throw "Unrecognised MIDI event type: " + eventType + /* + console.log("Unrecognised MIDI event type: " + eventType); + stream.readInt8(); + event.subtype = 'unknown'; + return event; + */ + } + } + } + + stream = Stream(data); + var headerChunk = readChunk(stream); + if (headerChunk.id != 'MThd' || headerChunk.length != 6) { + throw "Bad .mid file - header not found"; + } + var headerStream = Stream(headerChunk.data); + var formatType = headerStream.readInt16(); + var trackCount = headerStream.readInt16(); + var timeDivision = headerStream.readInt16(); + + if (timeDivision & 0x8000) { + throw "Expressing time division in SMTPE frames is not supported yet" + } else { + ticksPerBeat = timeDivision; + } + + var header = { + 'formatType': formatType, + 'trackCount': trackCount, + 'ticksPerBeat': ticksPerBeat + } + var tracks = []; + for (var i = 0; i < header.trackCount; i++) { + tracks[i] = []; + var trackChunk = readChunk(stream); + if (trackChunk.id != 'MTrk') { + throw "Unexpected chunk - expected MTrk, got "+ trackChunk.id; + } + var trackStream = Stream(trackChunk.data); + while (!trackStream.eof()) { + var event = readEvent(trackStream); + tracks[i].push(event); + //console.log(event); + } + } + + return { + 'header': header, + 'tracks': tracks + } +} \ No newline at end of file diff --git a/js/lib/jasmid/jasmid.min.js b/js/lib/jasmid/jasmid.min.js new file mode 100644 index 0000000..8c9e86a --- /dev/null +++ b/js/lib/jasmid/jasmid.min.js @@ -0,0 +1 @@ +function Stream(e){function n(n){var r=e.substr(t,n);t+=n;return r}function r(){var n=(e.charCodeAt(t)<<24)+(e.charCodeAt(t+1)<<16)+(e.charCodeAt(t+2)<<8)+e.charCodeAt(t+3);t+=4;return n}function i(){var n=(e.charCodeAt(t)<<8)+e.charCodeAt(t+1);t+=2;return n}function s(n){var r=e.charCodeAt(t);if(n&&r>127)r-=256;t+=1;return r}function o(){return t>=e.length}function u(){var e=0;while(true){var t=s();if(t&128){e+=t&127;e<<=7}else{return e+t}}}var t=0;return{eof:o,read:n,readInt32:r,readInt16:i,readInt8:s,readVarInt:u}}function MidiFile(e){function t(e){var t=e.read(4);var n=e.readInt32();return{id:t,length:n,data:e.read(n)}}function r(e){var t={};t.deltaTime=e.readVarInt();var r=e.readInt8();if((r&240)==240){if(r==255){t.type="meta";var i=e.readInt8();var s=e.readVarInt();switch(i){case 0:t.subtype="sequenceNumber";if(s!=2)throw"Expected length for sequenceNumber event is 2, got "+s;t.number=e.readInt16();return t;case 1:t.subtype="text";t.text=e.read(s);return t;case 2:t.subtype="copyrightNotice";t.text=e.read(s);return t;case 3:t.subtype="trackName";t.text=e.read(s);return t;case 4:t.subtype="instrumentName";t.text=e.read(s);return t;case 5:t.subtype="lyrics";t.text=e.read(s);return t;case 6:t.subtype="marker";t.text=e.read(s);return t;case 7:t.subtype="cuePoint";t.text=e.read(s);return t;case 32:t.subtype="midiChannelPrefix";if(s!=1)throw"Expected length for midiChannelPrefix event is 1, got "+s;t.channel=e.readInt8();return t;case 47:t.subtype="endOfTrack";if(s!=0)throw"Expected length for endOfTrack event is 0, got "+s;return t;case 81:t.subtype="setTempo";if(s!=3)throw"Expected length for setTempo event is 3, got "+s;t.microsecondsPerBeat=(e.readInt8()<<16)+(e.readInt8()<<8)+e.readInt8();return t;case 84:t.subtype="smpteOffset";if(s!=5)throw"Expected length for smpteOffset event is 5, got "+s;var o=e.readInt8();t.frameRate={0:24,32:25,64:29,96:30}[o&96];t.hour=o&31;t.min=e.readInt8();t.sec=e.readInt8();t.frame=e.readInt8();t.subframe=e.readInt8();return t;case 88:t.subtype="timeSignature";if(s!=4)throw"Expected length for timeSignature event is 4, got "+s;t.numerator=e.readInt8();t.denominator=Math.pow(2,e.readInt8());t.metronome=e.readInt8();t.thirtyseconds=e.readInt8();return t;case 89:t.subtype="keySignature";if(s!=2)throw"Expected length for keySignature event is 2, got "+s;t.key=e.readInt8(true);t.scale=e.readInt8();return t;case 127:t.subtype="sequencerSpecific";t.data=e.read(s);return t;default:t.subtype="unknown";t.data=e.read(s);return t}t.data=e.read(s);return t}else if(r==240){t.type="sysEx";var s=e.readVarInt();t.data=e.read(s);return t}else if(r==247){t.type="dividedSysEx";var s=e.readVarInt();t.data=e.read(s);return t}else{throw"Unrecognised MIDI event type byte: "+r}}else{var u;if((r&128)==0){u=r;r=n}else{u=e.readInt8();n=r}var a=r>>4;t.channel=r&15;t.type="channel";switch(a){case 8:t.subtype="noteOff";t.noteNumber=u;t.velocity=e.readInt8();return t;case 9:t.noteNumber=u;t.velocity=e.readInt8();if(t.velocity==0){t.subtype="noteOff"}else{t.subtype="noteOn"}return t;case 10:t.subtype="noteAftertouch";t.noteNumber=u;t.amount=e.readInt8();return t;case 11:t.subtype="controller";t.controllerType=u;t.value=e.readInt8();return t;case 12:t.subtype="programChange";t.programNumber=u;return t;case 13:t.subtype="channelAftertouch";t.amount=u;return t;case 14:t.subtype="pitchBend";t.value=u+(e.readInt8()<<7);return t;default:throw"Unrecognised MIDI event type: "+a}}}var n;stream=Stream(e);var i=t(stream);if(i.id!="MThd"||i.length!=6){throw"Bad .mid file - header not found"}var s=Stream(i.data);var o=s.readInt16();var u=s.readInt16();var a=s.readInt16();if(a&32768){throw"Expressing time division in SMTPE frames is not supported yet"}else{ticksPerBeat=a}var f={formatType:o,trackCount:u,ticksPerBeat:ticksPerBeat};var l=[];for(var c=0;c= 0 && j < len ? [ this[j] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: deletedIds.sort, + splice: deletedIds.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + // parseFloat NaNs numeric-cast false positives (null|true|false|"") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0; + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( support.ownLast ) { + for ( key in obj ) { + return hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call(obj) ] || "object" : + typeof obj; + }, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Support: Android<4.1, IE<9 + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( indexOf ) { + return indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + while ( j < len ) { + first[ i++ ] = second[ j++ ]; + } + + // Support: IE<9 + // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists) + if ( len !== len ) { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: function() { + return +( new Date() ); + }, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v1.10.19 + * http://sizzlejs.com/ + * + * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2014-04-18 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + -(new Date()), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + characterEncoding + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( documentIsHTML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document (jQuery #6963) + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== strundefined && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, + doc = node ? node.ownerDocument || node : preferredDoc, + parent = doc.defaultView; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsHTML = !isXML( doc ); + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent !== parent.top ) { + // IE11 does not have attachEvent, so all must suffer + if ( parent.addEventListener ) { + parent.addEventListener( "unload", function() { + setDocument(); + }, false ); + } else if ( parent.attachEvent ) { + parent.attachEvent( "onunload", function() { + setDocument(); + }); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if getElementsByClassName can be trusted + support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) { + div.innerHTML = "
"; + + // Support: Safari<4 + // Catch class over-caching + div.firstChild.className = "i"; + // Support: Opera<10 + // Catch gEBCN failure to find non-leading classes + return div.getElementsByClassName("i").length === 2; + }); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [ m ] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( div.querySelectorAll("[msallowclip^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( div.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (oldCache = outerCache[ dir ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + outerCache[ dir ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context !== document && context; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is no seed and only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome<14 +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + + +var rneedsContext = jQuery.expr.match.needsContext; + +var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); + + + +var risSimple = /^.[^:#\[\.,]*$/; + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( risSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; + }); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); +}; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +}); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + init = jQuery.fn.init = function( selector, context ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return typeof rootjQuery.ready !== "undefined" ? + rootjQuery.ready( selector ) : + // Execute immediately if ready is not present + selector( jQuery ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.extend({ + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +jQuery.fn.extend({ + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + matched.push( cur ); + break; + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.unique( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.unique( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +}); +var rnotwhite = (/\S+/g); + + + +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( values === progressValues ) { + deferred.notifyWith( contexts, values ); + + } else if ( !(--remaining) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); + + +// The deferred used on DOM ready +var readyList; + +jQuery.fn.ready = function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; +}; + +jQuery.extend({ + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + jQuery( document ).off( "ready" ); + } + } +}); + +/** + * Clean-up method for dom ready events + */ +function detach() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } +} + +/** + * The ready event handler and self cleanup method + */ +function completed() { + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } +} + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + + +var strundefined = typeof undefined; + + + +// Support: IE<9 +// Iteration over object's inherited properties before its own +var i; +for ( i in jQuery( support ) ) { + break; +} +support.ownLast = i !== "0"; + +// Note: most support tests are defined in their respective modules. +// false until the test is run +support.inlineBlockNeedsLayout = false; + +// Execute ASAP in case we need to set body.style.zoom +jQuery(function() { + // Minified: var a,b,c,d + var val, div, body, container; + + body = document.getElementsByTagName( "body" )[ 0 ]; + if ( !body || !body.style ) { + // Return for frameset docs that don't have a body + return; + } + + // Setup + div = document.createElement( "div" ); + container = document.createElement( "div" ); + container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; + body.appendChild( container ).appendChild( div ); + + if ( typeof div.style.zoom !== strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1"; + + support.inlineBlockNeedsLayout = val = div.offsetWidth === 3; + if ( val ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); +}); + + + + +(function() { + var div = document.createElement( "div" ); + + // Execute the test only if not already executed in another module. + if (support.deleteExpando == null) { + // Support: IE<9 + support.deleteExpando = true; + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + } + + // Null elements to avoid leaks in IE. + div = null; +})(); + + +/** + * Determines whether an object can have data + */ +jQuery.acceptData = function( elem ) { + var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ], + nodeType = +elem.nodeType || 1; + + // Do not set data on non-element DOM nodes because it will not be cleared (#8335). + return nodeType !== 1 && nodeType !== 9 ? + false : + + // Nodes accept data unless otherwise specified; rejection can be conditional + !noData || noData !== true && elem.getAttribute("classid") === noData; +}; + + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /([A-Z])/g; + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + +function internalData( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // The following elements (space-suffixed to avoid Object.prototype collisions) + // throw uncatchable exceptions if you attempt to set expando properties + noData: { + "applet ": true, + "embed ": true, + // ...but Flash objects (which have this classid) *can* handle expandos + "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var i, name, data, + elem = this[0], + attrs = elem && elem.attributes; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE11+ + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return arguments.length > 1 ? + + // Sets one value + this.each(function() { + jQuery.data( this, key, value ); + }) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined; + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + + +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHidden = function( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); + }; + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; +}; +var rcheckableType = (/^(?:checkbox|radio)$/i); + + + +(function() { + // Minified: var a,b,c + var input = document.createElement( "input" ), + div = document.createElement( "div" ), + fragment = document.createDocumentFragment(); + + // Setup + div.innerHTML = "
a"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName( "tbody" ).length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName( "link" ).length; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = + document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav>"; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + input.type = "checkbox"; + input.checked = true; + fragment.appendChild( input ); + support.appendChecked = input.checked; + + // Make sure textarea (and checkbox) defaultValue is properly cloned + // Support: IE6-IE11+ + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // #11217 - WebKit loses check when the name is after the checked attribute + fragment.appendChild( div ); + div.innerHTML = ""; + + // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 + // old WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + support.noCloneEvent = true; + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Execute the test only if not already executed in another module. + if (support.deleteExpando == null) { + // Support: IE<9 + support.deleteExpando = true; + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + } +})(); + + +(function() { + var i, eventName, + div = document.createElement( "div" ); + + // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event) + for ( i in { submit: true, change: true, focusin: true }) { + eventName = "on" + i; + + if ( !(support[ i + "Bubbles" ] = eventName in window) ) { + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + div.setAttribute( eventName, "t" ); + support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false; + } + } + + // Null elements to avoid leaks in IE. + div = null; +})(); + + +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && jQuery.acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + // Support: IE < 9, Android < 4.0 + src.returnValue === false ? + returnTrue : + returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && e.stopImmediatePropagation ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = jQuery._data( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + jQuery._data( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = jQuery._data( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + jQuery._removeData( doc, fix ); + } else { + jQuery._data( doc, fix, attaches ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
", "
" ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + col: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
", "
" ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!support.noCloneEvent || !support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
" && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + deletedIds.push( id ); + } + } + } + } + } +}); + +jQuery.fn.extend({ + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + remove: function( selector, keepData /* Internal Use Only */ ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map(function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var arg = arguments[ 0 ]; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + arg = this.parentNode; + + jQuery.cleanData( getAll( this ) ); + + if ( arg ) { + arg.replaceChild( elem, this ); + } + }); + + // Force removal if there was no new content (e.g., from empty arguments) + return arg && (arg.length || arg.nodeType) ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, self.html() ); + } + self.domManip( args, callback ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[i], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + + +var iframe, + elemdisplay = {}; + +/** + * Retrieve the actual display of a element + * @param {String} name nodeName of the element + * @param {Object} doc Document object + */ +// Called only from within defaultDisplay +function actualDisplay( name, doc ) { + var style, + elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), + + // getDefaultComputedStyle might be reliably used only on attached element + display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? + + // Use of this method is a temporary fix (more like optmization) until something better comes along, + // since it was removed from specification and supported only in FF + style.display : jQuery.css( elem[ 0 ], "display" ); + + // We don't have any data stored on the element, + // so use "detach" method as fast way to get rid of the element + elem.detach(); + + return display; +} + +/** + * Try to determine the default display value of an element + * @param {String} nodeName + */ +function defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + + // Use the already-created iframe if possible + iframe = (iframe || jQuery( "