├── .gitignore
├── .rubocop.yml
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── Screenshot.png
└── src
├── html
├── step04.html
├── step05.html
├── step06.html
└── step07.html
├── images
├── 1.pdf
├── 1.svg
├── 10.pdf
├── 10.svg
├── 2.pdf
├── 2.svg
├── 3.pdf
├── 3.svg
├── 4.pdf
├── 4.svg
├── 5.pdf
├── 5.svg
├── 6.pdf
├── 6.svg
├── 7.pdf
├── 7.svg
├── 8.pdf
├── 8.svg
├── 9.pdf
├── 9.svg
└── transparent.png
├── step01.rb
├── step02.rb
├── step03.rb
├── step04.rb
├── step05.rb
├── step06.rb
├── step07.rb
├── tutorial.rb
└── vendor
├── modus
├── bootstrap.bundle.min.js
├── jquery.js
├── modus.css
└── modus.min.css
└── vue.js
/.gitignore:
--------------------------------------------------------------------------------
1 | /src/images/preview.png
2 |
--------------------------------------------------------------------------------
/.rubocop.yml:
--------------------------------------------------------------------------------
1 | AllCops:
2 | Exclude:
3 | - '**/*.rb'
4 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "ruby.rubocop.onSave": false,
3 | "ruby.lint": {
4 | "ruby": false,
5 | "rubocop": false,
6 | "ruby-lint": false
7 | },
8 | "dimmer.enabled": false,
9 | "dimmer.opacity": 20,
10 | "cSpell.enabled": false
11 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017 Trimble Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # `UI::HtmlDialog` Examples
2 |
3 | These examples were originally presented at SketchUp DevCamp 2017 in Leeds, UK.
4 |
5 | They have later been updated and tweaked.
6 |
7 | The examples are grouped into three parts:
8 | * [HtmlDialog class](#part-1-htmldialog-class) (key difference from WebDialog).
9 | * [Communication between Ruby and JS.](#part-2-communication-between-ruby-and-js) HTML content synchronization.
10 | * [Styling.](#part-3-styling)
11 |
12 | 
13 |
14 | Below are some of the notes for each example:
15 |
16 | ## Part 1: HtmlDialog Class
17 |
18 | ### Example 1
19 |
20 | * `UI::HtmlDialog` added in SU2017.
21 | * Key benefit is predictable web-engine.
22 | * Same Chromium version across platform for each SketchUp version.
23 | * Basic "Hello World".
24 | * Many similar methods from `UI::WebDialog`.
25 | * Some difference in behaviour.
26 | * Some extra visual options.
27 | * Bye skp actions - hello `sketchup` object.
28 | * `get_element_value` is gone - due to Chromium async nature.
29 |
30 | ### Example 2
31 |
32 | * Typical window behaviour - reuse window.
33 | * Bring to front if already visible.
34 | * Note: Different from WebDialog, html and action callbacks doesn't work reused.
35 | * Reason is related to Chromium being in another process. Keeping
36 | the registered callbacks turned difficult.
37 |
38 | ### Example 3
39 |
40 | * Another pattern for reusing window.
41 | * Register callbacks before showing dialog. Every time.
42 | * If using `set_html`, also do that before showing dialog.
43 |
44 | ## Part 2: Communication between Ruby and JS.
45 |
46 | ### Example 4
47 |
48 | * Syncing data with Ruby, JS and HTML.
49 | * Use frameworks like Vue, React, etc. to bind data.
50 | * Avoids DOM handling.
51 | * Vue is just one of many frameworks, React etc is similar.
52 | * In the template we can display data using `{{ }}`. When the data updates the
53 | HTML updates automatically.
54 | * For form elements use `v-model` or `v-bind` to bind data properties to the
55 | template. User interactions is synchronized back to `data`.
56 | * Notice `say_something` make consecutive callbacks and aren't lost as oppose to the old skp-actions.
57 |
58 | ### Example 5
59 |
60 | * Lets create something more realistic.
61 | * Material edit dialog.
62 | * Select entity, display material.
63 | * Pushing data to dialog when it's ready...
64 | * With Vue, use the `mounted` event.
65 | * With jQuery, use the `ready` callback.
66 | * When Ruby get `ready` callback, push data back to dialog.
67 | * We push data by calling JavaScript functions.
68 | * Recommend using JSON for object structures.
69 | * `self.material_to_hash` convert `Sketchup::Material` to a hash with its properties.
70 | * `v-if` conditionally control what to display based on data.
71 | * Opacity is special - data from API is 0.0-1.0, UI use 0-100.
72 | * Computed properties can be used for custom display of data.
73 |
74 | ## Part 3: Styling
75 |
76 | ### Example 6
77 |
78 | * Styling webdialogs.
79 | * Look at UI frameworks; Bootstrap, Trimble Modus.
80 | * Add reference to Trimble Modus CSS and JS libs.
81 | * Few Ruby change, we mostly add some HTML classes to our elements.
82 |
83 | ### Example 7
84 |
85 | * Tweaking layout.
86 | * Using grid system - two eight wide columns (in 16 columns max).
87 | * Some manual CSS adjustments.
88 | * Some padding around content.
89 | * Positioning the footer at the bottom.
90 | * Adjusting the input widths.
91 | * Custom element for color and texture preview.
92 |
--------------------------------------------------------------------------------
/Screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SketchUp/htmldialog-examples/130205067a7e64e8c32b4bad5bb78d1f425cb036/Screenshot.png
--------------------------------------------------------------------------------
/src/html/step04.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
Name:
10 |
Pokes:
11 |
Poke {{ name }}!
12 |
Greet
13 |
14 |
15 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/html/step05.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | {{ material.display_name }}
11 |
12 | Color
13 |
14 |
15 | Red
16 |
18 |
19 |
20 |
21 |
22 | Green
23 |
25 |
26 |
27 |
28 |
29 | Blue
30 |
32 |
33 |
34 |
35 |
36 | Opacity
37 |
39 |
40 |
41 |
42 |
43 | Texture
44 |
45 |
46 | Pixel Size:
47 | {{ material.texture.pixel_width }}
48 | x
49 | {{ material.texture.pixel_height }}
50 |
51 |
52 |
53 | Model Size:
54 | {{ material.texture.model_width_formatted }}
55 | x
56 | {{ material.texture.model_height_formatted }}
57 |
58 |
59 |
60 | Colorize
61 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | [No Material Selected]
75 | Select an entity with a material.
76 |
77 |
78 |
83 |
84 |
85 |
86 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/src/html/step06.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | {{ material.display_name }}
13 |
14 | Color
15 |
16 |
59 |
60 |
61 | Texture
62 |
63 |
64 |
Pixel Size:
65 |
66 | {{ material.texture.pixel_width }}
67 | x
68 | {{ material.texture.pixel_height }}
69 |
70 |
71 |
72 |
73 |
Model Size:
74 |
75 | {{ material.texture.model_width_formatted }}
76 | x
77 | {{ material.texture.model_height_formatted }}
78 |
79 |
80 |
81 |
82 |
87 | Colorize
88 |
89 |
90 |
91 |
92 |
93 |
94 | [No Material Selected]
95 | Select an entity with a material.
96 |
97 |
98 |
99 | Apply
100 | Cancel
101 | OK
102 |
103 |
104 |
105 |
106 |
142 |
143 |
144 |
--------------------------------------------------------------------------------
/src/html/step07.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
64 |
65 |
66 |
67 |
68 | {{ material.display_name }}
69 |
70 |
71 |
72 |
73 |
Color
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
90 |
91 |
100 |
101 |
110 |
111 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 | Texture
128 |
129 |
130 |
131 |
132 |
133 |
Pixel Size:
134 |
135 | {{ material.texture.pixel_width }}
136 | x
137 | {{ material.texture.pixel_height }}
138 |
139 |
140 |
141 |
142 |
Model Size:
143 |
144 | {{ material.texture.model_width_formatted }}
145 | x
146 | {{ material.texture.model_height_formatted }}
147 |
148 |
149 |
150 |
151 |
156 | Colorize
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 | [No Material Selected]
167 | Select an entity with a material.
168 |
169 |
170 |
181 |
182 |
183 |
249 |
250 |
251 |
--------------------------------------------------------------------------------
/src/images/1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SketchUp/htmldialog-examples/130205067a7e64e8c32b4bad5bb78d1f425cb036/src/images/1.pdf
--------------------------------------------------------------------------------
/src/images/1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/images/10.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SketchUp/htmldialog-examples/130205067a7e64e8c32b4bad5bb78d1f425cb036/src/images/10.pdf
--------------------------------------------------------------------------------
/src/images/10.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
8 |
14 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/src/images/2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SketchUp/htmldialog-examples/130205067a7e64e8c32b4bad5bb78d1f425cb036/src/images/2.pdf
--------------------------------------------------------------------------------
/src/images/2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/images/3.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SketchUp/htmldialog-examples/130205067a7e64e8c32b4bad5bb78d1f425cb036/src/images/3.pdf
--------------------------------------------------------------------------------
/src/images/3.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/images/4.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SketchUp/htmldialog-examples/130205067a7e64e8c32b4bad5bb78d1f425cb036/src/images/4.pdf
--------------------------------------------------------------------------------
/src/images/4.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/images/5.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SketchUp/htmldialog-examples/130205067a7e64e8c32b4bad5bb78d1f425cb036/src/images/5.pdf
--------------------------------------------------------------------------------
/src/images/5.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/images/6.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SketchUp/htmldialog-examples/130205067a7e64e8c32b4bad5bb78d1f425cb036/src/images/6.pdf
--------------------------------------------------------------------------------
/src/images/6.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/src/images/7.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SketchUp/htmldialog-examples/130205067a7e64e8c32b4bad5bb78d1f425cb036/src/images/7.pdf
--------------------------------------------------------------------------------
/src/images/7.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/images/8.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SketchUp/htmldialog-examples/130205067a7e64e8c32b4bad5bb78d1f425cb036/src/images/8.pdf
--------------------------------------------------------------------------------
/src/images/8.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/images/9.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SketchUp/htmldialog-examples/130205067a7e64e8c32b4bad5bb78d1f425cb036/src/images/9.pdf
--------------------------------------------------------------------------------
/src/images/9.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/src/images/transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SketchUp/htmldialog-examples/130205067a7e64e8c32b4bad5bb78d1f425cb036/src/images/transparent.png
--------------------------------------------------------------------------------
/src/step01.rb:
--------------------------------------------------------------------------------
1 | module Examples
2 | module MaterialInspector
3 | module Step01
4 |
5 | # Basic Hello World.
6 | # Creates new window every time.
7 |
8 | def self.show_dialog
9 | html = <<-EOT
10 | Hello World
11 | Poke
12 | EOT
13 | options = {
14 | :dialog_title => "Material",
15 | :preferences_key => "example.htmldialog.materialinspector",
16 | :style => UI::HtmlDialog::STYLE_DIALOG # New feature!
17 | }
18 | dialog = UI::HtmlDialog.new(options)
19 | dialog.set_html(html)
20 | dialog.center # New feature!
21 | dialog.add_action_callback('poke') { |action_context, name, num_pokes|
22 | # New feature: callback parameters support basic types.
23 | self.on_poke(name, num_pokes) # Delegate to method for easier debugging.
24 | nil
25 | }
26 | dialog
27 | dialog.show
28 | end
29 |
30 | def self.on_poke(name, num_pokes)
31 | num_pokes.times {
32 | puts "Poke #{name}!"
33 | }
34 | end
35 |
36 | end # Step01
37 | end # MaterialInspector
38 | end # Examples
39 |
--------------------------------------------------------------------------------
/src/step02.rb:
--------------------------------------------------------------------------------
1 | module Examples
2 | module MaterialInspector
3 | module Step02
4 |
5 | # Reuse window, bring to front if already visible.
6 | # However, html and action callbacks not reusable.
7 |
8 | def self.create_dialog
9 | # The callbacks here only work the first time the dialog is shown and are
10 | # lost when it is closed.
11 | # Example 03 shows how to reattach the callbacks each time the dialog is
12 | # shown.
13 | html = <<-EOT
14 | Hello World
15 | Poke
16 | EOT
17 | options = {
18 | :dialog_title => "Material",
19 | :preferences_key => "example.htmldialog.materialinspector",
20 | :style => UI::HtmlDialog::STYLE_DIALOG
21 | }
22 | dialog = UI::HtmlDialog.new(options)
23 | dialog.set_html(html)
24 | dialog.center
25 | dialog.add_action_callback('poke') { |action_context, name, num_pokes|
26 | self.on_poke(name, num_pokes)
27 | nil
28 | }
29 | dialog
30 | end
31 |
32 | def self.show_dialog
33 | @dialog ||= self.create_dialog
34 | @dialog.visible? ? @dialog.bring_to_front : @dialog.show
35 | end
36 |
37 | def self.on_poke(name, num_pokes)
38 | num_pokes.times {
39 | puts "Poke #{name}!"
40 | }
41 | end
42 |
43 | end # Step02
44 | end # MaterialInspector
45 | end # Examples
--------------------------------------------------------------------------------
/src/step03.rb:
--------------------------------------------------------------------------------
1 | module Examples
2 | module MaterialInspector
3 | module Step03
4 |
5 | # Window fully reusable.
6 |
7 | def self.create_dialog
8 | options = {
9 | :dialog_title => "Material",
10 | :preferences_key => "example.htmldialog.materialinspector",
11 | :style => UI::HtmlDialog::STYLE_DIALOG
12 | }
13 | dialog = UI::HtmlDialog.new(options)
14 | dialog.center
15 | dialog
16 | end
17 |
18 | def self.show_dialog
19 | if @dialog && @dialog.visible?
20 | @dialog.bring_to_front
21 | else
22 | # Attach content and callbacks when showing the dialog,
23 | # not when creating it, to be able to use the same dialog again.
24 | html = <<-EOT
25 | Hello World
26 | Poke
27 | EOT
28 | @dialog ||= self.create_dialog
29 | @dialog.add_action_callback('poke') { |action_context, name, num_pokes|
30 | self.on_poke(name, num_pokes)
31 | nil
32 | }
33 | @dialog.set_html(html)
34 | @dialog.show
35 | end
36 | end
37 |
38 | def self.on_poke(name, num_pokes)
39 | num_pokes.times {
40 | puts "Poke #{name}!"
41 | }
42 | end
43 |
44 | end # Step03
45 | end # MaterialInspector
46 | end # Examples
--------------------------------------------------------------------------------
/src/step04.rb:
--------------------------------------------------------------------------------
1 | module Examples
2 | module MaterialInspector
3 | module Step04
4 |
5 | # Using Vue to bind data.
6 | # Multiple callbacks from JS is safe.
7 |
8 | def self.create_dialog
9 | html_file = File.join(__dir__, 'html', 'step04.html') # Use external HTML
10 | options = {
11 | :dialog_title => "Material",
12 | :preferences_key => "example.htmldialog.materialinspector",
13 | :style => UI::HtmlDialog::STYLE_DIALOG
14 | }
15 | dialog = UI::HtmlDialog.new(options)
16 | dialog.set_file(html_file) # Can be set here.
17 | dialog.center
18 | dialog
19 | end
20 |
21 | def self.show_dialog
22 | if @dialog && @dialog.visible?
23 | @dialog.bring_to_front
24 | else
25 | @dialog ||= self.create_dialog
26 | @dialog.add_action_callback('poke') { |action_context, name, num_pokes|
27 | self.on_poke(name, num_pokes)
28 | nil
29 | }
30 | @dialog.add_action_callback('say') { |action_context, string|
31 | puts string
32 | nil
33 | }
34 | @dialog.show
35 | end
36 | end
37 |
38 | def self.on_poke(name, num_pokes)
39 | puts 'Get ready...'
40 | num_pokes.times {
41 | puts "Poke #{name}!"
42 | }
43 | # More pokes next time!
44 | @dialog.execute_script("app.num_pokes = #{num_pokes + 1}")
45 | # Switch target - muhahaha!
46 | target = %w[Thom Chris Jin Jeremy].sample
47 | @dialog.execute_script("app.name = '#{target}'")
48 | end
49 |
50 | end # Step04
51 | end # MaterialInspector
52 | end # Examples
53 |
--------------------------------------------------------------------------------
/src/step05.rb:
--------------------------------------------------------------------------------
1 | require 'sketchup.rb'
2 | require 'json'
3 |
4 | module Examples
5 | module MaterialInspector
6 | module Step05
7 |
8 | # More realistic example.
9 | # Material-Edit dialog. Just the data exchange logic with Vue.
10 |
11 | def self.create_dialog
12 | html_file = File.join(__dir__, 'html', 'step05.html')
13 | options = {
14 | :dialog_title => "Material",
15 | :preferences_key => "example.htmldialog.materialinspector",
16 | :style => UI::HtmlDialog::STYLE_DIALOG
17 | }
18 | dialog = UI::HtmlDialog.new(options)
19 | dialog.set_file(html_file)
20 | dialog.center
21 | dialog
22 | end
23 |
24 | def self.show_dialog
25 | @dialog ||= self.create_dialog
26 | @dialog.add_action_callback("ready") { |action_context|
27 | self.update_dialog
28 | nil
29 | }
30 | @dialog.add_action_callback("accept") { |action_context, value|
31 | self.update_material(value)
32 | @dialog.close
33 | nil
34 | }
35 | @dialog.add_action_callback("cancel") { |action_context, value|
36 | @dialog.close
37 | nil
38 | }
39 | @dialog.add_action_callback("apply") { |action_context, value|
40 | self.update_material(value)
41 | nil
42 | }
43 | @dialog.show
44 | end
45 |
46 | # Populate dialog with selected material.
47 |
48 | def self.update_dialog
49 | return if @dialog.nil?
50 | material_data = nil
51 | model = Sketchup.active_model
52 | if model.selection.size == 1
53 | material = self.selected_material
54 | material_data = self.material_to_hash(material) if material
55 | end
56 | json = material_data ? JSON.pretty_generate(material_data) : 'null'
57 | @dialog.execute_script("updateMaterial(#{json})")
58 | end
59 |
60 | # Edit a material.
61 |
62 | def self.update_material(data)
63 | model = Sketchup.active_model
64 | material = model.materials[data['name']]
65 | r = data['color']['red']
66 | g = data['color']['green']
67 | b = data['color']['blue']
68 | color = Sketchup::Color.new(r, g, b)
69 | model.start_operation('Edit Material')
70 | material.color = color
71 | material.alpha = data['alpha']
72 | material.colorize_type = data['colorize_type']
73 | model.commit_operation
74 | end
75 |
76 | # Observer handling.
77 |
78 | def self.on_selection_change(selection)
79 | self.update_dialog
80 | end
81 |
82 | def self.on_material_change(material)
83 | if material == self.selected_material
84 | self.update_dialog
85 | end
86 | end
87 |
88 | # Collect model data.
89 |
90 | def self.selected_material
91 | material = nil
92 | model = Sketchup.active_model
93 | if model.selection.size == 1
94 | material = nil
95 | entity = model.selection.first
96 | if entity.respond_to?(:material) && entity.material
97 | material = entity.material
98 | elsif entity.respond_to?(:back_material)
99 | material = entity.back_material
100 | end
101 | end
102 | material
103 | end
104 |
105 | # Convert objects to Hashes.
106 |
107 | def self.material_to_hash(material)
108 | return nil if material.nil?
109 | {
110 | name: material.name,
111 | display_name: material.display_name,
112 | type: material.materialType,
113 | color: self.color_to_hash(material.color),
114 | alpha: material.alpha,
115 | texture: self.texture_to_hash(material.texture),
116 | colorize_type: material.colorize_type,
117 | colorize_deltas: material.colorize_deltas,
118 | }
119 | end
120 |
121 | def self.color_to_hash(color)
122 | {
123 | red: color.red,
124 | green: color.green,
125 | blue: color.blue,
126 | alpha: color.alpha,
127 | }
128 | end
129 |
130 | def self.texture_to_hash(texture)
131 | return nil if texture.nil?
132 | {
133 | filename: texture.filename,
134 | pixel_width: texture.image_width,
135 | pixel_height: texture.image_height,
136 | model_width: texture.width,
137 | model_height: texture.height,
138 | model_width_formatted: texture.width.to_l.to_s,
139 | model_height_formatted: texture.height.to_l.to_s,
140 | average_color: self.color_to_hash(texture.average_color)
141 | }
142 | end
143 |
144 | # Observe selected material.
145 |
146 | PLUGIN = self
147 | class SelectionChangeObserver < Sketchup::SelectionObserver
148 | def onSelectionAdded(selection, entity)
149 | PLUGIN.on_selection_change(selection)
150 | end
151 | def onSelectionBulkChange(selection)
152 | PLUGIN.on_selection_change(selection)
153 | end
154 | def onSelectionCleared(selection)
155 | PLUGIN.on_selection_change(selection)
156 | end
157 | def onSelectionRemoved(selection, entity)
158 | PLUGIN.on_selection_change(selection)
159 | end
160 | def onSelectedRemoved(selection, entity)
161 | PLUGIN.on_selection_change(selection)
162 | end
163 | end
164 |
165 | class MaterialChangeObserver < Sketchup::MaterialsObserver
166 | def onMaterialChange(materials, material)
167 | PLUGIN.on_material_change(material)
168 | end
169 | def onMaterialRemove(materials, material)
170 | PLUGIN.on_material_change(material)
171 | end
172 | end
173 |
174 | class AppObserver < Sketchup::AppObserver
175 | def onNewModel(model)
176 | observe_model(model)
177 | end
178 | def onOpenModel(model)
179 | observe_model(model)
180 | end
181 | def expectsStartupModelNotifications
182 | return true
183 | end
184 | private
185 | def observe_model(model)
186 | model.selection.add_observer(SelectionChangeObserver.new)
187 | model.materials.add_observer(MaterialChangeObserver.new)
188 | end
189 | end
190 |
191 | unless file_loaded?(__FILE__)
192 | Sketchup.add_observer(AppObserver.new)
193 | end
194 |
195 | file_loaded(__FILE__)
196 |
197 | end # Step05
198 | end # MaterialInspector
199 | end # Examples
200 |
--------------------------------------------------------------------------------
/src/step06.rb:
--------------------------------------------------------------------------------
1 | require 'sketchup.rb'
2 | require 'json'
3 |
4 | module Examples
5 | module MaterialInspector
6 | module Step06
7 |
8 | # Adding UI frameworks for some style.
9 |
10 | def self.create_dialog
11 | html_file = File.join(__dir__, 'html', 'step06.html')
12 | options = {
13 | :dialog_title => "Material",
14 | :preferences_key => "example.htmldialog.materialinspector",
15 | :style => UI::HtmlDialog::STYLE_DIALOG
16 | }
17 | dialog = UI::HtmlDialog.new(options)
18 | dialog.set_file(html_file)
19 | dialog.center
20 | dialog
21 | end
22 |
23 | def self.show_dialog
24 | @dialog ||= self.create_dialog
25 | @dialog.add_action_callback("ready") {
26 | self.update_dialog
27 | nil
28 | }
29 | @dialog.add_action_callback("accept") { |_, value|
30 | self.update_material(value)
31 | @dialog.close
32 | nil
33 | }
34 | @dialog.add_action_callback("cancel") { |_, value|
35 | @dialog.close
36 | nil
37 | }
38 | @dialog.add_action_callback("apply") { |_, value|
39 | self.update_material(value)
40 | nil
41 | }
42 | @dialog.show
43 | end
44 |
45 | # Populate dialog with selected material.
46 |
47 | def self.update_dialog
48 | return if @dialog.nil?
49 | material_data = nil
50 | model = Sketchup.active_model
51 | if model.selection.size == 1
52 | material = self.selected_material
53 | material_data = self.material_to_hash(material) if material
54 | end
55 | json = material_data ? JSON.pretty_generate(material_data) : 'null'
56 | @dialog.execute_script("updateMaterial(#{json})")
57 | end
58 |
59 | # Edit a material.
60 |
61 | def self.update_material(data)
62 | model = Sketchup.active_model
63 | material = model.materials[data['name']]
64 | r = data['color']['red']
65 | g = data['color']['green']
66 | b = data['color']['blue']
67 | color = Sketchup::Color.new(r, g, b)
68 | model.start_operation('Edit Material')
69 | material.color = color
70 | material.alpha = data['alpha']
71 | material.colorize_type = data['colorize_type']
72 | model.commit_operation
73 | end
74 |
75 | # Observer handling.
76 |
77 | def self.on_selection_change(selection)
78 | self.update_dialog
79 | end
80 |
81 | def self.on_material_change(material)
82 | if material == self.selected_material
83 | self.update_dialog
84 | end
85 | end
86 |
87 | # Collect model data.
88 |
89 | def self.selected_material
90 | material = nil
91 | model = Sketchup.active_model
92 | if model.selection.size == 1
93 | material = nil
94 | entity = model.selection.first
95 | if entity.respond_to?(:material) && entity.material
96 | material = entity.material
97 | elsif entity.respond_to?(:back_material)
98 | material = entity.back_material
99 | end
100 | end
101 | material
102 | end
103 |
104 | # Convert objects to Hashes.
105 |
106 | def self.material_to_hash(material)
107 | return nil if material.nil?
108 | {
109 | name: material.name,
110 | display_name: material.display_name,
111 | type: material.materialType,
112 | color: self.color_to_hash(material.color),
113 | alpha: material.alpha,
114 | texture: self.texture_to_hash(material.texture),
115 | colorize_type: material.colorize_type,
116 | colorize_deltas: material.colorize_deltas,
117 | }
118 | end
119 |
120 | def self.color_to_hash(color)
121 | {
122 | red: color.red,
123 | green: color.green,
124 | blue: color.blue,
125 | alpha: color.alpha,
126 | }
127 | end
128 |
129 | def self.texture_to_hash(texture)
130 | return nil if texture.nil?
131 | {
132 | filename: texture.filename,
133 | pixel_width: texture.image_width,
134 | pixel_height: texture.image_height,
135 | model_width: texture.width,
136 | model_height: texture.height,
137 | model_width_formatted: texture.width.to_l.to_s,
138 | model_height_formatted: texture.height.to_l.to_s,
139 | average_color: self.color_to_hash(texture.average_color)
140 | }
141 | end
142 |
143 | # Observe selected material.
144 |
145 | PLUGIN = self
146 | class SelectionChangeObserver < Sketchup::SelectionObserver
147 | def onSelectionAdded(selection, entity)
148 | PLUGIN.on_selection_change(selection)
149 | end
150 | def onSelectionBulkChange(selection)
151 | PLUGIN.on_selection_change(selection)
152 | end
153 | def onSelectionCleared(selection)
154 | PLUGIN.on_selection_change(selection)
155 | end
156 | def onSelectionRemoved(selection, entity)
157 | PLUGIN.on_selection_change(selection)
158 | end
159 | def onSelectedRemoved(selection, entity)
160 | PLUGIN.on_selection_change(selection)
161 | end
162 | end
163 |
164 | class MaterialChangeObserver < Sketchup::MaterialsObserver
165 | def onMaterialChange(materials, material)
166 | PLUGIN.on_material_change(material)
167 | end
168 | def onMaterialRemove(materials, material)
169 | PLUGIN.on_material_change(material)
170 | end
171 | end
172 |
173 | class AppObserver < Sketchup::AppObserver
174 | def onNewModel(model)
175 | observe_model(model)
176 | end
177 | def onOpenModel(model)
178 | observe_model(model)
179 | end
180 | def expectsStartupModelNotifications
181 | return true
182 | end
183 | private
184 | def observe_model(model)
185 | model.selection.add_observer(SelectionChangeObserver.new)
186 | model.materials.add_observer(MaterialChangeObserver.new)
187 | end
188 | end
189 |
190 | unless file_loaded?(__FILE__)
191 | Sketchup.add_observer(AppObserver.new)
192 | end
193 |
194 | file_loaded(__FILE__)
195 |
196 | end # Step06
197 | end # MaterialInspector
198 | end # Examples
199 |
--------------------------------------------------------------------------------
/src/step07.rb:
--------------------------------------------------------------------------------
1 | require 'sketchup.rb'
2 | require 'json'
3 |
4 | module Examples
5 | module MaterialInspector
6 | module Step07
7 |
8 | # Fine tuning UI.
9 |
10 | def self.create_dialog
11 | html_file = File.join(__dir__, 'html', 'step07.html')
12 | # Define pixel perfect dimensions matching our content.
13 | width = 15 + 128 + 15 + 15 + 128 + 15
14 | height = 470
15 | # Add some extra space for older SU versions that don't support inner sizing.
16 | if Sketchup.version.to_f < 21.1
17 | width += 20
18 | height += 40
19 | end
20 | options = {
21 | :dialog_title => "Material",
22 | :preferences_key => "com.sketchup.example.htmldialog.materialinspector",
23 | :style => UI::HtmlDialog::STYLE_DIALOG,
24 | # Set a fixed size now that we know the content size.
25 | :resizable => false,
26 | :width => width,
27 | :height => height,
28 | :use_content_size => true
29 | }
30 | dialog = UI::HtmlDialog.new(options)
31 | dialog.set_file(html_file)
32 | dialog.center
33 | dialog
34 | end
35 |
36 | def self.show_dialog
37 | @dialog ||= self.create_dialog
38 | @dialog.add_action_callback("ready") {
39 | self.update_dialog
40 | nil
41 | }
42 | @dialog.add_action_callback("accept") { |_, value|
43 | self.update_material(value)
44 | @dialog.close
45 | nil
46 | }
47 | @dialog.add_action_callback("cancel") { |_, value|
48 | @dialog.close
49 | nil
50 | }
51 | @dialog.add_action_callback("apply") { |_, value|
52 | self.update_material(value)
53 | nil
54 | }
55 | @dialog.show
56 | end
57 |
58 | # Populate dialog with selected material.
59 |
60 | def self.update_dialog
61 | return if @dialog.nil?
62 | material_data = nil
63 | model = Sketchup.active_model
64 | if model.selection.size == 1
65 | material = self.selected_material
66 | if material
67 | material_data = self.material_to_hash(material)
68 | # Write out a material thumbnail.
69 | self.generate_texture_preview(material)
70 | end
71 | end
72 | json = material_data ? JSON.pretty_generate(material_data) : 'null'
73 | @dialog.execute_script("updateMaterial(#{json})")
74 | end
75 |
76 | # Edit a material.
77 |
78 | def self.update_material(data)
79 | model = Sketchup.active_model
80 | material = model.materials[data['name']]
81 | r = data['color']['red']
82 | g = data['color']['green']
83 | b = data['color']['blue']
84 | color = Sketchup::Color.new(r, g, b)
85 | model.start_operation('Edit Material')
86 | material.color = color
87 | material.alpha = data['alpha']
88 | material.colorize_type = data['colorize_type']
89 | model.commit_operation
90 | end
91 |
92 | # Observer handling.
93 |
94 | def self.on_selection_change(selection)
95 | self.update_dialog
96 | end
97 |
98 | def self.on_material_change(material)
99 | if material == self.selected_material
100 | self.update_dialog
101 | end
102 | end
103 |
104 | # Collect model data.
105 |
106 | def self.selected_material
107 | material = nil
108 | model = Sketchup.active_model
109 | if model.selection.size == 1
110 | material = nil
111 | entity = model.selection.first
112 | if entity.respond_to?(:material) && entity.material
113 | material = entity.material
114 | elsif entity.respond_to?(:back_material)
115 | material = entity.back_material
116 | end
117 | end
118 | material
119 | end
120 |
121 | def self.generate_texture_preview(material)
122 | return unless material && material.texture
123 | preview_file = File.join(__dir__, 'images', 'preview.png')
124 | unless material.write_thumbnail(preview_file, 128)
125 | # .write_thumbnail fails can fail if dimensions are equal or smaller than
126 | # the actual size of the textures.
127 | material.texture.write(preview_file)
128 | end
129 | end
130 |
131 | # Convert objects to Hashes.
132 |
133 | def self.material_to_hash(material)
134 | return nil if material.nil?
135 | {
136 | name: material.name,
137 | display_name: material.display_name,
138 | type: material.materialType,
139 | color: self.color_to_hash(material.color),
140 | alpha: material.alpha,
141 | texture: self.texture_to_hash(material.texture),
142 | colorize_type: material.colorize_type,
143 | colorize_deltas: material.colorize_deltas,
144 | }
145 | end
146 |
147 | def self.color_to_hash(color)
148 | {
149 | red: color.red,
150 | green: color.green,
151 | blue: color.blue,
152 | alpha: color.alpha,
153 | }
154 | end
155 |
156 | def self.texture_to_hash(texture)
157 | return nil if texture.nil?
158 | {
159 | filename: texture.filename,
160 | pixel_width: texture.image_width,
161 | pixel_height: texture.image_height,
162 | model_width: texture.width,
163 | model_height: texture.height,
164 | model_width_formatted: texture.width.to_l.to_s,
165 | model_height_formatted: texture.height.to_l.to_s,
166 | average_color: self.color_to_hash(texture.average_color)
167 | }
168 | end
169 |
170 | # Observe selected material.
171 |
172 | PLUGIN = self
173 | class SelectionChangeObserver < Sketchup::SelectionObserver
174 | def onSelectionAdded(selection, entity)
175 | PLUGIN.on_selection_change(selection)
176 | end
177 | def onSelectionBulkChange(selection)
178 | PLUGIN.on_selection_change(selection)
179 | end
180 | def onSelectionCleared(selection)
181 | PLUGIN.on_selection_change(selection)
182 | end
183 | def onSelectionRemoved(selection, entity)
184 | PLUGIN.on_selection_change(selection)
185 | end
186 | def onSelectedRemoved(selection, entity)
187 | PLUGIN.on_selection_change(selection)
188 | end
189 | end
190 |
191 | class MaterialChangeObserver < Sketchup::MaterialsObserver
192 | def onMaterialChange(materials, material)
193 | PLUGIN.on_material_change(material)
194 | end
195 | def onMaterialRemove(materials, material)
196 | PLUGIN.on_material_change(material)
197 | end
198 | end
199 |
200 | class AppObserver < Sketchup::AppObserver
201 | def onNewModel(model)
202 | observe_model(model)
203 | end
204 | def onOpenModel(model)
205 | observe_model(model)
206 | end
207 | def expectsStartupModelNotifications
208 | return true
209 | end
210 | private
211 | def observe_model(model)
212 | model.selection.add_observer(SelectionChangeObserver.new)
213 | model.materials.add_observer(MaterialChangeObserver.new)
214 | end
215 | end
216 |
217 | unless file_loaded?(__FILE__)
218 | Sketchup.add_observer(AppObserver.new)
219 | end
220 |
221 | file_loaded(__FILE__)
222 |
223 | end # Step07
224 | end # MaterialInspector
225 | end # Examples
226 |
--------------------------------------------------------------------------------
/src/tutorial.rb:
--------------------------------------------------------------------------------
1 | require_relative 'step01.rb'
2 | require_relative 'step02.rb'
3 | require_relative 'step03.rb'
4 | require_relative 'step04.rb'
5 | require_relative 'step05.rb'
6 | require_relative 'step06.rb'
7 | require_relative 'step07.rb'
8 |
9 | require 'sketchup.rb'
10 |
11 | module Examples
12 | module MaterialInspector
13 | TUTORIALS = self
14 | module TutorialController
15 |
16 | OSX = Sketchup.platform == :platform_osx
17 |
18 | def self.create_step(index, title, &block)
19 | cmd = UI::Command.new(title, &block)
20 | cmd.tooltip = title
21 | ext = OSX ? 'pdf' : 'svg'
22 | # https://www.flaticon.com/free-icons/numbers_931
23 | icon = File.join(__dir__, 'images', "#{index}.#{ext}")
24 | cmd.small_icon = icon
25 | cmd.large_icon = icon
26 | cmd
27 | end
28 |
29 | unless file_loaded?(__FILE__)
30 | step01 = self.create_step(1, 'Step 01 - Basic Usage') {
31 | TUTORIALS::Step01.show_dialog
32 | }
33 |
34 | step02 = self.create_step(2, 'Step 02 - (Partially) Reusable window') {
35 | TUTORIALS::Step02.show_dialog
36 | }
37 |
38 | step03 = self.create_step(3, 'Step 03 - (Fully) Reusable Window') {
39 | TUTORIALS::Step03.show_dialog
40 | }
41 |
42 | step04 = self.create_step(4, 'Step 04 - Adding JS Framework') {
43 | TUTORIALS::Step04.show_dialog
44 | }
45 |
46 | step05 = self.create_step(5, 'Step 05 - Realistic Example') {
47 | TUTORIALS::Step05.show_dialog
48 | }
49 |
50 | step06 = self.create_step(6, 'Step 06 - Adding UI Framework') {
51 | TUTORIALS::Step06.show_dialog
52 | }
53 |
54 | step07 = self.create_step(7, 'Step 07 - Tuning UI') {
55 | TUTORIALS::Step07.show_dialog
56 | }
57 |
58 | toolbar = UI::Toolbar.new('HtmlDialog Examples')
59 | toolbar.add_item(step01)
60 | toolbar.add_item(step02)
61 | toolbar.add_item(step03)
62 | toolbar.add_separator
63 | toolbar.add_item(step04)
64 | toolbar.add_item(step05)
65 | toolbar.add_separator
66 | toolbar.add_item(step06)
67 | toolbar.add_item(step07)
68 | toolbar.restore
69 | file_loaded(__FILE__)
70 | end
71 |
72 | end # TutorialController
73 | end # MaterialInspector
74 | end # Examples
--------------------------------------------------------------------------------
/src/vendor/modus/bootstrap.bundle.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v4.4.1 (https://getbootstrap.com/)
3 | * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("jquery")):"function"==typeof define&&define.amd?define(["exports","jquery"],t):t((e=e||self).bootstrap={},e.jQuery)}(this,function(e,p){"use strict";function i(e,t){for(var n=0;nthis._items.length-1||e<0))if(this._isSliding)p(this._element).one(V.SLID,function(){return t.to(e)});else{if(n===e)return this.pause(),void this.cycle();var i=n=i.clientWidth&&n>=i.clientHeight}),u=0l[e]&&!i.escapeWithReference&&(n=Math.min(h[t],l[e]-("right"===e?h.width:h.height))),Ye({},t,n)}};return c.forEach(function(e){var t=-1!==["left","top"].indexOf(e)?"primary":"secondary";h=ze({},h,u[t](e))}),e.offsets.popper=h,e},priority:["left","right","top","bottom"],padding:5,boundariesElement:"scrollParent"},keepTogether:{order:400,enabled:!0,fn:function(e){var t=e.offsets,n=t.popper,i=t.reference,o=e.placement.split("-")[0],r=Math.floor,s=-1!==["top","bottom"].indexOf(o),a=s?"right":"bottom",l=s?"left":"top",c=s?"width":"height";return n[a]r(i[a])&&(e.offsets.popper[l]=r(i[a])),e}},arrow:{order:500,enabled:!0,fn:function(e,t){var n;if(!gt(e.instance.modifiers,"arrow","keepTogether"))return e;var i=t.element;if("string"==typeof i){if(!(i=e.instance.popper.querySelector(i)))return e}else if(!e.instance.popper.contains(i))return console.warn("WARNING: `arrow.element` must be child of its popper element!"),e;var o=e.placement.split("-")[0],r=e.offsets,s=r.popper,a=r.reference,l=-1!==["left","right"].indexOf(o),c=l?"height":"width",h=l?"Top":"Left",u=h.toLowerCase(),f=l?"left":"top",d=l?"bottom":"right",p=nt(i)[c];a[d]-ps[d]&&(e.offsets.popper[u]+=a[u]+p-s[d]),e.offsets.popper=Xe(e.offsets.popper);var m=a[u]+a[c]/2-p/2,g=ke(e.instance.popper),_=parseFloat(g["margin"+h],10),v=parseFloat(g["border"+h+"Width"],10),y=m-e.offsets.popper[u]-_-v;return y=Math.max(Math.min(s[c]-p,y),0),e.arrowElement=i,e.offsets.arrow=(Ye(n={},u,Math.round(y)),Ye(n,f,""),n),e},element:"[x-arrow]"},flip:{order:600,enabled:!0,fn:function(m,g){if(at(m.instance.modifiers,"inner"))return m;if(m.flipped&&m.placement===m.originalPlacement)return m;var _=Ze(m.instance.popper,m.instance.reference,g.padding,g.boundariesElement,m.positionFixed),v=m.placement.split("-")[0],y=it(v),E=m.placement.split("-")[1]||"",b=[];switch(g.behavior){case Et:b=[v,y];break;case bt:b=yt(v);break;case wt:b=yt(v,!0);break;default:b=g.behavior}return b.forEach(function(e,t){if(v!==e||b.length===t+1)return m;v=m.placement.split("-")[0],y=it(v);var n=m.offsets.popper,i=m.offsets.reference,o=Math.floor,r="left"===v&&o(n.right)>o(i.left)||"right"===v&&o(n.left)o(i.top)||"bottom"===v&&o(n.top)o(_.right),l=o(n.top)o(_.bottom),h="left"===v&&s||"right"===v&&a||"top"===v&&l||"bottom"===v&&c,u=-1!==["top","bottom"].indexOf(v),f=!!g.flipVariations&&(u&&"start"===E&&s||u&&"end"===E&&a||!u&&"start"===E&&l||!u&&"end"===E&&c),d=!!g.flipVariationsByContent&&(u&&"start"===E&&a||u&&"end"===E&&s||!u&&"start"===E&&c||!u&&"end"===E&&l),p=f||d;(r||h||p)&&(m.flipped=!0,(r||h)&&(v=b[t+1]),p&&(E=function(e){return"end"===e?"start":"start"===e?"end":e}(E)),m.placement=v+(E?"-"+E:""),m.offsets.popper=ze({},m.offsets.popper,ot(m.instance.popper,m.offsets.reference,m.placement)),m=st(m.instance.modifiers,m,"flip"))}),m},behavior:"flip",padding:5,boundariesElement:"viewport",flipVariations:!1,flipVariationsByContent:!1},inner:{order:700,enabled:!1,fn:function(e){var t=e.placement,n=t.split("-")[0],i=e.offsets,o=i.popper,r=i.reference,s=-1!==["left","right"].indexOf(n),a=-1===["top","left"].indexOf(n);return o[s?"left":"top"]=r[n]-(a?o[s?"width":"height"]:0),e.placement=it(t),e.offsets.popper=Xe(o),e}},hide:{order:800,enabled:!0,fn:function(e){if(!gt(e.instance.modifiers,"hide","preventOverflow"))return e;var t=e.offsets.reference,n=rt(e.instance.modifiers,function(e){return"preventOverflow"===e.name}).boundaries;if(t.bottomn.right||t.top>n.bottom||t.rightdocument.documentElement.clientHeight;!this._isBodyOverflowing&&e&&(this._element.style.paddingLeft=this._scrollbarWidth+"px"),this._isBodyOverflowing&&!e&&(this._element.style.paddingRight=this._scrollbarWidth+"px")},e._resetAdjustments=function(){this._element.style.paddingLeft="",this._element.style.paddingRight=""},e._checkScrollbar=function(){var e=document.body.getBoundingClientRect();this._isBodyOverflowing=e.left+e.right
',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent",sanitize:!0,sanitizeFn:null,whiteList:Cn,popperConfig:null},Fn="show",Mn="out",Wn={HIDE:"hide"+Nn,HIDDEN:"hidden"+Nn,SHOW:"show"+Nn,SHOWN:"shown"+Nn,INSERTED:"inserted"+Nn,CLICK:"click"+Nn,FOCUSIN:"focusin"+Nn,FOCUSOUT:"focusout"+Nn,MOUSEENTER:"mouseenter"+Nn,MOUSELEAVE:"mouseleave"+Nn},Un="fade",Bn="show",qn=".tooltip-inner",Kn=".arrow",Qn="hover",Vn="focus",Yn="click",zn="manual",Xn=function(){function i(e,t){if("undefined"==typeof St)throw new TypeError("Bootstrap's tooltips require Popper.js (https://popper.js.org/)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=e,this.config=this._getConfig(t),this.tip=null,this._setListeners()}var e=i.prototype;return e.enable=function(){this._isEnabled=!0},e.disable=function(){this._isEnabled=!1},e.toggleEnabled=function(){this._isEnabled=!this._isEnabled},e.toggle=function(e){if(this._isEnabled)if(e){var t=this.constructor.DATA_KEY,n=p(e.currentTarget).data(t);n||(n=new this.constructor(e.currentTarget,this._getDelegateConfig()),p(e.currentTarget).data(t,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(p(this.getTipElement()).hasClass(Bn))return void this._leave(null,this);this._enter(null,this)}},e.dispose=function(){clearTimeout(this._timeout),p.removeData(this.element,this.constructor.DATA_KEY),p(this.element).off(this.constructor.EVENT_KEY),p(this.element).closest(".modal").off("hide.bs.modal",this._hideModalHandler),this.tip&&p(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,this._activeTrigger=null,this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},e.show=function(){var t=this;if("none"===p(this.element).css("display"))throw new Error("Please use show on visible elements");var e=p.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){p(this.element).trigger(e);var n=m.findShadowRoot(this.element),i=p.contains(null!==n?n:this.element.ownerDocument.documentElement,this.element);if(e.isDefaultPrevented()||!i)return;var o=this.getTipElement(),r=m.getUID(this.constructor.NAME);o.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&p(o).addClass(Un);var s="function"==typeof this.config.placement?this.config.placement.call(this,o,this.element):this.config.placement,a=this._getAttachment(s);this.addAttachmentClass(a);var l=this._getContainer();p(o).data(this.constructor.DATA_KEY,this),p.contains(this.element.ownerDocument.documentElement,this.tip)||p(o).appendTo(l),p(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new St(this.element,o,this._getPopperConfig(a)),p(o).addClass(Bn),"ontouchstart"in document.documentElement&&p(document.body).children().on("mouseover",null,p.noop);var c=function(){t.config.animation&&t._fixTransition();var e=t._hoverState;t._hoverState=null,p(t.element).trigger(t.constructor.Event.SHOWN),e===Mn&&t._leave(null,t)};if(p(this.tip).hasClass(Un)){var h=m.getTransitionDurationFromElement(this.tip);p(this.tip).one(m.TRANSITION_END,c).emulateTransitionEnd(h)}else c()}},e.hide=function(e){function t(){n._hoverState!==Fn&&i.parentNode&&i.parentNode.removeChild(i),n._cleanTipClass(),n.element.removeAttribute("aria-describedby"),p(n.element).trigger(n.constructor.Event.HIDDEN),null!==n._popper&&n._popper.destroy(),e&&e()}var n=this,i=this.getTipElement(),o=p.Event(this.constructor.Event.HIDE);if(p(this.element).trigger(o),!o.isDefaultPrevented()){if(p(i).removeClass(Bn),"ontouchstart"in document.documentElement&&p(document.body).children().off("mouseover",null,p.noop),this._activeTrigger[Yn]=!1,this._activeTrigger[Vn]=!1,this._activeTrigger[Qn]=!1,p(this.tip).hasClass(Un)){var r=m.getTransitionDurationFromElement(i);p(i).one(m.TRANSITION_END,t).emulateTransitionEnd(r)}else t();this._hoverState=""}},e.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},e.isWithContent=function(){return Boolean(this.getTitle())},e.addAttachmentClass=function(e){p(this.getTipElement()).addClass(Ln+"-"+e)},e.getTipElement=function(){return this.tip=this.tip||p(this.config.template)[0],this.tip},e.setContent=function(){var e=this.getTipElement();this.setElementContent(p(e.querySelectorAll(qn)),this.getTitle()),p(e).removeClass(Un+" "+Bn)},e.setElementContent=function(e,t){"object"!=typeof t||!t.nodeType&&!t.jquery?this.config.html?(this.config.sanitize&&(t=In(t,this.config.whiteList,this.config.sanitizeFn)),e.html(t)):e.text(t):this.config.html?p(t).parent().is(e)||e.empty().append(t):e.text(p(t).text())},e.getTitle=function(){var e=this.element.getAttribute("data-original-title");return e=e||("function"==typeof this.config.title?this.config.title.call(this.element):this.config.title)},e._getPopperConfig=function(e){var t=this;return l({},{placement:e,modifiers:{offset:this._getOffset(),flip:{behavior:this.config.fallbackPlacement},arrow:{element:Kn},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(e){e.originalPlacement!==e.placement&&t._handlePopperPlacementChange(e)},onUpdate:function(e){return t._handlePopperPlacementChange(e)}},{},this.config.popperConfig)},e._getOffset=function(){var t=this,e={};return"function"==typeof this.config.offset?e.fn=function(e){return e.offsets=l({},e.offsets,{},t.config.offset(e.offsets,t.element)||{}),e}:e.offset=this.config.offset,e},e._getContainer=function(){return!1===this.config.container?document.body:m.isElement(this.config.container)?p(this.config.container):p(document).find(this.config.container)},e._getAttachment=function(e){return Hn[e.toUpperCase()]},e._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(e){if("click"===e)p(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(e){return i.toggle(e)});else if(e!==zn){var t=e===Qn?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=e===Qn?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;p(i.element).on(t,i.config.selector,function(e){return i._enter(e)}).on(n,i.config.selector,function(e){return i._leave(e)})}}),this._hideModalHandler=function(){i.element&&i.hide()},p(this.element).closest(".modal").on("hide.bs.modal",this._hideModalHandler),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},e._fixTitle=function(){var e=typeof this.element.getAttribute("data-original-title");!this.element.getAttribute("title")&&"string"==e||(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},e._enter=function(e,t){var n=this.constructor.DATA_KEY;(t=t||p(e.currentTarget).data(n))||(t=new this.constructor(e.currentTarget,this._getDelegateConfig()),p(e.currentTarget).data(n,t)),e&&(t._activeTrigger["focusin"===e.type?Vn:Qn]=!0),p(t.getTipElement()).hasClass(Bn)||t._hoverState===Fn?t._hoverState=Fn:(clearTimeout(t._timeout),t._hoverState=Fn,t.config.delay&&t.config.delay.show?t._timeout=setTimeout(function(){t._hoverState===Fn&&t.show()},t.config.delay.show):t.show())},e._leave=function(e,t){var n=this.constructor.DATA_KEY;(t=t||p(e.currentTarget).data(n))||(t=new this.constructor(e.currentTarget,this._getDelegateConfig()),p(e.currentTarget).data(n,t)),e&&(t._activeTrigger["focusout"===e.type?Vn:Qn]=!1),t._isWithActiveTrigger()||(clearTimeout(t._timeout),t._hoverState=Mn,t.config.delay&&t.config.delay.hide?t._timeout=setTimeout(function(){t._hoverState===Mn&&t.hide()},t.config.delay.hide):t.hide())},e._isWithActiveTrigger=function(){for(var e in this._activeTrigger)if(this._activeTrigger[e])return!0;return!1},e._getConfig=function(e){var t=p(this.element).data();return Object.keys(t).forEach(function(e){-1!==xn.indexOf(e)&&delete t[e]}),"number"==typeof(e=l({},this.constructor.Default,{},t,{},"object"==typeof e&&e?e:{})).delay&&(e.delay={show:e.delay,hide:e.delay}),"number"==typeof e.title&&(e.title=e.title.toString()),"number"==typeof e.content&&(e.content=e.content.toString()),m.typeCheckConfig(An,e,this.constructor.DefaultType),e.sanitize&&(e.template=In(e.template,e.whiteList,e.sanitizeFn)),e},e._getDelegateConfig=function(){var e={};if(this.config)for(var t in this.config)this.constructor.Default[t]!==this.config[t]&&(e[t]=this.config[t]);return e},e._cleanTipClass=function(){var e=p(this.getTipElement()),t=e.attr("class").match(Pn);null!==t&&t.length&&e.removeClass(t.join(""))},e._handlePopperPlacementChange=function(e){var t=e.instance;this.tip=t.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(e.placement))},e._fixTransition=function(){var e=this.getTipElement(),t=this.config.animation;null===e.getAttribute("x-placement")&&(p(e).removeClass(Un),this.config.animation=!1,this.hide(),this.show(),this.config.animation=t)},i._jQueryInterface=function(n){return this.each(function(){var e=p(this).data(On),t="object"==typeof n&&n;if((e||!/dispose|hide/.test(n))&&(e||(e=new i(this,t),p(this).data(On,e)),"string"==typeof n)){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.4.1"}},{key:"Default",get:function(){return Rn}},{key:"NAME",get:function(){return An}},{key:"DATA_KEY",get:function(){return On}},{key:"Event",get:function(){return Wn}},{key:"EVENT_KEY",get:function(){return Nn}},{key:"DefaultType",get:function(){return jn}}]),i}();p.fn[An]=Xn._jQueryInterface,p.fn[An].Constructor=Xn,p.fn[An].noConflict=function(){return p.fn[An]=kn,Xn._jQueryInterface};var Gn="popover",$n="bs.popover",Jn="."+$n,Zn=p.fn[Gn],ei="bs-popover",ti=new RegExp("(^|\\s)"+ei+"\\S+","g"),ni=l({},Xn.Default,{placement:"right",trigger:"click",content:"",template:''}),ii=l({},Xn.DefaultType,{content:"(string|element|function)"}),oi="fade",ri="show",si=".popover-header",ai=".popover-body",li={HIDE:"hide"+Jn,HIDDEN:"hidden"+Jn,SHOW:"show"+Jn,SHOWN:"shown"+Jn,INSERTED:"inserted"+Jn,CLICK:"click"+Jn,FOCUSIN:"focusin"+Jn,FOCUSOUT:"focusout"+Jn,MOUSEENTER:"mouseenter"+Jn,MOUSELEAVE:"mouseleave"+Jn},ci=function(e){function i(){return e.apply(this,arguments)||this}!function(e,t){e.prototype=Object.create(t.prototype),(e.prototype.constructor=e).__proto__=t}(i,e);var t=i.prototype;return t.isWithContent=function(){return this.getTitle()||this._getContent()},t.addAttachmentClass=function(e){p(this.getTipElement()).addClass(ei+"-"+e)},t.getTipElement=function(){return this.tip=this.tip||p(this.config.template)[0],this.tip},t.setContent=function(){var e=p(this.getTipElement());this.setElementContent(e.find(si),this.getTitle());var t=this._getContent();"function"==typeof t&&(t=t.call(this.element)),this.setElementContent(e.find(ai),t),e.removeClass(oi+" "+ri)},t._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},t._cleanTipClass=function(){var e=p(this.getTipElement()),t=e.attr("class").match(ti);null!==t&&0=this._offsets[o]&&("undefined"==typeof this._offsets[o+1]||e li > .active",qi='[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',Ki=".dropdown-toggle",Qi="> .dropdown-menu .active",Vi=function(){function i(e){this._element=e}var e=i.prototype;return e.show=function(){var n=this;if(!(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&p(this._element).hasClass(ji)||p(this._element).hasClass(Hi))){var e,i,t=p(this._element).closest(Wi)[0],o=m.getSelectorFromElement(this._element);if(t){var r="UL"===t.nodeName||"OL"===t.nodeName?Bi:Ui;i=(i=p.makeArray(p(t).find(r)))[i.length-1]}var s=p.Event(Pi.HIDE,{relatedTarget:this._element}),a=p.Event(Pi.SHOW,{relatedTarget:i});if(i&&p(i).trigger(s),p(this._element).trigger(a),!a.isDefaultPrevented()&&!s.isDefaultPrevented()){o&&(e=document.querySelector(o)),this._activate(this._element,t);var l=function(){var e=p.Event(Pi.HIDDEN,{relatedTarget:n._element}),t=p.Event(Pi.SHOWN,{relatedTarget:i});p(i).trigger(e),p(n._element).trigger(t)};e?this._activate(e,e.parentNode,l):l()}}},e.dispose=function(){p.removeData(this._element,Ni),this._element=null},e._activate=function(e,t,n){function i(){return o._transitionComplete(e,r,n)}var o=this,r=(!t||"UL"!==t.nodeName&&"OL"!==t.nodeName?p(t).children(Ui):p(t).find(Bi))[0],s=n&&r&&p(r).hasClass(Ri);if(r&&s){var a=m.getTransitionDurationFromElement(r);p(r).removeClass(Fi).one(m.TRANSITION_END,i).emulateTransitionEnd(a)}else i()},e._transitionComplete=function(e,t,n){if(t){p(t).removeClass(ji);var i=p(t.parentNode).find(Qi)[0];i&&p(i).removeClass(ji),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!1)}if(p(e).addClass(ji),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!0),m.reflow(e),e.classList.contains(Ri)&&e.classList.add(Fi),e.parentNode&&p(e.parentNode).hasClass(xi)){var o=p(e).closest(Mi)[0];if(o){var r=[].slice.call(o.querySelectorAll(Ki));p(r).addClass(ji)}e.setAttribute("aria-expanded",!0)}n&&n()},i._jQueryInterface=function(n){return this.each(function(){var e=p(this),t=e.data(Ni);if(t||(t=new i(this),e.data(Ni,t)),"string"==typeof n){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.4.1"}}]),i}();p(document).on(Pi.CLICK_DATA_API,qi,function(e){e.preventDefault(),Vi._jQueryInterface.call(p(this),"show")}),p.fn.tab=Vi._jQueryInterface,p.fn.tab.Constructor=Vi,p.fn.tab.noConflict=function(){return p.fn.tab=Li,Vi._jQueryInterface};var Yi="toast",zi="bs.toast",Xi="."+zi,Gi=p.fn[Yi],$i={CLICK_DISMISS:"click.dismiss"+Xi,HIDE:"hide"+Xi,HIDDEN:"hidden"+Xi,SHOW:"show"+Xi,SHOWN:"shown"+Xi},Ji="fade",Zi="hide",eo="show",to="showing",no={animation:"boolean",autohide:"boolean",delay:"number"},io={animation:!0,autohide:!0,delay:500},oo='[data-dismiss="toast"]',ro=function(){function i(e,t){this._element=e,this._config=this._getConfig(t),this._timeout=null,this._setListeners()}var e=i.prototype;return e.show=function(){var e=this,t=p.Event($i.SHOW);if(p(this._element).trigger(t),!t.isDefaultPrevented()){this._config.animation&&this._element.classList.add(Ji);var n=function(){e._element.classList.remove(to),e._element.classList.add(eo),p(e._element).trigger($i.SHOWN),e._config.autohide&&(e._timeout=setTimeout(function(){e.hide()},e._config.delay))};if(this._element.classList.remove(Zi),m.reflow(this._element),this._element.classList.add(to),this._config.animation){var i=m.getTransitionDurationFromElement(this._element);p(this._element).one(m.TRANSITION_END,n).emulateTransitionEnd(i)}else n()}},e.hide=function(){if(this._element.classList.contains(eo)){var e=p.Event($i.HIDE);p(this._element).trigger(e),e.isDefaultPrevented()||this._close()}},e.dispose=function(){clearTimeout(this._timeout),this._timeout=null,this._element.classList.contains(eo)&&this._element.classList.remove(eo),p(this._element).off($i.CLICK_DISMISS),p.removeData(this._element,zi),this._element=null,this._config=null},e._getConfig=function(e){return e=l({},io,{},p(this._element).data(),{},"object"==typeof e&&e?e:{}),m.typeCheckConfig(Yi,e,this.constructor.DefaultType),e},e._setListeners=function(){var e=this;p(this._element).on($i.CLICK_DISMISS,oo,function(){return e.hide()})},e._close=function(){function e(){t._element.classList.add(Zi),p(t._element).trigger($i.HIDDEN)}var t=this;if(this._element.classList.remove(eo),this._config.animation){var n=m.getTransitionDurationFromElement(this._element);p(this._element).one(m.TRANSITION_END,e).emulateTransitionEnd(n)}else e()},i._jQueryInterface=function(n){return this.each(function(){var e=p(this),t=e.data(zi);if(t||(t=new i(this,"object"==typeof n&&n),e.data(zi,t)),"string"==typeof n){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n](this)}})},s(i,null,[{key:"VERSION",get:function(){return"4.4.1"}},{key:"DefaultType",get:function(){return no}},{key:"Default",get:function(){return io}}]),i}();p.fn[Yi]=ro._jQueryInterface,p.fn[Yi].Constructor=ro,p.fn[Yi].noConflict=function(){return p.fn[Yi]=Gi,ro._jQueryInterface},e.Alert=_,e.Button=x,e.Carousel=he,e.Collapse=De,e.Dropdown=en,e.Modal=wn,e.Popover=ci,e.Scrollspy=Oi,e.Tab=Vi,e.Toast=ro,e.Tooltip=Xn,e.Util=m,Object.defineProperty(e,"__esModule",{value:!0})});
7 | //# sourceMappingURL=bootstrap.bundle.min.js.map
--------------------------------------------------------------------------------
/src/vendor/modus/jquery.js:
--------------------------------------------------------------------------------
1 | /*! jQuery v3.4.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector | (c) JS Foundation and other contributors | jquery.org/license */
2 | !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(g,e){"use strict";var t=[],v=g.document,r=Object.getPrototypeOf,s=t.slice,y=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,m=n.hasOwnProperty,a=m.toString,l=a.call(Object),b={},x=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},w=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function C(e,t,n){var r,i,o=(n=n||v).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function T(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector",E=function(e,t){return new E.fn.init(e,t)},d=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function p(e){var t=!!e&&"length"in e&&e.length,n=T(e);return!x(e)&&!w(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+R+")"+R+"*"),U=new RegExp(R+"|>"),V=new RegExp(W),X=new RegExp("^"+B+"$"),Q={ID:new RegExp("^#("+B+")"),CLASS:new RegExp("^\\.("+B+")"),TAG:new RegExp("^("+B+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+W),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+R+"*(even|odd|(([+-]|)(\\d*)n|)"+R+"*(?:([+-]|)"+R+"*(\\d+)|))"+R+"*\\)|)","i"),bool:new RegExp("^(?:"+I+")$","i"),needsContext:new RegExp("^"+R+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+R+"*((?:-\\d)?\\d*)"+R+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,G=/^(?:input|select|textarea|button)$/i,K=/^h\d$/i,J=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+R+"?|("+R+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){C()},ae=xe(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{O.apply(t=P.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){O={apply:t.length?function(e,t){q.apply(e,P.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,d=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==d&&9!==d&&11!==d)return n;if(!r&&((e?e.ownerDocument||e:m)!==T&&C(e),e=e||T,E)){if(11!==d&&(u=Z.exec(t)))if(i=u[1]){if(9===d){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return O.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&p.getElementsByClassName&&e.getElementsByClassName)return O.apply(n,e.getElementsByClassName(i)),n}if(p.qsa&&!S[t+" "]&&(!v||!v.test(t))&&(1!==d||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===d&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=N),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+be(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return O.apply(n,f.querySelectorAll(c)),n}catch(e){S(t,!0)}finally{s===N&&e.removeAttribute("id")}}}return g(t.replace(F,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>x.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[N]=!0,e}function ce(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)x.attrHandle[n[r]]=t}function de(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function pe(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in p=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},C=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==T&&9===r.nodeType&&r.documentElement&&(a=(T=r).documentElement,E=!i(T),m!==T&&(n=T.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),p.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),p.getElementsByTagName=ce(function(e){return e.appendChild(T.createComment("")),!e.getElementsByTagName("*").length}),p.getElementsByClassName=J.test(T.getElementsByClassName),p.getById=ce(function(e){return a.appendChild(e).id=N,!T.getElementsByName||!T.getElementsByName(N).length}),p.getById?(x.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},x.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(x.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},x.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),x.find.TAG=p.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):p.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},x.find.CLASS=p.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(p.qsa=J.test(T.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML=" ",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+R+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+R+"*(?:value|"+I+")"),e.querySelectorAll("[id~="+N+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+N+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML=" ";var t=T.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+R+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(p.matchesSelector=J.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){p.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",W)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=J.test(a.compareDocumentPosition),y=t||J.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!p.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument===m&&y(m,e)?-1:t===T||t.ownerDocument===m&&y(m,t)?1:u?H(u,e)-H(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===T?-1:t===T?1:i?-1:o?1:u?H(u,e)-H(u,t):0;if(i===o)return de(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?de(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),T},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==T&&C(e),p.matchesSelector&&E&&!S[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||p.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){S(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&V.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=d[e+" "];return t||(t=new RegExp("(^|"+R+")"+e+"("+R+"|$)"))&&d(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function L(e,n,r){return x(n)?E.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?E.grep(e,function(e){return e===n!==r}):"string"!=typeof n?E.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(E.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof E?t[0]:t,E.merge(this,E.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:v,!0)),D.test(r[1])&&E.isPlainObject(t))for(r in t)x(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=v.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):x(e)?void 0!==n.ready?n.ready(e):e(E):E.makeArray(e,this)}).prototype=E.fn,j=E(v);var O=/^(?:parents|prev(?:Until|All))/,P={children:!0,contents:!0,next:!0,prev:!0};function H(e,t){while((e=e[t])&&1!==e.nodeType);return e}E.fn.extend({has:function(e){var t=E(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,pe=/^$|^module$|\/(?:java|ecma)script/i,he={option:[1,""," "],thead:[1,""],col:[2,""],tr:[2,""],td:[3,""],_default:[0,"",""]};function ge(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&S(e,t)?E.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;nx",b.noCloneChecked=!!ye.cloneNode(!0).lastChild.defaultValue;var we=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Te=/^([^.]*)(?:\.(.+)|)/;function Ee(){return!0}function Ne(){return!1}function Ae(e,t){return e===function(){try{return v.activeElement}catch(e){}}()==("focus"===t)}function ke(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)ke(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Ne;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return E().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=E.guid++)),e.each(function(){E.event.add(this,t,i,r,n)})}function Se(e,i,o){o?(G.set(e,i,!1),E.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=G.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(E.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),G.set(this,i,r),t=o(this,i),this[i](),r!==(n=G.get(this,i))||t?G.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(G.set(this,i,{value:E.event.trigger(E.extend(r[0],E.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===G.get(e,i)&&E.event.add(e,i,Ee)}E.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,v=G.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&E.find.matchesSelector(ie,i),n.guid||(n.guid=E.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof E&&E.event.triggered!==e.type?E.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(I)||[""]).length;while(l--)p=g=(s=Te.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),p&&(f=E.event.special[p]||{},p=(i?f.delegateType:f.bindType)||p,f=E.event.special[p]||{},c=E.extend({type:p,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&E.expr.match.needsContext.test(i),namespace:h.join(".")},o),(d=u[p])||((d=u[p]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(p,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?d.splice(d.delegateCount++,0,c):d.push(c),E.event.global[p]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,d,p,h,g,v=G.hasData(e)&&G.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(I)||[""]).length;while(l--)if(p=g=(s=Te.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),p){f=E.event.special[p]||{},d=u[p=(r?f.delegateType:f.bindType)||p]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=d.length;while(o--)c=d[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(d.splice(o,1),c.selector&&d.delegateCount--,f.remove&&f.remove.call(e,c));a&&!d.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||E.removeEvent(e,p,v.handle),delete u[p])}else for(p in u)E.event.remove(e,p+t[l],n,r,!0);E.isEmptyObject(u)&&G.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=E.event.fix(e),u=new Array(arguments.length),l=(G.get(this,"events")||{})[s.type]||[],c=E.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,Le=/