diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index bdb0cab..0000000 --- a/.gitattributes +++ /dev/null @@ -1,17 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto - -# Custom for Visual Studio -*.cs diff=csharp - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..92a2798 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/.sass-cache/** +/node_modules/** +/package.json diff --git a/Gruntfile.coffee b/Gruntfile.coffee new file mode 100644 index 0000000..0d541fa --- /dev/null +++ b/Gruntfile.coffee @@ -0,0 +1,96 @@ +module.exports = (grunt) -> + + SRC_DIR = "src" + SRC_COFFEE_DIR = "#{SRC_DIR}/coffee/class" + SRC_SASS_DIR = "#{SRC_DIR}/sass" + + SRC_COFFEE_FILES = [] + SRC_SASS_FILES = [] + + pushFiles = (arr, dir) -> + grunt.file.recurse dir, (abspath, rootdir, subdir, filename) -> + arr.push "#{rootdir}/#{filename}" if not grunt.file.isDir abspath + + pushFiles SRC_SASS_FILES, SRC_SASS_DIR + + #Order is important, some classes extend others + SRC_COFFEE_FILES.push "#{SRC_DIR}/coffee/#{file}.coffee" for file in [ + "factory-start" + + "class/Registry" + + "private" + "public" + + #Classes + "class/CssController" + "class/EventListener" + "class/Widget" + "class/Composite" + "class/Label" + "class/Image" + "class/Button" + "class/ToggleButton" + "class/ButtonGroup" + "class/Text" + "class/Spinner" + "class/Switch" + "class/Check" + "class/Radio" + "class/AbstractItemList" + "class/List" + "class/Combo" + "class/Table" + "class/TabFolder" + "class/ProgressBar" + "class/FileChooser" + "class/ColorPicker" #Wrappers + "class/YTVideo" + + "events" + + "factory-end" + ] + + DIST_DIR = "dist" + DIST_JS_DIR = "#{DIST_DIR}/js/lib" + DIST_CSS_DIR = "#{DIST_DIR}/css" + + grunt.initConfig + pkg: grunt.file.readJSON "package.json" + banner: """ + Web Widget Toolkit (WWT) v<%= pkg.version %> + By <%= pkg.author %> + """ + coffee: + dist: + options: + join: true + joinExt: ".src.coffee" + files: + "#{DIST_JS_DIR}/wwt.js": SRC_COFFEE_FILES + uglify: + dist: + src: "#{DIST_JS_DIR}/wwt.js" + dest: "#{DIST_JS_DIR}/wwt.min.js" + sass: + dist: + options: + sourceMap: false + style: "expanded" + loadPath: "#{SRC_DIR}/sass-include/" + files: [ + { + expand: true + cwd: "#{SRC_SASS_DIR}/" + src: ["**/*.sass"] + ext: ".css" + dest: "dist/css/" + } + ] + + grunt.loadNpmTasks "grunt-contrib-coffee" + grunt.loadNpmTasks "grunt-contrib-uglify" + grunt.loadNpmTasks "grunt-contrib-sass" + + grunt.registerTask "default", "Default task", ["coffee", "uglify", "sass"] diff --git a/LICENSE-SPECTRUM b/LICENSE-SPECTRUM new file mode 100644 index 0000000..c9b44cb --- /dev/null +++ b/LICENSE-SPECTRUM @@ -0,0 +1,18 @@ +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. diff --git a/dist/css/demo-wwt.css b/dist/css/demo-wwt.css new file mode 100644 index 0000000..fc7c5ca --- /dev/null +++ b/dist/css/demo-wwt.css @@ -0,0 +1,61 @@ +#buttons { + width: 25%; + display: inline-block; + float: left; +} +#buttons > .Button, #buttons > .ToggleButton, #buttons .ButtonGroup { + width: calc(100% - 5px - .5em); +} + +#textboxes { + width: 15%; + display: inline-block; + float: left; +} +#textboxes .Text, #textboxes .TextArea { + width: calc(100% - 5px - .5em); +} + +#checkRadio { + width: 10%; + display: inline-block; + float: left; +} +#checkRadio .RadioContainer, #checkRadio .CheckContainer { + width: calc(100% - .5em); +} + +#spinners { + width: 5%; + display: inline-block; + float: left; +} +#spinners .Spinner { + width: calc(100% - .5em); +} + +#pickers { + width: 10%; + float: left; +} + +#lists { + width: 20%; + float: left; +} +#lists .List { + width: calc(50% - 4px - .25em); + margin-right: 0; +} +#lists .List:first-child { + margin-right: 0.25em; +} +#lists .Combo, #lists .ComboEditable, #lists .Table { + width: calc(100% - 2px); +} + +#progressEnabled { + width: 50em; +} + +/*# sourceMappingURL=demo-wwt.css.map */ diff --git a/dist/css/demo-wwt.css.map b/dist/css/demo-wwt.css.map new file mode 100644 index 0000000..d9963dd --- /dev/null +++ b/dist/css/demo-wwt.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "AAAA,QAAQ;EACN,KAAK,EAAE,GAAG;EACV,OAAO,EAAE,YAAY;EACrB,KAAK,EAAE,IAAI;;AAEX,mEAAwC;EACtC,KAAK,EAAE,uBAAuB;;;AAElC,UAAU;EACR,KAAK,EAAE,GAAG;EACV,OAAO,EAAE,YAAY;EACrB,KAAK,EAAE,IAAI;;AAEX,sCAAgB;EACd,KAAK,EAAE,uBAAuB;;;AAElC,WAAW;EACT,KAAK,EAAE,GAAG;EACV,OAAO,EAAE,YAAY;EACrB,KAAK,EAAE,IAAI;;AAEX,wDAAgC;EAC9B,KAAK,EAAE,iBAAiB;;;AAE5B,SAAS;EACP,KAAK,EAAE,EAAE;EACT,OAAO,EAAE,YAAY;EACrB,KAAK,EAAE,IAAI;;AAEX,kBAAQ;EACN,KAAK,EAAE,iBAAiB;;;AAE5B,QAAQ;EACN,KAAK,EAAE,GAAG;EACV,KAAK,EAAE,IAAI;;;AAEb,MAAM;EACJ,KAAK,EAAE,GAAG;EACV,KAAK,EAAE,IAAI;;AAEX,YAAK;EACH,KAAK,EAAE,uBAAuB;EAC9B,YAAY,EAAE,CAAC;;AAEjB,wBAAiB;EACf,YAAY,EAAE,MAAK;;AAErB,mDAA8B;EAC5B,KAAK,EAAE,gBAAgB;;;AAE3B,gBAAgB;EACd,KAAK,EAAE,IAAI", +"sources": ["../../src/sass/demo-wwt.sass"], +"names": [], +"file": "demo-wwt.css" +} diff --git a/dist/css/laf-aqua.css b/dist/css/laf-aqua.css new file mode 100644 index 0000000..828bf10 --- /dev/null +++ b/dist/css/laf-aqua.css @@ -0,0 +1,535 @@ +@charset "UTF-8"; +html, body { + padding: 0; + margin: 0; + font-family: "Trebuchet MS"; +} + +.noselect { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.sp-dd { + display: none; +} + +.sp-preview { + margin: 0; +} + +.sp-replacer { + padding: 0; +} + +.no-resize { + resize: none; +} + +.resize-v { + resize: vertical; +} + +.resize-h { + resize: horizontal; +} + +.resize-all { + resize: both; +} + +.Button, .ToggleButton, +.Text, .TextArea, .Spinner, +.CheckContainer, .RadioContainer, +.ColorPicker, .FileChooser + label, +.Combo, .ComboEditable, +.Table, +.TabFolder, +.ProgressBar { + margin: 0.25em; +} + +#wwt_tooltip { + background-color: rgba(0, 0, 0, 0.65); + border: 1px solid; + position: absolute; + padding: 2px 5px; + max-width: 20%; + font-size: 10pt; + z-index: 10000; +} + +.Button, .ToggleButton, .FileChooser + label, .Combo, .ComboEditableButton { + border: 1px solid; + color: inherit; + font-family: inherit; + font-size: inherit; + padding-left: 5px; + padding-right: 5px; + line-height: 1.5em; + text-align: center; + display: inline-block; +} +.Button .title, .ToggleButton .title, .FileChooser + label .title, .Combo .title, .ComboEditableButton .title { + cursor: default; +} +.Button .title.invisible, .ToggleButton .title.invisible, .FileChooser + label .title.invisible, .Combo .title.invisible, .ComboEditableButton .title.invisible { + opacity: 0; +} + +.Button:focus, .ToggleButton:focus, .Combo:focus { + outline: 0; +} + +.Button.disabled, .Button:hover.disabled, +.ToggleButton.state-out.disabled, .ToggleButton.state-in.disabled, +.ToggleButton.state-out.disabled:hover, .ToggleButton.state-in.disabled:hover, +.Spinner.disabled .SpinnerIncrement, .Spinner.disabled .SpinnerIncrement:hover, +.Spinner.disabled .SpinnerDecrement, .Spinner.disabled .SpinnerDecrement:hover, +.FileChooser.disabled + label, .FileChooser.disabled + label:hover, +.Combo.disabled, .Combo.disabled:hover, +.ComboEditable.disabled .ComboEditableButton, .ComboEditable.disabled .ComboEditableButton:hover { + background: none; +} + +.ButtonGroup { + margin: 0.25em; + display: inline-block; +} + +.ButtonGroup > .Button, .ButtonGroup > .ToggleButton { + margin: 0; +} + +.ButtonGroup > .Button:first-child, .ButtonGroup > .ToggleButton:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.ButtonGroup > .Button:last-child, .ButtonGroup > .ToggleButton:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.ButtonGroup > .Button:not(:last-child):not(:first-child), .ButtonGroup > .ToggleButton:not(:last-child):not(:first-child) { + border-radius: 0; +} + +.ButtonGroup > .Button:not(:last-child), .ButtonGroup > .ToggleButton:not(:last-child) { + border-right: none; +} + +.FileChooser { + width: 0.1px; + height: 0.1px; + opacity: 0; + overflow: hidden; + position: absolute; + z-index: -1; +} + +.Text, .TextArea, .sp-input { + border: 1px solid; + font-size: inherit; + font-family: inherit; + padding: 3px; + height: calc(1.5em + 2px); +} + +.Text:focus, .TextArea:focus, .sp-input:focus { + outline: none; +} + +.TextArea { + height: initial; +} + +.SpinnerButtonsContainer { + display: inline-block; + float: right; + width: 1em; +} + +.SpinnerIncrement, .SpinnerDecrement { + border: 1px solid; + border-left: none; + display: inline-block; + float: left; + width: 1em; + text-align: center; +} + +.SpinnerNumber { + margin: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + width: calc(100% - 1em); +} + +.SpinnerIncrement { + height: calc(.75em - 1px); +} + +.SpinnerDecrement { + height: calc(.75em); + border-top: none; +} + +.SpinnerUpArrow, .SpinnerDownArrow { + width: 0; + height: 0; + margin-top: 0.25em; + margin-left: 0.25em; +} + +.SpinnerUpArrow { + border-left: 0.25em solid transparent; + border-right: 0.25em solid transparent; + border-bottom: 0.25em solid; +} + +.SpinnerDownArrow { + border-left: 0.25em solid transparent; + border-right: 0.25em solid transparent; + border-top: 0.25em solid; +} + +.Spinner.disabled .SpinnerUpArrow { + border-bottom: 0.25em solid; +} + +.Spinner.disabled .SpinnerDownArrow { + border-top: 0.25em solid; +} + +.Spinner, .ComboEditable { + display: inline-block; +} + +.SwitchContainer, .CheckContainer, .RadioContainer { + display: inline-block; +} + +.Check:not(old), +.Radio:not(old), +.Switch:not(old) { + width: 2em; + margin: 0; + padding: 0; + font-size: 1em; + opacity: 0; +} + +.Check:not(old) + label, +.Radio:not(old) + label { + display: inline-block; + margin-left: -2em; + line-height: 1.5em; +} + +.Check:not(old) + label .outer, +.Radio:not(old) + label .outer { + display: inline-block; + width: 0.875em; + height: 0.875em; + margin: 0.25em 0.5em 0.25em 0.25em; + border: 0.0625em solid; + border-radius: 0.25em; + vertical-align: bottom; +} + +.Radio:not(old) + label .outer { + border-radius: 1em; +} + +.Check:not(old):checked + label .outer:before { + content: "✓"; + display: block; + width: 1em; + font-size: 0.875em; + line-height: 1em; + text-align: center; + font-weight: bold; +} + +.Radio:not(old):checked + label .inner { + display: block; + width: 0.5em; + height: 0.5em; + margin: 0.125em; + border: 0.0625em solid; + border-radius: 1em; +} + +.List { + display: inline-block; + padding: 0; + margin: 0.25em; + border: 1px solid; + overflow-y: auto; +} + +.List.h-scroll { + overflow-x: auto; +} + +.ListItem { + cursor: default; + padding: 0.175em 0.5em; +} + +.Combo .arrow-container { + width: 1em; + display: inline-block; + float: right; +} + +.Combo .arrow-up-container { + margin-top: 0.45em; +} + +.Combo .arrow-up-container, .Combo .arrow-down-container { + display: inline-block; + float: left; + line-height: initial; + width: 1em; + margin-left: 0.5em; + height: 0.4em; +} + +.Combo .arrow-up, .Combo .arrow-down { + width: 0; + height: 0; + border-left: 0.2em solid transparent; + border-right: 0.2em solid transparent; +} + +.Combo .arrow-up { + border-bottom: 0.2em solid; +} + +.Combo .arrow-down { + border-top: 0.2em solid; +} + +.Combo.disabled .arrow-up { + border-bottom: 0.2em solid; +} + +.Combo.disabled .arrow-down { + border-top: 0.2em solid; +} + +.Combo { + text-align: left; +} + +.ComboItemList { + position: absolute; + list-style-type: none; + padding: 0; + margin: 0; + border: 1px solid; + overflow: auto; + border-top: none; + z-index: 10000; +} + +.ComboItemList.hidden { + display: none; +} + +.ComboItemList:not(.hidden) { + z-index: 1; +} + +.ComboItemList.overlayed { + border-top: 1px solid; + -webkit-box-shadow: 0px 0px 25px 3px rgba(0, 0, 0, 0.75); + -moz-box-shadow: 0px 0px 25px 3px rgba(0, 0, 0, 0.75); + box-shadow: 0px 0px 25px 3px rgba(0, 0, 0, 0.75); +} + +.ComboItem { + cursor: default; + padding: 0.175em 5px; +} + +.ComboItem.selected { + display: none; +} + +.ComboEditable .Text { + margin: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + width: calc(100% - 1em - 3px); +} + +.ComboEditableButtonContainer { + margin-top: 0; + border-left: none; + display: inline-block; + float: right; +} + +.ComboEditableButton { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-left: none; + margin-left: 0; + height: 1.5em; +} + +.Combo.listShown, .ComboEditable.listShown .Text { + border-bottom-left-radius: 0; +} + +.Combo.listShown, .ComboEditable.listShown .ComboEditableButton { + border-bottom-right-radius: 0; +} + +.ComboEditableArrowContainer { + display: inline-block; + margin-top: 0.75em; +} + +.ComboEditableArrowContainer .down-arrow { + border-top: 0.25em solid; + border-left: 0.25em solid transparent; + border-right: 0.25em solid transparent; +} + +.ComboEditable.disabled .ComboEditableArrowContainer .down-arrow { + border-top: 0.25em solid; +} + +.Table { + border: 1px solid; + border-collapse: collapse; + font-size: inherit; + font-family: inherit; +} + +.TableHeader, .TableRowValue { + cursor: default; + padding: 5px; +} + +.TableHeader, .TableRow, .TableRowValue { + border: 1px solid; +} + +.ColorPickerReplacer, .ColorPickerReplacer:hover, .ColorPickerReplacer.sp-disabled, .ColorPicker.sp-active { + border: 1px solid; +} + +.ColorPickerReplacer { + margin: 0.25em; + height: calc(1.5em - 2px); + width: calc(1.75em - 2px); + border: 1px solid; + cursor: default; +} +.ColorPickerReplacer .sp-preview { + width: calc(1.25em - 4px); + height: calc(1em - 4px); + margin: 0.25em 0 0 0.25em; + border: 1px solid; +} + +.ColorPickerReplacer.sp-disabled > sp-preview { + border: 1px solid; +} + +.ColorPickerReplacer.sp-disabled, ColorPickerReplacer.sp-disabled:hover { + background: none; +} + +.ColorPickerContainer { + border: 1px solid; +} + +.sp-picker-container { + border-left: 1px solid; +} + +.sp-palette-container { + border-right: 1px solid; +} + +.sp-palette-disabled .sp-picker-container { + border-left: none; +} + +.sp-input:focus { + border: 1px solid; +} + +.TabFolder { + display: inline-block; +} + +.TabContainer { + width: 100%; + display: inline-block; +} + +.Tab { + display: inline-block; + padding: 5px; + border: 1px solid; + border-bottom: none; + cursor: default; +} + +.Tab:not(:first-child) { + border-left: none; +} + +.TabContentContainer { + width: calc(100% - 2px - 10px); + border: 1px solid; + padding: 5px; + overflow-y: auto; +} + +.ProgressBar { + height: 1em; + border: 1px solid; + display: inline-block; +} + +.ProgressBarInner { + height: 100%; + transition: width 0.3s ease; +} + +.ProgressBar:not(.full):not(.indeterminate) .ProgressBarInner { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.ProgressBar.indeterminate { + overflow-x: hidden; +} +.ProgressBar.indeterminate .ProgressBarInner { + animation: IndeterminateProgress 1.25s linear 0s infinite alternate; +} + +@keyframes IndeterminateProgress { + 0% { + width: 20%; + margin-left: 0; + } + 100% { + width: 20%; + margin-left: 80%; + } +} + +/*# sourceMappingURL=laf-aqua.css.map */ diff --git a/dist/css/laf-aqua.css.map b/dist/css/laf-aqua.css.map new file mode 100644 index 0000000..c037b4f --- /dev/null +++ b/dist/css/laf-aqua.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["../../src/sass-include/_common.sass","../../src/sass-include/_tooltip.sass","../../src/sass-include/_button.sass","../../src/sass-include/_text.sass","../../src/sass-include/_spinner.sass","../../src/sass-include/_switch.sass","../../src/sass-include/_list.sass","../../src/sass-include/_combo.sass","../../src/sass-include/_table.sass","../../src/sass-include/_color-picker.sass","../../src/sass-include/_tab-folder.sass","../../src/sass-include/_progress-bar.sass"], +"names": [], +"file": "laf-aqua.css" +} diff --git a/dist/css/laf-default.css b/dist/css/laf-default.css new file mode 100644 index 0000000..6b1497e --- /dev/null +++ b/dist/css/laf-default.css @@ -0,0 +1,715 @@ +@charset "UTF-8"; +html, body { + padding: 0; + margin: 0; + color: #CCC; + background-color: #1A1A1A; + font-family: "Trebuchet MS"; +} + +.noselect { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.sp-dd { + display: none; +} + +.sp-preview { + margin: 0; +} + +.sp-replacer { + padding: 0; +} + +.no-resize { + resize: none; +} + +.resize-v { + resize: vertical; +} + +.resize-h { + resize: horizontal; +} + +.resize-all { + resize: both; +} + +.Button, .ToggleButton, +.Text, .TextArea, .Spinner, +.CheckContainer, .RadioContainer, +.ColorPicker, .FileChooser + label, +.Combo, .ComboEditable, +.Table, +.TabFolder, +.ProgressBar { + margin: 0.25em; +} + +#wwt_tooltip { + background-color: rgba(0, 0, 0, 0.65); + border-radius: 5px; + border: 1px solid #000; + color: #CCC; + position: absolute; + padding: 2px 5px; + max-width: 20%; + font-size: 10pt; + z-index: 10000; +} + +.Button, .ToggleButton, .FileChooser + label, .Combo, .ComboEditableButton { + border-radius: 5px; + border: 1px solid #000; + background: linear-gradient(#313131, #222); + color: inherit; + font-family: inherit; + font-size: inherit; + padding-left: 5px; + padding-right: 5px; + line-height: 1.5em; + text-align: center; + display: inline-block; +} +.Button .title, .ToggleButton .title, .FileChooser + label .title, .Combo .title, .ComboEditableButton .title { + cursor: default; +} +.Button .title.invisible, .ToggleButton .title.invisible, .FileChooser + label .title.invisible, .Combo .title.invisible, .ComboEditableButton .title.invisible { + opacity: 0; +} + +.Button:focus, .ToggleButton:focus, .Combo:focus { + outline: 0; +} + +.Button:hover, .ToggleButton:not(.state-in):hover, .FileChooser + label:hover, .Combo:hover, .ComboEditableButton:hover { + background: linear-gradient(#414141, #333); +} + +.Button.disabled, .Button:hover.disabled, +.ToggleButton.state-out.disabled, .ToggleButton.state-in.disabled, +.ToggleButton.state-out.disabled:hover, .ToggleButton.state-in.disabled:hover, +.Spinner.disabled .SpinnerIncrement, .Spinner.disabled .SpinnerIncrement:hover, +.Spinner.disabled .SpinnerDecrement, .Spinner.disabled .SpinnerDecrement:hover, +.FileChooser.disabled + label, .FileChooser.disabled + label:hover, +.Combo.disabled, .Combo.disabled:hover, +.ComboEditable.disabled .ComboEditableButton, .ComboEditable.disabled .ComboEditableButton:hover { + color: #444; + background: none; + background-color: #101010; +} + +.ToggleButton.state-in, .Button:active, .ToggleButton:active, .FileChooser + label:active { + background: linear-gradient(#181818, #282828); +} + +.ToggleButton.state-in:hover { + background: linear-gradient(#282828, #383838); +} + +.ToggleButton.state-in.disabled, .ToggleButton.state-in.disabled:hover { + background: linear-gradient(#040404, #141414); +} + +.ButtonGroup { + margin: 0.25em; + display: inline-block; +} + +.ButtonGroup > .Button, .ButtonGroup > .ToggleButton { + margin: 0; +} + +.ButtonGroup > .Button:first-child, .ButtonGroup > .ToggleButton:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.ButtonGroup > .Button:last-child, .ButtonGroup > .ToggleButton:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.ButtonGroup > .Button:not(:last-child):not(:first-child), .ButtonGroup > .ToggleButton:not(:last-child):not(:first-child) { + border-radius: 0; +} + +.ButtonGroup > .Button:not(:last-child), .ButtonGroup > .ToggleButton:not(:last-child) { + border-right: none; +} + +.FileChooser { + width: 0.1px; + height: 0.1px; + opacity: 0; + overflow: hidden; + position: absolute; + z-index: -1; +} + +.Text, .TextArea, .sp-input { + border: 1px solid #000; + background-color: #222; + color: #CCC; + font-size: inherit; + font-family: inherit; + padding: 3px; + border-radius: 5px; + height: calc(1.5em + 2px); +} + +.Text.disabled, .TextArea.disabled, +.Spinner.disabled .SpinnerNumber, .Spinner.disabled .SpinnerIncrement, .Spinner.disabled .SpinnerDecrement, +.ComboEditable.disabled .Text { + background-color: #101010; + color: #444; +} + +.Text::placeholder { + color: #AAA; +} + +.Text::-webkit-input-placeholder, .TextArea::-webkit-input-placeholder { + color: #AAA; +} + +.Text:-moz-placeholder, .TextArea:-moz-placeholder { + color: #AAA; +} + +.Text::-moz-placeholder, .TextArea::-moz-placeholder { + color: #AAA; +} + +.Text::-webkit-input-placeholder, .TextArea::-webkit-input-placeholder { + color: #AAA; +} + +.Text:-ms-input-placeholder, .TextArea:-ms-input-placeholder { + color: #AAA; +} + +.Text::placeholder, .TextArea::placeholder { + color: #AAA; +} + +.Text.disabled::-webkit-input-placeholder, .TextArea.disabled::-webkit-input-placeholder { + color: #444; +} + +.Text.disabled::-moz-placeholder, .TextArea.disabled::-moz-placeholder { + color: #444; +} + +.Text.disabled:-moz-placeholder, .TextArea.disabled:-moz-placeholder { + color: #444; +} + +.Text.disabled:-ms-input-placeholder, .TextArea.disabled:-ms-input-placeholder { + color: #444; +} + +.Text.disabled::placeholder, .TextArea.disabled::placeholder { + color: #444; +} + +.Text:focus, .TextArea:focus, .sp-input:focus { + outline: none; + background-color: #333; +} + +.TextArea { + height: initial; +} + +.SpinnerButtonsContainer { + background: linear-gradient(#313131, #222); + display: inline-block; + float: right; + width: 1em; +} + +.SpinnerIncrement, .SpinnerDecrement { + border: 1px solid #000; + border-left: none; + display: inline-block; + float: left; + width: 1em; + text-align: center; +} + +.SpinnerIncrement:hover, .SpinnerDecrement:hover { + background: linear-gradient(#414141, #333); +} + +.SpinnerNumber { + margin: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + width: calc(100% - 1em); +} + +.SpinnerIncrement { + height: calc(.75em - 1px); +} + +.SpinnerDecrement { + height: calc(.75em); + border-top: none; +} + +.SpinnerUpArrow, .SpinnerDownArrow { + width: 0; + height: 0; + margin-top: 0.25em; + margin-left: 0.25em; +} + +.SpinnerUpArrow { + border-left: 0.25em solid transparent; + border-right: 0.25em solid transparent; + border-bottom: 0.25em solid #CCC; +} + +.SpinnerDownArrow { + border-left: 0.25em solid transparent; + border-right: 0.25em solid transparent; + border-top: 0.25em solid #CCC; +} + +.Spinner.disabled .SpinnerUpArrow { + border-bottom: 0.25em solid #444; +} + +.Spinner.disabled .SpinnerDownArrow { + border-top: 0.25em solid #444; +} + +.Spinner, .ComboEditable { + display: inline-block; +} + +.SwitchContainer, .CheckContainer, .RadioContainer { + display: inline-block; +} + +.Check:not(old), +.Radio:not(old), +.Switch:not(old) { + width: 2em; + margin: 0; + padding: 0; + font-size: 1em; + opacity: 0; +} + +.CheckContainer.disabled label, +.RadioContainer.disabled label { + color: #444; +} + +.Check:not(old) + label, +.Radio:not(old) + label { + display: inline-block; + margin-left: -2em; + line-height: 1.5em; +} + +.Check:not(old) + label .outer, +.Radio:not(old) + label .outer { + display: inline-block; + width: 0.875em; + height: 0.875em; + margin: 0.25em 0.5em 0.25em 0.25em; + border: 0.0625em solid #000; + border-radius: 0.25em; + background-color: #222; + vertical-align: bottom; +} + +.Radio:not(old) + label .outer { + border-radius: 1em; +} + +.Check:not(old):checked + label .outer, +.Radio:not(old):checked + label .outer, +.Check:not(old):hover + label .outer, +.Radio:not(old):hover + label .outer { + background-color: #333; +} + +.CheckContainer.disabled label .outer, +.RadioContainer.disabled label .outer, +.CheckContainer:hover.disabled label .outer, +.RadioContainer:hover.disabled label .outer { + background-color: #101010; +} + +.Check:not(old):checked + label .outer:before { + content: "✓"; + display: block; + width: 1em; + color: #CCC; + font-size: 0.875em; + line-height: 1em; + text-align: center; + font-weight: bold; +} + +.Radio:not(old):checked + label .inner { + display: block; + width: 0.5em; + height: 0.5em; + margin: 0.125em; + border: 0.0625em solid #000; + border-radius: 1em; + background-color: #CCC; +} + +.List { + display: inline-block; + padding: 0; + margin: 0.25em; + background-color: #222; + border: 1px solid #000; + overflow-y: auto; +} + +.List.disabled { + background-color: #101010; + color: #444; +} + +.List.h-scroll { + overflow-x: auto; +} + +.ListItem { + cursor: default; + padding: 0.175em 0.5em; +} + +.ListItem.selected { + background: linear-gradient(#414141, #333); +} + +.List.disabled .ListItem:hover, .List.disabled .ListItem.selected { + background-color: #101010; +} + +.Combo .arrow-container { + width: 1em; + display: inline-block; + float: right; +} + +.Combo .arrow-up-container { + margin-top: 0.45em; +} + +.Combo .arrow-up-container, .Combo .arrow-down-container { + display: inline-block; + float: left; + line-height: initial; + width: 1em; + margin-left: 0.5em; + height: 0.4em; +} + +.Combo .arrow-up, .Combo .arrow-down { + width: 0; + height: 0; + border-left: 0.2em solid transparent; + border-right: 0.2em solid transparent; +} + +.Combo .arrow-up { + border-bottom: 0.2em solid #CCC; +} + +.Combo .arrow-down { + border-top: 0.2em solid #CCC; +} + +.Combo.disabled .arrow-up { + border-bottom: 0.2em solid #444; +} + +.Combo.disabled .arrow-down { + border-top: 0.2em solid #444; +} + +.Combo { + text-align: left; +} + +.ComboItemList { + position: absolute; + list-style-type: none; + padding: 0; + margin: 0; + border: 1px solid #000; + overflow: auto; + border-top: none; + background-color: #222; + z-index: 10000; +} + +.ComboItemList.hidden { + display: none; +} + +.ComboItemList:not(.hidden) { + z-index: 1; +} + +.ComboItemList.overlayed { + border-top: 1px solid #000; + -webkit-box-shadow: 0px 0px 25px 3px rgba(0, 0, 0, 0.75); + -moz-box-shadow: 0px 0px 25px 3px rgba(0, 0, 0, 0.75); + box-shadow: 0px 0px 25px 3px rgba(0, 0, 0, 0.75); +} + +.ComboItem { + cursor: default; + padding: 0.175em 5px; +} + +.ComboItem.selected { + display: none; +} + +.ComboItem:hover { + background: linear-gradient(#414141, #333); +} + +.ComboEditable .Text { + margin: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + width: calc(100% - 1em - 3px); +} + +.ComboEditableButtonContainer { + margin-top: 0; + border-radius: 5px; + border-left: none; + display: inline-block; + float: right; + background: linear-gradient(#313131, #222); +} + +.ComboEditableButton { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-left: none; + margin-left: 0; + height: 1.5em; +} + +.Combo.listShown, .ComboEditable.listShown .Text { + border-bottom-left-radius: 0; +} + +.Combo.listShown, .ComboEditable.listShown .ComboEditableButton { + border-bottom-right-radius: 0; +} + +.ComboEditableArrowContainer { + display: inline-block; + margin-top: 0.75em; +} + +.ComboEditableArrowContainer .down-arrow { + border-top: 0.25em solid #CCC; + border-left: 0.25em solid transparent; + border-right: 0.25em solid transparent; +} + +.ComboEditable.disabled .ComboEditableArrowContainer .down-arrow { + border-top: 0.25em solid #444; +} + +.Table { + background-color: #222; + border: 1px solid #000; + border-collapse: collapse; + color: #CCC; + font-size: inherit; + font-family: inherit; +} + +.TableHeader { + background: linear-gradient(#414141, #333); +} + +.Table.disabled, .Table.disabled .TableRow:hover, .Table.disabled .TableHeader { + color: #444; + background-color: #101010; +} + +.TableHeader, .TableRowValue { + cursor: default; + padding: 5px; +} + +.TableHeader, .TableRow, .TableRowValue { + border: 1px solid #000; +} + +.TableRow:hover { + background: linear-gradient(#414141, #333); +} + +.ColorPickerReplacer, .ColorPickerReplacer:hover, .ColorPickerReplacer.sp-disabled, .ColorPicker.sp-active { + border: 1px solid #000; +} + +.ColorPickerReplacer { + margin: 0.25em; + height: calc(1.5em - 2px); + width: calc(1.75em - 2px); + background: linear-gradient(#313131, #222); + border: 1px solid #000; + cursor: default; +} +.ColorPickerReplacer .sp-preview { + width: calc(1.25em - 4px); + height: calc(1em - 4px); + margin: 0.25em 0 0 0.25em; + border: 1px solid #CCC; +} + +.ColorPickerReplacer.sp-disabled > sp-preview { + border: 1px solid #444; +} + +.ColorPickerReplacer:hover, .ColorPicker.sp-active, .sp-replacer.sp-active { + background: linear-gradient(#414141, #333); + border-color: #000; +} + +.ColorPickerReplacer.sp-disabled, ColorPickerReplacer.sp-disabled:hover { + background: none; + background-color: #101010; +} + +.ColorPickerContainer { + background-color: #1A1A1A; + border: 1px solid #000; +} + +.sp-picker-container { + border-left: 1px solid #000; +} + +.sp-palette-container { + border-right: 1px solid #000; +} + +.sp-palette-disabled .sp-picker-container { + border-left: none; +} + +.sp-input:focus { + border: 1px solid #000; +} + +.TabFolder { + display: inline-block; +} + +.TabContainer { + width: 100%; + display: inline-block; +} + +.Tab { + display: inline-block; + background: linear-gradient(#313131, #222); + padding: 5px; + border: 1px solid #000; + border-bottom: none; + cursor: default; +} + +.Tab:not(:first-child) { + border-left: none; +} + +.Tab:first-child { + border-top-left-radius: 5px; +} + +.Tab:last-child { + border-top-right-radius: 5px; +} + +.Tab:not(.disabled).selected { + background: linear-gradient(#181818, #282828); +} + +.Tab:not(.disabled):hover { + background: #333; +} + +.Tab.disabled { + background: #101010; +} + +.TabContentContainer { + width: calc(100% - 2px - 10px); + border: 1px solid #000; + padding: 5px; + overflow-y: auto; +} + +.ProgressBar { + height: 1em; + border: 1px solid #000; + display: inline-block; +} + +.ProgressBar, .ProgressBarInner { + border-radius: 5px; +} + +.ProgressBarInner { + height: 100%; + background-color: #333; + transition: width 0.3s ease; +} + +.ProgressBar:not(.full):not(.indeterminate) .ProgressBarInner { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.ProgressBar.indeterminate { + overflow-x: hidden; +} +.ProgressBar.indeterminate .ProgressBarInner { + animation: IndeterminateProgress 1.25s linear 0s infinite alternate; +} + +@keyframes IndeterminateProgress { + 0% { + width: 20%; + margin-left: 0; + } + 100% { + width: 20%; + margin-left: 80%; + } +} + +/*# sourceMappingURL=laf-default.css.map */ diff --git a/dist/css/laf-default.css.map b/dist/css/laf-default.css.map new file mode 100644 index 0000000..0e8dcfa --- /dev/null +++ b/dist/css/laf-default.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["../../src/sass-include/_common.sass","../../src/sass-include/_tooltip.sass","../../src/sass-include/_button.sass","../../src/sass-include/_text.sass","../../src/sass-include/_spinner.sass","../../src/sass-include/_switch.sass","../../src/sass-include/_list.sass","../../src/sass-include/_combo.sass","../../src/sass-include/_table.sass","../../src/sass-include/_color-picker.sass","../../src/sass-include/_tab-folder.sass","../../src/sass-include/_progress-bar.sass"], +"names": [], +"file": "laf-default.css" +} diff --git a/dist/css/laf-gtk.css b/dist/css/laf-gtk.css new file mode 100644 index 0000000..7cc5825 --- /dev/null +++ b/dist/css/laf-gtk.css @@ -0,0 +1,535 @@ +@charset "UTF-8"; +html, body { + padding: 0; + margin: 0; + font-family: "Trebuchet MS"; +} + +.noselect { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.sp-dd { + display: none; +} + +.sp-preview { + margin: 0; +} + +.sp-replacer { + padding: 0; +} + +.no-resize { + resize: none; +} + +.resize-v { + resize: vertical; +} + +.resize-h { + resize: horizontal; +} + +.resize-all { + resize: both; +} + +.Button, .ToggleButton, +.Text, .TextArea, .Spinner, +.CheckContainer, .RadioContainer, +.ColorPicker, .FileChooser + label, +.Combo, .ComboEditable, +.Table, +.TabFolder, +.ProgressBar { + margin: 0.25em; +} + +#wwt_tooltip { + background-color: rgba(0, 0, 0, 0.65); + border: 1px solid; + position: absolute; + padding: 2px 5px; + max-width: 20%; + font-size: 10pt; + z-index: 10000; +} + +.Button, .ToggleButton, .FileChooser + label, .Combo, .ComboEditableButton { + border: 1px solid; + color: inherit; + font-family: inherit; + font-size: inherit; + padding-left: 5px; + padding-right: 5px; + line-height: 1.5em; + text-align: center; + display: inline-block; +} +.Button .title, .ToggleButton .title, .FileChooser + label .title, .Combo .title, .ComboEditableButton .title { + cursor: default; +} +.Button .title.invisible, .ToggleButton .title.invisible, .FileChooser + label .title.invisible, .Combo .title.invisible, .ComboEditableButton .title.invisible { + opacity: 0; +} + +.Button:focus, .ToggleButton:focus, .Combo:focus { + outline: 0; +} + +.Button.disabled, .Button:hover.disabled, +.ToggleButton.state-out.disabled, .ToggleButton.state-in.disabled, +.ToggleButton.state-out.disabled:hover, .ToggleButton.state-in.disabled:hover, +.Spinner.disabled .SpinnerIncrement, .Spinner.disabled .SpinnerIncrement:hover, +.Spinner.disabled .SpinnerDecrement, .Spinner.disabled .SpinnerDecrement:hover, +.FileChooser.disabled + label, .FileChooser.disabled + label:hover, +.Combo.disabled, .Combo.disabled:hover, +.ComboEditable.disabled .ComboEditableButton, .ComboEditable.disabled .ComboEditableButton:hover { + background: none; +} + +.ButtonGroup { + margin: 0.25em; + display: inline-block; +} + +.ButtonGroup > .Button, .ButtonGroup > .ToggleButton { + margin: 0; +} + +.ButtonGroup > .Button:first-child, .ButtonGroup > .ToggleButton:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.ButtonGroup > .Button:last-child, .ButtonGroup > .ToggleButton:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.ButtonGroup > .Button:not(:last-child):not(:first-child), .ButtonGroup > .ToggleButton:not(:last-child):not(:first-child) { + border-radius: 0; +} + +.ButtonGroup > .Button:not(:last-child), .ButtonGroup > .ToggleButton:not(:last-child) { + border-right: none; +} + +.FileChooser { + width: 0.1px; + height: 0.1px; + opacity: 0; + overflow: hidden; + position: absolute; + z-index: -1; +} + +.Text, .TextArea, .sp-input { + border: 1px solid; + font-size: inherit; + font-family: inherit; + padding: 3px; + height: calc(1.5em + 2px); +} + +.Text:focus, .TextArea:focus, .sp-input:focus { + outline: none; +} + +.TextArea { + height: initial; +} + +.SpinnerButtonsContainer { + display: inline-block; + float: right; + width: 1em; +} + +.SpinnerIncrement, .SpinnerDecrement { + border: 1px solid; + border-left: none; + display: inline-block; + float: left; + width: 1em; + text-align: center; +} + +.SpinnerNumber { + margin: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + width: calc(100% - 1em); +} + +.SpinnerIncrement { + height: calc(.75em - 1px); +} + +.SpinnerDecrement { + height: calc(.75em); + border-top: none; +} + +.SpinnerUpArrow, .SpinnerDownArrow { + width: 0; + height: 0; + margin-top: 0.25em; + margin-left: 0.25em; +} + +.SpinnerUpArrow { + border-left: 0.25em solid transparent; + border-right: 0.25em solid transparent; + border-bottom: 0.25em solid; +} + +.SpinnerDownArrow { + border-left: 0.25em solid transparent; + border-right: 0.25em solid transparent; + border-top: 0.25em solid; +} + +.Spinner.disabled .SpinnerUpArrow { + border-bottom: 0.25em solid; +} + +.Spinner.disabled .SpinnerDownArrow { + border-top: 0.25em solid; +} + +.Spinner, .ComboEditable { + display: inline-block; +} + +.SwitchContainer, .CheckContainer, .RadioContainer { + display: inline-block; +} + +.Check:not(old), +.Radio:not(old), +.Switch:not(old) { + width: 2em; + margin: 0; + padding: 0; + font-size: 1em; + opacity: 0; +} + +.Check:not(old) + label, +.Radio:not(old) + label { + display: inline-block; + margin-left: -2em; + line-height: 1.5em; +} + +.Check:not(old) + label .outer, +.Radio:not(old) + label .outer { + display: inline-block; + width: 0.875em; + height: 0.875em; + margin: 0.25em 0.5em 0.25em 0.25em; + border: 0.0625em solid; + border-radius: 0.25em; + vertical-align: bottom; +} + +.Radio:not(old) + label .outer { + border-radius: 1em; +} + +.Check:not(old):checked + label .outer:before { + content: "✓"; + display: block; + width: 1em; + font-size: 0.875em; + line-height: 1em; + text-align: center; + font-weight: bold; +} + +.Radio:not(old):checked + label .inner { + display: block; + width: 0.5em; + height: 0.5em; + margin: 0.125em; + border: 0.0625em solid; + border-radius: 1em; +} + +.List { + display: inline-block; + padding: 0; + margin: 0.25em; + border: 1px solid; + overflow-y: auto; +} + +.List.h-scroll { + overflow-x: auto; +} + +.ListItem { + cursor: default; + padding: 0.175em 0.5em; +} + +.Combo .arrow-container { + width: 1em; + display: inline-block; + float: right; +} + +.Combo .arrow-up-container { + margin-top: 0.45em; +} + +.Combo .arrow-up-container, .Combo .arrow-down-container { + display: inline-block; + float: left; + line-height: initial; + width: 1em; + margin-left: 0.5em; + height: 0.4em; +} + +.Combo .arrow-up, .Combo .arrow-down { + width: 0; + height: 0; + border-left: 0.2em solid transparent; + border-right: 0.2em solid transparent; +} + +.Combo .arrow-up { + border-bottom: 0.2em solid; +} + +.Combo .arrow-down { + border-top: 0.2em solid; +} + +.Combo.disabled .arrow-up { + border-bottom: 0.2em solid; +} + +.Combo.disabled .arrow-down { + border-top: 0.2em solid; +} + +.Combo { + text-align: left; +} + +.ComboItemList { + position: absolute; + list-style-type: none; + padding: 0; + margin: 0; + border: 1px solid; + overflow: auto; + border-top: none; + z-index: 10000; +} + +.ComboItemList.hidden { + display: none; +} + +.ComboItemList:not(.hidden) { + z-index: 1; +} + +.ComboItemList.overlayed { + border-top: 1px solid; + -webkit-box-shadow: 0px 0px 25px 3px rgba(0, 0, 0, 0.75); + -moz-box-shadow: 0px 0px 25px 3px rgba(0, 0, 0, 0.75); + box-shadow: 0px 0px 25px 3px rgba(0, 0, 0, 0.75); +} + +.ComboItem { + cursor: default; + padding: 0.175em 5px; +} + +.ComboItem.selected { + display: none; +} + +.ComboEditable .Text { + margin: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + width: calc(100% - 1em - 3px); +} + +.ComboEditableButtonContainer { + margin-top: 0; + border-left: none; + display: inline-block; + float: right; +} + +.ComboEditableButton { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-left: none; + margin-left: 0; + height: 1.5em; +} + +.Combo.listShown, .ComboEditable.listShown .Text { + border-bottom-left-radius: 0; +} + +.Combo.listShown, .ComboEditable.listShown .ComboEditableButton { + border-bottom-right-radius: 0; +} + +.ComboEditableArrowContainer { + display: inline-block; + margin-top: 0.75em; +} + +.ComboEditableArrowContainer .down-arrow { + border-top: 0.25em solid; + border-left: 0.25em solid transparent; + border-right: 0.25em solid transparent; +} + +.ComboEditable.disabled .ComboEditableArrowContainer .down-arrow { + border-top: 0.25em solid; +} + +.Table { + border: 1px solid; + border-collapse: collapse; + font-size: inherit; + font-family: inherit; +} + +.TableHeader, .TableRowValue { + cursor: default; + padding: 5px; +} + +.TableHeader, .TableRow, .TableRowValue { + border: 1px solid; +} + +.ColorPickerReplacer, .ColorPickerReplacer:hover, .ColorPickerReplacer.sp-disabled, .ColorPicker.sp-active { + border: 1px solid; +} + +.ColorPickerReplacer { + margin: 0.25em; + height: calc(1.5em - 2px); + width: calc(1.75em - 2px); + border: 1px solid; + cursor: default; +} +.ColorPickerReplacer .sp-preview { + width: calc(1.25em - 4px); + height: calc(1em - 4px); + margin: 0.25em 0 0 0.25em; + border: 1px solid; +} + +.ColorPickerReplacer.sp-disabled > sp-preview { + border: 1px solid; +} + +.ColorPickerReplacer.sp-disabled, ColorPickerReplacer.sp-disabled:hover { + background: none; +} + +.ColorPickerContainer { + border: 1px solid; +} + +.sp-picker-container { + border-left: 1px solid; +} + +.sp-palette-container { + border-right: 1px solid; +} + +.sp-palette-disabled .sp-picker-container { + border-left: none; +} + +.sp-input:focus { + border: 1px solid; +} + +.TabFolder { + display: inline-block; +} + +.TabContainer { + width: 100%; + display: inline-block; +} + +.Tab { + display: inline-block; + padding: 5px; + border: 1px solid; + border-bottom: none; + cursor: default; +} + +.Tab:not(:first-child) { + border-left: none; +} + +.TabContentContainer { + width: calc(100% - 2px - 10px); + border: 1px solid; + padding: 5px; + overflow-y: auto; +} + +.ProgressBar { + height: 1em; + border: 1px solid; + display: inline-block; +} + +.ProgressBarInner { + height: 100%; + transition: width 0.3s ease; +} + +.ProgressBar:not(.full):not(.indeterminate) .ProgressBarInner { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.ProgressBar.indeterminate { + overflow-x: hidden; +} +.ProgressBar.indeterminate .ProgressBarInner { + animation: IndeterminateProgress 1.25s linear 0s infinite alternate; +} + +@keyframes IndeterminateProgress { + 0% { + width: 20%; + margin-left: 0; + } + 100% { + width: 20%; + margin-left: 80%; + } +} + +/*# sourceMappingURL=laf-gtk.css.map */ diff --git a/dist/css/laf-gtk.css.map b/dist/css/laf-gtk.css.map new file mode 100644 index 0000000..11d7b41 --- /dev/null +++ b/dist/css/laf-gtk.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["../../src/sass-include/_common.sass","../../src/sass-include/_tooltip.sass","../../src/sass-include/_button.sass","../../src/sass-include/_text.sass","../../src/sass-include/_spinner.sass","../../src/sass-include/_switch.sass","../../src/sass-include/_list.sass","../../src/sass-include/_combo.sass","../../src/sass-include/_table.sass","../../src/sass-include/_color-picker.sass","../../src/sass-include/_tab-folder.sass","../../src/sass-include/_progress-bar.sass"], +"names": [], +"file": "laf-gtk.css" +} diff --git a/dist/css/laf-win.css b/dist/css/laf-win.css new file mode 100644 index 0000000..2a90dbb --- /dev/null +++ b/dist/css/laf-win.css @@ -0,0 +1,535 @@ +@charset "UTF-8"; +html, body { + padding: 0; + margin: 0; + font-family: "Trebuchet MS"; +} + +.noselect { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.sp-dd { + display: none; +} + +.sp-preview { + margin: 0; +} + +.sp-replacer { + padding: 0; +} + +.no-resize { + resize: none; +} + +.resize-v { + resize: vertical; +} + +.resize-h { + resize: horizontal; +} + +.resize-all { + resize: both; +} + +.Button, .ToggleButton, +.Text, .TextArea, .Spinner, +.CheckContainer, .RadioContainer, +.ColorPicker, .FileChooser + label, +.Combo, .ComboEditable, +.Table, +.TabFolder, +.ProgressBar { + margin: 0.25em; +} + +#wwt_tooltip { + background-color: rgba(0, 0, 0, 0.65); + border: 1px solid; + position: absolute; + padding: 2px 5px; + max-width: 20%; + font-size: 10pt; + z-index: 10000; +} + +.Button, .ToggleButton, .FileChooser + label, .Combo, .ComboEditableButton { + border: 1px solid; + color: inherit; + font-family: inherit; + font-size: inherit; + padding-left: 5px; + padding-right: 5px; + line-height: 1.5em; + text-align: center; + display: inline-block; +} +.Button .title, .ToggleButton .title, .FileChooser + label .title, .Combo .title, .ComboEditableButton .title { + cursor: default; +} +.Button .title.invisible, .ToggleButton .title.invisible, .FileChooser + label .title.invisible, .Combo .title.invisible, .ComboEditableButton .title.invisible { + opacity: 0; +} + +.Button:focus, .ToggleButton:focus, .Combo:focus { + outline: 0; +} + +.Button.disabled, .Button:hover.disabled, +.ToggleButton.state-out.disabled, .ToggleButton.state-in.disabled, +.ToggleButton.state-out.disabled:hover, .ToggleButton.state-in.disabled:hover, +.Spinner.disabled .SpinnerIncrement, .Spinner.disabled .SpinnerIncrement:hover, +.Spinner.disabled .SpinnerDecrement, .Spinner.disabled .SpinnerDecrement:hover, +.FileChooser.disabled + label, .FileChooser.disabled + label:hover, +.Combo.disabled, .Combo.disabled:hover, +.ComboEditable.disabled .ComboEditableButton, .ComboEditable.disabled .ComboEditableButton:hover { + background: none; +} + +.ButtonGroup { + margin: 0.25em; + display: inline-block; +} + +.ButtonGroup > .Button, .ButtonGroup > .ToggleButton { + margin: 0; +} + +.ButtonGroup > .Button:first-child, .ButtonGroup > .ToggleButton:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.ButtonGroup > .Button:last-child, .ButtonGroup > .ToggleButton:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.ButtonGroup > .Button:not(:last-child):not(:first-child), .ButtonGroup > .ToggleButton:not(:last-child):not(:first-child) { + border-radius: 0; +} + +.ButtonGroup > .Button:not(:last-child), .ButtonGroup > .ToggleButton:not(:last-child) { + border-right: none; +} + +.FileChooser { + width: 0.1px; + height: 0.1px; + opacity: 0; + overflow: hidden; + position: absolute; + z-index: -1; +} + +.Text, .TextArea, .sp-input { + border: 1px solid; + font-size: inherit; + font-family: inherit; + padding: 3px; + height: calc(1.5em + 2px); +} + +.Text:focus, .TextArea:focus, .sp-input:focus { + outline: none; +} + +.TextArea { + height: initial; +} + +.SpinnerButtonsContainer { + display: inline-block; + float: right; + width: 1em; +} + +.SpinnerIncrement, .SpinnerDecrement { + border: 1px solid; + border-left: none; + display: inline-block; + float: left; + width: 1em; + text-align: center; +} + +.SpinnerNumber { + margin: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + width: calc(100% - 1em); +} + +.SpinnerIncrement { + height: calc(.75em - 1px); +} + +.SpinnerDecrement { + height: calc(.75em); + border-top: none; +} + +.SpinnerUpArrow, .SpinnerDownArrow { + width: 0; + height: 0; + margin-top: 0.25em; + margin-left: 0.25em; +} + +.SpinnerUpArrow { + border-left: 0.25em solid transparent; + border-right: 0.25em solid transparent; + border-bottom: 0.25em solid; +} + +.SpinnerDownArrow { + border-left: 0.25em solid transparent; + border-right: 0.25em solid transparent; + border-top: 0.25em solid; +} + +.Spinner.disabled .SpinnerUpArrow { + border-bottom: 0.25em solid; +} + +.Spinner.disabled .SpinnerDownArrow { + border-top: 0.25em solid; +} + +.Spinner, .ComboEditable { + display: inline-block; +} + +.SwitchContainer, .CheckContainer, .RadioContainer { + display: inline-block; +} + +.Check:not(old), +.Radio:not(old), +.Switch:not(old) { + width: 2em; + margin: 0; + padding: 0; + font-size: 1em; + opacity: 0; +} + +.Check:not(old) + label, +.Radio:not(old) + label { + display: inline-block; + margin-left: -2em; + line-height: 1.5em; +} + +.Check:not(old) + label .outer, +.Radio:not(old) + label .outer { + display: inline-block; + width: 0.875em; + height: 0.875em; + margin: 0.25em 0.5em 0.25em 0.25em; + border: 0.0625em solid; + border-radius: 0.25em; + vertical-align: bottom; +} + +.Radio:not(old) + label .outer { + border-radius: 1em; +} + +.Check:not(old):checked + label .outer:before { + content: "✓"; + display: block; + width: 1em; + font-size: 0.875em; + line-height: 1em; + text-align: center; + font-weight: bold; +} + +.Radio:not(old):checked + label .inner { + display: block; + width: 0.5em; + height: 0.5em; + margin: 0.125em; + border: 0.0625em solid; + border-radius: 1em; +} + +.List { + display: inline-block; + padding: 0; + margin: 0.25em; + border: 1px solid; + overflow-y: auto; +} + +.List.h-scroll { + overflow-x: auto; +} + +.ListItem { + cursor: default; + padding: 0.175em 0.5em; +} + +.Combo .arrow-container { + width: 1em; + display: inline-block; + float: right; +} + +.Combo .arrow-up-container { + margin-top: 0.45em; +} + +.Combo .arrow-up-container, .Combo .arrow-down-container { + display: inline-block; + float: left; + line-height: initial; + width: 1em; + margin-left: 0.5em; + height: 0.4em; +} + +.Combo .arrow-up, .Combo .arrow-down { + width: 0; + height: 0; + border-left: 0.2em solid transparent; + border-right: 0.2em solid transparent; +} + +.Combo .arrow-up { + border-bottom: 0.2em solid; +} + +.Combo .arrow-down { + border-top: 0.2em solid; +} + +.Combo.disabled .arrow-up { + border-bottom: 0.2em solid; +} + +.Combo.disabled .arrow-down { + border-top: 0.2em solid; +} + +.Combo { + text-align: left; +} + +.ComboItemList { + position: absolute; + list-style-type: none; + padding: 0; + margin: 0; + border: 1px solid; + overflow: auto; + border-top: none; + z-index: 10000; +} + +.ComboItemList.hidden { + display: none; +} + +.ComboItemList:not(.hidden) { + z-index: 1; +} + +.ComboItemList.overlayed { + border-top: 1px solid; + -webkit-box-shadow: 0px 0px 25px 3px rgba(0, 0, 0, 0.75); + -moz-box-shadow: 0px 0px 25px 3px rgba(0, 0, 0, 0.75); + box-shadow: 0px 0px 25px 3px rgba(0, 0, 0, 0.75); +} + +.ComboItem { + cursor: default; + padding: 0.175em 5px; +} + +.ComboItem.selected { + display: none; +} + +.ComboEditable .Text { + margin: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + width: calc(100% - 1em - 3px); +} + +.ComboEditableButtonContainer { + margin-top: 0; + border-left: none; + display: inline-block; + float: right; +} + +.ComboEditableButton { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-left: none; + margin-left: 0; + height: 1.5em; +} + +.Combo.listShown, .ComboEditable.listShown .Text { + border-bottom-left-radius: 0; +} + +.Combo.listShown, .ComboEditable.listShown .ComboEditableButton { + border-bottom-right-radius: 0; +} + +.ComboEditableArrowContainer { + display: inline-block; + margin-top: 0.75em; +} + +.ComboEditableArrowContainer .down-arrow { + border-top: 0.25em solid; + border-left: 0.25em solid transparent; + border-right: 0.25em solid transparent; +} + +.ComboEditable.disabled .ComboEditableArrowContainer .down-arrow { + border-top: 0.25em solid; +} + +.Table { + border: 1px solid; + border-collapse: collapse; + font-size: inherit; + font-family: inherit; +} + +.TableHeader, .TableRowValue { + cursor: default; + padding: 5px; +} + +.TableHeader, .TableRow, .TableRowValue { + border: 1px solid; +} + +.ColorPickerReplacer, .ColorPickerReplacer:hover, .ColorPickerReplacer.sp-disabled, .ColorPicker.sp-active { + border: 1px solid; +} + +.ColorPickerReplacer { + margin: 0.25em; + height: calc(1.5em - 2px); + width: calc(1.75em - 2px); + border: 1px solid; + cursor: default; +} +.ColorPickerReplacer .sp-preview { + width: calc(1.25em - 4px); + height: calc(1em - 4px); + margin: 0.25em 0 0 0.25em; + border: 1px solid; +} + +.ColorPickerReplacer.sp-disabled > sp-preview { + border: 1px solid; +} + +.ColorPickerReplacer.sp-disabled, ColorPickerReplacer.sp-disabled:hover { + background: none; +} + +.ColorPickerContainer { + border: 1px solid; +} + +.sp-picker-container { + border-left: 1px solid; +} + +.sp-palette-container { + border-right: 1px solid; +} + +.sp-palette-disabled .sp-picker-container { + border-left: none; +} + +.sp-input:focus { + border: 1px solid; +} + +.TabFolder { + display: inline-block; +} + +.TabContainer { + width: 100%; + display: inline-block; +} + +.Tab { + display: inline-block; + padding: 5px; + border: 1px solid; + border-bottom: none; + cursor: default; +} + +.Tab:not(:first-child) { + border-left: none; +} + +.TabContentContainer { + width: calc(100% - 2px - 10px); + border: 1px solid; + padding: 5px; + overflow-y: auto; +} + +.ProgressBar { + height: 1em; + border: 1px solid; + display: inline-block; +} + +.ProgressBarInner { + height: 100%; + transition: width 0.3s ease; +} + +.ProgressBar:not(.full):not(.indeterminate) .ProgressBarInner { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.ProgressBar.indeterminate { + overflow-x: hidden; +} +.ProgressBar.indeterminate .ProgressBarInner { + animation: IndeterminateProgress 1.25s linear 0s infinite alternate; +} + +@keyframes IndeterminateProgress { + 0% { + width: 20%; + margin-left: 0; + } + 100% { + width: 20%; + margin-left: 80%; + } +} + +/*# sourceMappingURL=laf-win.css.map */ diff --git a/dist/css/laf-win.css.map b/dist/css/laf-win.css.map new file mode 100644 index 0000000..0200e33 --- /dev/null +++ b/dist/css/laf-win.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["../../src/sass-include/_common.sass","../../src/sass-include/_tooltip.sass","../../src/sass-include/_button.sass","../../src/sass-include/_text.sass","../../src/sass-include/_spinner.sass","../../src/sass-include/_switch.sass","../../src/sass-include/_list.sass","../../src/sass-include/_combo.sass","../../src/sass-include/_table.sass","../../src/sass-include/_color-picker.sass","../../src/sass-include/_tab-folder.sass","../../src/sass-include/_progress-bar.sass"], +"names": [], +"file": "laf-win.css" +} diff --git a/dist/css/spectrum.css b/dist/css/spectrum.css new file mode 100644 index 0000000..a8ad9e4 --- /dev/null +++ b/dist/css/spectrum.css @@ -0,0 +1,507 @@ +/*** +Spectrum Colorpicker v1.8.0 +https://github.com/bgrins/spectrum +Author: Brian Grinstead +License: MIT +***/ + +.sp-container { + position:absolute; + top:0; + left:0; + display:inline-block; + *display: inline; + *zoom: 1; + /* https://github.com/bgrins/spectrum/issues/40 */ + z-index: 9999994; + overflow: hidden; +} +.sp-container.sp-flat { + position: relative; +} + +/* Fix for * { box-sizing: border-box; } */ +.sp-container, +.sp-container * { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +/* http://ansciath.tumblr.com/post/7347495869/css-aspect-ratio */ +.sp-top { + position:relative; + width: 100%; + display:inline-block; +} +.sp-top-inner { + position:absolute; + top:0; + left:0; + bottom:0; + right:0; +} +.sp-color { + position: absolute; + top:0; + left:0; + bottom:0; + right:20%; +} +.sp-hue { + position: absolute; + top:0; + right:0; + bottom:0; + left:84%; + height: 100%; +} + +.sp-clear-enabled .sp-hue { + top:33px; + height: 77.5%; +} + +.sp-fill { + padding-top: 80%; +} +.sp-sat, .sp-val { + position: absolute; + top:0; + left:0; + right:0; + bottom:0; +} + +.sp-alpha-enabled .sp-top { + margin-bottom: 18px; +} +.sp-alpha-enabled .sp-alpha { + display: block; +} +.sp-alpha-handle { + position:absolute; + top:-4px; + bottom: -4px; + width: 6px; + left: 50%; + cursor: pointer; + border: 1px solid black; + background: white; + opacity: .8; +} +.sp-alpha { + display: none; + position: absolute; + bottom: -14px; + right: 0; + left: 0; + height: 8px; +} +.sp-alpha-inner { + border: solid 1px #333; +} + +.sp-clear { + display: none; +} + +.sp-clear.sp-clear-display { + background-position: center; +} + +.sp-clear-enabled .sp-clear { + display: block; + position:absolute; + top:0px; + right:0; + bottom:0; + left:84%; + height: 28px; +} + +/* Don't allow text selection */ +.sp-container, .sp-replacer, .sp-preview, .sp-dragger, .sp-slider, .sp-alpha, .sp-clear, .sp-alpha-handle, .sp-container.sp-dragging .sp-input, .sp-container button { + -webkit-user-select:none; + -moz-user-select: -moz-none; + -o-user-select:none; + user-select: none; +} + +.sp-container.sp-input-disabled .sp-input-container { + display: none; +} +.sp-container.sp-buttons-disabled .sp-button-container { + display: none; +} +.sp-container.sp-palette-buttons-disabled .sp-palette-button-container { + display: none; +} +.sp-palette-only .sp-picker-container { + display: none; +} +.sp-palette-disabled .sp-palette-container { + display: none; +} + +.sp-initial-disabled .sp-initial { + display: none; +} + + +/* Gradients for hue, saturation and value instead of images. Not pretty... but it works */ +.sp-sat { + background-image: -webkit-gradient(linear, 0 0, 100% 0, from(#FFF), to(rgba(204, 154, 129, 0))); + background-image: -webkit-linear-gradient(left, #FFF, rgba(204, 154, 129, 0)); + background-image: -moz-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); + background-image: -o-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); + background-image: -ms-linear-gradient(left, #fff, rgba(204, 154, 129, 0)); + background-image: linear-gradient(to right, #fff, rgba(204, 154, 129, 0)); + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr=#FFFFFFFF, endColorstr=#00CC9A81)"; + filter : progid:DXImageTransform.Microsoft.gradient(GradientType = 1, startColorstr='#FFFFFFFF', endColorstr='#00CC9A81'); +} +.sp-val { + background-image: -webkit-gradient(linear, 0 100%, 0 0, from(#000000), to(rgba(204, 154, 129, 0))); + background-image: -webkit-linear-gradient(bottom, #000000, rgba(204, 154, 129, 0)); + background-image: -moz-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); + background-image: -o-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); + background-image: -ms-linear-gradient(bottom, #000, rgba(204, 154, 129, 0)); + background-image: linear-gradient(to top, #000, rgba(204, 154, 129, 0)); + -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#00CC9A81, endColorstr=#FF000000)"; + filter : progid:DXImageTransform.Microsoft.gradient(startColorstr='#00CC9A81', endColorstr='#FF000000'); +} + +.sp-hue { + background: -moz-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); + background: -ms-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); + background: -o-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); + background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), color-stop(0.17, #ffff00), color-stop(0.33, #00ff00), color-stop(0.5, #00ffff), color-stop(0.67, #0000ff), color-stop(0.83, #ff00ff), to(#ff0000)); + background: -webkit-linear-gradient(top, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); + background: linear-gradient(to bottom, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%); +} + +/* IE filters do not support multiple color stops. + Generate 6 divs, line them up, and do two color gradients for each. + Yes, really. + */ +.sp-1 { + height:17%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0000', endColorstr='#ffff00'); +} +.sp-2 { + height:16%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff00', endColorstr='#00ff00'); +} +.sp-3 { + height:17%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ff00', endColorstr='#00ffff'); +} +.sp-4 { + height:17%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00ffff', endColorstr='#0000ff'); +} +.sp-5 { + height:16%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0000ff', endColorstr='#ff00ff'); +} +.sp-6 { + height:17%; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff00ff', endColorstr='#ff0000'); +} + +.sp-hidden { + display: none !important; +} + +/* Clearfix hack */ +.sp-cf:before, .sp-cf:after { content: ""; display: table; } +.sp-cf:after { clear: both; } +.sp-cf { *zoom: 1; } + +/* Mobile devices, make hue slider bigger so it is easier to slide */ +@media (max-device-width: 480px) { + .sp-color { right: 40%; } + .sp-hue { left: 63%; } + .sp-fill { padding-top: 60%; } +} +.sp-dragger { + border-radius: 5px; + height: 5px; + width: 5px; + border: 1px solid #fff; + background: #000; + cursor: pointer; + position:absolute; + top:0; + left: 0; +} +.sp-slider { + position: absolute; + top:0; + cursor:pointer; + height: 3px; + left: -1px; + right: -1px; + border: 1px solid #000; + background: white; + opacity: .8; +} + +/* +Theme authors: +Here are the basic themeable display options (colors, fonts, global widths). +See http://bgrins.github.io/spectrum/themes/ for instructions. +*/ + +.sp-container { + border-radius: 0; + background-color: #ECECEC; + border: solid 1px #f0c49B; + padding: 0; +} +.sp-container, .sp-container button, .sp-container input, .sp-color, .sp-hue, .sp-clear { + font: normal 12px "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; +} +.sp-top { + margin-bottom: 3px; +} +.sp-color, .sp-hue, .sp-clear { + border: solid 1px #666; +} + +/* Input */ +.sp-input-container { + float:right; + width: 100px; + margin-bottom: 4px; +} +.sp-initial-disabled .sp-input-container { + width: 100%; +} +.sp-input { + font-size: 12px !important; + border: 1px inset; + padding: 4px 5px; + margin: 0; + width: 100%; + background:transparent; + border-radius: 3px; + color: #222; +} +.sp-input:focus { + border: 1px solid orange; +} +.sp-input.sp-validation-error { + border: 1px solid red; + background: #fdd; +} +.sp-picker-container , .sp-palette-container { + float:left; + position: relative; + padding: 10px; + padding-bottom: 300px; + margin-bottom: -290px; +} +.sp-picker-container { + width: 172px; + border-left: solid 1px #fff; +} + +/* Palettes */ +.sp-palette-container { + border-right: solid 1px #ccc; +} + +.sp-palette-only .sp-palette-container { + border: 0; +} + +.sp-palette .sp-thumb-el { + display: block; + position:relative; + float:left; + width: 24px; + height: 15px; + margin: 3px; + cursor: pointer; + border:solid 2px transparent; +} +.sp-palette .sp-thumb-el:hover, .sp-palette .sp-thumb-el.sp-thumb-active { + border-color: orange; +} +.sp-thumb-el { + position:relative; +} + +/* Initial */ +.sp-initial { + float: left; + border: solid 1px #333; +} +.sp-initial span { + width: 30px; + height: 25px; + border:none; + display:block; + float:left; + margin:0; +} + +.sp-initial .sp-clear-display { + background-position: center; +} + +/* Buttons */ +.sp-palette-button-container, +.sp-button-container { + float: right; +} + +/* Replacer (the little preview div that shows up instead of the ) */ +.sp-replacer { + margin:0; + overflow:hidden; + cursor:pointer; + padding: 4px; + display:inline-block; + *zoom: 1; + *display: inline; + border: solid 1px #91765d; + background: #eee; + color: #333; + vertical-align: middle; +} +.sp-replacer:hover, .sp-replacer.sp-active { + border-color: #F0C49B; + color: #111; +} +.sp-replacer.sp-disabled { + cursor:default; + border-color: silver; + color: silver; +} +.sp-dd { + padding: 2px 0; + height: 16px; + line-height: 16px; + float:left; + font-size:10px; +} +.sp-preview { + position:relative; + width:25px; + height: 20px; + border: solid 1px #222; + margin-right: 5px; + float:left; + z-index: 0; +} + +.sp-palette { + *width: 220px; + max-width: 220px; +} +.sp-palette .sp-thumb-el { + width:16px; + height: 16px; + margin:2px 1px; + border: solid 1px #d0d0d0; +} + +.sp-container { + padding-bottom:0; +} + + +/* Buttons: http://hellohappy.org/css3-buttons/ */ +.sp-container button { + background-color: #eeeeee; + background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc); + background-image: -moz-linear-gradient(top, #eeeeee, #cccccc); + background-image: -ms-linear-gradient(top, #eeeeee, #cccccc); + background-image: -o-linear-gradient(top, #eeeeee, #cccccc); + background-image: linear-gradient(to bottom, #eeeeee, #cccccc); + border: 1px solid #ccc; + border-bottom: 1px solid #bbb; + border-radius: 3px; + color: #333; + font-size: 14px; + line-height: 1; + padding: 5px 4px; + text-align: center; + text-shadow: 0 1px 0 #eee; + vertical-align: middle; +} +.sp-container button:hover { + background-color: #dddddd; + background-image: -webkit-linear-gradient(top, #dddddd, #bbbbbb); + background-image: -moz-linear-gradient(top, #dddddd, #bbbbbb); + background-image: -ms-linear-gradient(top, #dddddd, #bbbbbb); + background-image: -o-linear-gradient(top, #dddddd, #bbbbbb); + background-image: linear-gradient(to bottom, #dddddd, #bbbbbb); + border: 1px solid #bbb; + border-bottom: 1px solid #999; + cursor: pointer; + text-shadow: 0 1px 0 #ddd; +} +.sp-container button:active { + border: 1px solid #aaa; + border-bottom: 1px solid #888; + -webkit-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; + -moz-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; + -ms-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; + -o-box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; + box-shadow: inset 0 0 5px 2px #aaaaaa, 0 1px 0 0 #eeeeee; +} +.sp-cancel { + font-size: 11px; + color: #d93f3f !important; + margin:0; + padding:2px; + margin-right: 5px; + vertical-align: middle; + text-decoration:none; + +} +.sp-cancel:hover { + color: #d93f3f !important; + text-decoration: underline; +} + + +.sp-palette span:hover, .sp-palette span.sp-thumb-active { + border-color: #000; +} + +.sp-preview, .sp-alpha, .sp-thumb-el { + position:relative; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==); +} +.sp-preview-inner, .sp-alpha-inner, .sp-thumb-inner { + display:block; + position:absolute; + top:0;left:0;bottom:0;right:0; +} + +.sp-palette .sp-thumb-inner { + background-position: 50% 50%; + background-repeat: no-repeat; +} + +.sp-palette .sp-thumb-light.sp-thumb-active .sp-thumb-inner { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAIVJREFUeNpiYBhsgJFMffxAXABlN5JruT4Q3wfi/0DsT64h8UD8HmpIPCWG/KemIfOJCUB+Aoacx6EGBZyHBqI+WsDCwuQ9mhxeg2A210Ntfo8klk9sOMijaURm7yc1UP2RNCMbKE9ODK1HM6iegYLkfx8pligC9lCD7KmRof0ZhjQACDAAceovrtpVBRkAAAAASUVORK5CYII=); +} + +.sp-palette .sp-thumb-dark.sp-thumb-active .sp-thumb-inner { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjEwMPRyoQAAAMdJREFUOE+tkgsNwzAMRMugEAahEAahEAZhEAqlEAZhEAohEAYh81X2dIm8fKpEspLGvudPOsUYpxE2BIJCroJmEW9qJ+MKaBFhEMNabSy9oIcIPwrB+afvAUFoK4H0tMaQ3XtlrggDhOVVMuT4E5MMG0FBbCEYzjYT7OxLEvIHQLY2zWwQ3D+9luyOQTfKDiFD3iUIfPk8VqrKjgAiSfGFPecrg6HN6m/iBcwiDAo7WiBeawa+Kwh7tZoSCGLMqwlSAzVDhoK+6vH4G0P5wdkAAAAASUVORK5CYII=); +} + +.sp-clear-display { + background-repeat:no-repeat; + background-position: center; + background-image: url(data:image/gif;base64,R0lGODlhFAAUAPcAAAAAAJmZmZ2dnZ6enqKioqOjo6SkpKWlpaampqenp6ioqKmpqaqqqqurq/Hx8fLy8vT09PX19ff39/j4+Pn5+fr6+vv7+wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAUABQAAAihAP9FoPCvoMGDBy08+EdhQAIJCCMybCDAAYUEARBAlFiQQoMABQhKUJBxY0SPICEYHBnggEmDKAuoPMjS5cGYMxHW3IiT478JJA8M/CjTZ0GgLRekNGpwAsYABHIypcAgQMsITDtWJYBR6NSqMico9cqR6tKfY7GeBCuVwlipDNmefAtTrkSzB1RaIAoXodsABiZAEFB06gIBWC1mLVgBa0AAOw==); +} diff --git a/dist/factory.html b/dist/factory.html new file mode 100644 index 0000000..4b540e7 --- /dev/null +++ b/dist/factory.html @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/dist/js/demo/demo-wwt.js b/dist/js/demo/demo-wwt.js new file mode 100644 index 0000000..618e6e4 --- /dev/null +++ b/dist/js/demo/demo-wwt.js @@ -0,0 +1,117 @@ +$(document).ready(function() { + wwt.init(); + + var buttons = new wwt.Composite("", "buttons"); + var textboxes = new wwt.Composite("", "textboxes"); + var checkRadio = new wwt.Composite("", "checkRadio"); + var spinners = new wwt.Composite("", "spinners"); + var pickers = new wwt.Composite("", "pickers"); + var lists = new wwt.Composite("", "lists"); + var groups = new wwt.Composite("", "groups"); + var tabs = new wwt.Composite("", "tabs"); + var progress = new wwt.Composite("", "progressbars"); + + //fun fact - Android version names (1.5 - 6.0.x) + var items = [ + "Cupcake", + "Donut", + "Eclair", + "Froyo", + "Gingerbread", + "Honeycomb", + "Ice Cream Sandwich", + "Jelly Bean", + "KitKat", + "Lolipop", + "Marshmellow" + ] + + //Buttons + new wwt.Button(buttons, "buttonEnabled", "Button").setTooltip("I am a button!"); + new wwt.Button(buttons, "buttonDisabled", "Button").setEnabled(false); + + //ToggleButtons + new wwt.ToggleButton(buttons, "togglebuttonEnabled", "ToggleButton").setTooltip("I am a toggle button!"); + new wwt.ToggleButton(buttons, "togglebuttonEnabledActive", "ToggleButton").setState(true); + new wwt.ToggleButton(buttons, "togglebuttondDisabled", "ToggleButton").setEnabled(false); + new wwt.ToggleButton(buttons, "togglebuttonActiveDisabled", "ToggleButton").setState(true).setEnabled(false); + + //ButtonGroup + var bg1 = new wwt.ButtonGroup(buttons, "buttonGroupEnabled").setTooltip("This isn't shown!"); + var bg2 = new wwt.ButtonGroup(buttons, "buttonGroupDisabled").setEnabled(false); + var tbg1 = new wwt.ButtonGroup(buttons, "toggleButtonGroupEnabled", true); + var tbg2 = new wwt.ButtonGroup(buttons, "toggleButtonGroupDisabled", true).setEnabled(false); + + [bg1, bg2, tbg1, tbg2].forEach(function(e, i) { + var title = (e.isToggle() ? "Toggle" : "") + "Button"; + var b1 = e.addButton("", title).setTooltip("I am a button (in a group)!"); + var b2 = e.addButton("", title); + var b3 = e.addButton("", title); + + if(i >= 2){ + b1.setState(true); + b3.setState(true); + } + }); + + //Textboxes (single and multi) + new wwt.Text(textboxes, "textEnabled").setPlaceholder("Text").setTooltip("I am a textbox!"); + new wwt.Text(textboxes, "textDisabled").setPlaceholder("Text").setEnabled(false); + new wwt.Text(textboxes, "textMultiEnabled", "multi").setPlaceholder("Text").setTooltip("I am a (multi) textbox!"); + new wwt.Text(textboxes, "textMultiDisabled", "multi").setPlaceholder("Text").setEnabled(false); + new wwt.Text(textboxes, "textPasswordEnabled", "password").setPlaceholder("Text").setText("Password").setTooltip("I am a (password) textbox!"); + new wwt.Text(textboxes, "textPasswordDisabled", "password").setPlaceholder("Text").setEnabled(false).setText("Password"); + + //Radio buttons + new wwt.Radio(checkRadio, "radioEnabled", "Radio").setGroup("radios").setTooltip("I am a radio button!"); + new wwt.Radio(checkRadio, "radioDisabled", "Radio").setGroup("radios").setEnabled(false); + + //Checkboxes + new wwt.Check(checkRadio, "checkEnabled", "Check").setTooltip("I am a checkbox!"); + new wwt.Check(checkRadio, "checkDisabled", "Check").setEnabled(false); + + //Spinners + new wwt.Spinner(spinners, "spinnerEnabled").setTooltip("I am a spinner!"); + new wwt.Spinner(spinners, "spinnerDisabled").setEnabled(false); + + //ColorPickers + new wwt.ColorPicker(pickers, "colorPickerEnabled", { + color: "#B91F1F", + palette: ["red", "green", "blue"] + }).setTooltip("I am a color picker!"); + new wwt.ColorPicker(pickers, "colorPickerDisabled").setEnabled(false); + + //FileChoosers + new wwt.FileChooser(pickers, "fileChooserEnabled", "FileChooser").setTooltip("I am a filechooser!"); + new wwt.FileChooser(pickers, "fileChooserDisabled", "FileChooser").setEnabled(false); + + new wwt.List(lists, "listEnabled", items).setMultiSelect(true).setSelectedItems([8, 9]).setTooltip("I am a list!");; + new wwt.List(lists, "listDisabled", items).setEnabled(false); + + new wwt.Combo(lists, "comboEnabled").setItems(items).setText("Ice Cream Sandwich").setTooltip("I am a combo!");; + new wwt.Combo(lists, "comboDisabled").setItems(items).setText("KitKat").setEnabled(false); + new wwt.Combo(lists, "comboEditableEnabled", true).setItems(items).setText("").setTooltip("I am an (editable) combo!"); + new wwt.Combo(lists, "comboEditableDisabled", true).setItems(items).setText("KitKat").setEnabled(false); + + // new wwt.YTVideo("videos", "ytPlayer", new wwt.YTVideo.Options("rnQBF2CIygg").setAutoPlay(false).setSize(500, 500)); + + var tabs = new wwt.TabFolder(tabs, "tabsEnabled"); + tabs.append("Tab 1", "enabledTab1").append("BOLD TEXT").setTooltip("I am a tab in a tab folder!"); + tabs.append("Tab 2", "enabledTab2").append("ITALIC TEXT"); + var bigTab = tabs.append("Tab 3", "enabledTab3"); + new wwt.Button(bigTab, "buttonInsideTab", "Button"); + new wwt.Button(bigTab, "buttonInsideTab1", "Button"); + new wwt.Button(bigTab, "buttonInsideTab2", "Button"); + new wwt.Button(bigTab, "buttonInsideTab3", "Button"); + new wwt.Button(bigTab, "buttonInsideTab4", "Button"); + new wwt.Button(bigTab, "buttonInsideTab5", "Button"); + + var table = new wwt.Table(lists, "table").setTooltip("I am a table!");; + table.addHeader("Header by string"); + table.addHeader(new wwt.Table.Header("Header by class")); + table.addRow(new wwt.Table.Row(["0,0", "1,0"])); + table.addRow(["1,0", "1,1"]); + + var pb = new wwt.ProgressBar(progress, "progressEnabled").setTooltip("I am a progress bar!").setIndeterminate(); + +}); diff --git a/dist/js/lib/jquery.js b/dist/js/lib/jquery.js new file mode 100644 index 0000000..5fac9dd --- /dev/null +++ b/dist/js/lib/jquery.js @@ -0,0 +1,11015 @@ +/*! + * jQuery JavaScript Library v1.12.3 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-04-05T19:16Z + */ + +(function( global, factory ) { + + if ( typeof module === "object" && typeof module.exports === "object" ) { + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Support: Firefox 18+ +// Can't be in strict mode, several libs including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +//"use strict"; +var deletedIds = []; + +var document = window.document; + +var slice = deletedIds.slice; + +var concat = deletedIds.concat; + +var push = deletedIds.push; + +var indexOf = deletedIds.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var support = {}; + + + +var + version = "1.12.3", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android<4.1, IE<9 + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num != null ? + + // Return just the one element from the set + ( num < 0 ? this[ num + this.length ] : this[ num ] ) : + + // Return all the elements in a clean array + slice.call( this ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // 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 + // adding 1 corrects loss of precision from parseFloat (#15100) + var realStringObj = obj && obj.toString(); + return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 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.ownFirst ) { + 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; + }, + + // 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 ); // jscs:ignore requireDotNotation + } )( 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(); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === 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 length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + 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 +} ); + +// JSHint would error on this code due to the Symbol not being defined in ES5. +// Defining this global in .jshintrc would create a danger of using the global +// unguarded in another place, it seems safer to just disable JSHint for these +// three lines. +/* jshint ignore: start */ +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = deletedIds[ Symbol.iterator ]; +} +/* jshint ignore: end */ + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: iOS 8.2 (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.2.1 + * http://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2015-10-17 + */ +(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" + 1 * 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 + 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 as it's faster than native + // http://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[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 + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // 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 + rwhitespace = new RegExp( whitespace + "+", "g" ), + 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( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "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 ); + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }; + +// 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 m, i, elem, nid, nidselect, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + nidselect = ridentifier.test( nid ) ? "#" + nid : "[id='" + nid + "']"; + while ( i-- ) { + groups[i] = nidselect + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + 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 = arr.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 !== "undefined" && 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, parent, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( (parent = document.defaultView) && parent.top !== parent ) { + // Support: IE 11 + if ( parent.addEventListener ) { + parent.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( parent.attachEvent ) { + parent.attachEvent( "onunload", unloadHandler ); + } + } + + /* 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( document.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // 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 !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var m = context.getElementById( id ); + return m ? [ 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 !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + 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 !== "undefined" && 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( document.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 + docElem.appendChild( 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("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // 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"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibing-combinator selector` fails + if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( div ) { + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.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 self-exclusive + // 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 === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( 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 === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( 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 document; +}; + +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 && + !compilerCache[ expr + " " ] && + ( !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 !== "undefined" && 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.replace( rwhitespace, " " ) + " " ).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, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + 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 + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && 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 ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // 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 ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ 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( 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 ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + 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, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator 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 ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( (oldCache = uniqueCache[ 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 + uniqueCache[ 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( 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( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + 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 || outermost; + } + + // Add elements passing elementMatchers directly to results + // 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; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, 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 ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + 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 only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound 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, + !context || 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-35+ +// 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.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +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 ) > -1 ) !== 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, + + // 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, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // init accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // 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 || root ).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 root.ready !== "undefined" ? + root.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.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.uniqueSort( 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.uniqueSort( + 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 dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( 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.uniqueSort( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +} ); +var rnotwhite = ( /\S+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + 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" ? + 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, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( jQuery.isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + 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.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = true; + if ( !memory ) { + self.disable(); + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + 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() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } 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() + .progress( updateFunc( i, progressContexts, progressValues ) ) + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ); + } 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; + } + + // 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 ); + window.removeEventListener( "load", completed ); + + } 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 || + window.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. + // Support: IE6-10 + // Older IE sometimes signals "interactive" too soon + if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); + + // 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 window.setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + } )(); + } + } + } + return readyList.promise( obj ); +}; + +// Kick off the DOM ready check even if the user does not +jQuery.ready.promise(); + + + + +// Support: IE<9 +// Iteration over object's inherited properties before its own +var i; +for ( i in jQuery( support ) ) { + break; +} +support.ownFirst = 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 !== "undefined" ) { + + // 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" ); + + // Support: IE<9 + support.deleteExpando = true; + try { + delete div.test; + } catch ( e ) { + support.deleteExpando = false; + } + + // Null elements to avoid leaks in IE. + div = null; +} )(); +var 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 ( !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 ( !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, undefined + } else { + cache[ id ] = undefined; + } +} + +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 ); + } +} ); + + +( function() { + var shrinkWrapBlocksVal; + + support.shrinkWrapBlocks = function() { + if ( shrinkWrapBlocksVal != null ) { + return shrinkWrapBlocksVal; + } + + // Will be changed later if needed. + shrinkWrapBlocksVal = false; + + // Minified: var b,c,d + var div, body, container; + + body = document.getElementsByTagName( "body" )[ 0 ]; + if ( !body || !body.style ) { + + // Test fired too early or in an unsupported environment, exit. + 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 ); + + // Support: IE6 + // Check if elements with layout shrink-wrap their children + if ( typeof div.style.zoom !== "undefined" ) { + + // Reset CSS: box-sizing; display; margin; border + div.style.cssText = + + // Support: Firefox<29, Android 2.3 + // Vendor-prefix box-sizing + "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" + + "box-sizing:content-box;display:block;margin:0;border:0;" + + "padding:1px;width:1px;zoom:1"; + div.appendChild( document.createElement( "div" ) ).style.width = "5px"; + shrinkWrapBlocksVal = div.offsetWidth !== 3; + } + + body.removeChild( container ); + + return shrinkWrapBlocksVal; + }; + +} )(); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +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 ); + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, + scale = 1, + maxIterations = 20, + currentValue = tween ? + function() { return tween.cur(); } : + function() { return jQuery.css( elem, prop, "" ); }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + do { + + // If previous iteration zeroed out, double until we get *something*. + // Use string for doubling so we don't accidentally see scale as unchanged below + scale = scale || ".5"; + + // Adjust and apply + initialInUnit = initialInUnit / scale; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Update scale, tolerating zero or NaN from tween.cur() + // Break the loop if scale is unchanged or perfect, or if we've just had enough. + } while ( + scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations + ); + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var 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 ) { + 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 ); + +var rtagName = ( /<([\w:-]+)/ ); + +var rscriptType = ( /^$|\/(?:java|ecma)script/i ); + +var rleadingWhitespace = ( /^\s+/ ); + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|" + + "details|dialog|figcaption|figure|footer|header|hgroup|main|" + + "mark|meter|nav|output|picture|progress|section|summary|template|time|video"; + + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + + +( function() { + var div = document.createElement( "div" ), + fragment = document.createDocumentFragment(), + input = document.createElement( "input" ); + + // 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 ); + + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input = document.createElement( "input" ); + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // 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 + // Cloned elements keep attachEvent handlers, we use addEventListener on IE9+ + support.noCloneEvent = !!div.addEventListener; + + // Support: IE<9 + // Since attributes and properties are the same in IE, + // cleanData must set properties to undefined rather than use removeAttribute + div[ jQuery.expando ] = 1; + support.attributes = !div.getAttribute( jQuery.expando ); +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
", "
" ], + area: [ 1, "", "" ], + + // Support: IE8 + 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
", "
" ] +}; + +// Support: IE8-IE9 +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 !== "undefined" ? + context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== "undefined" ? + 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; +} + + +// 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" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/, + rtbody = / 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++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + + 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; +} + + +( function() { + var i, eventName, + div = document.createElement( "div" ); + + // Support: IE<9 (lack submit/change bubble), Firefox (lack focus(in | out) events) + for ( i in { submit: true, change: true, focusin: true } ) { + eventName = "on" + i; + + if ( !( support[ i ] = eventName in window ) ) { + + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + div.setAttribute( eventName, "t" ); + support[ i ] = 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|drag|drop)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE9 +// See #13393 for more info +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // 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 ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + 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 elem; + } + + 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 elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * 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 !== "undefined" && + ( !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( "." ) > -1 ) { + + // 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.rnamespace = 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 && 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 + ) && 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, j, ret, matched, handleObj, + 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.rnamespace || event.rnamespace.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 i, matches, sel, handleObj, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Support (at least): Chrome, IE9 + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // + // Support: Firefox<=42+ + // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343) + if ( delegateCount && cur.nodeType && + ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) { + + /* 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 ) > -1 : + 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: Safari 6-8+ + // 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 detail 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; + } + } + } + }, + + // Piggyback on a donor event to simulate a different one + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + + // Previously, `originalEvent: {}` was set here, so stopPropagation call + // would not be triggered on donor event, since in our own + // jQuery.event.stopPropagation function we had a check for existence of + // originalEvent.stopPropagation method, so, consequently it would be a noop. + // + // Guard for simulated events was moved to jQuery.event.stopPropagation function + // since `originalEvent` should point to the original event for the + // constancy with other events and for more focused logic + } + ); + + jQuery.event.trigger( e, null, elem ); + + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } + } : + 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 ] === "undefined" ) { + 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 = { + constructor: jQuery.Event, + 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 || this.isSimulated ) { + 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 +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://code.google.com/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +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 mouseenter/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.submit ) { + + 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" ) ? + + // Support: IE <=8 + // We use jQuery.prop instead of elem.form + // to allow fixing the IE8 delegated submit issue (gh-2332) + // by 3rd party polyfills/workarounds. + jQuery.prop( elem, "form" ) : + undefined; + + if ( form && !jQuery._data( form, "submit" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submitBubble = true; + } ); + jQuery._data( form, "submit", 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._submitBubble ) { + delete event._submitBubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event ); + } + } + }, + + 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.change ) { + + 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._justChanged = true; + } + } ); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._justChanged && !event.isTrigger ) { + this._justChanged = false; + } + + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event ); + } ); + } + 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, "change" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event ); + } + } ); + jQuery._data( elem, "change", 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 ); + } + }; +} + +// Support: Firefox +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome, Safari +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://code.google.com/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + 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 ) ); + }; + + 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 ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, 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 ); + } + } +} ); + + +var rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp( "<(?:" + nodeNames + ")[\\s/>]", "i" ), + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi, + + // Support: IE 10-11, Edge 10240+ + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement( "div" ) ); + +// 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; +} + +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; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = collection.length, + 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 collection.each( function( index ) { + var self = collection.eq( index ); + if ( isFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + 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 ) { + + // Support: Android<4.1, PhantomJS<2 + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ 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 collection; +} + +function remove( elem, selector, keepData ) { + var node, + elems = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = elems[ i ] ) != null; i++ ) { + + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + + 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; + }, + + cleanData: function( elems, /* internal */ forceAcceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + attributes = support.attributes, + special = jQuery.event.special; + + for ( ; ( elem = elems[ i ] ) != null; i++ ) { + if ( forceAcceptData || 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 ]; + + // Support: IE<9 + // IE does not allow us to delete expando properties from nodes + // IE creates expando attributes along with the property + // IE does not have a removeAttribute function on Document nodes + if ( !attributes && typeof elem.removeAttribute !== "undefined" ) { + elem.removeAttribute( internalKey ); + + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://code.google.com/p/chromium/issues/detail?id=378607 + } else { + elem[ internalKey ] = undefined; + } + + deletedIds.push( id ); + } + } + } + } + } +} ); + +jQuery.fn.extend( { + + // Keep domManip exposed until 3.0 (gh-2225) + domManip: domManip, + + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + 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 domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, 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 domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + 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 = jQuery.htmlPrefilter( value ); + + 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 ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +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 = { + + // Support: Firefox + // We have to pre-define these values for FF (#10227) + HTML: "block", + BODY: "block" + }; + +/** + * 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 elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), + + 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( ""); + }; + + function YTVideo(parent, id, options) { + if (options == null) { + options = {}; + } + root.util.validateObject("options", options); + YTVideo.__super__.constructor.call(this, parent, id); + if (options.videoId) { + root.util.validateString("options.videoId", options.videoId); + } + createPlayer(this.$__parent, id, options); + this.__afterAppend(); + } + + return YTVideo; + + })(Widget); + $(window).resize(function() { + var j, len, ref, results, w; + ref = registry.getByType(Combo); + results = []; + for (j = 0, len = ref.length; j < len; j++) { + w = ref[j]; + results.push(w.__hide()); + } + return results; + }); + $(window).mousemove(function(e) { + MOUSE.page.x = e.pageX; + MOUSE.page.y = e.pageY; + MOUSE.client.x = e.clientX; + MOUSE.client.y = e.clientY; + MOUSE.screen.x = e.screenX; + return MOUSE.screen.y = e.screenY; + }); + }); + +}).call(this); diff --git a/dist/js/lib/wwt.min.js b/dist/js/lib/wwt.min.js new file mode 100644 index 0000000..0fe5d5b --- /dev/null +++ b/dist/js/lib/wwt.min.js @@ -0,0 +1,2 @@ +(function(){"use strict";var a=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1},b=function(a,b){function d(){this.constructor=a}for(var e in b)c.call(b,e)&&(a[e]=b[e]);return d.prototype=b.prototype,a.prototype=new d,a.__super__=b.prototype,a},c={}.hasOwnProperty;!function(a){var b,c,d,e;if(!window)throw new Error("WWT cannot run in a windowless environment");if(e=window.jQuery?window.jQuery:require("jquery"),!e)throw new Error("WWT requires jQuery to run");if("object"==typeof module&&"object"==typeof module.exports){b=void 0;try{b=require("electron")}catch(d){c=d}return a(e,module.exports,b)}return a(e,window.wwt={})}(function(c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N;d.registry=N=new(w=function(){function a(){this.__widgets=[]}return a.prototype.add=function(a){return a instanceof D?this.__widgets.push(a):void 0},a.prototype.getByType=function(a,b){var c,d,e,f,g;if(null==b&&(b=!1),null!==a){for(e=this.__widgets,f=[],c=0,d=e.length;d>c;c++)g=e[c],(b?g.constructor===a:g instanceof a)&&f.push(g);return f}return[]},a.prototype.getById=function(a){var b,c,e,f;if(d.util.validateString("id",a),0===a.length)return null;for(e=this.__widgets,b=0,c=e.length;c>b;b++)if(f=e[b],f.getId()===a)return f;return null},a}()),F=function(a,b){if(null==b&&(b=""),"string"!=typeof a&&!d.util.isJQuery(a)&&!a instanceof l)throw new Error("parent must be a string, jQuery object, or an instanceof wwt.Composite");if(!(""===a||d.util.isJQuery(a)||a instanceof l)&&0===c("#"+a).length)throw new Error("DOM id "+a+" (parent) does not exist");if(d.util.validateString("id",b),b.length>0&&0!==c("#"+b).length)throw new Error("DOM id "+b+" (id) already exists")},I=function(a){return""===a?c("body"):"object"==typeof a&&a instanceof l?a.$__element:c("#"+a)},J=function(a){return"undefined"!=typeof a?a:""},H=function(a,b){return null==b&&(b=!1),"boolean"==typeof a?a:b},G=function(a){var b;return b=(""+a).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/),b?Math.max(0,b[1]?b[1].length:0,-(b[2]?+b[2]:0)):0},L=function(a,b){if(-1>b&&b=0?c:d},b.prototype.getLookAndFeel=function(){return k(i,e,c)},b.prototype.setLookAndFeel=function(a){return e=k(i,a,c)},b.prototype.isNativeLookAndFeel=function(){return"native"===e},b.prototype.getWindowsAccent=function(){return k(j,g,d)},b.prototype.setWindowsAccent=function(a){return k(j,a,d)},b.prototype.setResourceBase=function(a){return h=a},b.prototype.getResourceBase=function(){return h},b.prototype.isGtkDark=function(){return f},b.prototype.setGtkDark=function(a){return validateBoolean("dark",a),f=a},b}()),K=!1,t="",s={client:{},page:{},screen:{}},d.electron=e,d.updateTheme=function(){var a,b;if(K)return c("#_wwtTheme").remove(),a=M.getResourceBase(),b=M.isNativeLookAndFeel()?t:M.getLookAndFeel(),c("head").append("")},d.init=function(){var a;return K=!0,a=navigator.platform,t=a.startsWith("Win")?"windows":a.startsWith("Mac")?"aqua":"gtk",d.updateTheme()},d.getMousePos=function(){return c.extend({},s)},d.util={watch:function(a,b,c,d){var e,f;return e=a.prop(b),f=window.setTimeout(function(){return a.prop(b)!==e?c.call(d):void 0},100)},defineConstant:function(a,b,c){return Object.defineProperty(a,b,{enumerable:!1,configurable:!1,writable:!1,value:c})},isArray:function(a){return a instanceof Array},isJQuery:function(a){return a instanceof c},validate:function(a,b,c){if(typeof b!==c)throw new TypeError(a+" must be a "+c)},validateArray:function(a,b){if(!this.isArray(b))throw new TypeError(a+" must be an array")},validateString:function(a,b){return this.validate(a,b,"string")},validateBoolean:function(a,b){return this.validate(a,b,"boolean")},validateFunction:function(a,b){return this.validate(a,b,"function")},validateNumber:function(a,b){return this.validate(a,b,"number")},validateObject:function(a,b){return this.validate(a,b,"object")},validateInt:function(a,b){if("number"!=typeof b||!Number.isInteger(b))throw new Error(a+" must be an integer")},validateInteger:function(){return this.validaeInt.apply(this,arguments)},validateJQuery:function(a,b){if(!this.isJQuery(b))throw new Error(a+" must be a jQuery object")},async:function(a){var b,c,d,e,f,g,h,i,j,k;return e=null!=(h=a.fn)?h:null,g=a.fnThis,f=null!=(i=a.fnArgs)?i:[],b=null!=(j=a.callback)?j:null,d=a.callbackThis,c=null!=(k=a.callbackArgs)?k:[],null!==e&&null!==b?setTimeout(function(){return e.apply(g,isArray(f)?f:[]),b.apply(d,isArray(c)?c:[])},0):void 0}},d.util.defineConstant(d,"event",{Selection:"selection",AfterSelection:"after-selection",Hover:"hover",Dispose:"dispose",Modify:"modify",AfterModify:"after-modify",Show:"show",Hide:"hide",Resize:"resize",SpectrumChange:"spectrum-change",SpectrumShow:"spectrum-show",SpectrumHide:"spectrum-hide",SpectrumDragStart:"spectrum-drag-start",SpectrumDragEnd:"spectrum-drag-end",SpectrumMove:"spectrum-move"}),m=function(){function a(a,b){null==b&&(b=""),d.util.validateJQuery("$e",a),this.$__element=a,this.__id="","string"==typeof b&&(this.__id=b),"string"!=typeof this.$__element.attr("id")&&this.$__element.attr("id",this.__id),this.__classes=[]}return a.prototype.__classIf=function(a,b,c){return null==c&&(c=this.$__element),b===!0?c.addClass(a):c.removeClass(a),this},a.prototype.__cssIf=function(a,b,c,d){return null==d&&(d=this.$__element),c===!0?d.css(a):d.css(b)},a.prototype.__attrIf=function(a,b,c){return null==c&&(c=this.$__element),b===!0?c.attr(a,""):c.removeAttr(a)},a.prototype.hasClass=function(a){return"string"==typeof a&&c.inArray(a,this.__classes)>-1},a.prototype.addClass=function(a){if(d.util.validateString("className",a),a.indexOf(" ")>-1)throw new Error("className cannot have space");return this.hasClass(a)||(this.__classes.push(a),this.$__element.addClass(a)),this},a.prototype.removeClass=function(a){var b,c,e,f,g,h;if(d.util.isArray(a))throw new Error("className must be a string. Use removeClasses() for Array input");if(d.util.validateString("className",a),a.indexOf(" ")>-1)throw new Error("className cannot have space");for(e=-1,c=0,h=this.__addedClasses,f=0,g=h.length;g>f;f++){if(b=h[f],b===a){e=c;break}c++}return e>-1&&(this.__addedClasses.splice(e,1),this.$__element.removeClass(a)),this},a.prototype.removeClasses=function(a){var b,c,e;for(d.util.validateArray("classes",a),c=0,e=a.length;e>c;c++)b=a[c],"string"==typeof b&&removeClass(b);return this},a.prototype.clearClasses=function(){return this.$__element.removeClass(this.__addedClasses.join(" ")),this.__addedClasses.splice(0,this.__addedClasses.length),this},a.prototype.getClasses=function(){return this.__classes.slice(0)},a.prototype.css=function(){return this.$__element.css.apply(this.$__element,arguments),this},a.prototype.getId=function(){return this.__id},a}(),d.EventListener=n=function(){function a(){}return a.prototype.addListener=function(a,b){return this.__checkDisposeState(),d.util.validateString("eventType",a),d.util.validateFunction("listener",b),this.__getListeners(a).push(b),this},a.prototype.removeAllListeners=function(a){var b,c,e;if(null==a&&(a=null),null===a){c=this.__listeners;for(b in c)e=c[b],d.util.isArray(this.__listeners[b])&&this.__listeners[b].splice(0);return this}return __getListeners(a).splice(0)},a.prototype.removeListener=function(a,b){var c,d,e,f,g,h;if(e=-1,h=this.__getListeners(a),0!==h.length){for(d=f=0,g=h.length;g>f;d=++f)if(c=h[d],c===b){e=d;break}if(!(0>e))return h.splice(e,1)}},a.prototype.__getListeners=function(a){var b;return b=this.__listeners[a],d.util.isArray(b)||(b=this.__listeners[a]=[]),b},a.prototype.notifyListeners=function(a,b){var c,e,f,g;if(this.__checkDisposeState(),d.util.validateString(a,"string"),g=this.__listeners[a],d.util.isArray(g)){for("object"!=typeof b&&(b={}),c=0,f=g.length;f>c;c++)e=g[c],"function"==typeof e&&e.call(this,b);return this}},a}(),d.Widget=D=function(a){function e(a,b,c){null==b&&(b=""),null==c&&(c=!0),F(a,b),this.__classes=[],this.__listeners={},this.__eventsAdded=!1,this.__disposed=!1,this.__id=b,this.__appended=!1,this.$__parent=d.util.isJQuery(a)?a:I(a),this.__enabled=!0,this.__tooltip="",this.__showToolipWhenDisabled=!1,N.add(this),c&&this.update()}return b(e,a),c.extend(e.prototype,n.prototype),e.prototype.__checkDisposeState=function(){if(this.__disposed===!0)throw new Error("Widget has been disposed")},e.prototype.setEnabled=function(a,b){return null==a&&(a=!0),null==b&&(b=!0),this.__checkDisposeState(),this.__enabled=a===!0,b&&this.update(),this},e.prototype.isEnabled=function(){return this.__checkDisposeState(),this.__enabled},e.prototype.setTooltip=function(a){if(this.__checkDisposeState(),"string"!=typeof a&&"function"!=typeof a)throw new Error("tooltip must be a function or string");return this.__tooltip=a,this},e.prototype.getTooltip=function(){return this.__checkDisposeState(),this.__tooltip},e.prototype.__getTooltipElement=function(){return this.$__element},e.prototype.__afterAppend=function(){var a;return this.__appended=!0,d.util.watch(this.$__element,"clientWidth",function(a){return function(){return a.notifyListeners(d.event.Resize,a)}}(this)),d.util.watch(this.$__element,"clientWidth",function(a){return function(){return a.notifyListeners(d.event.Resize,a)}}(this)),a=this.__getTooltipElement(),null!==a?this.__getTooltipElement().hover(function(a){return function(){return a.__showTooltip()}}(this),function(a){return function(){return a.__hideTooltip()}}(this)):void 0},e.prototype.showTooltipWhenDisabled=function(a){return null==a&&(a=!0),this.__checkDisposeState(),this.__showToolipWhenDisabled=a===!0,this},e.prototype.tooltipShownWhenDisabled=function(){return this.__checkDisposeState(),this.__showToolipWhenDisabled},e.prototype.__showTooltip=function(){var a,b,d,f,g,h,i,j,k,l,m;if((this.__enabled||this.__showToolipWhenDisabled)&&(b=c(document).height(),d=c(document).width(),a=this.__getTooltipElement(),null!==a))return f=a.offset().top,k=a.outerWidth(),g=a.outerHeight(),e.Tooltip.setText("string"==typeof this.__tooltip?this.__tooltip:this.__tooltip.call(this)),0===e.Tooltip.getText().length?(e.Tooltip.hide(),this):(e.Tooltip.show(),h=e.Tooltip.$__element.outerHeight(),j=e.Tooltip.$__element.outerWidth(),i=10,l=function(){var a;return a=s.page.x+i,a+j>d?s.page.x-j-i:a}(),m=function(){var a;return a=s.page.y+i,a+h>b?s.page.y-h-i:a}(),e.Tooltip.setLocation(l,m))},e.prototype.__hideTooltip=function(){return e.Tooltip.hide()},e.prototype.__updateEnabledClass=function(){return this.__classIf("disabled",!this.__enabled)},e.prototype.__updateEnabledAttr=function(a){return null==a&&(a=this.$__element),this.__attrIf("disabled",!this.__enabled,a)},e.prototype.height=function(){return this.__checkDisposeState(),this.$__element.height()},e.prototype.outerHeight=function(){return this.__checkDisposeState(),this.$__element.outerHeight.apply(this.$__element,arguments)},e.prototype.innerHeight=function(){return this.__checkDisposeState(),this.$__element.innerHeight()},e.prototype.width=function(){return this.__checkDisposeState(),this.$__element.width()},e.prototype.outerWidth=function(){return this.__checkDisposeState(),this.$__element.outerWidth.apply(this.$__element,arguments)},e.prototype.innerWidth=function(){return this.__checkDisposeState(),this.$__element.innerWidth()},e.prototype.isDisposed=function(){return this.__disposed},e.prototype.dispose=function(){return!this.__disposed&&this.$__element?(this.$__element.remove(),this.__disposed=!0,this.__notifyListeners(d.event.Dispose)):void 0},e.prototype.update=function(){},e}(m),c(document).ready(function(){return D.Tooltip=new(function(a){function e(){e.__super__.constructor.call(this,"","wwt_tooltip"),this.hide()}return b(e,a),e.prototype.dispose=function(){},e.prototype.isDisposed=function(){return!1},e.prototype.setText=function(a){return null==a&&(a=""),d.util.validateString("text",a),this.__text=a,this.update(),this},e.prototype.getText=function(){return this.__text},e.prototype.hide=function(){return this.$__element.css({display:"none"}),this},e.prototype.show=function(a,b){return"string"==typeof this.__text&&0!==this.__text.length?(this.$__element.css({display:""}),this.setLocation(a,b),this):void 0},e.prototype.setLocation=function(a,b){return null==a&&(a=0),null==b&&(b=0),this.$__element.css({left:a,top:b})},e.prototype.update=function(){return this.__appended||(this.$__element=c("
").appendTo(this.$__parent),this.__afterAppend()),this.$__element.html(this.__text)},e}(D))}),d.Composite=l=function(a){function e(a,b){e.__super__.constructor.call(this,a,b)}var f;return b(e,a),f=function(a){function d(){this.__id="",this.$__element=c("body")}return b(d,a),d.prototype.update=function(){},d.prototype.isDisposed=function(){return!1},d.prototype.dispose=function(){},d}(e),e.prototype.update=function(){return this.__checkDisposeState(),this.__appended?void 0:(this.$__element=c("
").appendTo(this.$__parent),this.__afterAppend())},e.prototype.prepend=function(a){return this.__checkDisposeState(),this.$__element.prepend(a),this},e.prototype.append=function(a){return this.__checkDisposeState(),this.$__element.append(a),this},e.prototype.clear=function(){return this.__checkDisposeState(),this.$__element.empty(),this},e.prototype.setContent=function(a){return this.__checkDisposeState(),this.clear(),this.append(a),this},e.prototype.__getTooltipElement=function(){return null},d.util.defineConstant(e,"BODY",new f),e}(D),d.Label=q=function(a){function e(a,b,c){null==c&&(c=""),this.setText(c,!1),e.__super__.constructor.call(this,a,b)}return b(e,a),e.prototype.setText=function(a,b){return null==a&&(a=""),null==b&&(b=!0),this.__checkDisposeState(),d.util.validateString("text",a),this.__text=a,b?this.update():void 0},e.prototype.getText=function(){return this.__checkDisposeState(),this.__text},e.prototype.update=function(){return this.__checkDisposeState(),this.__appended||(this.$__element=c(""+this.__text+"").appendTo(this.$__parent),this.__afterAppend(),this.$__element.mouseenter(function(a){return function(){return a.notifyListeners(d.event.Hover)}}(this))),this.$__element.html(this.__text)},e}(D),d.Image=p=function(a){function d(a,b,c){null==c&&(c=""),d.__super__.constructor.call(this,a,b),this.setSrc(c)}return b(d,a),d.prototype.setSrc=function(a){return this.__checkDisposeState(),"string"==typeof a?(this.__src=a,this.update()):void 0},d.prototype.getSrc=function(){return this.__src},d.prototype.update=function(){return this.__appended||(this.$__element=c("").appendTo(this.$__parent)),this.$__element.attr("src",this.__src),this.__cssIf({display:"none"},{display:""},""===this.__src)},d}(D),d.Button=g=function(a){function e(a,b,c){null==c&&(c=""),e.__super__.constructor.call(this,a,b,!1),this.setText(c)}return b(e,a),e.prototype.setText=function(a,b){return null==b&&(b=!0),this.__checkDisposeState(),d.util.validateString("title",a),this.__title=a,this.__forceInvisibleText||(this.__textInvisible=!1),b&&this.update(),this},e.prototype.getText=function(){return this.__checkDisposeState(),J(this.__title)},e.prototype.setTextInvisible=function(a){return null==a&&(a=!0),this.__checkDisposeState(),this.__textInvisible=a===!0,this.update(),this},e.prototype.isTextInvisible=function(){return this.__textInvisible},e.prototype.forceInvisibleText=function(a){return this.__forceInvisibleText=a===!0,this},e.prototype.isInvisibleTextForced=function(){return this.__forceInvisibleText},e.prototype.getGroup=function(){return this.hasGroup?this.__group:null},e.prototype.hasGroup=function(){return this.__checkDisposeState(),"object"==typeof this.__group&&this.__group instanceof h},e.prototype.update=function(){return this.__checkDisposeState(),this.__appended||(this.$__element=c("").appendTo(this.$__parent),this.$__title=c("").appendTo(this.$__element),this.__afterAppend(),this.$__element.mouseenter(function(a){return function(){return a.notifyListeners(d.event.Hover)}}(this)),this.$__element.click(function(a){return function(){return a.__enabled?(a.notifyListeners(d.event.Selection),a.notifyListeners(d.event.AfterSelection)):void 0}}(this))),this.__updateEnabledClass(),this.$__title.html(this.__title),this.__classIf("invisible",this.__textInvisible,this.$__title)},e}(D),d.ToggleButton=C=function(a){function e(a,b,c){null==c&&(c=""),e.__super__.constructor.call(this,a,b,c)}return b(e,a),e.prototype.__updateStateClass=function(){return this.__state?(this.$__element.removeClass("state-out"),this.$__element.addClass("state-in")):(this.$__element.removeClass("state-in"),this.$__element.addClass("state-out"))},e.prototype.setState=function(a,b){return null==b&&(b=!0),this.__checkDisposeState(),d.util.validateBoolean("state",a),this.__state=a,b&&this.update(),this},e.prototype.getState=function(){return this.__checkDisposeState(),this.__state},e.prototype.update=function(){return this.__checkDisposeState(),this.__appended||(this.$__element=c("").appendTo(this.$__parent),this.$__title=c("").appendTo(this.$__element),this.__afterAppend(),this.$__element.hover(function(a){return function(){return d.event.Hover}}(this)),this.$__element.click(function(a){return function(){var b;if(a.__enabled&&(b={state:!a.__state,canceled:!1},a.notifyListeners(d.event.Selection,b),b.canceled!==!0))return a.__state=!a.__state,a.update()}}(this))),this.__updateEnabledClass(),this.__updateStateClass(),this.$__title.html(this.__title)},e}(g),d.ButtonGroup=h=function(a){function d(a,b,c){null==c&&(c=!1),this.__buttons=[],this.__toggle="boolean"==typeof c?c:!1,d.__super__.constructor.call(this,a,b)}return b(d,a),d.prototype.update=function(){return this.__checkDisposeState(),this.__appended?void 0:(this.$__element=c("
").appendTo(this.$__parent),this.__afterAppend())},d.prototype.addButton=function(a,b){var c;return null==b&&(b=""),this.__checkDisposeState(),c=new(this.__toggle?C:g)(this.$__element,a,b),c.__group=this,this.__buttons.push(c),c.setEnabled(this.__enabled)},d.prototype.getButton=function(a){return this.__checkDisposeState(),L(this.__buttons,a),this.__buttons[a]},d.prototype.removeButton=function(a){return this.__checkDisposeState(),L(this.__buttons,a),this.__buttons.splice(a,1),this},d.prototype.getButtons=function(){return this.__checkDisposeState(),this.__buttons.slice(0)},d.prototype.isToggle=function(){return this.__checkDisposeState(),this.__toggle},d.prototype.__getTooltipElement=function(){return null},d.prototype.setEnabled=function(a){var b,c,e,f;for(this.__checkDisposeState(),d.__super__.setEnabled.call(this,a,!1),f=this.__buttons,c=0,e=f.length;e>c;c++)b=f[c],b.setEnabled(a);return this},d}(D),d.Text=B=function(a){function e(a,b,f){null==f&&(f=""),d.util.validateString("type",f),this.__type=c.inArray(f,["multi","password"]>=0)?f:"",this.__text="",e.__super__.constructor.call(this,a,b)}var f,g;return b(e,a),f=function(a){return"id='"+a.__id+"' class='Text"+(a.isMulti()?"Area":"")+"' placeholder='"+a.getPlaceholder()+"'"},g=function(a,b){return a?b.text():b.val()},e.prototype.setPlaceholder=function(a,b){return null==b&&(b=!0),this.__checkDisposeState(),d.util.validateString("placeholder",a),this.__placeholder=a,b&&this.update(),this},e.prototype.getPlaceholder=function(){return this.__checkDisposeState(),J(this.__placeholder)},e.prototype.setText=function(a,b){return null==b&&(b=!0),this.__checkDisposeState(),d.util.validateString("text",a),this.__text=a,b&&this.update(),this},e.prototype.getText=function(){return this.__checkDisposeState(),this.__text},e.prototype.isMulti=function(){return this.__checkDisposeState(),"multi"===this.__type},e.prototype.isPassword=function(){return this.__checkDisposeState(),"password"===this.__type},e.prototype.isNormal=function(){return!(this.isMulti()||this.isPassword())},e.prototype.getCarsetPosition=function(){var a,b,c,d;return c=0,a=this.$__element[0],document.selection?(a.focus(),d=document.selection.createRange(),b=d.text.length,d.moveStart("character",-g(this.isMulti(),this.$__element).length),c=d.text.length-b):a.selectionStart&&(c=Math.min(a.selectionStart,a.selectionEnd)),c},e.prototype.setCaretPosition=function(a){var b,c;return b=this.$__element[0],b.setSelectionRange?b.setSelectionRange(a,a):b.createTextRange&&(c=b.createTextRange(),c.collapse(!0),0>a)?(a=this.getCurrentText.length+a,c.moveStart("character",a),c.moveEnd("character",a),c.select()):void 0},e.prototype.update=function(){return this.__checkDisposeState(),this.__appended||(this.$__element=c(this.isMulti()?"":""),this.$__element.appendTo(this.$__parent),this.__afterAppend(),this.$__element.focus(function(){return c(this).attr("placeholder","")}),this.$__element.blur(function(a){return function(b){return c(b.target).attr("placeholder",a.getPlaceholder())}}(this)),this.$__element.on("input",function(a){return function(){var b,c,e,f;return f={value:g(a.isMulti(),a.$__element),canceled:!1},a.notifyListeners(d.event.Modify,f),f.canceled?(c=a.getCarsetPosition(),b=a.__text.length,e=g(a.isMulti(),a.$__element).length,c-=Math.max(b,e)-Math.min(b,e),a.setText(a.__text),a.setCaretPosition(c)):a.__text=g(a.isMulti(),a.$__element),f.canceled?void 0:a.notifyListeners(d.event.AfterModify)}}(this)),this.$__element.mouseenter(function(a){return function(){return a.notifyListeners(d.event.Hover)}}(this))),this.__updateEnabledClass(),this.isMulti()?this.$__element.text(this.getText()):this.$__element.val(this.getText()),this.$__element.attr("placeholder",this.getPlaceholder()),this.__updateEnabledAttr()},e.prototype.setResize=function(a){if(this.__checkDisposeState(),this.$__element.removeClass("no-resize resize-v resize-h resize-all"),"none"===a||a===!1)return this.$__element.addClass("no-resize");if("all"===a||"*"===a||"both"===a||a===!0)return this.$__element.addClass("resize-all");if("object"==typeof a){if(a.h&&!a.v)return this.$__element.addClass("resize-h");if(a.v&&!a.h)return this.$__element.addClass("resize-v");if(a.v&&a.h)return this.$__element.addClass("resize-all");if(!a.h&&!a.v)return this.$__element.addClass("no-resize")}},e}(D),d.Spinner=x=function(a){function e(a,b,c){null==c&&(c=0),e.__super__.constructor.call(this,a,b,!1),this.setValue(c),this.__min=Number.NEGATIVE_INFINITY,this.__max=Number.POSATIVE_INFINITY,this.__interval=1}var f;return b(e,a),e.prototype.setDecimalAllowed=function(){return this.__checkDisposeState(),this.__allowDecimal=allowDecimal===!0,this},e.prototype.isDecimalAllowed=function(){return this.__checkDisposeState(),this.__allowDecimal},f=function(a,b){if(!b&&!Number.isInteger(a))throw new Error("decimals are not allowed for this Spinner")},e.prototype.setInterval=function(a){if(this.__checkDisposeState(),d.util.validateNumber("interval",a),f(a,this.__allowDecimal),0===a)throw new Error("interval cannot be 0");return this.__interval=a,this},e.prototype.getInterval=function(){return this.__checkDisposeState(),this.__interval},e.prototype.setMinimum=function(a){if(this.__checkDisposeState(),d.util.validateNumber("min",a),f(a,this.__allowDecimal),a>this.__max)throw new Error("Given minimum ("+a+") cannot more than the current maximum ("+this.__max+")");return this.__min=a,this.setValue(this.__num),this},e.prototype.getMinimum=function(){return this.__checkDisposeState(),this.__min},e.prototype.setMaximum=function(a){if(this.__checkDisposeState(),d.util.validateNumber("max",a),f(a,this.__allowDecimal),athis.__max?this.__max:a,b&&this.update(),this},e.prototype.getValue=function(){return this.__checkDisposeState(),this.__num},e.prototype.increment=function(a){return null==a&&(a=1),this.__checkDisposeState(),d.util.validateInt("steps",a),this.setValue(this.__num+a*this.__interval,!0)},e.prototype.decrement=function(a){return null==a&&(a=1),this.__checkDisposeState(),d.util.validateInt("steps",a),this.setValue(this.__num-a*this.__interval,!0)},e.prototype.update=function(){var a,b,e,f;return this.__checkDisposeState(),this.__appended||(this.$__element=c("
").appendTo(this.$__parent),this.$__number=c("").appendTo(this.$__element),this.$__buttonContainer=c("
").appendTo(this.$__element),this.$__upButton=c("
").appendTo(this.$__buttonContainer),this.$__downButton=c("
").appendTo(this.$__buttonContainer),this.__afterAppend(),this.$__element.mouseenter(function(a){return function(){return a.notifyListeners(d.event.Hover)}}(this)),e=0,f=100,a=function(a){return function(b,c,g){var h,i;return h={value:b+c,arrow:g,canceled:!1},(i=function(){return h.canceled=!1,a.notifyListeners(d.event.Modify,h),h.canceled===!0?!1:("number"==typeof h.value&&a.setValue(h.value),a.notifyListeners(d.event.AfterModify,{arrow:h.arrow}),!0)})()?e=window.setInterval(function(){return h.value+=c,i()},f):void 0}}(this),b=function(b){return function(c){var d;return d=c?b.$__upButton:b.$__downButton,d.mousedown(function(){return b.isEnabled()?a(b.__num,c?b.__interval:-b.__interval,c?0:1):void 0}).mouseup(function(){return b.isEnabled()?window.clearInterval(e):void 0})}}(this),b(!0),b(!1),this.$__number.on("input",function(a){return function(b){var c,e,f,g;if(f=a.$__number.val(),e=null,g="."===f||"-"===f||""===f)e=0;else if(e=Number(f),Number.isNaN(e)||ea.__max)return void a.$__number.val(a.__num);return c={value:e,arrow:!1,canceled:!1},a.notifyListeners(d.event.Modify,c),c.canceled===!0?void a.$__number.val(a.__num):(a.__num="number"==typeof c.value?c.value:e,a.__updateClassAndAttr(!g),a.notifyListeners(d.event.AfterModify,{arrow:c.arrow}))}}(this))),this.__updateClassAndAttr(!0),this},e.prototype.__updateClassAndAttr=function(a){return this.__updateEnabledClass(),a&&this.$__number.val(this.__num),this.__updateEnabledAttr(this.$__number)},e}(D),y=function(a){function e(a,b){null==this.__classname&&(this.__classname="Switch"),null==this.__inputType&&(this.__inputType="checkbox"),null==this.__labelOnLeft&&(this.__labelOnLeft=!1),this.setState(!1,!1),e.__super__.constructor.call(this,a,b)}var f,g;return b(e,a),g="",f=function(a,b){return""+(a?g:"")+b+(a?"":g)},e.prototype.setState=function(a,b){return null==b&&(b=!0),this.__checkDisposeState(),this.__state=a===!0,b&&this.update(),this},e.prototype.getState=function(){return this.__checkDisposeState(),H(this.__state)},e.prototype.update=function(){return this.__checkDisposeState(),this.__appended||(this.$__element=c("
").appendTo(this.$__parent),this.$__input=c("").appendTo(this.$__element),this.$__label=c("").appendTo(this.$__element),this.__afterAppend(),this.$__input.change(function(a){return function(){var b;b={state:a.$__input.prop("checked"),canceled:!1},a.notifyListeners(d.event.Selection,b),b.canceled===!0?a.$__input.prop("checked",a.__state):(a.__state=a.$__input.prop("checked"),a.notifyListeners(d.event.AfterSelection))}}(this)),this.$__element.mouseenter(function(a){return function(){return a.notifyListeners(d.event.Hover)}}(this))),this.__updateEnabledClass(),this.$__label.html(""+f(this.__labelOnLeft,this.getText())),this.__updateEnabledAttr(this.$__input),this.$__input.prop("checked",this.__state),this},e}(D),d.Check=i=function(a){function c(a,b,d){null==d&&(d=""),null==this.__classname&&(this.__classname="Check"),this.__labelOnLeft=!0,c.__super__.constructor.call(this,a,b),this.setText(d)}return b(c,a),c.prototype.setText=function(a,b){return null==b&&(b=!0),this.__checkDisposeState(),d.util.validateString("text",a),this.__text=a,b&&this.update(),this},c.prototype.getText=function(){return this.__checkDisposeState(),J(this.__text)},c}(y),d.Radio=v=function(a){function c(a,b,d){null==d&&(d=""),this.__classname="Radio",this.__inputType="radio",c.__super__.constructor.call(this,a,b,d)}return b(c,a),c.prototype.setGroup=function(a,b){return null==b&&(b=!0),this.__checkDisposeState(),d.util.validateString("group",a),this.__group=a,b&&this.update(),this},c.prototype.getGroup=function(){return this.__checkDisposeState(),J(this.__group)},c}(i),f=function(a){function e(a,b,c,d,f){this.__itemClassName=c,this.$__itemContainerElement=d,this.__unique=null!=f?f:!1,this.__items=[],e.__super__.constructor.call(this,a,b)}return b(e,a),e.prototype.addItem=function(a,b){return null==b&&(b=!0),this.__checkDisposeState(),"string"!=typeof a||this.__unique&&this.hasItem(a)||(this.__items.push(a),!b)?void 0:this.update()},e.prototype.setItems=function(a,b){var c,e,f;for(null==b&&(b=!0),this.__checkDisposeState(),d.util.validateArray("items",a),this.__items.splice(0),e=0,f=a.length;f>e;e++)c=a[e],this.addItem(c,!1);return this.__itemsChanged=!0,b&&this.update(),this},e.prototype.getItems=function(){return this.__checkDisposeState(),this.__items.slice(0)},e.prototype.removeItem=function(a,b){var e;return null==b&&(b=!0),this.__checkDisposeState(),d.util.validateString("item",a),e=c.inArray(a,this.__items),e>-1&&(this.__types.slice(e(1)),this.__itemsChanged=!0,b)?this.update():void 0},e.prototype.hasItem=function(a){return this.__checkDisposeState(),this.indexOf(a)>-1},e.prototype.indexOf=function(a){return this.__checkDisposeState(),"string"!=typeof a?-1:c.inArray(a,this.__items)},e.prototype.__append=function(){},e.prototype.update=function(){var a,b,c,d;if(this.__checkDisposeState(),this.__appended||(this.$__parent.append(this.$__element),this.__append(),this.__afterAppend()),this.__itemsChanged)for(this.$__itemContainerElement.find("."+this.__itemClassName).remove(),d=this.__items,b=0,c=d.length;c>b;b++)a=d[b],this.$__itemContainerElement.append(this.__renderItem(a));return this.__updateEnabledClass()},e}(D),d.List=r=function(a){function e(a,b,d){null==d&&(d=[]),this.__lastSelected=-1,this.__hScroll=!0,this.$__element=c("
"),e.__super__.constructor.call(this,a,b,"ListItem",this.$__element),this.setItems(d)}return b(e,a),e.prototype.setMultiSelect=function(a){return this.__checkDisposeState(),this.__multi=a===!0,this.__multi||setItemSelected(this.__lastSelected),this},e.prototype.isMultiSelect=function(){return this.__checkDisposeState(),this.__multi},e.prototype.setItems=function(a,b){return null==b&&(b=!0),this.__checkDisposeState(),this.__selected=[],e.__super__.setItems.call(this,a,b)},e.prototype.getSelectedItems=function(){var a,b,c,d;for(this.__checkDisposeState(),d=this.__selected,b=0,c=d.length;c>b;b++)if(a=d[b],this.__items.length>a&&a>0)return},e.prototype.getLastSelectedItem=function(){return this.__checkDisposeState(), +this.__lastSelected},e.prototype.setItemSelected=function(a,b){var d,e;if(null==b&&(b=!0),this.__checkDisposeState(),d=-1,"string"==typeof a)d=c.inArray(a,this.__items);else{if("number"!=typeof a)throw new Error("item must be a string or number");d=a}return 0>d?void 0:(e=this.isSelected(d),b&&!this.__multi&&this.deselectAll(),b&&!e&&this.__selected.push(a),b||this.__selected.splice(c.inArray(d,this.__selected),1),this.__selectionChanged=!0,this.update(),this)},e.prototype.toggleItemSelected=function(a){return this.__checkDisposeState(),this.setItemSelected(a,!this.isSelected(a))},e.prototype.isSelected=function(a){var b;return this.__checkDisposeState(),"number"==typeof a?c.inArray(a,this.__selected)>-1:"string"==typeof a?(b=c.inArray(a,this.items),b>-1&&c.inArray(b,this.__selected)>-1):!1},e.prototype.setSelectedItems=function(a,b){var c,e,f;if(null==b&&(b=!0),this.__checkDisposeState(),!this.__multi)throw new Error("list is not multi select");for(this.__selectionChanged=!0,this.__selected=[],d.util.validateArray("items",a),e=0,f=a.length;f>e;e++)c=a[e],this.setItemSelected(c);return b&&this.update(),this},e.prototype.getSelectedIndices=function(){return this.__checkDisposeState(),this.__selected.slice(0)},e.prototype.selectAll=function(){var a,b,c,d,e;for(this.__checkDisposeState(),d=this.__items,e=[],b=0,c=d.length;c>b;b++)a=d[b],e.push(this.setItemSelected(a,selected));return e},e.prototype.deselectAll=function(){return this.__checkDisposeState(),this.__selected.splice(0),this.__selectionChanged=!0},e.prototype.__renderItem=function(a){return"
"+a+"
"},e.prototype.__append=function(){return this.$__element.mouseenter(function(a){return function(){return a.notifyListeners(d.event.Hover)}}(this))},e.prototype.update=function(){return this.__checkDisposeState(),e.__super__.update.apply(this,arguments),this.__itemsChanged&&(this.$__element.find(".ListItem").click(function(a){return function(b){var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,u,v;if(f=c(b.target).index(),h=function(b){var c;return c={index:b[0],indices:b,canceled:!1},a.notifyListeners(d.event.Selection,c),c},"aqua"===t&&b.metaKey||"aqua"!==t&&b.ctrlKey){if(g=h([f]),g.canceled===!0)return;if(d.util.isArray(g.indices))for(r=g.indices,l=0,m=r.length;m>l;l++)i=r[l],a.toggleItemSelected(i);afterEvent(g)}else if(b.shiftKey){for(e=!0,j=function(){v=[];for(var b=s=a.__lastSelected;f>=s?f>=b:b>=f;f>=s?b++:b--)v.push(b);return v}.apply(this),p=0,n=j.length;n>p&&(k=j[p],e=e&&a.isSelected(k),e);p++);if(g=h(j),g.canceled===!0)return;if(d.util.isArray(g.indices))for(u=g.indices,q=0,o=u.length;o>q;q++)k=u[q],a.setItemSelected(k,!e);afterEvent(g)}else{if(g=h([f]),g.canceled===!0)return;a.deselectAll(),a.toggleItemSelected(f),afterEvent(g)}return a.__lastSelected=f}}(this)),this.__itemsChanged=!1),this.__selectionChanged?(this.$__element.find(".ListItem").each(function(a){return function(b,d){var e;return e=c(d),a.isSelected(b)?e.addClass("selected"):e.removeClass("selected")}}(this)),this.__selectionChanged=!1):void 0},e}(f),d.Combo=k=function(a){function e(a,b,d){null==d&&(d=!1),this.__editable=d===!0,this.__hideSelectedItem=this.__editable,this.__lastSelectedItem=-1,this.__editable?(this.$__element=c("
"),this.$__textfield=c("").appendTo(this.$__element),this.$__button=c("
").appendTo(this.$__element)):this.$__element=c(""),this.__listOverlayed=!this.__editable&&"win"!==M.getLookAndFeel(),e.__super__.constructor.call(this,a,b,"ComboItem",c(""),!0),this.__listOverlayed&&this.$__itemContainerElement.addClass("overlayed")}return b(e,a),e.prototype.__renderItem=function(a){return"
  • "+a+"
  • "},e.prototype.setText=function(a,b){return null==b&&(b=!0),this.__checkDisposeState(),d.util.validateString("text",a),this.__text=a,b&&this.update(),this},e.prototype.getText=function(){return this.__checkDisposeState(),this.__text},e.prototype.setHideSelected=function(a){return null==a&&(a=!0),this.__checkDisposeState(),this.__editable?this.__hideSelectedItem=a===!0:void 0},e.prototype.getHideSelected=function(){return this.__checkDisposeState(),this.__hideSelectedItem},e.prototype.setEnabled=function(a){return null==a&&(a=!0),e.__super__.setEnabled.apply(this,arguments),this.__editable&&this.__updateEnabledAttr(this.$__textfield),this},e.prototype.__hide=function(){return this.$__element.removeClass("listShown"),this.$__itemContainerElement.addClass("hidden"),this.__listVisible=!1},e.prototype.__show=function(){return this.$__element.addClass("listShown"),this.$__itemContainerElement.removeClass("hidden"),this.__listVisible=!0},e.prototype.__append=function(){var a,b;return c("body").append(this.$__itemContainerElement),this.__listVisible=!1,a=!1,(this.__editable?this.$__button:this.$__element).click(function(a){return function(b){var f,g,h,i,j,k,l,m,n,o,p,q,r;if(a.isEnabled()&&0!==a.__items.length){if("object"==typeof e.__CURRENT__&&e.__CURRENT__ instanceof e&&e.__CURRENT__.__hide(),b.stopPropagation(),e.__CURRENT__=a,a.__listVisible)return void a.__hide();if(q=0,a.$__itemContainerElement.children().each(function(b,d){var e;return e=c(d),e.text()===a.__text&&a.__hideSelectedItem?e.addClass("selected"):e.removeClass("selected")}),k=c(document).outerHeight(),l=c(document).outerWidth(),!a.__editable||(n={canceled:!1},a.notifyListeners(d.event.Show,n),n.canceled!==!0))return a.__show(),o=a.$__itemContainerElement.outerWidth()-a.$__itemContainerElement.innerWidth(),a.$__itemContainerElement.css({width:a.$__element.outerWidth()-o}),m=a.$__element.offset(),a.__listOverlayed?(i=0,j=null,r=0,a.$__itemContainerElement.children().each(function(b,d){var e;return e=c(d),i===a.__lastSelectedItem||-1===a.__lastSelectedItem&&e.text()===a.__text?(j=e,!1):(e.hasClass("selected")||(r+=e.outerHeight()),i++)}),f=a.$__itemContainerElement.css("border-top-width"),q=m.top-r-parseInt(f.substring(0,f.length-2),10)):q=m.top+a.$__element.outerHeight(),h={left:m.left,top:0>q?a.$__element.css("border-top-width"):q,height:"","max-height":"50%"},a.$__itemContainerElement.css(h),q=a.$__itemContainerElement.offset().top,p=a.$__itemContainerElement.outerHeight(),q+p>k?(g=a.$__itemContainerElement.css("border-bottom-width"),a.$__itemContainerElement.css({height:p-(q+p-k)-5}),a.$__itemContainerElement.css({left:a.$__element.offset().left})):void 0}}}(this)),this.$__itemContainerElement.delegate("li","click",function(a){return function(b){var e,f,g,h;return e=c(b.target),h=e.text(),f=e.index(),g={selection:h,index:f,canceled:!1},a.notifyListeners(d.event.Selection,g),g.canceled!==!0?(a.notifyListeners(d.event.AfterSelection,{index:g.index}),a.setText(g.selection),a.__lastSelectedItem=f,a.__hide()):void 0}}(this)),this.__editable&&this.$__textfield.on("input",function(a){return function(){var b;return b={value:a.$__textfield.val(),canceled:!1},a.notifyListeners(d.event.Modify,b),b.canceled===!0?a.$__textfield.val(a.__text):a.__text=b.value}}(this)),this.__editable?(b=function(a){return function(b){var c;return c={part:b},a.notifyListeners(d.event.Hover,c)}}(this),this.$__textfield.mouseenter(function(a){return function(){return b("textbox")}}(this)),this.$__button.mouseenter(function(a){return function(){return b("button")}}(this))):this.$__element.mouseenter(function(a){return function(){return a.notifyListeners(d.event.Hover)}}(this)),c("body").click(function(b){return function(){return a||b.__hide(),null}}(this))},e.prototype.update=function(){return e.__super__.update.apply(this,arguments),this.__hide(),this.__editable?this.$__textfield.val(this.__text):this.$__element.find(".title").text(this.__text)},e.prototype.dispose=function(){return!this.__disposed&&this.$__element?(this.$__itemContainerElement.remove(),e.__super__.dispose.apply(this,arguments)):void 0},e}(f),d.Table=A=function(a){function e(a,b){this.__headers=[],this.__rows=[],e.__super__.constructor.call(this,a,b)}var f,g,h,i,j,k,l,n;return b(e,a),d.util.defineConstant(e,"Header",f=function(a){function e(a,b){null==b&&(b=""),e.__super__.constructor.call(this,c("
    "),b),this.setValue(a)}return b(e,a),e.prototype.setValue=function(a){return d.util.validateString("value",a),this.__value=a,this.$__element.text(this.__value),this},e.prototype.getValue=function(){return this.__value},e}(m)),d.util.defineConstant(e,"Row",g=function(a){function e(a,b){var h,i,j,k;for(null==b&&(b=""),d.util.validateArray("values",a),this.__values=[],h=0,i=a.length;i>h;h++)j=a[h],(k=g(j))instanceof f&&this.__values.push(k);e.__super__.constructor.call(this,c(""),b)}var f,g;return b(e,a),d.util.defineConstant(e,"Value",f=function(a){function d(a,b){null==b&&(b=""),d.__super__.constructor.call(this,c(""),b),this.setValue(a)}return b(d,a),d.prototype.setValue=function(a){if("string"!=typeof a&&"number"!=typeof a)throw new Error("value must be a string or a number");return this.__value=a,this.$__element.text(this.__value),this},d.prototype.getValue=function(){return this.__value},d}(m)),g=function(a){return a instanceof f?a:"string"==typeof a||"number"==typeof a?new f(a):null},e.prototype.setValue=function(a,b){if(d.util.validateInt("index",a),!b instanceof f){if("string"!=typeof b&&"number"!=typeof b)throw new Error("value must be an instance of Table.Row.Value, a string, or a number");b=new f(b)}return this.__values[a]=b,this},e.prototype.getValue=function(a){return null===a?this.getValues():(d.util.validateInt("index",a),this.__values[a])},e.prototype.getValues=function(){var a,b,c,d,e;for(a=[],d=this.__values,b=0,c=d.length;c>b;b++)e=d[b],e instanceof f&&a.push(e);return a},e.prototype.__getValues=function(){var a,b,d,e,g;for(a=[],e=this.__values,b=0,d=e.length;d>b;b++)g=e[b],a.push(g instanceof f?g:c(""));return a},e}(m)),e.prototype.getHeaders=function(){var a,b,c,d,e;for(this.__checkDisposeState(),a=[],e=this.__headers,c=0,d=e.length;d>c;c++)b=e[c],a.push(b);return a},e.prototype.update=function(){var a,b,d,e,f,h,i,j,k,l,m,n,o,p,q;for(this.__checkDisposeState(),this.__appended||(this.$__element=c("
    ").appendTo(this.$__parent),this.__afterAppend()),b=this.$__parent.find("thead"),a=this.$__parent.find("tbody"),a.empty(),b.empty(),n=this.__headers,f=0,h=n.length;h>f;f++)e=n[f],b.append(e.$__element);for(o=this.__rows,k=0,i=o.length;i>k;k++){for(m=o[k],d=m.$__element,d.empty(),p=m.__getValues(),l=0,j=p.length;j>l;l++)q=p[l],d.append(q instanceof g.Value?q.$__element:q);d.appendTo(a)}return this.__updateEnabledClass()},j=function(a,b){var c;if(null==b&&(b=""),c=a,"string"==typeof a&&(c=new f(a,"string"==typeof b?b:"")),!a instanceof f)throw new Error("header must be a string or an instance of Table.Header");return c},k=function(a,b){var c;if(null==b&&(b=""),c=a,d.util.isArray(a)&&(c=new g(a,"string"==typeof b?b:"")),!a instanceof g)throw new Error("row must be an array or an instance of Table.Row");return c},n=function(a,b,c,d,e,f){var g;return L(b,a),g=c(d,e),b[a]=g,f.update()},h=function(a,b,c,d){var e;return e=b(a),c.push(e),d.update(),e},i=function(a,b,c){return L(b,a),b[a],c.update()},l=function(a,b,d){var e;return e=Number.isInteger(a)?a:a instanceof d?c.inArray(a,b):-1,-1>e&&e").appendTo(this.$__parent),this.__afterAppend()),this.$__tab.text(this.__title),this.$__tab.mouseenter(function(a){return function(){return a.notifyListeners(d.event.Hover)}}(this))},e.prototype.isDisposed=function(){return!1},e.prototype.dispose=function(){},e.prototype.__getTooltipElement=function(){return this.$__tab},e.prototype.getTabFolder=function(){return this.__folder},e.prototype.setText=function(a,b){return null==b&&(b=!0),"string"==typeof a&&(this.__title=a),b&&this.update(),this},e.prototype.getText=function(){return this.__title},e}(l),e.prototype.remove=function(a){return this.__checkDisposeState(),L(this.__tabs,a),this.__tabs.splice(a,1),this},e.prototype.append=function(a,b){var e,g;return this.__checkDisposeState(),e=c("
    "),g=new f(this,b,e.appendTo(this.$__tabContainer)),g.setText(a),e.click(function(a){return function(){var b;if(g.isEnabled())return b={selection:e.index(),tab:g,canceled:!1},a.notifyListeners(d.event.Selection,b),b.canceled!==!0?a.setSelectedIndex(e.index()):void 0}}(this)),this.__tabs.push(g),this.setSelectedIndex(this.__tabs.length-1),g},e.prototype.clear=function(){var a;for(this.__checkDisposeState(),a=[];this.__tabs.length>0;)a.push(this.remove(0));return a},e.prototype.getSelectedIndex=function(){return this.__checkDisposeState(),this.__selectedTab},e.prototype.getSelectedTab=function(){return this.__checkDisposeState(),this.__tabs[this.__selectedTab]},e.prototype.setSelectedIndex=function(a){var b;return this.__checkDisposeState(),L(this.__tabs,a),b=this.__tabs[this.__selectedTab],b.$__tab.removeClass("selected"),b.$__element.css({display:"none"}),this.__selectedTab=a,b=this.__tabs[a],b.$__tab.addClass("selected"),b.$__element.css({display:""})},e.prototype.__getTooltipElement=function(){return null},e.prototype.getTabs=function(){return this.__checkDisposeState(),this.__tabs.slice(0)},e.prototype.update=function(){return this.__checkDisposeState(),this.__appended?void 0:(this.$__element=c("
    ").appendTo(this.$__parent),this.$__tabContainer=this.$__element.find(".TabContainer"),this.$__content=this.$__element.find(".TabContentContainer"),this.__afterAppend())},e}(D),d.ProgressBar=u=function(a){function e(a,b){this.__progress=0,e.__super__.constructor.call(this,a,b)}return b(e,a),e.prototype.update=function(){return this.__checkDisposeState(),this.__appended||(this.$__element=c("
    ").appendTo(this.$__parent),this.$__inner=c("
    ").appendTo(this.$__element),this.$__element.mouseenter(function(a){return function(){return a.notifyListeners(d.event.Hover)}}(this)),this.__afterAppend()),this.$__inner.css("width",this.__progress+"%"),this.__classIf("full",100===this.__progress),this.__classIf("indeterminate",this.__indeterminate)},e.prototype.setProgress=function(a,b){return null==b&&(b=100),this.__checkDisposeState(),d.util.validateNumber("progress",a),d.util.validateNumber("denominator",b),this.__progress=a/b*100,this.update(),this},e.prototype.getProgress=function(){return this.__checkDisposeState(),this.__progress},e.prototype.setIndeterminate=function(a){return null==a&&(a=!0),this.__indeterminate=a===!0,this.update(),this},e.prototype.isIndeterminate=function(){return this.__indeterminate},e}(D),d.FileChooser=o=function(a){function e(a,b,c){null==c&&(c=""),this.__files=[],this.__types=[],this.setText(c,!1),e.__super__.constructor.call(this,a,b)}return b(e,a),e.prototype.setMulti=function(a){return null==a&&(a=!0),this.__checkDisposeState(),d.util.validateBoolean("multi",a),this.__multi=a},e.prototype.accept=function(a){var b,c,d;if(this.__checkDisposeState(),"string"==typeof a)this.__types.push(a);else if("array"==typeof typeof a)for(b=0,c=a.length;c>b;b++)d=a[b],accept(d);return this},e.prototype.getAccepted=function(){return this.__checkDisposeState(),this.__types.slice(0)},e.prototype.getAcceptedString=function(){return this.__checkDisposeState(),"array"==typeof this.__types?this.__types.join():""},e.prototype.clearAcceptedTypes=function(){return this.__checkDisposeState(),this.__types.splice(0,this.__types.length)},e.prototype.stopAccepting=function(a){var b,d,e,f;if(this.__checkDisposeState(),"string"==typeof a)b=c.inArray(a,this.__types),b>-1&&this.__types.splice(b,1);else if("array"==typeof a)for(d=0,e=a.length;e>d;d++)f=a[d],stopAccepting(f);return this},e.prototype.setText=function(a,b){return null==b&&(b=!0),this.__checkDisposeState(),d.util.validateString("text",a),this.__text=a,b&&this.update(),this},e.prototype.getText=function(){return this.__checkDisposeState(),this.__text},e.prototype.getFiles=function(){return this.__checkDisposeState(),this.__files.slice(0)},e.prototype.__getTooltipElement=function(){return this.$__label},e.prototype.update=function(){return this.__checkDisposeState(),this.__appended||(this.$__element=c("").appendTo(this.$__parent),this.$__label=c("").insertAfter(this.$__element),this.$__element.change(function(a){return function(b){return a.__files=b.files,a.notifyListeners(d.event.Selection)}}(this)),this.$__element.click(function(a){return function(b){var c;if(a.__enabled)return c={canceled:!1},a.notifyListeners(d.event.Show,c),c.canceled===!0?b.preventDefault():void 0}}(this)),this.$__element.mouseenter(function(a){return function(){return a.notifyListeners(d.event.Hover)}}(this)),this.__afterAppend()),this.__multi?this.$__element.attr("multiple",""):this.$__element.removeAttr("multiple"),this.$__element.attr("accept",this.getAcceptedString()),this.__updateEnabledClass(),this.__updateEnabledAttr()},e}(D),d.ColorPicker=j=function(a){function e(a,b,f){null==f&&(f={}),d.util.validateObject("options",f),null==f.showPalette&&(f.showPalette="object"==typeof f.palette&&f.palette.constructor===Array),null==f.showInput&&(f.showInput=!0),null==f.showAlpha&&(f.showAlpha=!0),null==f.showInital&&(f.showInital=!0),null==f.showButtons&&(f.showButtons=!1),"string"!=typeof f.containerClassName&&(f.containerClassName=""),f.containerClassName="ColorPickerContainer "+f.containerClassName,"string"!=typeof f.replacerClassName&&(f.replacerClassName=""),f.replacerClassName="ColorPickerReplacer "+f.replacerClassName,null==f.preferredFormat&&(f.preferredFormat="hex3"),this.__options=c.extend({},f),e.__super__.constructor.call(this,a,b)}return b(e,a),e.prototype.setOption=function(a,b){return d.util.validateString("option",a),this.__spectrum("option",a,b),this},e.prototype.setOptions=function(a){var b,c;d.util.validateObject("options",a);for(b in a)c=a[b],"string"!=typeof b||"object"==typeof c&&!d.util.isArray(c)||setOption(b,c);return this},e.prototype.getOption=function(a){return d.util.validateString("option",a),this.__spectrum(a)},e.prototype.hide=function(){return this.__checkDisposeState(),this.__spectrum("hide"),this},e.prototype.show=function(){return this.__checkDisposeState(),this.__spectrum("show"),this},e.prototype.toggle=function(){return this.__checkDisposeState(),this.__spectrum("toggle"),this},e.prototype.setColor=function(a){return this.__checkDisposeState(),d.util.validateString("color",a),this.__spectrum("set",a),this},e.prototype.getColor=function(){return this.__spectrum("get")},e.prototype.__hookEvent=function(a,b){return this.__options[a]=function(c){return function(){var d;switch(d={},a){case"move":case"hide":case"show":case"beforeShow":case"change":d.color=arguments[0];break;default:d.spectrumEvent=arguments[0],d.color=arguments[1]}return c.notifyListeners(b,d)}}(this)},e.prototype.setEnabled=function(a){return e.__super__.setEnabled.call(this,a),a?this.__spectrum("enable"):this.__spectrum("disable"),this},e.prototype.dispose=function(){return this.__spectrum("destroy"),e.__super__.dispose.apply(this,arguments)},e.prototype.__spectrum=function(){return this.$__element.spectrum.apply(this.$__element,arguments)},e.prototype.__getTooltipElement=function(){return null===this.__replacer?this.$__element:this.__replacer},e.prototype.update=function(){this.__checkDisposeState(),this.__appended||(this.$__element=c("").appendTo(this.$__parent),this.__hookEvent("change",d.event.SpectrumChange),this.__hookEvent("move",d.event.SpectrumMove),this.__hookEvent("hide",d.event.SpectrumHide),this.__hookEvent("show",d.event.SpectrumShow),this.__hookEvent("dragStart",d.event.DragStart),this.__hookEvent("dragEnd",d.event.DragEnd),this.__options.beforeShow=function(a){return function(b){var c;return c={color:b,canceled:!1},a.notifyListeners(d.event.Show,c),c.canceled===!0?!1:void 0}}(this),this.__spectrum(this.__options),this.__replacer=c(this.__spectrum("replacer")),this.__getTooltipElement().mouseenter(function(a){return function(){return a.notifyListeners(d.event.Hover)}}(this)),this.__afterAppend())},e}(D),d.YTVideo=E=function(a){function c(a,b,e){null==e&&(e={}),d.util.validateObject("options",e),c.__super__.constructor.call(this,a,b),e.videoId&&d.util.validateString("options.videoId",e.videoId),g(this.$__parent,b,e),this.__afterAppend()}var e,f,g,h;return b(c,a),h=function(a,b){return d.util.defineConstant(c,a,b)},h("Options",e=function(){function a(a){null==a&&(a=""),this.setVideoId(a)}return a.prototype.setAutoHide=function(a){return d.util.validateBoolean("autohide",a),this.autohide=a?c.TRUE:c.FALSE,this},a.prototype.isAutoHide=function(){return this.autohide===c.TRUE},a.prototype.setAutoPlay=function(a){return d.util.validateBoolean("autoplay",a),this.autoplay=a?c.TRUE:c.FALSE,this},a.prototype.isAutoPlay=function(){return this.autoplay},a.prototype.setSize=function(a,b){return Number.isInteger(a)&&(this.width=a),Number.isInteger(b)&&(this.height=a),this},a.prototype.setCcLoadPolicy=function(a){return d.util.validateInt("ccLoadPolicy",a),this.cc_load_policy=a,this},a.prototype.getCcLoadPolicy=function(){return this.cc_load_policy},a.prototype.setColor=function(a){if(d.util.validateString("color"),"red"!==a&&"white"!==a)throw new Error("color must be 'red' or 'white'");return this.color=a,this},a.prototype.getColor=function(){return this.color},a.prototype.setControlPolicy=function(a){return d.util.validateInt(a),this.controls=a,this},a.prototype.getControlPolicy=function(){return this.controls},a.prototype.enableKeyboardControls=function(){return this.disablekb=c.FALSE,this},a.prototype.disableKeyboardControls=function(){return this.disablekb=c.TRUE,this},a.prototype.enableJsApi=function(){return this.enablejsapi=c.TRUE,this},a.prototype.disableJsApi=function(){return this.enablejsapi=c.FALSE,this},a.prototype.setEnd=function(a){return d.util.validateNumber("end",a),this.end=a,this},a.prototype.getEnd=function(){return this.end},a.prototype.setFullscreenAllowed=function(a){return d.util.validateBoolean("fsAllowed",a),this.fs=a?c.TRUE:c.FALSE,this},a.prototype.isFullscreenAllowed=function(){return this.fs===c.TRUE},a.prototype.setInterfaceLanguage=function(a){return d.util.validateString("interfaceString",interfaceString),this.hl=a,this},a.prototype.getInterfaceLanguage=function(){return this.hl},a.prototype.setAnnotationsShownByDefault=function(){return this.iv_load_policy=c.ANNOTATIONS_SHOWN_BY_DEFAULT,this},a.prototype.setAnnotationsHiddenByDefault=function(){return this.iv_load_policy=c.ANNOTATIONS_NOT_SHOWN_BY_DEFAULT,this},a.prototype.areAnnotationShownByDefault=function(){return this.iv_load_policy===c.ANNOTATIONS_SHOWN_BY_DEFAULT},a.prototype.setListSearch=function(a){return d.util.validateString("query",a),this.listType="search",this.list=a,this},a.prototype.setListUserUploads=function(a){return d.util.validateString("user",a),this.listType="user_uploads",this.list=a,this},a.prototype.setListPlaylist=function(a){return d.util.validateString("id",a),this.listType="playlist",this.list="PL"+a,this},a.prototype.setLooping=function(a){return d.util.validateBoolean("looping",a),this.loop=a?c.TRUE:c.FALSE,this},a.prototype.isLooping=function(){return this.loop===c.TRUE},a.prototype.setModestBranding=function(a){return d.util.validateBoolean("modestBranding",a),this.modestbranding=a?c.TRUE:c.FALSE,this},a.prototype.hasModestBranding=function(){return this.modestbranding===c.TRUE},a.prototype.setOrigin=function(a){return d.util.validateString("origin",a),this.origin=a,this},a.prototype.getOrigin=function(){return this.origin},a.prototype.setPlayerApiId=function(a){return d.util.validateString("playerApiId",a),this.playerapiid=a,this},a.prototype.getPlayerApiId=function(){return this.playerapiid},a.prototype.setPlaylist=function(a){var b,c,e;for(d.util.validateArray("playlist",a),this.playlist=[],c=0,e=a.length;e>c;c++)b=a[c],"string"==typeof b&&this.playlist_.push(b);return this},a.prototype.getPlaylist=function(){return this.playlist},a.prototype.setPlaysInline=function(a){return d.util.validateBoolean("playsInline",a),this.playsinline=a?c.TRUE:c.FALSE,this},a.prototype.playsInline=function(){return this.playsinline===c.TRUE},a.prototype.setShowRelatedVideos=function(a){return d.util.validateBoolean("showRelated",a),this.rel=a?c.TRUE:c.FALSE,this},a.prototype.showsRelatedVideos=function(){return this.rel===c.TRUE},a.prototype.setShowInfo=function(a){return d.util.validateBoolean("showInfo",a),this.showinfo=a?c.TRUE:c.FALSE,this},a.prototype.getShowInfo=function(){return this.showinfo===c.TRUE},a.prototype.setStart=function(a){return d.util.validateNumber("start",a),this.start=a,this},a.prototype.getStart=function(){return this.start},a.prototype.setVideoId=function(a){return null==a&&(a=""),d.util.validateString("videoId",a),this.videoId=a},a.prototype.setDarkTheme=function(){return this.theme=c.THEME_DARK,this},a.prototype.setLightTheme=function(){return this.theme=c.THEME_LIGHT,this},a.prototype.isDarkTheme=function(){return this.theme===c.THEME_DARK},a}()),h("TRUE",1),h("FALSE",0),h("AUTOHIDE_VISIBLE",0),h("AUTOHIDE_AUTO",1),h("AUTOHIDE_AUTO_OR_VISIBLE",2),h("CC_SHOW_BY_DEFAULT",1),h("CONTROLS_HIDDEN",0),h("CONTROLS_VISIBLE_IMMEDIATELY",1),h("CONTROLS_FLASH_LOAD_AFTER_PLAYBACK",2),h("ANNOTATIONS_SHOWN_BY_DEFAULT",1),h("ANNOTATIONS_NOT_SHOWN_BY_DEFAULT",3),h("THEME_DARK","dark"),h("THEME_LIGHT","light"),f=function(a){var b,c,d;c="";for(b in a)d=a[b],"string"!=typeof d&&"number"!=typeof d||(c+=b+"="+d+"&");return c.substring(0,c.length-1)},g=function(a,b,c){return null==c&&(c={}),null==c.videoId&&(c.videoId=""),b="string"==typeof this.__id?"id='"+this.__id+"''":"",a.append("")},c}(D),c(window).resize(function(){var a,b,c,d,e;for(c=N.getByType(k),d=[],a=0,b=c.length;b>a;a++)e=c[a],d.push(e.__hide());return d}),c(window).mousemove(function(a){return s.page.x=a.pageX,s.page.y=a.pageY,s.client.x=a.clientX,s.client.y=a.clientY,s.screen.x=a.screenX,s.screen.y=a.screenY})})}).call(this); \ No newline at end of file diff --git a/src/coffee/class/AbstractItemList.coffee b/src/coffee/class/AbstractItemList.coffee new file mode 100644 index 0000000..bbcaeb9 --- /dev/null +++ b/src/coffee/class/AbstractItemList.coffee @@ -0,0 +1,57 @@ + #Parent Class for List, Combo, EditableCombo(Better name, Entry maybe?), etc + #=============================== + class AbstractItemList extends Widget + + constructor: (parent, id, @__itemClassName, @$__itemContainerElement, @__unique = false) -> + @__items = [] + super parent, id + + addItem: (item, update = true) -> + @__checkDisposeState() + + if typeof item is "string" and (not (@__unique and @hasItem item)) + @__items.push item + @update() if update + setItems: (items, update = true) -> + @__checkDisposeState() + root.util.validateArray "items", items + @__items.splice 0 + @addItem item, false for item in items + @__itemsChanged = true + @update() if update + return @ + getItems: -> + @__checkDisposeState() + @__items.slice 0 #return copy of array to prevent modification + removeItem: (item, update = true) -> + @__checkDisposeState() + root.util.validateString "item", item + index = $.inArray item, @__items + if index > -1 + @__types.slice index 1 + @__itemsChanged = true + @update() if update + + hasItem: (item) -> + @__checkDisposeState() + return @indexOf(item) > -1 + + indexOf: (item) -> + @__checkDisposeState() + return -1 if typeof item isnt "string" + return $.inArray item, @__items + + # Subclasses should override + __append: -> + + update: -> + @__checkDisposeState() + if not @__appended + @$__parent.append @$__element + @__append() + @__afterAppend() + + if @__itemsChanged + @$__itemContainerElement.find(".#{@__itemClassName}").remove() + @$__itemContainerElement.append @__renderItem item for item in @__items + @__updateEnabledClass() diff --git a/src/coffee/class/Accelerator.coffee b/src/coffee/class/Accelerator.coffee new file mode 100644 index 0000000..995d3e8 --- /dev/null +++ b/src/coffee/class/Accelerator.coffee @@ -0,0 +1,19 @@ + class Accelerator + + constructor: (accelerator) -> + root.util.validateString "accelerator", accelerator + split = accelerator.split /\+/g + for k in split + if k is "CmdOrCtrl" + if NATIVE_LAF is "cocoa" + @__meta = true + else + @__ctrl = true + else if k is "Ctrl" + @__ctrl = true + else if k is "Cmd" or k is "Meta" or k is "Win" + @__mod = true + else if k is "Shift" + @__shift = true + else if k.length is 1 + # keycode for character diff --git a/src/coffee/class/Audio.coffee b/src/coffee/class/Audio.coffee new file mode 100644 index 0000000..e69de29 diff --git a/src/coffee/class/Button.coffee b/src/coffee/class/Button.coffee new file mode 100644 index 0000000..dfbec61 --- /dev/null +++ b/src/coffee/class/Button.coffee @@ -0,0 +1,56 @@ + # BUTTON CLASS DEFINITION + # Buttons are boxes that can be clicked to trigger an action + # Events: + # - Hover + # - Selection + #========================================================== + root.Button = class Button extends Widget + + constructor: (parent, id, title = "") -> + super parent, id, false + @setText title + + setText: (title, update = true) -> + @__checkDisposeState() + root.util.validateString "title", title + @__title = title + @__textInvisible = false if not @__forceInvisibleText + @update() if update + return @ + getText: -> + @__checkDisposeState() + getString @__title + + setTextInvisible: (invisible = true) -> + @__checkDisposeState() + @__textInvisible = invisible is true + @update() + return @ + isTextInvisible: -> @__textInvisible + forceInvisibleText: (force) -> + @__forceInvisibleText = force is true + return @ + isInvisibleTextForced: -> @__forceInvisibleText + + getGroup: -> + return if @hasGroup then @__group else null + hasGroup: -> + @__checkDisposeState() + return typeof @__group is "object" and @__group instanceof ButtonGroup + + update: -> + @__checkDisposeState() + if not @__appended + @$__element = $("").appendTo @$__parent + @$__title = $("").appendTo @$__element + @__afterAppend() + + @$__element.mouseenter => @notifyListeners root.event.Hover + @$__element.click => + return if not @__enabled + @notifyListeners root.event.Selection + @notifyListeners root.event.AfterSelection + + @__updateEnabledClass() + @$__title.html @__title + @__classIf "invisible", @__textInvisible, @$__title diff --git a/src/coffee/class/ButtonGroup.coffee b/src/coffee/class/ButtonGroup.coffee new file mode 100644 index 0000000..62b878d --- /dev/null +++ b/src/coffee/class/ButtonGroup.coffee @@ -0,0 +1,45 @@ + # BUTTONGROUP CLASS DEFINITION + #============================= + root.ButtonGroup = class ButtonGroup extends Widget + + constructor: (parent, id, toggle = false) -> + @__buttons = [] + @__toggle = if typeof toggle is "boolean" then toggle else false + super parent, id + + update: -> + @__checkDisposeState() + if not @__appended + @$__element = $("
    ").appendTo @$__parent + @__afterAppend() + + addButton: (id, title = "") -> + @__checkDisposeState() + button = new (if @__toggle then ToggleButton else Button) @$__element, id, title + button.__group = @ + @__buttons.push button + button.setEnabled @__enabled + getButton: (index) -> + @__checkDisposeState() + indexCheck @__buttons, index + return @__buttons[index] + removeButton: (index) -> + @__checkDisposeState() + indexCheck @__buttons, index + @__buttons.splice index, 1 + return @ + getButtons: -> + @__checkDisposeState() + @__buttons.slice 0 + + isToggle: -> + @__checkDisposeState() + @__toggle + + __getTooltipElement: -> null + + setEnabled: (enabled) -> + @__checkDisposeState() + super enabled, false + b.setEnabled enabled for b in @__buttons + return @ diff --git a/src/coffee/class/Check.coffee b/src/coffee/class/Check.coffee new file mode 100644 index 0000000..ec7b056 --- /dev/null +++ b/src/coffee/class/Check.coffee @@ -0,0 +1,24 @@ + # CHECK CLASS DEFINITION + # This is primarly a wrapper for input[type="checkbox"]. Although it extends Switch, this widget should + # look like an actual checkbox (via CSS) + # Events: + # - Hover + # - Selection + #====================================================================================================== + root.Check = class Check extends Switch + + constructor: (parent, id, text = "") -> + @__classname ?= "Check" + @__labelOnLeft = true + super parent, id + @setText text + + setText: (text, update = true) -> + @__checkDisposeState() + root.util.validateString "text", text + @__text = text + @update() if update + return @ + getText: -> + @__checkDisposeState() + getString @__text diff --git a/src/coffee/class/ColorPicker.coffee b/src/coffee/class/ColorPicker.coffee new file mode 100644 index 0000000..de968be --- /dev/null +++ b/src/coffee/class/ColorPicker.coffee @@ -0,0 +1,117 @@ + # COLORPICKER CLASS DEFINITION + # (Wrapper for Spectrum by Brian Grinstead) + # https://github.com/bgrins/spectrum + # Events: + # - Show - (beforeShow.spectrum) + # - SpectrumChange (change.spectrum) + # - SpectrumMove (move.spectrum) + # - SpectrumShow (show.spectrum) + # - SpectrumHide (hide.spectrum) + # - SpectrumDragStart (dragStart.spectrum) + # - SpectrumDragEnd (dragEnd.spectrum) + # ================================================= + root.ColorPicker = class ColorPicker extends Widget + + constructor: (parent, id, options = {}) -> + root.util.validateObject "options", options + + #default Spectrum options + #(set if not defined) + options.showPalette ?= typeof options.palette is "object" and options.palette.constructor is Array + options.showInput ?= true + options.showAlpha ?= true + options.showInital ?= true + options.showButtons ?= false + options.containerClassName = "" if typeof options.containerClassName isnt "string" + options.containerClassName = "ColorPickerContainer " + options.containerClassName + options.replacerClassName = "" if typeof options.replacerClassName isnt "string" + options.replacerClassName = "ColorPickerReplacer " + options.replacerClassName + options.preferredFormat ?= "hex3" + + @__options = $.extend {}, options + super parent, id + + setOption: (option, value) -> + root.util.validateString "option", option + @__spectrum "option", option, value + return @ + setOptions: (options) -> + root.util.validateObject "options", options + for k, v of options + setOption k, v if typeof k is "string" and (typeof v isnt "object" or root.util.isArray v) + return @ + getOption: (option) -> + root.util.validateString "option", option + return @__spectrum option + + hide: -> + @__checkDisposeState() + @__spectrum "hide" + return @ + show: -> + @__checkDisposeState() + @__spectrum "show" + return @ + toggle: -> + @__checkDisposeState() + @__spectrum "toggle" + return @ + + setColor: (color) -> + @__checkDisposeState() + root.util.validateString "color", color + @__spectrum "set", color + return @ + getColor: -> @__spectrum "get" + + __hookEvent: (event, eventName) -> + @__options[event] = => + eventData = {} + switch event + when "move", "hide", "show", "beforeShow", "change" + eventData.color = arguments[0] + else #dragStart dragEnd + eventData.spectrumEvent = arguments[0] + eventData.color = arguments[1] + @notifyListeners eventName, eventData + + setEnabled: (enabled) -> + super enabled + if enabled + @__spectrum "enable" + else + @__spectrum "disable" + return @ + + dispose: -> + @__spectrum "destroy" + super + + __spectrum: -> + @$__element.spectrum.apply @$__element, arguments + + __getTooltipElement: -> if @__replacer is null then @$__element else @__replacer + + update: -> + @__checkDisposeState() + if not @__appended + @$__element = $("").appendTo @$__parent + @__hookEvent "change", root.event.SpectrumChange + @__hookEvent "move", root.event.SpectrumMove + @__hookEvent "hide", root.event.SpectrumHide + @__hookEvent "show", root.event.SpectrumShow + @__hookEvent "dragStart", root.event.DragStart + @__hookEvent "dragEnd", root.event.DragEnd + @__options.beforeShow = (color) => + event = + color: color + canceled: false + @notifyListeners root.event.Show, event + return false if event.canceled is true + @__spectrum @__options + # Note: The method 'replacer' does not exist within Spectrum. + # It has been added to the provided version of spectrum + @__replacer = $ @__spectrum "replacer" + @__getTooltipElement().mouseenter => @notifyListeners root.event.Hover + @__afterAppend() + return diff --git a/src/coffee/class/Combo.coffee b/src/coffee/class/Combo.coffee new file mode 100644 index 0000000..4b1a77c --- /dev/null +++ b/src/coffee/class/Combo.coffee @@ -0,0 +1,209 @@ + # COMBO CLASS DEFINITON + # Inspiration: SWT + #====================== + root.Combo = class Combo extends AbstractItemList + + constructor: (parent, id, editable = false) -> + @__editable = editable is true + @__hideSelectedItem = @__editable + @__lastSelectedItem = -1 + # Look and Feel decides whether to use both arrow-down and arrow-up or just arrow-down + # (or even only arrow-up, but the list is always positioned below, so that doesn't make sense) + #TODO: if not editable then this is a Text, add arrow down + if @__editable + @$__element = $("
    ") + @$__textfield = $("").appendTo @$__element + @$__button = $("
    +
    + +
    +
    ").appendTo @$__element + else + @$__element = $("") + @__listOverlayed = not @__editable and options.getLookAndFeel() isnt "win" + + super parent, id, "ComboItem", $(""), true + @$__itemContainerElement.addClass "overlayed" if @__listOverlayed + + __renderItem: (item) -> + return "
  • #{item}
  • " + + setText: (text, update = true) -> + @__checkDisposeState() + root.util.validateString "text", text + @__text = text + @update() if update + return @ + getText: -> + @__checkDisposeState() + @__text + + setHideSelected: (hideSelected = true) -> + @__checkDisposeState() + @__hideSelectedItem = hideSelected is true if @__editable + getHideSelected: -> + @__checkDisposeState() + @__hideSelectedItem + + setEnabled: (enabled = true) -> + super + if @__editable + @__updateEnabledAttr @$__textfield + + return @ + + __hide: -> + @$__element.removeClass "listShown" + @$__itemContainerElement.addClass "hidden" + @__listVisible = false + + __show: -> + @$__element.addClass "listShown" + @$__itemContainerElement.removeClass "hidden" + @__listVisible = true + + __append: -> + $("body").append @$__itemContainerElement + @__listVisible = false + justShown = false + + # Determine position of list. + # On GTK, Cocoa, and Default LAFs, the list will always be overlayed over the Combo. The exact position depends on the selected item (getText()) + # (The list will be pushed down if the top of the list exceeds the document) + # On Win LAF, the list will always be below the combo + # For editable Combos (textfield visibile), the list will always be below the combo + (if not @__editable then @$__element else @$__button).click (e) => + return if not @isEnabled() or @__items.length is 0 + Combo.__CURRENT__.__hide() if typeof Combo.__CURRENT__ is "object" and Combo.__CURRENT__ instanceof Combo + e.stopPropagation() + Combo.__CURRENT__ = @ + if @__listVisible + @__hide() + return + listTop = 0 + + @$__itemContainerElement.children().each (i, e) => + $e = $(e) + if $e.text() is @__text and @__hideSelectedItem + $e.addClass "selected" + else + $e.removeClass "selected" + + docHeight = $(document).outerHeight() + docWidth = $(document).outerWidth() + + if @__editable + event = + canceled: false + @notifyListeners root.event.Show, event + return if event.canceled is true + + @__show() + itemListBorderWidth = @$__itemContainerElement.outerWidth() - @$__itemContainerElement.innerWidth() + @$__itemContainerElement.css width: @$__element.outerWidth() - (itemListBorderWidth) + elemPos = @$__element.offset() + if @__listOverlayed + currIndex = 0 + currItem = null + offset = 0 + @$__itemContainerElement.children().each (i, e) => + $item = $(e) + if currIndex is @__lastSelectedItem or (@__lastSelectedItem is -1 and $item.text() is @__text) + currItem = $item + return false + else + offset += $item.outerHeight() if not $item.hasClass "selected" + currIndex++ + borderTop = @$__itemContainerElement.css("border-top-width") + listTop = (elemPos.top - offset) - parseInt borderTop.substring(0, borderTop.length - 2), 10 #assumes the border width is in pixels + else + listTop = elemPos.top + @$__element.outerHeight() + + css = + left: elemPos.left + top: if listTop < 0 then @$__element.css "border-top-width" else listTop + height: "" + "max-height": "50%" + + @$__itemContainerElement.css css + + listTop = @$__itemContainerElement.offset().top + listHeight = @$__itemContainerElement.outerHeight() + + if listTop + listHeight > docHeight + bottomBorderWith = @$__itemContainerElement.css "border-bottom-width" + @$__itemContainerElement.css + height: (listHeight - ((listTop + listHeight) - docHeight)) - 5 + @$__itemContainerElement.css # Done in another invocation to ensure that @$__element's offset is correct after the item list's height correction + left: @$__element.offset().left + + # When an an item (current or future) is clicked, set the text and hide the list + @$__itemContainerElement.delegate "li", "click", (e) => + $e = $(e.target) + text = $e.text() + index = $e.index() + selectionEvent = + selection: text + index: index + canceled: false + @notifyListeners root.event.Selection, selectionEvent + return if selectionEvent.canceled is true + @notifyListeners root.event.AfterSelection, {index: selectionEvent.index} + @setText selectionEvent.selection + @__lastSelectedItem = index + + @__hide() + + # When typing into the text field, update __text + # The change event is fired when the textfield loses focus, so we use the input event instead + (@$__textfield.on "input", => + event = + value: @$__textfield.val() + canceled: false + @notifyListeners root.event.Modify, event + + if event.canceled is true + @$__textfield.val @__text + else + @__text = event.value + + # This event only applies if the Combo is editable, otherwise @$__textfield would be undefined + ) if @__editable + + if @__editable + onHover = (part) => + event = + part: part + @notifyListeners root.event.Hover, event + @$__textfield.mouseenter => onHover "textbox" + @$__button.mouseenter => onHover "button" + else + @$__element.mouseenter => @notifyListeners root.event.Hover + + # Hide the list if the user clicks somewhere else + $("body").click => + @__hide() if not justShown + return null + + update: -> + super + @__hide() + + if not @__editable + @$__element.find(".title").text @__text + else + @$__textfield.val @__text + + dispose: -> + return if @__disposed or not @$__element + @$__itemContainerElement.remove() + super diff --git a/src/coffee/class/Composite.coffee b/src/coffee/class/Composite.coffee new file mode 100644 index 0000000..9c84c26 --- /dev/null +++ b/src/coffee/class/Composite.coffee @@ -0,0 +1,43 @@ + root.Composite = class Composite extends Widget + + class BodyComposite extends Composite + + constructor: -> + @__id = "" + @$__element = $("body") + + update: -> #do nothing + + isDisposed: -> false + dispose: -> # do nothing + + constructor: (parent, id) -> + super parent, id + + update: -> + @__checkDisposeState() + if not @__appended + @$__element = $("
    ").appendTo @$__parent + @__afterAppend() + + prepend: (thingToPrepend) -> + @__checkDisposeState() + @$__element.prepend thingToPrepend + return @ + append: (thingToAppend) -> + @__checkDisposeState() + @$__element.append thingToAppend + return @ + clear: -> + @__checkDisposeState() + @$__element.empty() + return @ + setContent: (content) -> + @__checkDisposeState() + @clear() + @append content + return @ + + __getTooltipElement: -> null + + root.util.defineConstant Composite, "BODY", new BodyComposite() diff --git a/src/coffee/class/CssController.coffee b/src/coffee/class/CssController.coffee new file mode 100644 index 0000000..f9dfd86 --- /dev/null +++ b/src/coffee/class/CssController.coffee @@ -0,0 +1,67 @@ + # CSSCONTROLLER CLASS DEFINITION + # Allows the setting/getting of an objects id and classes + #======================================================== + class CssController + + constructor: ($e, id = "") -> + root.util.validateJQuery "$e", $e + @$__element = $e + @__id = "" + @__id = id if typeof id is "string" + @$__element.attr "id", @__id if typeof @$__element.attr("id") isnt "string" + @__classes = [] + + __classIf: (classname, shouldAdd, $elem = @$__element) -> + if shouldAdd is true + $elem.addClass classname + else + $elem.removeClass classname + return @ + __cssIf: (cssTrue, cssFalse, shouldAdd, $elem = @$__element) -> + if shouldAdd is true + $elem.css cssTrue + else + $elem.css cssFalse + __attrIf: (attr, condition, $elem = @$__element) -> + if condition is true + $elem.attr attr, "" + else + $elem.removeAttr attr + + hasClass: (className) -> typeof className is "string" and $.inArray(className, @__classes) > -1 + addClass: (className) -> + root.util.validateString "className", className + throw new Error("className cannot have space") if className.indexOf(" ") > -1 + if not @hasClass className + @__classes.push className + @$__element.addClass className + return @ + removeClass: (className) -> + throw new Error("className must be a string. Use removeClasses() for Array input") if root.util.isArray className + root.util.validateString "className", className + throw new Error("className cannot have space") if className.indexOf(" ") > -1 + index = -1 + count = 0 + for c in @__addedClasses + if c is className + index = count + break + count++ + if index > -1 + @__addedClasses.splice index, 1 + @$__element.removeClass className + return @ + removeClasses: (classes) -> + root.util.validateArray "classes", classes + (removeClass c if typeof c is "string") for c in classes + return @ + clearClasses: -> + @$__element.removeClass @__addedClasses.join " " + @__addedClasses.splice 0, @__addedClasses.length + return @ + getClasses: -> @__classes.slice 0 + css: -> + @$__element.css.apply @$__element, arguments + return @ + + getId: -> @__id diff --git a/src/coffee/class/EventListener.coffee b/src/coffee/class/EventListener.coffee new file mode 100644 index 0000000..88adbc9 --- /dev/null +++ b/src/coffee/class/EventListener.coffee @@ -0,0 +1,38 @@ + root.EventListener = class EventListener + + addListener: (eventType, listener) -> + @__checkDisposeState() + root.util.validateString "eventType", eventType + root.util.validateFunction "listener", listener + @__getListeners(eventType).push listener + return @ + removeAllListeners: (eventType = null) -> + if eventType is null + for k, v of @__listeners + @__listeners[k].splice 0 if root.util.isArray @__listeners[k] + return @ + __getListeners(eventType).splice 0 + removeListener: (eventType, listener) -> + index = -1 + listeners = @__getListeners eventType + return if listeners.length is 0 + for fn, i in listeners + if fn is listener + index = i + break + return if index < 0 + listeners.splice index, 1 + + __getListeners: (eventType) -> + list = @__listeners[eventType] + list = (@__listeners[eventType] = []) if not root.util.isArray list + return list + + notifyListeners: (eventType, eventData) -> + @__checkDisposeState() + root.util.validateString eventType, "string" + listenerList = @__listeners[eventType] + return if not root.util.isArray listenerList + eventData = {} if typeof eventData isnt "object" + l.call @, eventData for l in listenerList when typeof l is "function" + return @ diff --git a/src/coffee/class/FileChooser.coffee b/src/coffee/class/FileChooser.coffee new file mode 100644 index 0000000..ac442e1 --- /dev/null +++ b/src/coffee/class/FileChooser.coffee @@ -0,0 +1,86 @@ + #FILECHOOSER CLASS DEFINITION + #At the moment, no way to get the names of files or their content + #================================================================ + root.FileChooser = class FileChooser extends Widget + + constructor: (parent, id, text = "") -> + @__files = [] + @__types = [] + @setText text, false + super parent, id + + setMulti: (multi = true) -> + @__checkDisposeState() + root.util.validateBoolean "multi", multi + @__multi = multi + + accept: (type) -> + @__checkDisposeState() + if typeof type is "string" + @__types.push type + else if typeof typeof type is "array" + accept t for t in type + + return @ + + getAccepted: -> + @__checkDisposeState() + @__types.slice 0 + getAcceptedString: -> + @__checkDisposeState() + if typeof @__types is "array" then @__types.join() else "" + + clearAcceptedTypes: -> + @__checkDisposeState() + @__types.splice 0, @__types.length + + stopAccepting: (type) -> + @__checkDisposeState() + if typeof type is "string" + index = $.inArray type, @__types + @__types.splice index, 1 if index > -1 + else if typeof type is "array" + stopAccepting t for t in type + + return @ + + setText: (text, update = true) -> + @__checkDisposeState() + root.util.validateString "text", text + @__text = text + @update() if update + return @ + getText: -> + @__checkDisposeState() + @__text + + getFiles: -> + @__checkDisposeState() + @__files.slice 0 + + __getTooltipElement: -> @$__label + + update: -> + @__checkDisposeState() + if not @__appended + @$__element = $("").appendTo @$__parent + @$__label = $("").insertAfter @$__element + @$__element.change (e) => + @__files = e.files + @notifyListeners root.event.Selection + @$__element.click (e) => + return if not @__enabled + event = + canceled: false + @notifyListeners root.event.Show, event + e.preventDefault() if event.canceled is true + @$__element.mouseenter => @notifyListeners root.event.Hover + @__afterAppend() + + if @__multi + @$__element.attr "multiple", "" + else + @$__element.removeAttr "multiple" + @$__element.attr "accept", @getAcceptedString() + @__updateEnabledClass() + @__updateEnabledAttr() diff --git a/src/coffee/class/Image.coffee b/src/coffee/class/Image.coffee new file mode 100644 index 0000000..ecdb65b --- /dev/null +++ b/src/coffee/class/Image.coffee @@ -0,0 +1,19 @@ + root.Image = class Image extends Widget + + constructor: (parent, id, src = "") -> + super parent, id + @setSrc src + + setSrc: (src) -> + @__checkDisposeState() + return if typeof src isnt "string" + @__src = src + @update() + getSrc: -> @__src + + update: -> + if not @__appended + @$__element = $("").appendTo @$__parent + + @$__element.attr "src", @__src + @__cssIf {display: "none"}, {display: ""}, @__src is "" diff --git a/src/coffee/class/Label.coffee b/src/coffee/class/Label.coffee new file mode 100644 index 0000000..5d951bf --- /dev/null +++ b/src/coffee/class/Label.coffee @@ -0,0 +1,23 @@ + root.Label = class Label extends Widget + + constructor: (parent, id, text = "") -> + @setText text, false + super parent, id + + setText: (text = "", update = true) -> + @__checkDisposeState() + root.util.validateString "text", text + @__text = text + @update() if update + getText: -> + @__checkDisposeState() + @__text + + update: -> + @__checkDisposeState() + if not @__appended + @$__element = $("#{@__text}").appendTo @$__parent + @__afterAppend() + @$__element.mouseenter => @notifyListeners root.event.Hover + + @$__element.html @__text diff --git a/src/coffee/class/List.coffee b/src/coffee/class/List.coffee new file mode 100644 index 0000000..98c8e41 --- /dev/null +++ b/src/coffee/class/List.coffee @@ -0,0 +1,150 @@ + # LIST CLASS DEFINITION + #====================== + root.List = class List extends AbstractItemList + + constructor: (parent, id, items = []) -> + @__lastSelected = -1 + @__hScroll = true + @$__element = $("
    ") + super parent, id, "ListItem", @$__element + @setItems items + + setMultiSelect: (multi) -> + @__checkDisposeState() + @__multi = multi is true + setItemSelected @__lastSelected if not @__multi + return @ + isMultiSelect: -> + @__checkDisposeState() + return @__multi + + setItems: (items, update = true) -> + @__checkDisposeState() + @__selected = [] + super items, update + + getSelectedItems: -> + @__checkDisposeState() + return for i in @__selected when @__items.length > i > 0 + + getLastSelectedItem: -> + @__checkDisposeState() + @__lastSelected + + setItemSelected: (item, selected = true) -> + @__checkDisposeState() + index = -1 + if typeof item is "string" + index = $.inArray item, @__items + else if typeof item is "number" + index = item + else + throw new Error("item must be a string or number") + + return if index < 0 + + isSelected = @isSelected index + + @deselectAll() if selected and not @__multi + @__selected.push item if selected and not isSelected + @__selected.splice $.inArray(index, @__selected), 1 if not selected + @__selectionChanged = true + @update() + return @ + + toggleItemSelected: (item) -> + @__checkDisposeState() + @setItemSelected item, not @isSelected item + + isSelected: (item) -> + @__checkDisposeState() + if typeof item is "number" + return $.inArray(item, @__selected) > -1 + else if typeof item is "string" + index = $.inArray item, @items + return index > -1 and $.inArray(index, @__selected) > -1 + else + return false + + #items = number, string, array[number or string] + setSelectedItems: (items, update = true) -> + @__checkDisposeState() + throw new Error("list is not multi select") if not @__multi + @__selectionChanged = true + @__selected = [] + root.util.validateArray "items", items + @setItemSelected item for item in items + @update() if update + return @ + + getSelectedIndices: -> + @__checkDisposeState() + @__selected.slice 0 + + selectAll: -> + @__checkDisposeState() + @setItemSelected item, selected for item in @__items + deselectAll: -> + @__checkDisposeState() + @__selected.splice 0 + @__selectionChanged = true + + __renderItem: (item) -> + return "
    #{item}
    " + + __append: -> + @$__element.mouseenter => @notifyListeners root.event.Hover + + update: -> + @__checkDisposeState() + super + if @__itemsChanged + @$__element.find(".ListItem").click (e) => + currentIndex = $(e.target).index() + + fireEvent = (indices) => + event = + index: indices[0] + indices: indices + canceled: false + @notifyListeners root.event.Selection, event + return event + + afterEvent: (e) -> @notifyListeners root.event.AfterSelection, {index: e.index, indices: e.indices} + + if (NATIVE_LAF is "aqua" and e.metaKey) or (NATIVE_LAF isnt "aqua" and e.ctrlKey) + event = fireEvent [currentIndex] + return if event.canceled is true + @toggleItemSelected index for index in event.indices if root.util.isArray event.indices + afterEvent event + else if e.shiftKey + allSelected = true + indices = [@__lastSelected..currentIndex] + for item in indices + allSelected = allSelected and @isSelected item + break if not allSelected + + event = fireEvent indices + return if event.canceled is true + + @setItemSelected item, not allSelected for item in event.indices if root.util.isArray event.indices + afterEvent event + else + event = fireEvent [currentIndex] + return if event.canceled is true + @deselectAll() + @toggleItemSelected currentIndex + afterEvent event + + @__lastSelected = currentIndex + + @__itemsChanged = false + + if @__selectionChanged + @$__element.find(".ListItem").each (i, e) => + $e = $(e) + if @isSelected i + $e.addClass "selected" + else + $e.removeClass "selected" + @__selectionChanged = false diff --git a/src/coffee/class/ProgressBar.coffee b/src/coffee/class/ProgressBar.coffee new file mode 100644 index 0000000..5921166 --- /dev/null +++ b/src/coffee/class/ProgressBar.coffee @@ -0,0 +1,34 @@ + root.ProgressBar = class ProgressBar extends Widget + + constructor: (parent, id) -> + @__progress = 0 + super parent, id + + update: -> + @__checkDisposeState() + if not @__appended + @$__element = $("
    ").appendTo @$__parent + @$__inner = $("
    ").appendTo @$__element + @$__element.mouseenter => @notifyListeners root.event.Hover + @__afterAppend() + + @$__inner.css "width", "#{@__progress}%" + @__classIf "full", @__progress is 100 + @__classIf "indeterminate", @__indeterminate + + setProgress: (progress, denominator = 100) -> + @__checkDisposeState() + root.util.validateNumber "progress", progress + root.util.validateNumber "denominator", denominator + @__progress = (progress / denominator) * 100 + @update() + return @ + getProgress: -> + @__checkDisposeState() + @__progress + + setIndeterminate: (indeterminate = true) -> + @__indeterminate = indeterminate is true + @update() + return @ + isIndeterminate: -> @__indeterminate diff --git a/src/coffee/class/Radio.coffee b/src/coffee/class/Radio.coffee new file mode 100644 index 0000000..b195ce3 --- /dev/null +++ b/src/coffee/class/Radio.coffee @@ -0,0 +1,20 @@ + # RADIO CLASS DEFINITION + # Radio buttons are buttons in which only one can be selected at a time within its group. The programmer + # can use the setGroup(string) function to set the button group. + #======================================================================================================= + root.Radio = class Radio extends Check + + constructor: (parent, id, text = "") -> + @__classname = "Radio" + @__inputType = "radio" + super parent, id, text + + setGroup: (group, update = true) -> + @__checkDisposeState() + root.util.validateString "group", group + @__group = group + @update() if update + return @ + getGroup: -> + @__checkDisposeState() + getString @__group diff --git a/src/coffee/class/Registry.coffee b/src/coffee/class/Registry.coffee new file mode 100644 index 0000000..776921c --- /dev/null +++ b/src/coffee/class/Registry.coffee @@ -0,0 +1,14 @@ + root.registry = registry = new class Registry + + constructor: () -> + @__widgets = [] + + add: (widget) -> @__widgets.push widget if widget instanceof Widget + getByType: (type, strict = false) -> + if type isnt null then (w for w in @__widgets when (if not strict then w instanceof type else w.constructor is type)) else [] + getById: (id) -> + root.util.validateString "id", id + return null if id.length is 0 + for w in @__widgets + return w if w.getId() is id + return null diff --git a/src/coffee/class/Spinner.coffee b/src/coffee/class/Spinner.coffee new file mode 100644 index 0000000..54e0d64 --- /dev/null +++ b/src/coffee/class/Spinner.coffee @@ -0,0 +1,164 @@ + # SPINNER CLASS DEFINITION + # Spinners are textboxes that only takes numerical input and have two arrows next to them. + # The arrows control whether the input increments or decrements. + # The minimum and maximum value of the spinner can be altered, as well as the interval + # for when the arrows are clicked. + # The user can click and hold the mouse button over the arrows to continously increment + # or decrement the value of the Spinner. + #======================================================================================== + root.Spinner = class Spinner extends Widget + + constructor: (parent, id, num = 0) -> + super parent, id, false + @setValue num + @__min = Number.NEGATIVE_INFINITY + @__max = Number.POSATIVE_INFINITY + @__interval = 1 + + setDecimalAllowed: -> + @__checkDisposeState() + @__allowDecimal = allowDecimal is true + return @ + isDecimalAllowed: -> + @__checkDisposeState() + @__allowDecimal + + __testInputAllowed = (input, allowDecimal) -> + throw new Error("decimals are not allowed for this Spinner") if not allowDecimal and not Number.isInteger input + + setInterval: (interval) -> + @__checkDisposeState() + root.util.validateNumber "interval", interval + __testInputAllowed interval, @__allowDecimal + throw new Error("interval cannot be 0") if interval is 0 + @__interval = interval + return @ + getInterval: -> + @__checkDisposeState() + @__interval + + setMinimum: (min) -> + @__checkDisposeState() + root.util.validateNumber "min", min + __testInputAllowed min, @__allowDecimal + throw new Error("Given minimum (#{min}) cannot more than the current maximum (#{@__max})") if min > @__max + @__min = min + @setValue @__num + return @ + getMinimum: -> + @__checkDisposeState() + @__min + + setMaximum: (max) -> + @__checkDisposeState() + root.util.validateNumber "max", max + __testInputAllowed max, @__allowDecimal + throw new Error("Given maximum (#{max}) cannot less than the current minimum (#{@__min})") if max < @__min + @__max = max + @setValue @__num + return @ + getMaximum: -> + @__checkDisposeState() + @__max + + setValue: (num, update = true) -> + @__checkDisposeState() + root.util.validateNumber "num", num + __testInputAllowed num, @__allowDecimal + @__num = if num < @__min then @__min else if num > @__max then @__max else num + @update() if update + return @ + getValue: -> + @__checkDisposeState() + @__num + + increment: (steps = 1) -> + @__checkDisposeState() + root.util.validateInt "steps", steps + @setValue @__num + (steps * @__interval), true + + decrement: (steps = 1) -> + @__checkDisposeState() + root.util.validateInt "steps", steps + @setValue @__num - (steps * @__interval), true + + update: -> + @__checkDisposeState() + if not @__appended + @$__element = $("
    ").appendTo @$__parent + @$__number = $("").appendTo @$__element + @$__buttonContainer = $("
    ").appendTo @$__element + @$__upButton = $("
    ").appendTo @$__buttonContainer + @$__downButton = $("
    ").appendTo @$__buttonContainer + @__afterAppend() + + @$__element.mouseenter => @notifyListeners root.event.Hover + + intervalId = 0 + updateInterval = 100 + + fireEvent = (num, increment, arrow) => + event = + value: num + increment + arrow: arrow + canceled: false + fire = => + event.canceled = false + @notifyListeners root.event.Modify, event + return false if event.canceled is true + @setValue event.value if typeof event.value is "number" + @notifyListeners root.event.AfterModify, {arrow: event.arrow} + return true + return if not fire() + intervalId = window.setInterval => + event.value += increment + fire() + , updateInterval + + hookEvents = (increment) => + $e = if increment then @$__upButton else @$__downButton + $e.mousedown => + return if not @isEnabled() + fireEvent @__num, (if increment then @__interval else -@__interval), if increment then 0 else 1 + .mouseup => + return if not @isEnabled() + window.clearInterval intervalId + + hookEvents true + hookEvents false + + @$__number.on "input", (e) => + + numString = @$__number.val() + newNum = null + zeroAlias = numString is "." or numString is "-" or numString is "" + if zeroAlias + newNum = 0 + else + newNum = Number numString + if Number.isNaN(newNum) or newNum < @__min or newNum > @__max + @$__number.val @__num + return + + event = + value: newNum + arrow: false + canceled: false + @notifyListeners root.event.Modify, event + + if event.canceled is true + @$__number.val @__num + return + else + @__num = if typeof event.value is "number" then event.value else newNum + @__updateClassAndAttr not zeroAlias + + @notifyListeners root.event.AfterModify, {arrow: event.arrow} + + @__updateClassAndAttr true + return @ + + __updateClassAndAttr: (number) -> + @__updateEnabledClass() + @$__number.val(@__num) if number + @__updateEnabledAttr @$__number diff --git a/src/coffee/class/Switch.coffee b/src/coffee/class/Switch.coffee new file mode 100644 index 0000000..7ae2dd7 --- /dev/null +++ b/src/coffee/class/Switch.coffee @@ -0,0 +1,54 @@ + # SWITCH CLASS DEFINITION + # A Switch is a very basic wrapper for input[type="checkbox"]. Although a label is added in the DOM, + # no display text is allowed. + # A switch is like a fancy ToggleButton. However, instead of a 'pressesd/depressed' look, it should + # look more like a circle/rectangle sliding left or right inside its container, depending on its state. + #====================================================================================================== + class Switch extends Widget + + switchHtml = "" + + labelHtml = (left, text) -> + return "#{if left then switchHtml else ""}#{text}#{if not left then switchHtml else ""}" + + constructor: (parent, id) -> + @__classname ?= "Switch" + @__inputType ?= "checkbox" + @__labelOnLeft ?= false + @setState false, false + super parent, id + + setState: (state, update = true) -> + @__checkDisposeState() + @__state = state is true + @update() if update + return @ + getState: -> + @__checkDisposeState() + getBoolean @__state + + update: -> + @__checkDisposeState() + if not @__appended + @$__element = $("
    ").appendTo @$__parent + @$__input = $("").appendTo @$__element + @$__label = $("").appendTo @$__element + @__afterAppend() + @$__input.change => + event = + state: @$__input.prop "checked" # Modifying this has no effect on the event + canceled: false + @notifyListeners root.event.Selection, event + if event.canceled is true + @$__input.prop "checked", @__state + else + @__state = @$__input.prop "checked" + @notifyListeners root.event.AfterSelection + return + @$__element.mouseenter => @notifyListeners root.event.Hover + + @__updateEnabledClass() + @$__label.html "#{labelHtml @__labelOnLeft, @getText()}" + @__updateEnabledAttr @$__input + @$__input.prop "checked", @__state + return @ diff --git a/src/coffee/class/TabFolder.coffee b/src/coffee/class/TabFolder.coffee new file mode 100644 index 0000000..6ac73e6 --- /dev/null +++ b/src/coffee/class/TabFolder.coffee @@ -0,0 +1,93 @@ + root.TabFolder = class TabFolder extends Widget + + class Tab extends Composite + + constructor: (@__folder, id, @$__tab) -> + @__items = [] + super @__folder.$__content, id + + update: -> + if not @__appended + @$__element = $("
    ").appendTo @$__parent + @__afterAppend() + + @$__tab.text @__title + @$__tab.mouseenter => + @notifyListeners root.event.Hover + + isDisposed: -> false + dispose: -> #do nothing, dipose by removeTab() in TabFolder + + __getTooltipElement: -> @$__tab + + getTabFolder: -> @__folder + + setText: (title, update = true) -> + @__title = title if typeof title is "string" + @update() if update + return @ + getText: -> @__title + + constructor: (parent, id) -> + @__tabs = [] + @__selectedTab = 0 + super parent, id + + remove: (index) -> + @__checkDisposeState() + indexCheck @__tabs, index + @__tabs.splice index, 1 + return @ + append: (title, id) -> + @__checkDisposeState() + $t = $("
    ") + tab = new Tab this, id, $t.appendTo @$__tabContainer + tab.setText title + $t.click => + return if not tab.isEnabled() + event = + selection: $t.index() + tab: tab + canceled: false + @notifyListeners root.event.Selection, event + @setSelectedIndex $t.index() if event.canceled isnt true + @__tabs.push tab + @setSelectedIndex @__tabs.length - 1 + return tab + clear: -> + @__checkDisposeState() + @remove 0 while @__tabs.length > 0 + + getSelectedIndex: -> + @__checkDisposeState() + @__selectedTab + getSelectedTab: -> + @__checkDisposeState() + @__tabs[@__selectedTab] + setSelectedIndex: (index) -> + @__checkDisposeState() + indexCheck @__tabs, index + selectedTab = @__tabs[@__selectedTab] + selectedTab.$__tab.removeClass "selected" + selectedTab.$__element.css display: "none" + @__selectedTab = index + selectedTab = @__tabs[index] + selectedTab.$__tab.addClass "selected" + selectedTab.$__element.css display: "" + + __getTooltipElement: -> null + + getTabs: -> + @__checkDisposeState() + @__tabs.slice 0 + + update: -> + @__checkDisposeState() + if not @__appended + @$__element = $("
    +
    +
    +
    ").appendTo @$__parent + @$__tabContainer = @$__element.find ".TabContainer" + @$__content = @$__element.find ".TabContentContainer" + @__afterAppend() diff --git a/src/coffee/class/Table.coffee b/src/coffee/class/Table.coffee new file mode 100644 index 0000000..b78015d --- /dev/null +++ b/src/coffee/class/Table.coffee @@ -0,0 +1,168 @@ + # TABLE CLASS DEFINITION + #======================= + root.Table = class Table extends Widget + + root.util.defineConstant Table, "Header", class Header extends CssController + + #Table.Header + constructor: (value, id = "") -> + super $(""), id + @setValue value + + setValue: (value) -> + root.util.validateString "value", value + @__value = value + @$__element.text @__value + return @ + getValue: -> @__value + + root.util.defineConstant Table, "Row", class Row extends CssController + + root.util.defineConstant Row, "Value", class Value extends CssController + + #Table.Row.Value + constructor: (value, id = "") -> + super $(""), id + @setValue value + + setValue: (value) -> + throw new Error("value must be a string or a number") if typeof value isnt "string" and typeof value isnt "number" + @__value = value + @$__element.text @__value + return @ + getValue: -> @__value + + makeValue = (value) -> + if value instanceof Value then value else (if typeof value is "string" or typeof value is "number" then new Value(value) else null) + + #Table.Row + constructor: (values, id = "") -> + root.util.validateArray "values", values + @__values = [] + (@__values.push v_ if (v_ = makeValue v) instanceof Value) for v in values + super $(""), id + + setValue: (index, value) -> + root.util.validateInt "index", index + if not value instanceof Value + throw new Error("value must be an instance of Table.Row.Value, a string, or a number") if typeof value isnt "string" and typeof value isnt "number" + value = new Value(value) + @__values[index] = value + return @ + getValue: (index) -> + return @getValues() if index is null + root.util.validateInt "index", index + @__values[index] + getValues: -> + arr = [] + (arr.push v if v instanceof Value) for v in @__values + return arr + __getValues: -> + arr = [] + (arr.push if v instanceof Value then v else $("")) for v in @__values + return arr + + # Table + constructor: (parent, id) -> + @__headers = [] + @__rows = [] + super parent, id + + getHeaders: -> + @__checkDisposeState() + arr = [] + arr.push header for header in @__headers + return arr + + update: -> + @__checkDisposeState() + if not @__appended + @$__element = $(" + + + + +
    + ").appendTo @$__parent + @__afterAppend() + + $headers = @$__parent.find "thead" + $body = @$__parent.find "tbody" + + #empty headers and body + $body.empty() + $headers.empty() + + $headers.append h.$__element for h in @__headers + for r in @__rows + $row = r.$__element + $row.empty() + ($row.append if v instanceof Row.Value then v.$__element else v) for v in r.__getValues() + $row.appendTo $body + + @__updateEnabledClass() + #TODO: sortable? + + makeHeader = (header, id = "") -> + header_ = header + if typeof header is "string" + header_ = new Header(header, if typeof id is "string" then id else "") + throw new Error("header must be a string or an instance of Table.Header") if not header instanceof Header + return header_ + + makeRow = (row, id = "") -> + row_ = row + if root.util.isArray row + row_ = new Row(row, if typeof id is "string" then id else "") + throw new Error("row must be an array or an instance of Table.Row") if not row instanceof Row + return row_ + + set = (index, arr, make, thing, id, _this) -> + indexCheck arr, index + thing_ = make thing, id + arr[index] = thing_ + _this.update() + + add = (thing, make, arr, _this) -> + thing_ = make thing + arr.push thing_ + _this.update() + return thing_ + + get = (index, arr, _this) -> + indexCheck arr, index + arr[index] + _this.update() + + remove = (thing, arr, instanceClass) -> #index or Row|Header + index = if Number.isInteger thing then thing else if thing instanceof instanceClass then $.inArray thing, arr else -1 + arr.splice index, 1 if -1 > index < arr.length + return null + + setHeader: (index, header, id = "") -> #indexCheck + @__checkDisposeState() + set index, @__headers, makeHeader, header, id, @ + return @ + addHeader: (header) -> + @__checkDisposeState() + add header, makeHeader, @__headers, @ + getHeader: (index) -> + @__checkDisposeState() + get index, @__headers, @ + removeHeader: (header) -> + @__checkDisposeState() + remove header, @__headers, Header + + setRow: (index, row, id = "") -> + @__checkDisposeState() + set index, @__rows, makeRow, row, id, @ + return @ + addRow: (row) -> + @__checkDisposeState() + add row, makeRow, @__rows, @ + getRow: (index) -> + @__checkDisposeState() + get index, @__rows, @ + removeRow: (row) -> + @__checkDisposeState() + remove row, @__rows, Row, @ diff --git a/src/coffee/class/Text.coffee b/src/coffee/class/Text.coffee new file mode 100644 index 0000000..c84b225 --- /dev/null +++ b/src/coffee/class/Text.coffee @@ -0,0 +1,135 @@ + # TEXT CLASS DEFINITION + # Texts are textboxes. This is more of a wrapper for input[type="text(area)"] + #============================================================================ + root.Text = class Text extends Widget + + getAttributes = (text) -> + "id='#{text.__id}' class='Text#{if text.isMulti() then "Area" else ""}' placeholder='#{text.getPlaceholder()}'" + + getCurrentText = (multi, element) -> return if multi then element.text() else element.val() + + constructor: (parent, id, type = "") -> + root.util.validateString "type", type + @__type = if $.inArray type, ["multi", "password"] >= 0 then type else "" + @__text = "" + super parent, id + + setPlaceholder: (placeholder, update = true) -> + @__checkDisposeState() + root.util.validateString "placeholder", placeholder + @__placeholder = placeholder + @update() if update + return @ + getPlaceholder: -> + @__checkDisposeState() + getString @__placeholder + + setText: (text, update = true) -> + @__checkDisposeState() + root.util.validateString "text", text + @__text = text + @update() if update + return @ + getText: -> + @__checkDisposeState() + @__text + + isMulti: -> + @__checkDisposeState() + return @__type is "multi" + + isPassword: -> + @__checkDisposeState() + return @__type is "password" + + isNormal: -> + return not (@isMulti() or @isPassword()) + + # Somewhat experimental via some internet stuff + # It is surprising to me that JavaScript doesn't have something native + getCarsetPosition: -> + pos = 0 + e = @$__element[0] + + # IE + if document.selection + e.focus() + sel = document.selection.createRange() + length = sel.text.length + sel.moveStart("character", -(getCurrentText(@isMulti(), @$__element).length)) + pos = sel.text.length - length + + # Everything else? + else if e.selectionStart + # selectionStart may be greator than selectionEnd (if backwards), so we use min of start and end + pos = Math.min e.selectionStart, e.selectionEnd + + return pos + + # Also kinda experimental + setCaretPosition: (pos) -> + e = @$__element[0] + if e.setSelectionRange + e.setSelectionRange(pos, pos) + else if e.createTextRange + range = e.createTextRange() + range.collapse true + if pos < 0 + pos = @getCurrentText.length + pos + range.moveStart("character", pos) + range.moveEnd("character", pos) + range.select() + + update: -> + @__checkDisposeState() + if not @__appended + @$__element = + if @isMulti() then $("") + else $("") + @$__element.appendTo @$__parent + @__afterAppend() + @$__element.focus -> + $(this).attr "placeholder", "" + @$__element.blur (e) => + $(e.target).attr "placeholder", @getPlaceholder() + @$__element.on "input", => + event = + value: getCurrentText(@isMulti(), @$__element) + canceled: false + @notifyListeners root.event.Modify, event + if event.canceled + caret = @getCarsetPosition() + cachedLength = @__text.length + currentLength = getCurrentText(@isMulti(), @$__element).length + caret -= Math.max(cachedLength, currentLength) - Math.min(cachedLength, currentLength) + @setText @__text + @setCaretPosition caret + else + @__text = getCurrentText(@isMulti(), @$__element) + @notifyListeners root.event.AfterModify if not event.canceled + @$__element.mouseenter => @notifyListeners root.event.Hover + + @__updateEnabledClass() + if @isMulti() + @$__element.text @getText() + else + @$__element.val @getText() + @$__element.attr "placeholder", @getPlaceholder() + @__updateEnabledAttr() + + setResize: (resize) -> + @__checkDisposeState() + @$__element.removeClass "no-resize resize-v resize-h resize-all" + if resize is "none" or resize is false + @$__element.addClass "no-resize" + else if resize is "all" or resize is "*" or resize is "both" or resize is true + @$__element.addClass "resize-all" + else if typeof resize is "object" + if resize.h and not resize.v + @$__element.addClass "resize-h" + else if resize.v and not resize.h + @$__element.addClass "resize-v" + else if resize.v and resize.h + @$__element.addClass "resize-all" + else if not resize.h and not resize.v + @$__element.addClass "no-resize" diff --git a/src/coffee/class/ToggleButton.coffee b/src/coffee/class/ToggleButton.coffee new file mode 100644 index 0000000..dbb3f0b --- /dev/null +++ b/src/coffee/class/ToggleButton.coffee @@ -0,0 +1,48 @@ + # TOGGLEBUTTON CLASS DEFINITION + # ToggleButtons retain a certain state. When state === true then the button looks pressed in + #========================================================================================== + root.ToggleButton = class ToggleButton extends Button + + + constructor: (parent, id, title = "") -> + super parent, id, title + + __updateStateClass: () -> + if @__state + @$__element.removeClass "state-out" + @$__element.addClass "state-in" + else + @$__element.removeClass "state-in" + @$__element.addClass "state-out" + + setState: (state, update = true) -> + @__checkDisposeState() + root.util.validateBoolean "state", state + @__state = state + @update() if update + return @ + getState: -> + @__checkDisposeState() + @__state + + update: -> + @__checkDisposeState() + if not @__appended + @$__element = $("").appendTo @$__parent + @$__title = $("").appendTo @$__element + @__afterAppend() + + @$__element.hover => root.event.Hover + @$__element.click => + return if not @__enabled + event = + state: not @__state + canceled: false + @notifyListeners root.event.Selection, event + return if event.canceled is true + @__state = not @__state + @update() + + @__updateEnabledClass() + @__updateStateClass() + @$__title.html @__title diff --git a/src/coffee/class/Widget.coffee b/src/coffee/class/Widget.coffee new file mode 100644 index 0000000..6547c79 --- /dev/null +++ b/src/coffee/class/Widget.coffee @@ -0,0 +1,181 @@ + # WIDGET CLASS DEFINITION + # This is the base class for all controls + # Made public so others can make their own Widgets. Usage of 'new Widget()' + # is not reccomended, extend the class (via $.extend or 'extends' in CoffeeScript) + #================================================================================= + root.Widget = class Widget extends CssController + + $.extend Widget.prototype, EventListener.prototype + + constructor: (parent, id = "", update = true) -> + check parent, id + @__classes = [] + @__listeners = {} + @__eventsAdded = false + @__disposed = false + @__id = id + @__appended = false + @$__parent = if root.util.isJQuery parent then parent else getParent parent + @__enabled = true + @__tooltip = "" + @__showToolipWhenDisabled = false + registry.add @ + @update() if update + + __checkDisposeState: -> throw new Error("Widget has been disposed") if @__disposed is true + + setEnabled: (enabled = true, update = true) -> + @__checkDisposeState() + @__enabled = enabled is true + @update() if update + return @ + isEnabled: -> + @__checkDisposeState() + return @__enabled + + setTooltip: (tooltip) -> + @__checkDisposeState() + throw new Error("tooltip must be a function or string") if not (typeof tooltip is "string" or typeof tooltip is "function") + @__tooltip = tooltip + return @ + getTooltip: -> + @__checkDisposeState() + return @__tooltip + + __getTooltipElement: -> @$__element + + __afterAppend: -> + @__appended = true + + # The resize event is only passed to the window, so we simulate it by watching the clientHeight and clientWidth properties + # and notify the Resize listeners when they have changed + root.util.watch @$__element, "clientWidth", => @notifyListeners root.event.Resize, @ + root.util.watch @$__element, "clientWidth", => @notifyListeners root.event.Resize, @ + + $tipElement = @__getTooltipElement() + return if $tipElement is null + @__getTooltipElement().hover (=> @__showTooltip()), (=> @__hideTooltip()) + + showTooltipWhenDisabled: (tooltipWhenDisabled = true) -> + @__checkDisposeState() + @__showToolipWhenDisabled = tooltipWhenDisabled is true + return @ + tooltipShownWhenDisabled: -> + @__checkDisposeState() + @__showToolipWhenDisabled + + __showTooltip: -> + return if not (@__enabled or @__showToolipWhenDisabled) + docHeight = $(document).height() + docWidth = $(document).width() + $tipElement = @__getTooltipElement() + return if $tipElement is null + elemTop = $tipElement.offset().top + width = $tipElement.outerWidth() + height = $tipElement.outerHeight() + Widget.Tooltip.setText(if typeof @__tooltip is "string" then @__tooltip else @__tooltip.call @) + if Widget.Tooltip.getText().length is 0 + Widget.Tooltip.hide() + return @ + Widget.Tooltip.show() + tipHeight = Widget.Tooltip.$__element.outerHeight() + tipWidth = Widget.Tooltip.$__element.outerWidth() + + tipOffset = 10 + + x = (-> + initial = MOUSE.page.x + tipOffset + if initial + tipWidth > docWidth + # return docWidth - tipWidth + return MOUSE.page.x - tipWidth - tipOffset + else + return initial + )() + + y = (-> + # initial = elemTop + height + initial = MOUSE.page.y + tipOffset + if initial + tipHeight > docHeight + # return elemTop - tipHeight + return MOUSE.page.y - tipHeight - tipOffset + else + return initial + )() + + Widget.Tooltip.setLocation(x, y) + + __hideTooltip: -> Widget.Tooltip.hide() + + __updateEnabledClass: -> @__classIf "disabled", not @__enabled + __updateEnabledAttr: ($elem = @$__element) -> @__attrIf "disabled", not @__enabled, $elem + + height: -> + @__checkDisposeState() + @$__element.height() + outerHeight: -> + @__checkDisposeState() + @$__element.outerHeight.apply @$__element, arguments + innerHeight: -> + @__checkDisposeState() + @$__element.innerHeight() + + width: -> + @__checkDisposeState() + @$__element.width() + outerWidth: -> + @__checkDisposeState() + @$__element.outerWidth.apply @$__element, arguments + innerWidth: -> + @__checkDisposeState() + @$__element.innerWidth() + + isDisposed: -> @__disposed + dispose: -> + return if @__disposed or not @$__element + @$__element.remove() + @__disposed = true + @__notifyListeners root.event.Dispose + + # Subclasses should override + update: -> + + $(document).ready -> #This is done so $(body) isn't undefined + Widget.Tooltip = new class extends Widget + + constructor: -> + super "", "wwt_tooltip" + @hide() + + dispose: -> # Cannot dispose + isDisposed: -> false + + setText: (text = "") -> + root.util.validateString "text", text + @__text = text + @update() + return @ + getText: -> @__text + + hide: -> + @$__element.css display: "none" + return @ + + # x, y in pixels + show: (x, y) -> + return if typeof @__text isnt "string" or @__text.length is 0 + @$__element.css display: "" + @setLocation x, y + return @ + + # x, y in pixels + setLocation: (x = 0, y = 0) -> + @$__element.css + left: x + top: y + + update: -> + if not @__appended + @$__element = $("
    ").appendTo @$__parent + @__afterAppend() + + @$__element.html @__text diff --git a/src/coffee/class/YTVideo.coffee b/src/coffee/class/YTVideo.coffee new file mode 100644 index 0000000..c281b88 --- /dev/null +++ b/src/coffee/class/YTVideo.coffee @@ -0,0 +1,226 @@ + # YTVIDEO CLASS DEFINITION + # This is a wrapper for YouTube's embedded iframe player. The programmer can also utilize the IFrame API + # (make sure to set 'enablejsapi' to 1 in the options, or call enableJsApi() in the Options object) + #======================================================================================================= + root.YTVideo = class YTVideo extends Widget + + ytConstant = (name, value) -> + root.util.defineConstant YTVideo, name, value + + # YTVideo.Options CLASS DEFINITION + # This is a helper class. All values passed are normalized to their correct value. + # All set... methods return this for chaining + #================================================================================= + ytConstant "Options", class Options + + constructor: (videoId = "") -> + @setVideoId videoId + + setAutoHide: (autohide) -> + root.util.validateBoolean "autohide", autohide + @autohide = if autohide then YTVideo.TRUE else YTVideo.FALSE + return @ + isAutoHide: -> if @autohide is YTVideo.TRUE then true else false + + setAutoPlay: (autoplay) -> + root.util.validateBoolean "autoplay", autoplay + @autoplay = if autoplay then YTVideo.TRUE else YTVideo.FALSE + return @ + isAutoPlay: -> @autoplay + + setSize: (width, height) -> + @width = width if Number.isInteger width + @height = width if Number.isInteger height + return @ + + setCcLoadPolicy: (ccLoadPolicy) -> + root.util.validateInt "ccLoadPolicy", ccLoadPolicy + @cc_load_policy = ccLoadPolicy + return @ + getCcLoadPolicy: -> @cc_load_policy + + setColor: (color) -> + root.util.validateString "color" + throw new Error("color must be 'red' or 'white'") if color isnt "red" and color isnt "white" + @color = color + return @ + getColor: -> @color + + setControlPolicy: (controlPolicy) -> + root.util.validateInt controlPolicy + @controls = controlPolicy + return @ + getControlPolicy: -> @controls + + enableKeyboardControls: -> + @disablekb = YTVideo.FALSE + return @ + disableKeyboardControls: -> + @disablekb = YTVideo.TRUE + return @ + + enableJsApi: -> + @enablejsapi = YTVideo.TRUE + return @ + disableJsApi: -> + @enablejsapi = YTVideo.FALSE + return @ + + setEnd: (end) -> + root.util.validateNumber "end", end + @end = end + return @ + getEnd: -> @end + + setFullscreenAllowed: (fsAllowed) -> + root.util.validateBoolean "fsAllowed", fsAllowed + @fs = if fsAllowed then YTVideo.TRUE else YTVideo.FALSE + return @ + isFullscreenAllowed: -> if @fs is YTVideo.TRUE then true else false + + setInterfaceLanguage: (interfaceLanguage) -> + root.util.validateString "interfaceString", interfaceString + @hl = interfaceLanguage + return @ + getInterfaceLanguage: -> @hl + + setAnnotationsShownByDefault: -> + @iv_load_policy = YTVideo.ANNOTATIONS_SHOWN_BY_DEFAULT + return @ + setAnnotationsHiddenByDefault: -> + @iv_load_policy = YTVideo.ANNOTATIONS_NOT_SHOWN_BY_DEFAULT + return @ + areAnnotationShownByDefault: -> @iv_load_policy is YTVideo.ANNOTATIONS_SHOWN_BY_DEFAULT + + setListSearch: (query) -> + root.util.validateString "query", query + @listType = "search" + @list = query + return @ + + setListUserUploads: (user) -> + root.util.validateString "user", user + @listType = "user_uploads" + @list = user + return @ + + setListPlaylist: (id) -> + root.util.validateString "id", id + @listType = "playlist" + @list = "PL#{id}" + return @ + + setLooping: (looping) -> + root.util.validateBoolean "looping", looping + @loop = if looping then YTVideo.TRUE else YTVideo.FALSE + return @ + isLooping: -> @loop is YTVideo.TRUE + + setModestBranding: (modestBranding) -> + root.util.validateBoolean "modestBranding", modestBranding + @modestbranding = if modestBranding then YTVideo.TRUE else YTVideo.FALSE + return @ + hasModestBranding: -> @modestbranding is YTVideo.TRUE + + setOrigin: (origin) -> + root.util.validateString "origin", origin + @origin = origin + return @ + getOrigin: -> @origin + + setPlayerApiId: (playerApiId) -> + root.util.validateString "playerApiId", playerApiId + @playerapiid = playerApiId + return @ + getPlayerApiId: -> @playerapiid + + setPlaylist: (playlist) -> + root.util.validateArray "playlist", playlist + @playlist = [] + (@playlist_.push id if typeof id is "string") for id in playlist + return @ + getPlaylist: -> @playlist + + setPlaysInline: (playsInline) -> + root.util.validateBoolean "playsInline", playsInline + @playsinline = if playsInline then YTVideo.TRUE else YTVideo.FALSE + return @ + playsInline: -> if @playsinline is YTVideo.TRUE then true else false + + setShowRelatedVideos: (showRelated) -> + root.util.validateBoolean "showRelated", showRelated + @rel = if showRelated then YTVideo.TRUE else YTVideo.FALSE + return @ + showsRelatedVideos: -> if @rel is YTVideo.TRUE then true else false + + setShowInfo: (showInfo) -> + root.util.validateBoolean "showInfo", showInfo + @showinfo = if showInfo then YTVideo.TRUE else YTVideo.FALSE + return @ + getShowInfo: -> if @showinfo is YTVideo.TRUE then true else false + + setStart: (start) -> + root.util.validateNumber "start", start + @start = start + return @ + getStart: -> @start + + setVideoId: (videoId = "") -> + root.util.validateString "videoId", videoId + @videoId = videoId + + setDarkTheme: -> + @theme = YTVideo.THEME_DARK + return @ + setLightTheme: -> + @theme = YTVideo.THEME_LIGHT + return @ + isDarkTheme: -> @theme is YTVideo.THEME_DARK + + #booleans + ytConstant "TRUE", 1 + ytConstant "FALSE", 0 + + #autohide + ytConstant "AUTOHIDE_VISIBLE", 0 + ytConstant "AUTOHIDE_AUTO", 1 + ytConstant "AUTOHIDE_AUTO_OR_VISIBLE", 2 + + #cc_load_policy + ytConstant "CC_SHOW_BY_DEFAULT", 1 + + #controls + ytConstant "CONTROLS_HIDDEN", 0 + ytConstant "CONTROLS_VISIBLE_IMMEDIATELY", 1 + ytConstant "CONTROLS_FLASH_LOAD_AFTER_PLAYBACK", 2 + + #iv_load_policy (annotations) + ytConstant "ANNOTATIONS_SHOWN_BY_DEFAULT", 1 + ytConstant "ANNOTATIONS_NOT_SHOWN_BY_DEFAULT", 3 + + #theme + ytConstant "THEME_DARK", "dark" + ytConstant "THEME_LIGHT", "light" + + createParamList = (options) -> + params = "" + (params += "#{k}=#{v}&" if typeof v is "string" or typeof v is "number") for k, v of options + return params.substring 0, params.length - 1 + + createPlayer = ($parent, id, options = {}) -> + options.videoId ?= "" + id = if typeof @__id is "string" then "id='#{@__id}''" else "" + $parent.append " + + " + + constructor: (parent, id, options = {}) -> + root.util.validateObject "options", options + super parent, id + root.util.validateString "options.videoId", options.videoId if options.videoId + createPlayer @$__parent, id, options + @__afterAppend() diff --git a/src/coffee/events.coffee b/src/coffee/events.coffee new file mode 100644 index 0000000..2df9038 --- /dev/null +++ b/src/coffee/events.coffee @@ -0,0 +1,17 @@ + $(window).resize -> + w.__hide() for w in registry.getByType Combo + + $(window).mousemove (e) -> + # Relative to document + MOUSE.page.x = e.pageX + MOUSE.page.y = e.pageY + + # Relative to client area + MOUSE.client.x = e.clientX + MOUSE.client.y = e.clientY + + # Relative to entire screen + MOUSE.screen.x = e.screenX + MOUSE.screen.y = e.screenY + + return diff --git a/src/coffee/factory-end.coffee b/src/coffee/factory-end.coffee new file mode 100644 index 0000000..57cec24 --- /dev/null +++ b/src/coffee/factory-end.coffee @@ -0,0 +1,5 @@ +) +# TODO +# Audio? +# Tree (Lists within Lists) +# Slider diff --git a/src/coffee/factory-start.coffee b/src/coffee/factory-start.coffee new file mode 100644 index 0000000..9c46669 --- /dev/null +++ b/src/coffee/factory-start.coffee @@ -0,0 +1,21 @@ +"use strict" +((factory) -> + throw new Error("WWT cannot run in a windowless environment") if not window + + # Allows jQuery to still be used as a dependency in Electron using the + # trick + # Otherwise, try to load jQuery as a module + jq = if window.jQuery then window.jQuery else require "jquery" + + throw new Error("WWT requires jQuery to run") if not jq + + if typeof module is "object" and typeof module.exports is "object" + electron = undefined + try + electron = require "electron" + catch error + # nothing + factory jq, module.exports, electron + else + factory jq, (window.wwt = {}) +)(($, root, electron) -> diff --git a/src/coffee/private.coffee b/src/coffee/private.coffee new file mode 100644 index 0000000..65fec42 --- /dev/null +++ b/src/coffee/private.coffee @@ -0,0 +1,32 @@ + # PRIVATE FUNCTIONS + #================== + + #Private Widget functions + check = (parent, id = "") -> + throw new Error("parent must be a string, jQuery object, or an instanceof wwt.Composite") if typeof parent isnt "string" and not root.util.isJQuery(parent) and not parent instanceof Composite + throw new Error("DOM id #{parent} (parent) does not exist") if $("##{parent}").length is 0 unless parent is "" or root.util.isJQuery(parent) or parent instanceof Composite + root.util.validateString "id", id + throw new Error("DOM id #{id} (id) already exists") if id.length > 0 and $("##{id}").length isnt 0 + + getParent = (parent) -> + if parent is "" then $("body") else if typeof parent is "object" and parent instanceof Composite then parent.$__element else $("##{parent}") + + getString = (variable) -> + if typeof variable isnt "undefined" then variable else "" + + getBoolean = (variable, def = false) -> + if typeof variable is "boolean" then variable else def + + #http://stackoverflow.com/a/10454560 + decimalPlaces = (num) -> + match = ('' + num).match /(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/ + return 0 if not match + return Math.max( + 0, + # Number of digits right of decimal point. + if match[1] then match[1].length else 0 + # Adjust for scientific notation. + - if match[2] then +match[2] else 0) + + indexCheck = (arr, index) -> + throw new Error("index (#{index}) out of bounds (0-#{arr.length - 1})") if -1 > index < arr.length diff --git a/src/coffee/public.coffee b/src/coffee/public.coffee new file mode 100644 index 0000000..2cc1940 --- /dev/null +++ b/src/coffee/public.coffee @@ -0,0 +1,149 @@ + #OPTIONS CLASS DEFINITON + #======================= + options = root.Options = new class + + #Look And Feel + DEF_LAF = "default" + LAF = DEF_LAF + VALID_LAF = ["default", "win", "cocoa", "gtk", "native", "custom"] + + #Accent color for Windows LAF + DEF_LAF_WINDOWS_ACCENT = "blue" + LAF_WINDOWS_ACCENT = DEF_LAF_WINDOWS_ACCENT + VALID_LAF_WINDOWS_ACCENT = ["gray", "red", "green", "blue", "orange", "yellow", "purple"] + + #GTK LAF boolean for dark theme. Default: false (normal/light theme) + LAF_GTK_DARK = false + + RES_BASE = "" + + get = (valid, value, def) -> + if value in valid then value else def + + getLookAndFeel: -> get(VALID_LAF, LAF, DEF_LAF) + setLookAndFeel: (laf) -> LAF = get(VALID_LAF, laf, DEF_LAF) + isNativeLookAndFeel: -> LAF is "native" + + getWindowsAccent: -> get(VALID_LAF_WINDOWS_ACCENT, LAF_WINDOWS_ACCENT, DEF_LAF_WINDOWS_ACCENT) + setWindowsAccent: (accent) -> get(VALID_LAF_WINDOWS_ACCENT, accent, DEF_LAF_WINDOWS_ACCENT) + + setResourceBase: (base) -> RES_BASE = base + getResourceBase: -> return RES_BASE + + isGtkDark: -> LAF_GTK_DARK + setGtkDark: (dark) -> + validateBoolean "dark", dark + LAF_GTK_DARK = dark + + hasBeenInit = false + NATIVE_LAF = "" + MOUSE = + client: {} + page: {} + screen: {} + + #WWT Public Functions + #==================== + + root.electron = electron + + root.updateTheme = -> + return if not hasBeenInit + $("#_wwtTheme").remove() + base = options.getResourceBase() + laf = if options.isNativeLookAndFeel() then NATIVE_LAF else options.getLookAndFeel() + $("head").append "" + + root.init = -> + hasBeenInit = true + os = navigator.platform + if os.startsWith "Win" + NATIVE_LAF = "windows" + else if os.startsWith "Mac" + NATIVE_LAF = "aqua" + else + NATIVE_LAF = "gtk" + + root.updateTheme() + + root.getMousePos = -> $.extend {}, MOUSE + + root.util = + watch: ($element, property, onChange, thisArg) -> + oldValue = $element.prop property + timer = window.setTimeout(-> + onChange.call thisArg if $element.prop(property) isnt oldValue + , 100) + + defineConstant: (obj, name, val) -> + Object.defineProperty obj, name, + enumerable: false + configurable: false + writable: false + value: val + + isArray: (arr) -> + return arr instanceof Array + + isJQuery: (obj) -> + return obj instanceof $ + + validate: (name, variable, type) -> + throw new TypeError("#{name} must be a #{type}") if typeof variable isnt type + + validateArray: (name, variable) -> + throw new TypeError("#{name} must be an array") if not @isArray variable + + validateString: (name, variable) -> + @validate name, variable, "string" + + validateBoolean:(name, variable) -> + @validate name, variable, "boolean" + + validateFunction: (name, variable) -> + @validate name, variable, "function" + + validateNumber: (name, variable) -> + @validate name, variable, "number" + + validateObject: (name, variable) -> + @validate name, variable, "object" + + validateInt: (name, variable) -> + throw new Error("#{name} must be an integer") if typeof variable isnt "number" or not Number.isInteger variable + + validateInteger: -> @validaeInt.apply this, arguments + + validateJQuery: (name, variable) -> + throw new Error("#{name} must be a jQuery object") if not @isJQuery variable + + async: ({fn = null, fnThis, fnArgs = [], callback = null, callbackThis, callbackArgs = []}) -> + return if fn is null or callback is null + setTimeout -> + fn.apply fnThis, if isArray fnArgs then fnArgs else [] + callback.apply callbackThis, if isArray callbackArgs then callbackArgs else [] + , 0 + + # Event Name Constants + # Name inspiration/concept from SWT + # Note: Events are only fired when values are changed internally. Calling set methods (setText, setItems, etc), will not fire events + # Some events are fired after the fact (and cannot be canceled), while others are fired before, and can be modified/canceled + root.util.defineConstant root, "event", + Selection: "selection" # (Toggle)Button is pressed, Check/Radio checked, Tab change, List/Combo selection ... + AfterSelection: "after-selection" + Hover: "hover" # Widget is hovered over by mouse (cannot be canceled) + Dispose: "dispose" # Widget is disposed (cannot be canceled) + Modify: "modify" # Text contents/Spinner number changed + AfterModify: "after-modify" + Show: "show" # Combo's list or tooltip/FileChooser shown. Also used for Spectrum's before-show event + Hide: "hide" # Opposite of Show + Resize: "resize" # Widget is resized via CSS or other action (cannot be canceled) + + # ColorPicker (Spectrum) Events + # Due to how spectrum handles its events, they are not cancelable; the events are fired after they have been completed. + SpectrumChange: "spectrum-change" # Color Picker color changed + SpectrumShow: "spectrum-show" # Color Picker shown + SpectrumHide: "spectrum-hide" # Color Picker hide + SpectrumDragStart: "spectrum-drag-start" # Color Picker drag (start) + SpectrumDragEnd: "spectrum-drag-end" # Color Picker drag (end, before move completion) + SpectrumMove: "spectrum-move" # Color Picker drag (end, after move completion) diff --git a/src/sass-include/_button.sass b/src/sass-include/_button.sass new file mode 100644 index 0000000..4c48b95 --- /dev/null +++ b/src/sass-include/_button.sass @@ -0,0 +1,77 @@ +.Button, .ToggleButton, .FileChooser + label, .Combo, .ComboEditableButton + border-radius : get($controlBorderRadius) + border : $controlBorder + background : get($controlBgGradient) + color : inherit + font-family : inherit + font-size : inherit + padding-left : 5px + padding-right : 5px + line-height : 1.5em + text-align : center + display : inline-block + + .title + cursor: default + + .title.invisible + opacity: 0 + +.Button:focus, .ToggleButton:focus, .Combo:focus + outline: 0 + +.Button:hover, .ToggleButton:not(.state-in):hover, .FileChooser + label:hover, .Combo:hover, .ComboEditableButton:hover + background: get($controlBgHoverGradient) + +.Button.disabled, .Button:hover.disabled, +.ToggleButton.state-out.disabled, .ToggleButton.state-in.disabled, +.ToggleButton.state-out.disabled:hover, .ToggleButton.state-in.disabled:hover, +.Spinner.disabled .SpinnerIncrement, .Spinner.disabled .SpinnerIncrement:hover, +.Spinner.disabled .SpinnerDecrement, .Spinner.disabled .SpinnerDecrement:hover, +.FileChooser.disabled + label, .FileChooser.disabled + label:hover, +.Combo.disabled, .Combo.disabled:hover, +.ComboEditable.disabled .ComboEditableButton, .ComboEditable.disabled .ComboEditableButton:hover + color : get($fgDisabled) + background : none + background-color : get($controlBgDisabled) + +.ToggleButton.state-in, .Button:active, .ToggleButton:active, .FileChooser + label:active + background : get($inBgGradient) + +.ToggleButton.state-in:hover + background: get($inBgHoverGradient) + +.ToggleButton.state-in.disabled, .ToggleButton.state-in.disabled:hover + background: get($inBgDisabledGradient) + +.ButtonGroup + margin : $controlMargin + display : inline-block + +.ButtonGroup > .Button, .ButtonGroup > .ToggleButton + margin: 0 + +.ButtonGroup > .Button:first-child, .ButtonGroup > .ToggleButton:first-child + border-top-right-radius: 0 + border-bottom-right-radius: 0 + +.ButtonGroup > .Button:last-child, .ButtonGroup > .ToggleButton:last-child + border-top-left-radius: 0 + border-bottom-left-radius: 0 + +.ButtonGroup > .Button:not(:last-child):not(:first-child), .ButtonGroup > .ToggleButton:not(:last-child):not(:first-child) + border-radius: 0 + +.ButtonGroup > .Button:not(:last-child), .ButtonGroup > .ToggleButton:not(:last-child) + border-right: none + + +//Technically a FileChooser is Button, right?.. It just wants to be a special snowflake +//This applies to the element +.FileChooser + width : 0.1px + height : 0.1px + opacity : 0 + overflow : hidden + position : absolute + z-index : -1 diff --git a/src/sass-include/_color-picker.sass b/src/sass-include/_color-picker.sass new file mode 100644 index 0000000..6db2280 --- /dev/null +++ b/src/sass-include/_color-picker.sass @@ -0,0 +1,43 @@ +.ColorPickerReplacer, .ColorPickerReplacer:hover, .ColorPickerReplacer.sp-disabled, .ColorPicker.sp-active + border: $controlBorder + +.ColorPickerReplacer + margin : $controlMargin + height : calc(1.5em - 2px) + width : calc(1.75em - 2px) + background : get($controlBgGradient) + border : $controlBorder + cursor : default + + .sp-preview + width : calc(1.25em - 4px) + height : calc(1em - 4px) + margin : 0.25em 0 0 0.25em + border : 1px solid get($fg) + +.ColorPickerReplacer.sp-disabled > sp-preview + border: 1px solid get($fgDisabled) + +.ColorPickerReplacer:hover, .ColorPicker.sp-active, .sp-replacer.sp-active + background : get($controlBgHoverGradient) + border-color : get($controlBorderColor) + +.ColorPickerReplacer.sp-disabled, ColorPickerReplacer.sp-disabled:hover + background : none + background-color : get($controlBgDisabled) + +.ColorPickerContainer + background-color: get($bg) + border: $controlBorder + +.sp-picker-container + border-left: $controlBorder + +.sp-palette-container + border-right: $controlBorder + +.sp-palette-disabled .sp-picker-container + border-left: none + +.sp-input:focus + border: $controlBorder diff --git a/src/sass-include/_combo.sass b/src/sass-include/_combo.sass new file mode 100644 index 0000000..09ad8f9 --- /dev/null +++ b/src/sass-include/_combo.sass @@ -0,0 +1,108 @@ +.Combo .arrow-container + width : 1em + display : inline-block + float : right + +.Combo .arrow-up-container + margin-top: .45em + +.Combo .arrow-up-container, .Combo .arrow-down-container + display : inline-block + float : left + line-height : initial + width : 1em + margin-left : .5em + height : .4em + +.Combo .arrow-up, .Combo .arrow-down + width : 0 + height : 0 + border-left : .20em solid transparent + border-right : .20em solid transparent + +.Combo .arrow-up + border-bottom: .20em solid get($fg) + +.Combo .arrow-down + border-top: .20em solid get($fg) + +.Combo.disabled .arrow-up + border-bottom: .20em solid get($fgDisabled) + +.Combo.disabled .arrow-down + border-top: .20em solid get($fgDisabled) + +.Combo + text-align: left + +.ComboItemList + position : absolute + list-style-type : none + padding : 0 + margin : 0 + border : $controlBorder + overflow : auto + border-top : none + background-color : get($controlBg) + z-index : 10000 + +.ComboItemList.hidden + display: none + +.ComboItemList:not(.hidden) + z-index: 1 + +.ComboItemList.overlayed + border-top : $controlBorder + -webkit-box-shadow : 0px 0px 25px 3px rgba(0,0,0,0.75) + -moz-box-shadow : 0px 0px 25px 3px rgba(0,0,0,0.75) + box-shadow : 0px 0px 25px 3px rgba(0,0,0,0.75) + +.ComboItem + cursor : default + padding : 0.175em 5px + +.ComboItem.selected + display: none + +.ComboItem:hover + background: get($controlBgHoverGradient) + +.ComboEditable .Text + margin : 0 + border-top-right-radius : 0 + border-bottom-right-radius : 0 + width : calc(100% - 1em - 3px) + +.ComboEditableButtonContainer + margin-top : 0 + border-radius : get($controlBorderRadius) + border-left : none + display : inline-block + float : right + background : get($controlBgGradient) + +.ComboEditableButton + border-top-left-radius : 0 + border-bottom-left-radius : 0 + border-left : none + margin-left : 0 + height : 1.5em + +.Combo.listShown, .ComboEditable.listShown .Text + border-bottom-left-radius : 0 + +.Combo.listShown, .ComboEditable.listShown .ComboEditableButton + border-bottom-right-radius : 0 + +.ComboEditableArrowContainer + display : inline-block + margin-top : .75em + +.ComboEditableArrowContainer .down-arrow + border-top : .25em solid get($fg) + border-left : .25em solid transparent + border-right : .25em solid transparent + +.ComboEditable.disabled .ComboEditableArrowContainer .down-arrow + border-top : .25em solid get($fgDisabled) diff --git a/src/sass-include/_common.sass b/src/sass-include/_common.sass new file mode 100644 index 0000000..473d2ee --- /dev/null +++ b/src/sass-include/_common.sass @@ -0,0 +1,74 @@ +@function get($map) + @return map-get($map, $LAF) + +//mapped +$bg : (def: #1A1A1A) +$fg : (def: #CCC) +$ph : (def: #AAA) +$fgDisabled : (def: #444) +$controlBg : (def: #222) +$controlBgGradient : (def: linear-gradient(#313131, #222)) +$controlBgAlt : (def: #1A1A1A) +$controlBgDisabled : (def: #101010) +$controlBgHover : (def: #333) +$controlBgHoverGradient : (def: linear-gradient(#414141, #333)) +$controlBorderColor : (def: #000) +$inBgGradient : (def: linear-gradient(#181818, #282828)) +$inBgHoverGradient : (def: linear-gradient(#282828, #383838)) +$inBgDisabledGradient : (def: linear-gradient(#040404, #141414)) +$controlBorderRadius : (def: 5px) + +//non-mapped +$controlMargin : .25em +$controlBorder : 1px solid get($controlBorderColor) + +html, body + padding : 0 + margin : 0 + color : get($fg) + background-color : get($bg) + font-family : 'Trebuchet MS' + //TODO: font-family specific to LAF + +.noselect + -webkit-touch-callout : none /* iOS Safari */ + -webkit-user-select : none /* Chrome/Safari/Opera */ + -khtml-user-select : none /* Konqueror */ + -moz-user-select : none /* Firefox */ + -ms-user-select : none /* IE/Edge */ + user-select : none /* non-prefixed version, currently not supported by any browser */ + +//Spectrum styling + +//No need to see the down arrow +.sp-dd + display: none + +.sp-preview + margin: 0 + +.sp-replacer + padding: 0 + +//NOTE: resize classes will not work in IE +.no-resize + resize: none + +.resize-v + resize: vertical + +.resize-h + resize: horizontal + +.resize-all + resize: both + +.Button, .ToggleButton, +.Text, .TextArea, .Spinner, +.CheckContainer, .RadioContainer, +.ColorPicker, .FileChooser + label, +.Combo, .ComboEditable, +.Table, +.TabFolder, +.ProgressBar, + margin: $controlMargin diff --git a/src/sass-include/_list.sass b/src/sass-include/_list.sass new file mode 100644 index 0000000..40b511f --- /dev/null +++ b/src/sass-include/_list.sass @@ -0,0 +1,24 @@ +.List + display : inline-block + padding : 0 + margin : $controlMargin + background-color : get($controlBg) + border : $controlBorder + overflow-y : auto + +.List.disabled + background-color : get($controlBgDisabled) + color : get($fgDisabled) + +.List.h-scroll + overflow-x: auto + +.ListItem + cursor : default + padding : 0.175em 0.5em + +.ListItem.selected + background: get($controlBgHoverGradient) + +.List.disabled .ListItem:hover, .List.disabled .ListItem.selected + background-color: get($controlBgDisabled) diff --git a/src/sass-include/_progress-bar.sass b/src/sass-include/_progress-bar.sass new file mode 100644 index 0000000..6e41cf9 --- /dev/null +++ b/src/sass-include/_progress-bar.sass @@ -0,0 +1,33 @@ +.ProgressBar + height : 1em + border : $controlBorder + display : inline-block + +.ProgressBar, .ProgressBarInner + border-radius : get($controlBorderRadius) + +.ProgressBarInner + height : 100% + background-color : get($controlBgHover) + transition : width 0.3s ease + +.ProgressBar:not(.full):not(.indeterminate) .ProgressBarInner + border-top-right-radius: 0 + border-bottom-right-radius: 0 + +.ProgressBar.indeterminate + overflow-x: hidden + + .ProgressBarInner + animation: IndeterminateProgress 1.25s linear 0s infinite alternate + +//TODO: Alter based on LAF +@keyframes IndeterminateProgress + $w: 20% + 0% + width: $w + margin-left: 0 + + 100% + width: $w + margin-left: 100% - $w diff --git a/src/sass-include/_spinner.sass b/src/sass-include/_spinner.sass new file mode 100644 index 0000000..65dedc7 --- /dev/null +++ b/src/sass-include/_spinner.sass @@ -0,0 +1,59 @@ +$spinnerTriangleSize : .25em +$spinnerTriangleTrans : $spinnerTriangleSize solid transparent +$spinnerTriangleColor : $spinnerTriangleSize solid get($fg) +$spinnerTriangleColorDisabled : $spinnerTriangleSize solid get($fgDisabled) + +.SpinnerButtonsContainer + background : get($controlBgGradient) + display : inline-block + float : right + width : 1em + +.SpinnerIncrement, .SpinnerDecrement + border : $controlBorder + border-left : none + display : inline-block + float : left + width : 1em + text-align : center + +.SpinnerIncrement:hover, .SpinnerDecrement:hover + background: get($controlBgHoverGradient) + +.SpinnerNumber + margin : 0 + border-top-right-radius : 0 + border-bottom-right-radius : 0 + width : calc(100% - 1em) + +.SpinnerIncrement + height: calc(.75em - 1px) + +.SpinnerDecrement + height : calc(.75em) + border-top : none + +.SpinnerUpArrow, .SpinnerDownArrow + width : 0 + height : 0 + margin-top : 0.25em + margin-left : 0.25em + +.SpinnerUpArrow + border-left : $spinnerTriangleTrans + border-right : $spinnerTriangleTrans + border-bottom : $spinnerTriangleColor + +.SpinnerDownArrow + border-left : $spinnerTriangleTrans + border-right : $spinnerTriangleTrans + border-top : $spinnerTriangleColor + +.Spinner.disabled .SpinnerUpArrow + border-bottom: $spinnerTriangleColorDisabled + +.Spinner.disabled .SpinnerDownArrow + border-top: $spinnerTriangleColorDisabled + +.Spinner, .ComboEditable + display : inline-block diff --git a/src/sass-include/_switch.sass b/src/sass-include/_switch.sass new file mode 100644 index 0000000..34d25eb --- /dev/null +++ b/src/sass-include/_switch.sass @@ -0,0 +1,66 @@ +.SwitchContainer, .CheckContainer, .RadioContainer + display: inline-block + +.Check:not(old), +.Radio:not(old), +.Switch:not(old) + width : 2em + margin : 0 + padding : 0 + font-size : 1em + opacity : 0 + +.CheckContainer.disabled label, +.RadioContainer.disabled label + color: get($fgDisabled) + +.Check:not(old) + label, +.Radio:not(old) + label + display : inline-block + margin-left : -2em + line-height : 1.5em + +.Check:not(old) + label .outer, +.Radio:not(old) + label .outer + display : inline-block + width : 0.875em + height : 0.875em + margin : 0.25em 0.5em 0.25em 0.25em + border : 0.0625em solid get($controlBorderColor) + border-radius : 0.25em + background-color : get($controlBg) + vertical-align : bottom + +.Radio:not(old) + label .outer + border-radius : 1em + +.Check:not(old):checked + label .outer, +.Radio:not(old):checked + label .outer, +.Check:not(old):hover + label .outer, +.Radio:not(old):hover + label .outer + background-color: get($controlBgHover) + +.CheckContainer.disabled label .outer, +.RadioContainer.disabled label .outer, +.CheckContainer:hover.disabled label .outer, +.RadioContainer:hover.disabled label .outer + background-color: get($controlBgDisabled) + +.Check:not(old):checked + label .outer:before + content : "\2713" + display : block + width : 1em + color : get($fg) + font-size : 0.875em + line-height : 1em + text-align : center + font-weight : bold + +.Radio:not(old):checked + label .inner + display : block + width : 0.5em + height : 0.5em + margin : 0.125em + border : 0.0625em solid get($controlBorderColor) + border-radius : 1em + background-color : get($fg) diff --git a/src/sass-include/_tab-folder.sass b/src/sass-include/_tab-folder.sass new file mode 100644 index 0000000..9cbf551 --- /dev/null +++ b/src/sass-include/_tab-folder.sass @@ -0,0 +1,38 @@ +.TabFolder + display: inline-block + +.TabContainer + width: 100% + display: inline-block + +.Tab + display : inline-block + background : get($controlBgGradient) + padding : 5px + border : $controlBorder + border-bottom : none + cursor : default + +.Tab:not(:first-child) + border-left: none + +.Tab:first-child + border-top-left-radius: get($controlBorderRadius) + +.Tab:last-child + border-top-right-radius: get($controlBorderRadius) + +.Tab:not(.disabled).selected + background: get($inBgGradient) + +.Tab:not(.disabled):hover + background: get($controlBgHover) + +.Tab.disabled + background: get($controlBgDisabled) + +.TabContentContainer + width : calc(100% - 2px - 10px) + border : $controlBorder + padding : 5px + overflow-y : auto diff --git a/src/sass-include/_table.sass b/src/sass-include/_table.sass new file mode 100644 index 0000000..1266f00 --- /dev/null +++ b/src/sass-include/_table.sass @@ -0,0 +1,24 @@ +.Table + background-color : get($controlBg) + border : $controlBorder + border-collapse : collapse + color : get($fg) + font-size : inherit + font-family : inherit + +.TableHeader + background: get($controlBgHoverGradient) + +.Table.disabled, .Table.disabled .TableRow:hover, .Table.disabled .TableHeader + color : get($fgDisabled) + background-color : get($controlBgDisabled) + +.TableHeader, .TableRowValue + cursor : default + padding : 5px + +.TableHeader, .TableRow, .TableRowValue + border: $controlBorder + +.TableRow:hover + background: get($controlBgHoverGradient) diff --git a/src/sass-include/_text.sass b/src/sass-include/_text.sass new file mode 100644 index 0000000..5261894 --- /dev/null +++ b/src/sass-include/_text.sass @@ -0,0 +1,59 @@ +.Text, .TextArea, .sp-input + border : $controlBorder + background-color : get($controlBg) + color : get($fg) + font-size : inherit + font-family : inherit + padding : 3px + border-radius : get($controlBorderRadius) + height : calc(1.5em + 2px) + +.Text.disabled, .TextArea.disabled, +.Spinner.disabled .SpinnerNumber, .Spinner.disabled .SpinnerIncrement, .Spinner.disabled .SpinnerDecrement, +.ComboEditable.disabled .Text + background-color : get($controlBgDisabled) + color : get($fgDisabled) + +.Text::placeholder + color: get($ph) + +//If these placeholder rules are not separated by vendor, they may not work properly +.Text::-webkit-input-placeholder, .TextArea::-webkit-input-placeholder + color: get($ph) + +.Text:-moz-placeholder, .TextArea:-moz-placeholder + color: get($ph) + +.Text::-moz-placeholder, .TextArea::-moz-placeholder + color: get($ph) + +.Text::-webkit-input-placeholder, .TextArea::-webkit-input-placeholder + color: get($ph) + +.Text:-ms-input-placeholder, .TextArea:-ms-input-placeholder + color: get($ph) + +.Text::placeholder, .TextArea::placeholder + color: get($ph) + +.Text.disabled::-webkit-input-placeholder, .TextArea.disabled::-webkit-input-placeholder + color: get($fgDisabled) + +.Text.disabled::-moz-placeholder, .TextArea.disabled::-moz-placeholder + color: get($fgDisabled) + +.Text.disabled:-moz-placeholder, .TextArea.disabled:-moz-placeholder + color: get($fgDisabled) + +.Text.disabled:-ms-input-placeholder, .TextArea.disabled:-ms-input-placeholder + color: get($fgDisabled) + +.Text.disabled::placeholder, .TextArea.disabled::placeholder + color: get($fgDisabled) + +.Text:focus, .TextArea:focus, .sp-input:focus + outline : none + background-color : get($controlBgHover) + +.TextArea + height: initial diff --git a/src/sass-include/_tooltip.sass b/src/sass-include/_tooltip.sass new file mode 100644 index 0000000..df08bc1 --- /dev/null +++ b/src/sass-include/_tooltip.sass @@ -0,0 +1,10 @@ +#wwt_tooltip + background-color : rgba(0, 0, 0, .65) + border-radius : get($controlBorderRadius) + border : $controlBorder + color : get($fg) + position : absolute + padding : 2px 5px + max-width : 20% + font-size : 10pt + z-index : 10000 diff --git a/src/sass/_base.sass b/src/sass/_base.sass new file mode 100644 index 0000000..d19f804 --- /dev/null +++ b/src/sass/_base.sass @@ -0,0 +1,12 @@ +@import common +@import tooltip +@import button +@import text +@import spinner +@import switch +@import list +@import combo +@import table +@import color-picker +@import tab-folder +@import progress-bar diff --git a/src/sass/demo-wwt.sass b/src/sass/demo-wwt.sass new file mode 100644 index 0000000..d85be63 --- /dev/null +++ b/src/sass/demo-wwt.sass @@ -0,0 +1,52 @@ +#buttons + width: 25% + display: inline-block + float: left + + > .Button, > .ToggleButton, .ButtonGroup + width: calc(100% - 5px - .5em) + +#textboxes + width: 15% + display: inline-block + float: left + + .Text, .TextArea + width: calc(100% - 5px - .5em) + +#checkRadio + width: 10% + display: inline-block + float: left + + .RadioContainer, .CheckContainer + width: calc(100% - .5em) + +#spinners + width: 5% + display: inline-block + float: left + + .Spinner + width: calc(100% - .5em) + +#pickers + width: 10% + float: left + +#lists + width: 20% + float: left + + .List + width: calc(50% - 4px - .25em) + margin-right: 0 + + .List:first-child + margin-right: .25em + + .Combo, .ComboEditable, .Table + width: calc(100% - 2px) + +#progressEnabled + width: 50em diff --git a/src/sass/laf-aqua.sass b/src/sass/laf-aqua.sass new file mode 100644 index 0000000..434bf13 --- /dev/null +++ b/src/sass/laf-aqua.sass @@ -0,0 +1,3 @@ +$LAF: "aqua" + +@import base diff --git a/src/sass/laf-default.sass b/src/sass/laf-default.sass new file mode 100644 index 0000000..5131c43 --- /dev/null +++ b/src/sass/laf-default.sass @@ -0,0 +1,3 @@ +$LAF: "def" + +@import base diff --git a/src/sass/laf-gtk.sass b/src/sass/laf-gtk.sass new file mode 100644 index 0000000..332f6cf --- /dev/null +++ b/src/sass/laf-gtk.sass @@ -0,0 +1,3 @@ +$LAF: "gtk" + +@import base diff --git a/src/sass/laf-win.sass b/src/sass/laf-win.sass new file mode 100644 index 0000000..df035b7 --- /dev/null +++ b/src/sass/laf-win.sass @@ -0,0 +1,3 @@ +$LAF: "win" + +@import base